Skip to content
Commits on Source (5)
repo: d5f45924411123cfd02d035fd50b8e37536eadef
node: f58f8d749b95d85a792e786a0256d0cc2278cc4d
branch: OrthancDicomWeb-0.4
node: b5f71018159133105d5cc1eb60d852a385bab998
branch: OrthancDicomWeb-0.5
latesttag: null
latesttagdistance: 179
changessincelatesttag: 189
latesttagdistance: 210
changessincelatesttag: 221
......@@ -14,7 +14,7 @@ Authors
4000 Liege
Belgium
* Osimis <info@osimis.io>
* Osimis S.A. <info@osimis.io>
Rue des Chasseurs Ardennais 3
4031 Liege
Belgium
# Orthanc - A Lightweight, RESTful DICOM Store
# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
# Department, University Hospital of Liege, Belgium
# Copyright (C) 2017 Osimis, Belgium
# Copyright (C) 2017-2018 Osimis S.A., Belgium
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
......@@ -21,47 +21,50 @@ cmake_minimum_required(VERSION 2.8)
project(OrthancDicomWeb)
set(ORTHANC_DICOM_WEB_VERSION "0.4")
set(ORTHANC_DICOM_WEB_VERSION "0.5")
if (ORTHANC_DICOM_WEB_VERSION STREQUAL "mainline")
set(ORTHANC_FRAMEWORK_VERSION "mainline")
set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg")
else()
set(ORTHANC_FRAMEWORK_VERSION "1.3.2")
set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web")
endif()
# Parameters of the build
set(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)")
set(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages")
set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")")
set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"")
set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"")
# Advanced parameters to fine-tune linking against system libraries
set(USE_SYSTEM_BOOST ON CACHE BOOL "Use the system version of Boost")
set(USE_SYSTEM_GDCM ON CACHE BOOL "Use the system version of Grassroot DICOM (GDCM)")
set(USE_SYSTEM_GOOGLE_TEST ON CACHE BOOL "Use the system version of Google Test")
set(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp")
set(USE_SYSTEM_ZLIB ON CACHE BOOL "Use the system version of zlib")
set(USE_SYSTEM_PUGIXML ON CACHE BOOL "Use the system version of Pugixml")
set(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK")
# Distribution-specific settings
set(USE_GTEST_DEBIAN_SOURCE_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (Debian only)")
mark_as_advanced(USE_GTEST_DEBIAN_SOURCE_PACKAGE)
set(USE_PUGIXML ON)
set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR}/Orthanc)
set(ORTHANC_DISABLE_PATCH ON) # No need for the "patch" command-line tool
include(CheckIncludeFiles)
include(CheckIncludeFileCXX)
include(CheckLibraryExists)
include(FindPythonInterp)
include(${ORTHANC_ROOT}/Resources/CMake/Compiler.cmake)
include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake)
include(${ORTHANC_ROOT}/Resources/CMake/BoostConfiguration.cmake)
include(${ORTHANC_ROOT}/Resources/CMake/GoogleTestConfiguration.cmake)
include(${ORTHANC_ROOT}/Resources/CMake/JsonCppConfiguration.cmake)
include(${ORTHANC_ROOT}/Resources/CMake/ZlibConfiguration.cmake)
include(${ORTHANC_ROOT}/Resources/CMake/PugixmlConfiguration.cmake)
# Download and setup the Orthanc framework
include(${CMAKE_SOURCE_DIR}/Resources/Orthanc/DownloadOrthancFramework.cmake)
set(ORTHANC_FRAMEWORK_PLUGIN ON)
include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
set(ENABLE_LOCALE ON) # Enable support for locales (notably in Boost)
set(ENABLE_GOOGLE_TEST ON)
set(ENABLE_PUGIXML ON)
set(USE_BOOST_ICONV ON)
include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkConfiguration.cmake)
include_directories(${ORTHANC_ROOT})
include(${CMAKE_SOURCE_DIR}/Resources/CMake/GdcmConfiguration.cmake)
if (STATIC_BUILD OR NOT USE_SYSTEM_ORTHANC_SDK)
include_directories(${ORTHANC_ROOT}/Sdk-1.1.0)
include_directories(${CMAKE_SOURCE_DIR}/Resources/Orthanc/Sdk-1.1.0)
else ()
CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCPlugin.h HAVE_ORTHANC_H)
if (NOT HAVE_ORTHANC_H)
......@@ -100,32 +103,19 @@ if (APPLE)
endif()
include_directories(${ORTHANC_ROOT}/Core) # To access "OrthancException.h"
add_definitions(
-DORTHANC_ENABLE_MD5=0
-DORTHANC_ENABLE_BASE64=0
-DORTHANC_ENABLE_LOGGING=0
-DORTHANC_SANDBOXED=0
-DHAS_ORTHANC_EXCEPTION=1
)
include_directories(${ORTHANC_ROOT}/Core) # To access "OrthancException.h"
set(CORE_SOURCES
${BOOST_SOURCES}
${JSONCPP_SOURCES}
${ZLIB_SOURCES}
${PUGIXML_SOURCES}
${ORTHANC_ROOT}/Core/ChunkedBuffer.cpp
${ORTHANC_ROOT}/Core/Enumerations.cpp
${ORTHANC_ROOT}/Core/Toolbox.cpp
${ORTHANC_ROOT}/Core/SystemToolbox.cpp
${ORTHANC_ROOT}/Core/WebServiceParameters.cpp
${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp
Plugin/Configuration.cpp
Plugin/Dicom.cpp
Plugin/DicomResults.cpp
${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp
${ORTHANC_CORE_SOURCES}
)
add_library(OrthancDicomWeb SHARED ${CORE_SOURCES}
......@@ -159,12 +149,15 @@ install(
add_executable(UnitTests
${CORE_SOURCES}
${GTEST_SOURCES}
${GOOGLE_TEST_SOURCES}
${CMAKE_SOURCE_DIR}/Plugin/DicomWebServers.cpp
UnitTestsSources/UnitTestsMain.cpp
)
target_link_libraries(UnitTests ${GDCM_LIBRARIES})
target_link_libraries(UnitTests
${GDCM_LIBRARIES}
${GOOGLE_TEST_LIBRARIES}
)
if (STATIC_BUILD OR NOT USE_SYSTEM_GDCM)
add_dependencies(OrthancDicomWeb GDCM)
......
......@@ -2,6 +2,20 @@ Pending changes in the mainline
===============================
Version 0.5 (2018-08-19)
========================
* New option: "QidoCaseSensitive" to make queries to QIDO-RS server case insensitive
* Defaults to JSON answers instead of XML
* Use of "application/dicom+json" MIME type instead of "application/json"
* Added "?expand" argument to "/servers" route
* Fix generation of numeric tags part of sequences for ".../metadata" routes
* Support for OpenBSD
* Support for Linux Standard Base
* Upgrade to GDCM 2.8.4 for static builds
* Resort to Orthanc framework
Version 0.4 (2017-07-19)
========================
......
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#include "PrecompiledHeaders.h"
#include "ChunkedBuffer.h"
#include <cassert>
#include <string.h>
namespace Orthanc
{
void ChunkedBuffer::Clear()
{
numBytes_ = 0;
for (Chunks::iterator it = chunks_.begin();
it != chunks_.end(); ++it)
{
delete *it;
}
}
void ChunkedBuffer::AddChunk(const void* chunkData,
size_t chunkSize)
{
if (chunkSize == 0)
{
return;
}
else
{
assert(chunkData != NULL);
chunks_.push_back(new std::string(reinterpret_cast<const char*>(chunkData), chunkSize));
numBytes_ += chunkSize;
}
}
void ChunkedBuffer::AddChunk(const std::string& chunk)
{
if (chunk.size() > 0)
{
AddChunk(&chunk[0], chunk.size());
}
}
void ChunkedBuffer::Flatten(std::string& result)
{
result.resize(numBytes_);
size_t pos = 0;
for (Chunks::iterator it = chunks_.begin();
it != chunks_.end(); ++it)
{
assert(*it != NULL);
size_t s = (*it)->size();
if (s != 0)
{
memcpy(&result[pos], (*it)->c_str(), s);
pos += s;
}
delete *it;
}
chunks_.clear();
numBytes_ = 0;
}
}
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#pragma once
#include <list>
#include <string>
namespace Orthanc
{
class ChunkedBuffer
{
private:
typedef std::list<std::string*> Chunks;
size_t numBytes_;
Chunks chunks_;
void Clear();
public:
ChunkedBuffer() : numBytes_(0)
{
}
~ChunkedBuffer()
{
Clear();
}
size_t GetNumBytes() const
{
return numBytes_;
}
void AddChunk(const void* chunkData,
size_t chunkSize);
void AddChunk(const std::string& chunk);
void Flatten(std::string& result);
};
}
This diff is collapsed.
This diff is collapsed.
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#pragma once
#include <iostream>
#if !defined(ORTHANC_ENABLE_LOGGING)
# error The macro ORTHANC_ENABLE_LOGGING must be defined
#endif
#if !defined(ORTHANC_ENABLE_LOGGING_PLUGIN)
# if ORTHANC_ENABLE_LOGGING == 1
# error The macro ORTHANC_ENABLE_LOGGING_PLUGIN must be defined
# else
# define ORTHANC_ENABLE_LOGGING_PLUGIN 0
# endif
#endif
#if ORTHANC_ENABLE_LOGGING_PLUGIN == 1
# include <orthanc/OrthancCPlugin.h>
#endif
namespace Orthanc
{
namespace Logging
{
#if ORTHANC_ENABLE_LOGGING_PLUGIN == 1
void Initialize(OrthancPluginContext* context);
#else
void Initialize();
#endif
void Finalize();
void Reset();
void Flush();
void EnableInfoLevel(bool enabled);
void EnableTraceLevel(bool enabled);
void SetTargetFile(const std::string& path);
void SetTargetFolder(const std::string& path);
struct NullStream : public std::ostream
{
NullStream() :
std::ios(0),
std::ostream(0)
{
}
std::ostream& operator<< (const std::string& message)
{
return *this;
}
// This overload fixes build problems with Visual Studio 2015
std::ostream& operator<< (const char* message)
{
return *this;
}
};
}
}
#if ORTHANC_ENABLE_LOGGING != 1
# define LOG(level) ::Orthanc::Logging::NullStream()
# define VLOG(level) ::Orthanc::Logging::NullStream()
#elif ORTHANC_ENABLE_LOGGING_PLUGIN == 1
# include <boost/noncopyable.hpp>
# define LOG(level) ::Orthanc::Logging::InternalLogger(#level, __FILE__, __LINE__)
# define VLOG(level) ::Orthanc::Logging::InternalLogger("TRACE", __FILE__, __LINE__)
namespace Orthanc
{
namespace Logging
{
class InternalLogger : public boost::noncopyable
{
private:
std::string level_;
std::string message_;
public:
InternalLogger(const char* level,
const char* file,
int line);
~InternalLogger();
InternalLogger& operator<< (const std::string& message);
InternalLogger& operator<< (const char* message);
InternalLogger& operator<< (int message);
};
}
}
#else /* ORTHANC_ENABLE_LOGGING_PLUGIN == 0 && ORTHANC_ENABLE_LOGGING == 1 */
# include <boost/thread/mutex.hpp>
# define LOG(level) ::Orthanc::Logging::InternalLogger(#level, __FILE__, __LINE__)
# define VLOG(level) ::Orthanc::Logging::InternalLogger("TRACE", __FILE__, __LINE__)
namespace Orthanc
{
namespace Logging
{
class InternalLogger
{
private:
boost::mutex::scoped_lock lock_;
NullStream null_;
std::ostream* stream_;
public:
InternalLogger(const char* level,
const char* file,
int line);
~InternalLogger();
std::ostream& operator<< (const std::string& message)
{
return (*stream_) << message;
}
// This overload fixes build problems with Visual Studio 2015
std::ostream& operator<< (const char* message)
{
return (*stream_) << message;
}
};
}
}
#endif // ORTHANC_ENABLE_LOGGING
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#pragma once
#include <stdint.h>
#include <string>
#include "Enumerations.h"
namespace Orthanc
{
class OrthancException
{
protected:
ErrorCode errorCode_;
HttpStatus httpStatus_;
public:
explicit OrthancException(ErrorCode errorCode) :
errorCode_(errorCode),
httpStatus_(ConvertErrorCodeToHttpStatus(errorCode))
{
}
OrthancException(ErrorCode errorCode,
HttpStatus httpStatus) :
errorCode_(errorCode),
httpStatus_(httpStatus)
{
}
ErrorCode GetErrorCode() const
{
return errorCode_;
}
HttpStatus GetHttpStatus() const
{
return httpStatus_;
}
const char* What() const
{
return EnumerationToString(errorCode_);
}
};
}
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#pragma once
#if defined(_WIN32) && !defined(NOMINMAX)
#define NOMINMAX
#endif
#if ORTHANC_USE_PRECOMPILED_HEADERS == 1
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/locale.hpp>
#include <boost/regex.hpp>
#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <json/value.h>
#if ORTHANC_ENABLE_PUGIXML == 1
#include <pugixml.hpp>
#endif
#include "Enumerations.h"
#include "Logging.h"
#include "OrthancException.h"
#include "Toolbox.h"
#endif
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#include "PrecompiledHeaders.h"
#include "SystemToolbox.h"
#if BOOST_HAS_DATE_TIME == 1
# include <boost/date_time/posix_time/posix_time.hpp>
#endif
#if defined(_WIN32)
# include <windows.h>
# include <process.h> // For "_spawnvp()" and "_getpid()"
#else
# include <unistd.h> // For "execvp()"
# include <sys/wait.h> // For "waitpid()"
#endif
#if defined(__APPLE__) && defined(__MACH__)
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
# include <limits.h> /* PATH_MAX */
#endif
#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
# include <limits.h> /* PATH_MAX */
# include <signal.h>
# include <unistd.h>
#endif
// Inclusions for UUID
// http://stackoverflow.com/a/1626302
extern "C"
{
#ifdef WIN32
# include <rpc.h>
#else
# include <uuid/uuid.h>
#endif
}
#include "Logging.h"
#include "OrthancException.h"
#include "Toolbox.h"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
namespace Orthanc
{
static bool finish_;
static ServerBarrierEvent barrierEvent_;
#if defined(_WIN32)
static BOOL WINAPI ConsoleControlHandler(DWORD dwCtrlType)
{
// http://msdn.microsoft.com/en-us/library/ms683242(v=vs.85).aspx
finish_ = true;
return true;
}
#else
static void SignalHandler(int signal)
{
if (signal == SIGHUP)
{
barrierEvent_ = ServerBarrierEvent_Reload;
}
finish_ = true;
}
#endif
static ServerBarrierEvent ServerBarrierInternal(const bool* stopFlag)
{
#if defined(_WIN32)
SetConsoleCtrlHandler(ConsoleControlHandler, true);
#else
signal(SIGINT, SignalHandler);
signal(SIGQUIT, SignalHandler);
signal(SIGTERM, SignalHandler);
signal(SIGHUP, SignalHandler);
#endif
// Active loop that awakens every 100ms
finish_ = false;
barrierEvent_ = ServerBarrierEvent_Stop;
while (!(*stopFlag || finish_))
{
SystemToolbox::USleep(100 * 1000);
}
#if defined(_WIN32)
SetConsoleCtrlHandler(ConsoleControlHandler, false);
#else
signal(SIGINT, NULL);
signal(SIGQUIT, NULL);
signal(SIGTERM, NULL);
signal(SIGHUP, NULL);
#endif
return barrierEvent_;
}
ServerBarrierEvent SystemToolbox::ServerBarrier(const bool& stopFlag)
{
return ServerBarrierInternal(&stopFlag);
}
ServerBarrierEvent SystemToolbox::ServerBarrier()
{
const bool stopFlag = false;
return ServerBarrierInternal(&stopFlag);
}
void SystemToolbox::USleep(uint64_t microSeconds)
{
#if defined(_WIN32)
::Sleep(static_cast<DWORD>(microSeconds / static_cast<uint64_t>(1000)));
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__native_client__)
usleep(microSeconds);
#else
#error Support your platform here
#endif
}
static std::streamsize GetStreamSize(std::istream& f)
{
// http://www.cplusplus.com/reference/iostream/istream/tellg/
f.seekg(0, std::ios::end);
std::streamsize size = f.tellg();
f.seekg(0, std::ios::beg);
return size;
}
void SystemToolbox::ReadFile(std::string& content,
const std::string& path)
{
if (!IsRegularFile(path))
{
LOG(ERROR) << std::string("The path does not point to a regular file: ") << path;
throw OrthancException(ErrorCode_RegularFileExpected);
}
boost::filesystem::ifstream f;
f.open(path, std::ifstream::in | std::ifstream::binary);
if (!f.good())
{
throw OrthancException(ErrorCode_InexistentFile);
}
std::streamsize size = GetStreamSize(f);
content.resize(size);
if (size != 0)
{
f.read(reinterpret_cast<char*>(&content[0]), size);
}
f.close();
}
bool SystemToolbox::ReadHeader(std::string& header,
const std::string& path,
size_t headerSize)
{
if (!IsRegularFile(path))
{
LOG(ERROR) << std::string("The path does not point to a regular file: ") << path;
throw OrthancException(ErrorCode_RegularFileExpected);
}
boost::filesystem::ifstream f;
f.open(path, std::ifstream::in | std::ifstream::binary);
if (!f.good())
{
throw OrthancException(ErrorCode_InexistentFile);
}
bool full = true;
{
std::streamsize size = GetStreamSize(f);
if (size <= 0)
{
headerSize = 0;
full = false;
}
else if (static_cast<size_t>(size) < headerSize)
{
headerSize = size; // Truncate to the size of the file
full = false;
}
}
header.resize(headerSize);
if (headerSize != 0)
{
f.read(reinterpret_cast<char*>(&header[0]), headerSize);
}
f.close();
return full;
}
void SystemToolbox::WriteFile(const void* content,
size_t size,
const std::string& path)
{
boost::filesystem::ofstream f;
f.open(path, std::ofstream::out | std::ofstream::binary);
if (!f.good())
{
throw OrthancException(ErrorCode_CannotWriteFile);
}
if (size != 0)
{
f.write(reinterpret_cast<const char*>(content), size);
if (!f.good())
{
f.close();
throw OrthancException(ErrorCode_FileStorageCannotWrite);
}
}
f.close();
}
void SystemToolbox::WriteFile(const std::string& content,
const std::string& path)
{
WriteFile(content.size() > 0 ? content.c_str() : NULL,
content.size(), path);
}
void SystemToolbox::RemoveFile(const std::string& path)
{
if (boost::filesystem::exists(path))
{
if (IsRegularFile(path))
{
boost::filesystem::remove(path);
}
else
{
throw OrthancException(ErrorCode_RegularFileExpected);
}
}
}
uint64_t SystemToolbox::GetFileSize(const std::string& path)
{
try
{
return static_cast<uint64_t>(boost::filesystem::file_size(path));
}
catch (boost::filesystem::filesystem_error&)
{
throw OrthancException(ErrorCode_InexistentFile);
}
}
void SystemToolbox::MakeDirectory(const std::string& path)
{
if (boost::filesystem::exists(path))
{
if (!boost::filesystem::is_directory(path))
{
throw OrthancException(ErrorCode_DirectoryOverFile);
}
}
else
{
if (!boost::filesystem::create_directories(path))
{
throw OrthancException(ErrorCode_MakeDirectory);
}
}
}
bool SystemToolbox::IsExistingFile(const std::string& path)
{
return boost::filesystem::exists(path);
}
#if defined(_WIN32)
static std::string GetPathToExecutableInternal()
{
// Yes, this is ugly, but there is no simple way to get the
// required buffer size, so we use a big constant
std::vector<char> buffer(32768);
/*int bytes =*/ GetModuleFileNameA(NULL, &buffer[0], static_cast<DWORD>(buffer.size() - 1));
return std::string(&buffer[0]);
}
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
static std::string GetPathToExecutableInternal()
{
std::vector<char> buffer(PATH_MAX + 1);
ssize_t bytes = readlink("/proc/self/exe", &buffer[0], buffer.size() - 1);
if (bytes == 0)
{
throw OrthancException(ErrorCode_PathToExecutable);
}
return std::string(&buffer[0]);
}
#elif defined(__APPLE__) && defined(__MACH__)
static std::string GetPathToExecutableInternal()
{
char pathbuf[PATH_MAX + 1];
unsigned int bufsize = static_cast<int>(sizeof(pathbuf));
_NSGetExecutablePath( pathbuf, &bufsize);
return std::string(pathbuf);
}
#else
#error Support your platform here
#endif
std::string SystemToolbox::GetPathToExecutable()
{
boost::filesystem::path p(GetPathToExecutableInternal());
return boost::filesystem::absolute(p).string();
}
std::string SystemToolbox::GetDirectoryOfExecutable()
{
boost::filesystem::path p(GetPathToExecutableInternal());
return boost::filesystem::absolute(p.parent_path()).string();
}
void SystemToolbox::ExecuteSystemCommand(const std::string& command,
const std::vector<std::string>& arguments)
{
// Convert the arguments as a C array
std::vector<char*> args(arguments.size() + 2);
args.front() = const_cast<char*>(command.c_str());
for (size_t i = 0; i < arguments.size(); i++)
{
args[i + 1] = const_cast<char*>(arguments[i].c_str());
}
args.back() = NULL;
int status;
#if defined(_WIN32)
// http://msdn.microsoft.com/en-us/library/275khfab.aspx
status = static_cast<int>(_spawnvp(_P_OVERLAY, command.c_str(), &args[0]));
#else
int pid = fork();
if (pid == -1)
{
// Error in fork()
#if ORTHANC_ENABLE_LOGGING == 1
LOG(ERROR) << "Cannot fork a child process";
#endif
throw OrthancException(ErrorCode_SystemCommand);
}
else if (pid == 0)
{
// Execute the system command in the child process
execvp(command.c_str(), &args[0]);
// We should never get here
_exit(1);
}
else
{
// Wait for the system command to exit
waitpid(pid, &status, 0);
}
#endif
if (status != 0)
{
#if ORTHANC_ENABLE_LOGGING == 1
LOG(ERROR) << "System command failed with status code " << status;
#endif
throw OrthancException(ErrorCode_SystemCommand);
}
}
int SystemToolbox::GetProcessId()
{
#if defined(_WIN32)
return static_cast<int>(_getpid());
#else
return static_cast<int>(getpid());
#endif
}
bool SystemToolbox::IsRegularFile(const std::string& path)
{
namespace fs = boost::filesystem;
try
{
if (fs::exists(path))
{
fs::file_status status = fs::status(path);
return (status.type() == boost::filesystem::regular_file ||
status.type() == boost::filesystem::reparse_file); // Fix BitBucket issue #11
}
}
catch (fs::filesystem_error&)
{
}
return false;
}
FILE* SystemToolbox::OpenFile(const std::string& path,
FileMode mode)
{
#if defined(_WIN32)
// TODO Deal with special characters by converting to the current locale
#endif
const char* m;
switch (mode)
{
case FileMode_ReadBinary:
m = "rb";
break;
case FileMode_WriteBinary:
m = "wb";
break;
default:
throw OrthancException(ErrorCode_ParameterOutOfRange);
}
return fopen(path.c_str(), m);
}
std::string SystemToolbox::GenerateUuid()
{
#ifdef WIN32
UUID uuid;
UuidCreate ( &uuid );
unsigned char * str;
UuidToStringA ( &uuid, &str );
std::string s( ( char* ) str );
RpcStringFreeA ( &str );
#else
uuid_t uuid;
uuid_generate_random ( uuid );
char s[37];
uuid_unparse ( uuid, s );
#endif
return s;
}
#if BOOST_HAS_DATE_TIME == 1
std::string SystemToolbox::GetNowIsoString()
{
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
return boost::posix_time::to_iso_string(now);
}
void SystemToolbox::GetNowDicom(std::string& date,
std::string& time)
{
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
tm tm = boost::posix_time::to_tm(now);
char s[32];
sprintf(s, "%04d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
date.assign(s);
// TODO milliseconds
sprintf(s, "%02d%02d%02d.%06d", tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
time.assign(s);
}
#endif
}
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#pragma once
#if !defined(ORTHANC_SANDBOXED)
# error The macro ORTHANC_SANDBOXED must be defined
#endif
#if ORTHANC_SANDBOXED == 1
# error The namespace SystemToolbox cannot be used in sandboxed environments
#endif
#include "Enumerations.h"
#include <vector>
#include <string>
#include <stdint.h>
namespace Orthanc
{
namespace SystemToolbox
{
void USleep(uint64_t microSeconds);
ServerBarrierEvent ServerBarrier(const bool& stopFlag);
ServerBarrierEvent ServerBarrier();
void ReadFile(std::string& content,
const std::string& path);
bool ReadHeader(std::string& header,
const std::string& path,
size_t headerSize);
void WriteFile(const void* content,
size_t size,
const std::string& path);
void WriteFile(const std::string& content,
const std::string& path);
void RemoveFile(const std::string& path);
uint64_t GetFileSize(const std::string& path);
void MakeDirectory(const std::string& path);
bool IsExistingFile(const std::string& path);
std::string GetPathToExecutable();
std::string GetDirectoryOfExecutable();
void ExecuteSystemCommand(const std::string& command,
const std::vector<std::string>& arguments);
int GetProcessId();
bool IsRegularFile(const std::string& path);
FILE* OpenFile(const std::string& path,
FileMode mode);
std::string GenerateUuid();
#if BOOST_HAS_DATE_TIME == 1
std::string GetNowIsoString();
void GetNowDicom(std::string& date,
std::string& time);
#endif
}
}
This diff is collapsed.
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#pragma once
#include "Enumerations.h"
#include <stdint.h>
#include <vector>
#include <string>
#include <json/json.h>
#if !defined(ORTHANC_ENABLE_BASE64)
# error The macro ORTHANC_ENABLE_BASE64 must be defined
#endif
#if !defined(ORTHANC_ENABLE_MD5)
# error The macro ORTHANC_ENABLE_MD5 must be defined
#endif
#if !defined(ORTHANC_ENABLE_PUGIXML)
# error The macro ORTHANC_ENABLE_PUGIXML must be defined
#endif
#if !defined(BOOST_HAS_REGEX)
# error The macro BOOST_HAS_REGEX must be defined
#endif
/**
* NOTE: GUID vs. UUID
* The simple answer is: no difference, they are the same thing. Treat
* them as a 16 byte (128 bits) value that is used as a unique
* value. In Microsoft-speak they are called GUIDs, but call them
* UUIDs when not using Microsoft-speak.
* http://stackoverflow.com/questions/246930/is-there-any-difference-between-a-guid-and-a-uuid
**/
namespace Orthanc
{
typedef std::vector<std::string> UriComponents;
class NullType
{
};
namespace Toolbox
{
void ToUpperCase(std::string& s); // Inplace version
void ToLowerCase(std::string& s); // Inplace version
void ToUpperCase(std::string& result,
const std::string& source);
void ToLowerCase(std::string& result,
const std::string& source);
void SplitUriComponents(UriComponents& components,
const std::string& uri);
void TruncateUri(UriComponents& target,
const UriComponents& source,
size_t fromLevel);
bool IsChildUri(const UriComponents& baseUri,
const UriComponents& testedUri);
std::string AutodetectMimeType(const std::string& path);
std::string FlattenUri(const UriComponents& components,
size_t fromLevel = 0);
#if ORTHANC_ENABLE_MD5 == 1
void ComputeMD5(std::string& result,
const std::string& data);
void ComputeMD5(std::string& result,
const void* data,
size_t size);
#endif
void ComputeSHA1(std::string& result,
const std::string& data);
void ComputeSHA1(std::string& result,
const void* data,
size_t size);
bool IsSHA1(const char* str,
size_t size);
bool IsSHA1(const std::string& s);
#if ORTHANC_ENABLE_BASE64 == 1
void DecodeBase64(std::string& result,
const std::string& data);
void EncodeBase64(std::string& result,
const std::string& data);
# if BOOST_HAS_REGEX == 1
bool DecodeDataUriScheme(std::string& mime,
std::string& content,
const std::string& source);
# endif
void EncodeDataUriScheme(std::string& result,
const std::string& mime,
const std::string& content);
#endif
std::string ConvertToUtf8(const std::string& source,
Encoding sourceEncoding);
std::string ConvertFromUtf8(const std::string& source,
Encoding targetEncoding);
bool IsAsciiString(const void* data,
size_t size);
std::string ConvertToAscii(const std::string& source);
std::string StripSpaces(const std::string& source);
// In-place percent-decoding for URL
void UrlDecode(std::string& s);
Endianness DetectEndianness();
#if BOOST_HAS_REGEX == 1
std::string WildcardToRegularExpression(const std::string& s);
#endif
void TokenizeString(std::vector<std::string>& result,
const std::string& source,
char separator);
#if ORTHANC_ENABLE_PUGIXML == 1
void JsonToXml(std::string& target,
const Json::Value& source,
const std::string& rootElement = "root",
const std::string& arrayElement = "item");
#endif
bool IsInteger(const std::string& str);
void CopyJsonWithoutComments(Json::Value& target,
const Json::Value& source);
bool StartsWith(const std::string& str,
const std::string& prefix);
void UriEncode(std::string& target,
const std::string& source);
std::string GetJsonStringField(const ::Json::Value& json,
const std::string& key,
const std::string& defaultValue);
bool GetJsonBooleanField(const ::Json::Value& json,
const std::string& key,
bool defaultValue);
int GetJsonIntegerField(const ::Json::Value& json,
const std::string& key,
int defaultValue);
unsigned int GetJsonUnsignedIntegerField(const ::Json::Value& json,
const std::string& key,
unsigned int defaultValue);
bool IsUuid(const std::string& str);
bool StartsWithUuid(const std::string& str);
}
}
This diff is collapsed.
/**
* Orthanc - A Lightweight, RESTful DICOM Store
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
* Department, University Hospital of Liege, Belgium
* Copyright (C) 2017 Osimis, Belgium
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* In addition, as a special exception, the copyright holders of this
* program give permission to link the code of its release with the
* OpenSSL project's "OpenSSL" library (or with modified versions of it
* that use the same license as the "OpenSSL" library), and distribute
* the linked executables. You must obey the GNU General Public License
* in all respects for all of the code used other than "OpenSSL". If you
* modify file(s) with this exception, you may extend this exception to
* your version of the file(s), but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files
* in the program, then also delete it here.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#pragma once
#if !defined(ORTHANC_SANDBOXED)
# error The macro ORTHANC_SANDBOXED must be defined
#endif
#include <string>
#include <json/json.h>
namespace Orthanc
{
class WebServiceParameters
{
private:
bool advancedFormat_;
std::string url_;
std::string username_;
std::string password_;
std::string certificateFile_;
std::string certificateKeyFile_;
std::string certificateKeyPassword_;
bool pkcs11Enabled_;
void FromJsonArray(const Json::Value& peer);
void FromJsonObject(const Json::Value& peer);
public:
WebServiceParameters();
const std::string& GetUrl() const
{
return url_;
}
void SetUrl(const std::string& url)
{
url_ = url;
}
const std::string& GetUsername() const
{
return username_;
}
void SetUsername(const std::string& username)
{
username_ = username;
}
const std::string& GetPassword() const
{
return password_;
}
void SetPassword(const std::string& password)
{
password_ = password;
}
void ClearClientCertificate();
#if ORTHANC_SANDBOXED == 0
void SetClientCertificate(const std::string& certificateFile,
const std::string& certificateKeyFile,
const std::string& certificateKeyPassword);
#endif
const std::string& GetCertificateFile() const
{
return certificateFile_;
}
const std::string& GetCertificateKeyFile() const
{
return certificateKeyFile_;
}
const std::string& GetCertificateKeyPassword() const
{
return certificateKeyPassword_;
}
void SetPkcs11Enabled(bool pkcs11Enabled)
{
pkcs11Enabled_ = pkcs11Enabled;
}
bool IsPkcs11Enabled() const
{
return pkcs11Enabled_;
}
void FromJson(const Json::Value& peer);
void ToJson(Json::Value& value) const;
};
}
# This is the list of the symbols that must be exported by Orthanc
# plugins, if targeting OS X
_OrthancPluginInitialize
_OrthancPluginFinalize
_OrthancPluginGetName
_OrthancPluginGetVersion