changeset 140:a0f9a3df1110

resort to Orthanc framework
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 17 Apr 2018 15:47:47 +0200
parents f2f58f288172
children c9271bb5ef94
files Applications/ApplicationToolbox.cpp Applications/ApplicationToolbox.h Applications/CMakeLists.txt Applications/DicomToTiff.cpp Applications/Dicomizer.cpp Framework/Algorithms/PyramidReader.cpp Framework/Algorithms/ReconstructPyramidCommand.cpp Framework/Algorithms/ReconstructPyramidCommand.h Framework/Algorithms/TranscodeTileCommand.cpp Framework/Algorithms/TranscodeTileCommand.h Framework/DicomToolbox.cpp Framework/DicomizerParameters.cpp Framework/DicomizerParameters.h Framework/Enumerations.cpp Framework/Enumerations.h Framework/ImageToolbox.cpp Framework/ImageToolbox.h Framework/ImagedVolumeParameters.cpp Framework/Inputs/DicomPyramid.cpp Framework/Inputs/DicomPyramidInstance.cpp Framework/Inputs/DicomPyramidInstance.h Framework/Inputs/DicomPyramidLevel.cpp Framework/Inputs/HierarchicalTiff.cpp Framework/Inputs/ITiledPyramid.h Framework/Inputs/OpenSlideLibrary.cpp Framework/Inputs/OpenSlideLibrary.h Framework/Inputs/OpenSlidePyramid.cpp Framework/Inputs/PyramidWithRawTiles.cpp Framework/Inputs/SingleLevelDecodedPyramid.cpp Framework/Inputs/TiledJpegImage.h Framework/Inputs/TiledPngImage.h Framework/Inputs/TiledPyramidStatistics.cpp Framework/Jpeg2000Reader.cpp Framework/Jpeg2000Reader.h Framework/Jpeg2000Writer.cpp Framework/Jpeg2000Writer.h Framework/Outputs/DicomPyramidWriter.cpp Framework/Outputs/HierarchicalTiffWriter.cpp Framework/Outputs/IPyramidWriter.h Framework/Outputs/InMemoryTiledImage.cpp Framework/Outputs/MultiframeDicomWriter.cpp Framework/Outputs/MultiframeDicomWriter.h Framework/Outputs/PyramidWriterBase.cpp Framework/Outputs/TruncatedPyramidWriter.cpp Framework/Targets/FolderTarget.cpp Framework/Targets/OrthancTarget.cpp Framework/Targets/OrthancTarget.h NEWS Resources/CMake/BoostExtendedConfiguration.cmake Resources/CMake/LinuxStandardBaseToolchain.cmake Resources/CMake/Version.cmake Resources/Orthanc/Core/Cache/LeastRecentlyUsedIndex.h Resources/Orthanc/Core/ChunkedBuffer.cpp Resources/Orthanc/Core/ChunkedBuffer.h Resources/Orthanc/Core/DicomFormat/DicomArray.cpp Resources/Orthanc/Core/DicomFormat/DicomArray.h Resources/Orthanc/Core/DicomFormat/DicomElement.h Resources/Orthanc/Core/DicomFormat/DicomMap.cpp Resources/Orthanc/Core/DicomFormat/DicomMap.h Resources/Orthanc/Core/DicomFormat/DicomTag.cpp Resources/Orthanc/Core/DicomFormat/DicomTag.h Resources/Orthanc/Core/DicomFormat/DicomValue.cpp Resources/Orthanc/Core/DicomFormat/DicomValue.h Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.cpp Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.h Resources/Orthanc/Core/DicomParsing/ITagVisitor.h Resources/Orthanc/Core/DicomParsing/ToDcmtkBridge.cpp Resources/Orthanc/Core/DicomParsing/ToDcmtkBridge.h Resources/Orthanc/Core/Endianness.h Resources/Orthanc/Core/EnumerationDictionary.h Resources/Orthanc/Core/Enumerations.cpp Resources/Orthanc/Core/Enumerations.h Resources/Orthanc/Core/HttpClient.cpp Resources/Orthanc/Core/HttpClient.h Resources/Orthanc/Core/ICommand.h Resources/Orthanc/Core/IDynamicObject.h Resources/Orthanc/Core/Images/IImageWriter.cpp Resources/Orthanc/Core/Images/IImageWriter.h Resources/Orthanc/Core/Images/Image.cpp Resources/Orthanc/Core/Images/Image.h Resources/Orthanc/Core/Images/ImageAccessor.cpp Resources/Orthanc/Core/Images/ImageAccessor.h Resources/Orthanc/Core/Images/ImageBuffer.cpp Resources/Orthanc/Core/Images/ImageBuffer.h Resources/Orthanc/Core/Images/ImageProcessing.cpp Resources/Orthanc/Core/Images/ImageProcessing.h Resources/Orthanc/Core/Images/JpegErrorManager.cpp Resources/Orthanc/Core/Images/JpegErrorManager.h Resources/Orthanc/Core/Images/JpegReader.cpp Resources/Orthanc/Core/Images/JpegReader.h Resources/Orthanc/Core/Images/JpegWriter.cpp Resources/Orthanc/Core/Images/JpegWriter.h Resources/Orthanc/Core/Images/PixelTraits.h Resources/Orthanc/Core/Images/PngReader.cpp Resources/Orthanc/Core/Images/PngReader.h Resources/Orthanc/Core/Images/PngWriter.cpp Resources/Orthanc/Core/Images/PngWriter.h Resources/Orthanc/Core/Logging.cpp Resources/Orthanc/Core/Logging.h Resources/Orthanc/Core/MultiThreading/BagOfTasks.h Resources/Orthanc/Core/MultiThreading/BagOfTasksProcessor.cpp Resources/Orthanc/Core/MultiThreading/BagOfTasksProcessor.h Resources/Orthanc/Core/MultiThreading/Semaphore.cpp Resources/Orthanc/Core/MultiThreading/Semaphore.h Resources/Orthanc/Core/MultiThreading/SharedMessageQueue.cpp Resources/Orthanc/Core/MultiThreading/SharedMessageQueue.h Resources/Orthanc/Core/OrthancException.h Resources/Orthanc/Core/PrecompiledHeaders.cpp Resources/Orthanc/Core/PrecompiledHeaders.h Resources/Orthanc/Core/SharedLibrary.cpp Resources/Orthanc/Core/SharedLibrary.h Resources/Orthanc/Core/SystemToolbox.cpp Resources/Orthanc/Core/SystemToolbox.h Resources/Orthanc/Core/TemporaryFile.cpp Resources/Orthanc/Core/TemporaryFile.h Resources/Orthanc/Core/Toolbox.cpp Resources/Orthanc/Core/Toolbox.h Resources/Orthanc/Core/WebServiceParameters.cpp Resources/Orthanc/Core/WebServiceParameters.h Resources/Orthanc/DownloadOrthancFramework.cmake Resources/Orthanc/LinuxStandardBaseToolchain.cmake Resources/Orthanc/MinGW-W64-Toolchain32.cmake Resources/Orthanc/MinGW-W64-Toolchain64.cmake Resources/Orthanc/MinGWToolchain.cmake Resources/Orthanc/NEWS Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h Resources/Orthanc/Plugins/Samples/Common/DicomPath.cpp Resources/Orthanc/Plugins/Samples/Common/DicomPath.h Resources/Orthanc/Plugins/Samples/Common/DicomTag.cpp Resources/Orthanc/Plugins/Samples/Common/DicomTag.h Resources/Orthanc/Plugins/Samples/Common/ExportedSymbols.list Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.cpp Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h Resources/Orthanc/Plugins/Samples/Common/IDicomDataset.h Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.cpp Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.cpp Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.h Resources/Orthanc/Plugins/Samples/Common/OrthancPluginConnection.cpp Resources/Orthanc/Plugins/Samples/Common/OrthancPluginConnection.h Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h Resources/Orthanc/Plugins/Samples/Common/OrthancPluginException.h Resources/Orthanc/Plugins/Samples/Common/SimplifiedOrthancDataset.cpp Resources/Orthanc/Plugins/Samples/Common/SimplifiedOrthancDataset.h Resources/Orthanc/Plugins/Samples/Common/VersionScript.map Resources/Orthanc/Resources/CMake/AutoGeneratedCode.cmake Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake Resources/Orthanc/Resources/CMake/Compiler.cmake Resources/Orthanc/Resources/CMake/DcmtkConfiguration.cmake Resources/Orthanc/Resources/CMake/DownloadPackage.cmake Resources/Orthanc/Resources/CMake/JsonCppConfiguration.cmake Resources/Orthanc/Resources/CMake/LibCurlConfiguration.cmake Resources/Orthanc/Resources/CMake/LibIconvConfiguration.cmake Resources/Orthanc/Resources/CMake/LibJpegConfiguration.cmake Resources/Orthanc/Resources/CMake/LibPngConfiguration.cmake Resources/Orthanc/Resources/CMake/OpenSslConfiguration.cmake Resources/Orthanc/Resources/CMake/UuidConfiguration.cmake Resources/Orthanc/Resources/CMake/VisualStudioPrecompiledHeaders.cmake Resources/Orthanc/Resources/CMake/ZlibConfiguration.cmake Resources/Orthanc/Resources/EmbedResources.py Resources/Orthanc/Resources/LinuxStandardBaseToolchain.cmake Resources/Orthanc/Resources/MinGW-W64-Toolchain32.cmake Resources/Orthanc/Resources/MinGW-W64-Toolchain64.cmake Resources/Orthanc/Resources/MinGWToolchain.cmake Resources/Orthanc/Resources/Patches/boost-1.66.0-linux-standard-base.patch Resources/Orthanc/Resources/Patches/curl-7.57.0-cmake.patch Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-dulparse-vulnerability.patch Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-mingw64.patch Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-speed.patch Resources/Orthanc/Resources/Patches/dcmtk-3.6.2-cmath.patch Resources/Orthanc/Resources/Patches/dcmtk-3.6.2-linux-standard-base.patch Resources/Orthanc/Resources/ThirdParty/VisualStudio/stdint.h Resources/Orthanc/Resources/ThirdParty/base64/base64.cpp Resources/Orthanc/Resources/ThirdParty/base64/base64.h Resources/Orthanc/Resources/ThirdParty/patch/NOTES.txt Resources/Orthanc/Resources/ThirdParty/patch/msys-1.0.dll Resources/Orthanc/Resources/ThirdParty/patch/patch.exe Resources/Orthanc/Resources/ThirdParty/patch/patch.exe.manifest Resources/Orthanc/Resources/WindowsResources.py Resources/Orthanc/Resources/WindowsResources.rc Resources/SyncOrthancFolder.py ViewerPlugin/CMakeLists.txt ViewerPlugin/DicomPyramidCache.h ViewerPlugin/Plugin.cpp
diffstat 186 files changed, 631 insertions(+), 27636 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/ApplicationToolbox.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Applications/ApplicationToolbox.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,12 +22,13 @@
 #include "ApplicationToolbox.h"
 
 #include "../Framework/Inputs/OpenSlideLibrary.h"
-#include "../Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.h"
-#include "../Resources/Orthanc/Core/HttpClient.h"
-#include "../Resources/Orthanc/Core/Logging.h"
-#include "../Resources/Orthanc/Core/MultiThreading/BagOfTasksProcessor.h"
-#include "../Resources/Orthanc/Core/OrthancException.h"
-#include "../Resources/Orthanc/Core/SystemToolbox.h"
+
+#include <Core/DicomParsing/FromDcmtkBridge.h>
+#include <Core/HttpClient.h>
+#include <Core/Logging.h>
+#include <Core/MultiThreading/BagOfTasksProcessor.h>
+#include <Core/OrthancException.h>
+#include <Core/SystemToolbox.h>
 
 #include <boost/filesystem.hpp>
 #include <boost/lexical_cast.hpp>
--- a/Applications/ApplicationToolbox.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Applications/ApplicationToolbox.h	Tue Apr 17 15:47:47 2018 +0200
@@ -21,8 +21,8 @@
 
 #pragma once
 
-#include "../Resources/Orthanc/Core/MultiThreading/BagOfTasks.h"
-#include "../Resources/Orthanc/Core/WebServiceParameters.h"
+#include <Core/MultiThreading/BagOfTasks.h>
+#include <Core/WebServiceParameters.h>
 
 #include <string>
 #include <stdint.h>
--- a/Applications/CMakeLists.txt	Wed Apr 11 16:24:26 2018 +0200
+++ b/Applications/CMakeLists.txt	Tue Apr 17 15:47:47 2018 +0200
@@ -1,6 +1,8 @@
 cmake_minimum_required(VERSION 2.8)
 project(OrthancWSIApplications)
 
+include(${CMAKE_SOURCE_DIR}/../Resources/CMake/Version.cmake)
+
 
 #####################################################################
 ## Parameters of the build
@@ -11,36 +13,11 @@
 SET(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages")
 SET(ENABLE_PROFILING OFF CACHE BOOL "Whether to enable the generation of profiling information with gprof")
 
-# Optional components
-SET(ENABLE_SSL ON CACHE BOOL "Include support for SSL")
-SET(USE_DCMTK_361 OFF CACHE BOOL "Use forthcoming DCMTK version 3.6.1 in static builds (instead of 3.6.0)")
-
-if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
-  set(TMP ON)
-else()
-  set(TMP OFF)
-endif()
-
-
 # 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_CURL ON CACHE BOOL "Use the system version of LibCurl")
-SET(USE_SYSTEM_DCMTK ON CACHE BOOL "Use the system version of DCMTK")
-SET(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp")
-SET(USE_SYSTEM_LIBICONV ON CACHE BOOL "Use the system version of libiconv")
-SET(USE_SYSTEM_LIBJPEG ON CACHE BOOL "Use the system version of libjpeg")
-SET(USE_SYSTEM_LIBPNG ON CACHE BOOL "Use the system version of libpng")
 SET(USE_SYSTEM_LIBTIFF ON CACHE BOOL "Use the system version of libtiff")
 SET(USE_SYSTEM_OPENJPEG ON CACHE BOOL "Use the system version of OpenJpeg")
-SET(USE_SYSTEM_OPENSSL ON CACHE BOOL "Use the system version of OpenSSL")
 SET(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK")
-SET(USE_SYSTEM_ZLIB ON CACHE BOOL "Use the system version of ZLib")
-set(USE_SYSTEM_UUID ON CACHE BOOL "Use the system version of the uuid library from e2fsprogs")
 
-SET(DCMTK_DICTIONARY_DIR "" CACHE PATH "Directory containing the DCMTK dictionaries \"dicom.dic\" and \"private.dic\" (only when using system version of DCMTK)") 
-
-SET(USE_BOOST_ICONV ON CACHE BOOL "Use iconv instead of wconv (Windows only)")
-mark_as_advanced(USE_BOOST_ICONV)
 
 
 #####################################################################
@@ -48,68 +25,38 @@
 #####################################################################
 
 SET(ORTHANC_WSI_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
-SET(ORTHANC_ROOT ${ORTHANC_WSI_DIR}/Resources/Orthanc)
 SET(USE_OPENJPEG_JP2 ON)
-SET(ENABLE_JPEG OFF)           # Disable DCMTK's support for JPEG, that clashes with libtiff
-SET(ENABLE_JPEG_LOSSLESS OFF)  # Disable DCMTK's support for JPEG-LS
-SET(ENABLE_DCMTK_NETWORK OFF)  # Disable DCMTK's support for DICOM networking
-SET(ENABLE_LOCALE ON)          # Enable support for locales (notably in Boost)
+
+include(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/DownloadOrthancFramework.cmake)
+
+UNSET(STANDALONE_BUILD CACHE)
 SET(STANDALONE_BUILD ON)       # Embed DCMTK's dictionaries for static builds
-SET(USE_DCMTK_361_PRIVATE_DIC OFF)  # No need for private tags
+
+set(ORTHANC_FRAMEWORK_PLUGIN OFF)
+include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
 
-include(CheckFunctionExists)
-include(CheckIncludeFile)
-include(CheckIncludeFiles)
-include(CheckIncludeFileCXX)
-include(CheckLibraryExists)
-include(CheckStructHasMember)
-include(FindPythonInterp)
-include(FindPkgConfig)
-include(CheckSymbolExists)
+SET(ENABLE_CRYPTO_OPTIONS ON)
+SET(ENABLE_DCMTK ON)
+SET(ENABLE_DCMTK_JPEG OFF)          # Disable DCMTK's support for JPEG, that clashes with libtiff
+SET(ENABLE_DCMTK_JPEG_LOSSLESS OFF) # Disable DCMTK's support for JPEG-LS
+SET(ENABLE_DCMTK_NETWORKING OFF)    # Disable DCMTK's support for DICOM networking
+SET(ENABLE_JPEG ON)
+SET(ENABLE_LOCALE ON)               # Enable support for locales (notably in Boost)
+SET(ENABLE_PNG ON)
+SET(ENABLE_SSL ON)
+SET(ENABLE_WEB_CLIENT ON)
+SET(ENABLE_ZLIB ON)
+SET(HAS_EMBEDDED_RESOURCES ON)
 
-include(${ORTHANC_ROOT}/Resources/CMake/Compiler.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/AutoGeneratedCode.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/VisualStudioPrecompiledHeaders.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkConfiguration.cmake)
+include_directories(${ORTHANC_ROOT})
 
-# Third-party components shipped with Orthanc
-include(${ORTHANC_ROOT}/Resources/CMake/DcmtkConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/JsonCppConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/LibCurlConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/LibIconvConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/LibJpegConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/LibPngConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/UuidConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/ZlibConfiguration.cmake)
 
 # Include components specific to WSI
-include(${ORTHANC_WSI_DIR}/Resources/CMake/Version.cmake)
 include(${ORTHANC_WSI_DIR}/Resources/CMake/BoostExtendedConfiguration.cmake)
 include(${ORTHANC_WSI_DIR}/Resources/CMake/OpenJpegConfiguration.cmake)
 include(${ORTHANC_WSI_DIR}/Resources/CMake/LibTiffConfiguration.cmake)
 
-add_definitions(
-  -DHAS_ORTHANC_EXCEPTION=1
-  -DORTHANC_BUILD_UNIT_TESTS=0  # For FromDcmtkBridge
-  -DORTHANC_DEFAULT_DICOM_ENCODING=Encoding_Latin1
-  -DORTHANC_ENABLE_BASE64=1
-  -DORTHANC_ENABLE_CURL=1
-  -DORTHANC_ENABLE_DCMTK=1
-  -DORTHANC_ENABLE_DCMTK_JPEG=0           # Disable DCMTK's support for JPEG
-  -DORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS=0  # Disable DCMTK's support for JPEG-LS
-  -DORTHANC_ENABLE_JPEG=1
-  -DORTHANC_ENABLE_LOCALE=1
-  -DORTHANC_ENABLE_LOGGING=1
-  -DORTHANC_ENABLE_LOGGING_STDIO=0
-  -DORTHANC_ENABLE_LOGGING_PLUGIN=0
-  -DORTHANC_ENABLE_LUA=0        # For FromDcmtkBridge
-  -DORTHANC_ENABLE_MD5=0
-  -DORTHANC_ENABLE_PKCS11=0
-  -DORTHANC_ENABLE_PNG=1
-  -DORTHANC_ENABLE_PUGIXML=0
-  -DORTHANC_MAXIMUM_TAG_LENGTH=256
-  -DORTHANC_SANDBOXED=0
-  )
 
 
 #####################################################################
@@ -117,7 +64,7 @@
 #####################################################################
 
 if (STATIC_BUILD OR NOT USE_SYSTEM_ORTHANC_SDK)
-  include_directories(${ORTHANC_ROOT}/Sdk-1.0.0)
+  include_directories(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/Sdk-1.0.0)
 else ()
   CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCPlugin.h HAVE_ORTHANC_H)
   if (NOT HAVE_ORTHANC_H)
@@ -127,19 +74,6 @@
 
 
 #####################################################################
-## Configure optional third-party components
-#####################################################################
-
-if (ENABLE_SSL)
-  set(ENABLE_PKCS11 OFF)
-  add_definitions(-DORTHANC_ENABLE_SSL=1)
-  include(${ORTHANC_ROOT}/Resources/CMake/OpenSslConfiguration.cmake)
-else()
-  add_definitions(-DORTHANC_ENABLE_SSL=0)
-endif()
-
-
-#####################################################################
 ## Create the list of the source files that depend upon the
 ## precompiled headers
 #####################################################################
@@ -175,48 +109,6 @@
   ${ORTHANC_WSI_DIR}/Framework/Outputs/TruncatedPyramidWriter.cpp
   )
 
-set(ORTHANC_CORE_SOURCES
-  ${ORTHANC_ROOT}/Core/ChunkedBuffer.cpp
-  ${ORTHANC_ROOT}/Core/DicomFormat/DicomArray.cpp
-  ${ORTHANC_ROOT}/Core/DicomFormat/DicomMap.cpp
-  ${ORTHANC_ROOT}/Core/DicomFormat/DicomTag.cpp
-  ${ORTHANC_ROOT}/Core/DicomFormat/DicomValue.cpp
-  ${ORTHANC_ROOT}/Core/DicomParsing/FromDcmtkBridge.cpp
-  ${ORTHANC_ROOT}/Core/DicomParsing/ToDcmtkBridge.cpp
-  ${ORTHANC_ROOT}/Core/Enumerations.cpp
-  ${ORTHANC_ROOT}/Core/HttpClient.cpp
-  ${ORTHANC_ROOT}/Core/Images/IImageWriter.cpp
-  ${ORTHANC_ROOT}/Core/Images/Image.cpp
-  ${ORTHANC_ROOT}/Core/Images/ImageAccessor.cpp
-  ${ORTHANC_ROOT}/Core/Images/ImageBuffer.cpp
-  ${ORTHANC_ROOT}/Core/Images/ImageProcessing.cpp
-  ${ORTHANC_ROOT}/Core/Images/JpegErrorManager.cpp
-  ${ORTHANC_ROOT}/Core/Images/JpegReader.cpp
-  ${ORTHANC_ROOT}/Core/Images/JpegWriter.cpp
-  ${ORTHANC_ROOT}/Core/Images/PngReader.cpp
-  ${ORTHANC_ROOT}/Core/Images/PngWriter.cpp
-  ${ORTHANC_ROOT}/Core/Logging.cpp
-  ${ORTHANC_ROOT}/Core/MultiThreading/BagOfTasksProcessor.cpp
-  ${ORTHANC_ROOT}/Core/MultiThreading/SharedMessageQueue.cpp
-  ${ORTHANC_ROOT}/Core/SharedLibrary.cpp
-  ${ORTHANC_ROOT}/Core/SystemToolbox.cpp
-  ${ORTHANC_ROOT}/Core/TemporaryFile.cpp
-  ${ORTHANC_ROOT}/Core/Toolbox.cpp
-  ${ORTHANC_ROOT}/Core/WebServiceParameters.cpp
-
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomDatasetReader.cpp
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomPath.cpp
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomTag.cpp
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/FullOrthancDataset.cpp
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/IOrthancConnection.cpp
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancHttpConnection.cpp
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginConnection.cpp
-  ${ORTHANC_ROOT}/Plugins/Samples/Common/SimplifiedOrthancDataset.cpp
-
-  ${ORTHANC_ROOT}/Resources/ThirdParty/base64/base64.cpp
-  )
-
 EmbedResources(
   ${DCMTK_DICTIONARIES}
   BRIGHTFIELD_OPTICAL_PATH  ${ORTHANC_WSI_DIR}/Resources/BrightfieldOpticalPath.json
@@ -232,9 +124,14 @@
 if (MSVC)
   add_definitions(-DORTHANC_USE_PRECOMPILED_HEADERS=1)
 
+  set(TMP
+    ${ORTHANC_CORE_SOURCES_INTERNAL}
+    ${ORTHANC_DICOM_SOURCES_INTERNAL}
+    )
+  
   ADD_VISUAL_STUDIO_PRECOMPILED_HEADERS(
-    "PrecompiledHeaders.h" "${ORTHANC_WSI_DIR}/Resources/Orthanc/Core/PrecompiledHeaders.cpp"
-    ORTHANC_CORE_SOURCES ORTHANC_CORE_PCH)
+    "PrecompiledHeaders.h" "${ORTHANC_ROOT}/Core/PrecompiledHeaders.cpp"
+    TMP ORTHANC_CORE_PCH)
 
   ADD_VISUAL_STUDIO_PRECOMPILED_HEADERS(
     "PrecompiledHeadersWSI.h" "${ORTHANC_WSI_DIR}/Framework/PrecompiledHeadersWSI.cpp"
@@ -250,26 +147,28 @@
 
 add_library(OrthancWSIFramework STATIC
   ${ORTHANC_CORE_PCH}
-  ${ORTHANC_CORE_SOURCES}
+  ${ORTHANC_CORE_SOURCES_INTERNAL}
+  ${ORTHANC_CORE_SOURCES_DEPENDENCIES}
+  ${ORTHANC_DICOM_SOURCES_INTERNAL}
+  ${ORTHANC_DICOM_SOURCES_DEPENDENCIES}
   ${ORTHANC_WSI_PCH}
   ${ORTHANC_WSI_SOURCES}
   ${AUTOGENERATED_SOURCES}
+  ${BOOST_EXTENDED_SOURCES}
+
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomDatasetReader.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomPath.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomTag.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/FullOrthancDataset.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/IOrthancConnection.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancHttpConnection.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginConnection.cpp
+  ${ORTHANC_ROOT}/Plugins/Samples/Common/SimplifiedOrthancDataset.cpp
 
   # Mandatory components
-  ${BOOST_SOURCES}
-  ${CURL_SOURCES}
-  ${DCMTK_SOURCES}
-  ${JSONCPP_SOURCES}
-  ${LIBICONV_SOURCES}
-  ${LIBJPEG_SOURCES}
-  ${LIBPNG_SOURCES}
   ${LIBTIFF_SOURCES}
   ${OPENJPEG_SOURCES}
-  ${UUID_SOURCES}
-  ${ZLIB_SOURCES}
-
-  # Optional components
-  ${OPENSSL_SOURCES}
   )
 
 
--- a/Applications/DicomToTiff.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Applications/DicomToTiff.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -25,9 +25,9 @@
 #include "../Framework/Inputs/TiledPyramidStatistics.h"
 #include "../Framework/Outputs/HierarchicalTiffWriter.h"
 
-#include "../Resources/Orthanc/Core/Logging.h"
-#include "../Resources/Orthanc/Core/OrthancException.h"
-#include "../Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
+#include <Plugins/Samples/Common/OrthancHttpConnection.h>
 
 #include "ApplicationToolbox.h"
 
--- a/Applications/Dicomizer.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Applications/Dicomizer.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -32,11 +32,11 @@
 #include "../Framework/Outputs/DicomPyramidWriter.h"
 #include "../Framework/Outputs/TruncatedPyramidWriter.h"
 
-#include "../Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.h"
-#include "../Resources/Orthanc/Core/Logging.h"
-#include "../Resources/Orthanc/Core/MultiThreading/BagOfTasksProcessor.h"
-#include "../Resources/Orthanc/Core/OrthancException.h"
-#include "../Resources/Orthanc/Core/SystemToolbox.h"
+#include <Core/DicomParsing/FromDcmtkBridge.h>
+#include <Core/Logging.h>
+#include <Core/MultiThreading/BagOfTasksProcessor.h>
+#include <Core/OrthancException.h>
+#include <Core/SystemToolbox.h>
 
 #include "ApplicationToolbox.h"
 
--- a/Framework/Algorithms/PyramidReader.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Algorithms/PyramidReader.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -23,8 +23,8 @@
 #include "PyramidReader.h"
 
 #include "../ImageToolbox.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
 
 #include <cassert>
 
--- a/Framework/Algorithms/ReconstructPyramidCommand.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Algorithms/ReconstructPyramidCommand.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -23,9 +23,9 @@
 #include "ReconstructPyramidCommand.h"
 
 #include "../ImageToolbox.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/Images/Image.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
+#include <Core/Images/Image.h>
 
 #include <cassert>
 
--- a/Framework/Algorithms/ReconstructPyramidCommand.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Algorithms/ReconstructPyramidCommand.h	Tue Apr 17 15:47:47 2018 +0200
@@ -23,7 +23,7 @@
 
 #include "PyramidReader.h"
 #include "../Outputs/IPyramidWriter.h"
-#include "../../Resources/Orthanc/Core/MultiThreading/BagOfTasks.h"
+#include <Core/MultiThreading/BagOfTasks.h>
 
 
 namespace OrthancWSI
--- a/Framework/Algorithms/TranscodeTileCommand.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Algorithms/TranscodeTileCommand.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,8 +22,8 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "TranscodeTileCommand.h"
 
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
+#include <Core/OrthancException.h>
+#include <Core/Logging.h>
 
 #include <cassert>
 
--- a/Framework/Algorithms/TranscodeTileCommand.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Algorithms/TranscodeTileCommand.h	Tue Apr 17 15:47:47 2018 +0200
@@ -24,7 +24,7 @@
 #include "PyramidReader.h"
 #include "../Outputs/IPyramidWriter.h"
 
-#include "../../Resources/Orthanc/Core/MultiThreading/BagOfTasks.h"
+#include <Core/MultiThreading/BagOfTasks.h>
 
 namespace OrthancWSI
 {
--- a/Framework/DicomToolbox.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/DicomToolbox.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,9 +22,9 @@
 #include "PrecompiledHeadersWSI.h"
 #include "DicomToolbox.h"
 
-#include "../Resources/Orthanc/Core/Logging.h"
-#include "../Resources/Orthanc/Core/OrthancException.h"
-#include "../Resources/Orthanc/Core/Toolbox.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
+#include <Core/Toolbox.h>
 
 #if ORTHANC_ENABLE_DCMTK == 1
 #  include <dcmtk/dcmdata/dcelem.h>
--- a/Framework/DicomizerParameters.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/DicomizerParameters.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -25,7 +25,7 @@
 #include "Targets/FolderTarget.h"
 #include "Targets/OrthancTarget.h"
 
-#include "../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/OrthancException.h>
 
 #include <boost/thread.hpp>
 #include <boost/lexical_cast.hpp>
--- a/Framework/DicomizerParameters.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/DicomizerParameters.h	Tue Apr 17 15:47:47 2018 +0200
@@ -25,7 +25,7 @@
 #include "Outputs/IPyramidWriter.h"
 #include "Targets/IFileTarget.h"
 #include "DicomToolbox.h"
-#include "../Resources/Orthanc/Core/WebServiceParameters.h"
+#include <Core/WebServiceParameters.h>
 
 #include <stdint.h>
 
--- a/Framework/Enumerations.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Enumerations.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -23,9 +23,9 @@
 #include "Enumerations.h"
 
 #include "Jpeg2000Reader.h"
-#include "../Resources/Orthanc/Core/OrthancException.h"
-#include "../Resources/Orthanc/Core/SystemToolbox.h"
-#include "../Resources/Orthanc/Core/Toolbox.h"
+#include <Core/OrthancException.h>
+#include <Core/SystemToolbox.h>
+#include <Core/Toolbox.h>
 
 #include <string.h>
 #include <boost/algorithm/string/predicate.hpp>
--- a/Framework/Enumerations.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Enumerations.h	Tue Apr 17 15:47:47 2018 +0200
@@ -21,7 +21,7 @@
 
 #pragma once
 
-#include "../Resources/Orthanc/Core/Enumerations.h"
+#include <Core/Enumerations.h>
 
 #include <stdint.h>
 #include <string>
--- a/Framework/ImageToolbox.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/ImageToolbox.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -25,13 +25,13 @@
 #include "Jpeg2000Reader.h"
 #include "Jpeg2000Writer.h"
 
-#include "../Resources/Orthanc/Core/OrthancException.h"
-#include "../Resources/Orthanc/Core/Images/ImageProcessing.h"
-#include "../Resources/Orthanc/Core/Images/PngReader.h"
-#include "../Resources/Orthanc/Core/Images/PngWriter.h"
-#include "../Resources/Orthanc/Core/Images/JpegReader.h"
-#include "../Resources/Orthanc/Core/Images/JpegWriter.h"
-#include "../Resources/Orthanc/Core/Logging.h"
+#include <Core/OrthancException.h>
+#include <Core/Images/ImageProcessing.h>
+#include <Core/Images/PngReader.h>
+#include <Core/Images/PngWriter.h>
+#include <Core/Images/JpegReader.h>
+#include <Core/Images/JpegWriter.h>
+#include <Core/Logging.h>
 
 #include <string.h>
 #include <memory>
--- a/Framework/ImageToolbox.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/ImageToolbox.h	Tue Apr 17 15:47:47 2018 +0200
@@ -21,7 +21,7 @@
 
 #pragma once
 
-#include "../Resources/Orthanc/Core/Images/ImageAccessor.h"
+#include <Core/Images/ImageAccessor.h>
 #include "Enumerations.h"
 #include "Inputs/ITiledPyramid.h"
 
--- a/Framework/ImagedVolumeParameters.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/ImagedVolumeParameters.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,7 +22,7 @@
 #include "PrecompiledHeadersWSI.h"
 #include "ImagedVolumeParameters.h"
 
-#include "../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/OrthancException.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Inputs/DicomPyramid.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/DicomPyramid.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -23,8 +23,8 @@
 #include "DicomPyramid.h"
 
 #include "../DicomToolbox.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
 
 #include <algorithm>
 #include <cassert>
--- a/Framework/Inputs/DicomPyramidInstance.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/DicomPyramidInstance.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,11 +22,11 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "DicomPyramidInstance.h"
 
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/Toolbox.h"
-#include "../../Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h"
-#include "../../Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
+#include <Core/Toolbox.h>
+#include <Plugins/Samples/Common/DicomDatasetReader.h>
+#include <Plugins/Samples/Common/FullOrthancDataset.h>
 #include "../DicomToolbox.h"
 
 #include <cassert>
--- a/Framework/Inputs/DicomPyramidInstance.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/DicomPyramidInstance.h	Tue Apr 17 15:47:47 2018 +0200
@@ -22,7 +22,7 @@
 #pragma once
 
 #include "../Enumerations.h"
-#include "../../Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h"
+#include <Plugins/Samples/Common/IOrthancConnection.h>
 
 #include <boost/noncopyable.hpp>
 #include <vector>
--- a/Framework/Inputs/DicomPyramidLevel.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/DicomPyramidLevel.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,8 +22,8 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "DicomPyramidLevel.h"
 
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
 
 #include <boost/lexical_cast.hpp>
 
--- a/Framework/Inputs/HierarchicalTiff.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/HierarchicalTiff.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,8 +22,8 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "HierarchicalTiff.h"
 
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
 
 #include <iostream>
 #include <algorithm>
--- a/Framework/Inputs/ITiledPyramid.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/ITiledPyramid.h	Tue Apr 17 15:47:47 2018 +0200
@@ -23,7 +23,7 @@
 
 #include "../Enumerations.h"
 
-#include "../../Resources/Orthanc/Core/Images/ImageAccessor.h"
+#include <Core/Images/ImageAccessor.h>
 
 #include <boost/noncopyable.hpp>
 #include <string>
--- a/Framework/Inputs/OpenSlideLibrary.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/OpenSlideLibrary.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,9 +22,11 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "OpenSlideLibrary.h"
 
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/Images/Image.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/Logging.h>
+#include <Core/Images/Image.h>
+#include <Core/OrthancException.h>
+
+#include <memory>
 
 namespace OrthancWSI
 {
--- a/Framework/Inputs/OpenSlideLibrary.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/OpenSlideLibrary.h	Tue Apr 17 15:47:47 2018 +0200
@@ -21,8 +21,8 @@
 
 #pragma once
 
-#include "../../Resources/Orthanc/Core/Images/ImageAccessor.h"
-#include "../../Resources/Orthanc/Core/SharedLibrary.h"
+#include <Core/Images/ImageAccessor.h>
+#include <Core/SharedLibrary.h>
 
 #include <vector>
 
--- a/Framework/Inputs/OpenSlidePyramid.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/OpenSlidePyramid.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,9 +22,11 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "OpenSlidePyramid.h"
 
-#include "../../Resources/Orthanc/Core/Images/ImageProcessing.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
+#include <Core/Images/ImageProcessing.h>
+#include <Core/OrthancException.h>
+#include <Core/Logging.h>
+
+#include <memory>
 
 namespace OrthancWSI
 {
--- a/Framework/Inputs/PyramidWithRawTiles.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/PyramidWithRawTiles.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,9 +22,9 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "PyramidWithRawTiles.h"
 
-#include "../../Resources/Orthanc/Core/Images/PngReader.h"
-#include "../../Resources/Orthanc/Core/Images/JpegReader.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/Images/PngReader.h>
+#include <Core/Images/JpegReader.h>
+#include <Core/OrthancException.h>
 #include "../Jpeg2000Reader.h"
 
 namespace OrthancWSI
--- a/Framework/Inputs/SingleLevelDecodedPyramid.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/SingleLevelDecodedPyramid.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -23,7 +23,7 @@
 #include "SingleLevelDecodedPyramid.h"
 #include "../ImageToolbox.h"
 
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/OrthancException.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Inputs/TiledJpegImage.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/TiledJpegImage.h	Tue Apr 17 15:47:47 2018 +0200
@@ -23,7 +23,7 @@
 
 #include "SingleLevelDecodedPyramid.h"
 
-#include "../../Resources/Orthanc/Core/Images/JpegReader.h"
+#include <Core/Images/JpegReader.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Inputs/TiledPngImage.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/TiledPngImage.h	Tue Apr 17 15:47:47 2018 +0200
@@ -23,7 +23,7 @@
 
 #include "SingleLevelDecodedPyramid.h"
 
-#include "../../Resources/Orthanc/Core/Images/PngReader.h"
+#include <Core/Images/PngReader.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Inputs/TiledPyramidStatistics.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Inputs/TiledPyramidStatistics.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,7 +22,7 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "TiledPyramidStatistics.h"
 
-#include "../../Resources/Orthanc/Core/Logging.h"
+#include <Core/Logging.h>
 
 
 namespace OrthancWSI
--- a/Framework/Jpeg2000Reader.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Jpeg2000Reader.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,8 +22,8 @@
 #include "PrecompiledHeadersWSI.h"
 #include "Jpeg2000Reader.h"
 
-#include "../Resources/Orthanc/Core/OrthancException.h"
-#include "../Resources/Orthanc/Core/SystemToolbox.h"
+#include <Core/OrthancException.h>
+#include <Core/SystemToolbox.h>
 #include "ImageToolbox.h"
 
 #include <cassert>
--- a/Framework/Jpeg2000Reader.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Jpeg2000Reader.h	Tue Apr 17 15:47:47 2018 +0200
@@ -21,7 +21,7 @@
 
 #pragma once
 
-#include "../Resources/Orthanc/Core/Images/Image.h"
+#include <Core/Images/Image.h>
 #include <memory>
 
 namespace OrthancWSI
--- a/Framework/Jpeg2000Writer.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Jpeg2000Writer.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,8 +22,8 @@
 #include "PrecompiledHeadersWSI.h"
 #include "Jpeg2000Writer.h"
 
-#include "../Resources/Orthanc/Core/ChunkedBuffer.h"
-#include "../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/ChunkedBuffer.h>
+#include <Core/OrthancException.h>
 
 #include <openjpeg.h>
 #include <string.h>
--- a/Framework/Jpeg2000Writer.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Jpeg2000Writer.h	Tue Apr 17 15:47:47 2018 +0200
@@ -21,7 +21,7 @@
 
 #pragma once
 
-#include "../Resources/Orthanc/Core/Images/IImageWriter.h"
+#include <Core/Images/IImageWriter.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Outputs/DicomPyramidWriter.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Outputs/DicomPyramidWriter.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -24,9 +24,9 @@
 
 #include "../DicomToolbox.h"
 
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
+#include <Core/DicomParsing/FromDcmtkBridge.h>
 
 #include <dcmtk/dcmdata/dcdeftag.h>
 #include <boost/lexical_cast.hpp>
--- a/Framework/Outputs/HierarchicalTiffWriter.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Outputs/HierarchicalTiffWriter.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,9 +22,9 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "HierarchicalTiffWriter.h"
 
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/TemporaryFile.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
+#include <Core/TemporaryFile.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Outputs/IPyramidWriter.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Outputs/IPyramidWriter.h	Tue Apr 17 15:47:47 2018 +0200
@@ -22,7 +22,7 @@
 #pragma once
 
 #include "../Enumerations.h"
-#include "../../Resources/Orthanc/Core/Images/ImageAccessor.h"
+#include <Core/Images/ImageAccessor.h>
 
 #include <boost/noncopyable.hpp>
 
--- a/Framework/Outputs/InMemoryTiledImage.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Outputs/InMemoryTiledImage.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -23,8 +23,8 @@
 #include "InMemoryTiledImage.h"
 
 #include "../ImageToolbox.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/Logging.h>
+#include <Core/OrthancException.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Outputs/MultiframeDicomWriter.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Outputs/MultiframeDicomWriter.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,8 +22,8 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "MultiframeDicomWriter.h"
 
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
+#include <Core/OrthancException.h>
+#include <Core/Logging.h>
 #include "../DicomToolbox.h"
 
 #include <dcmtk/dcmdata/dcuid.h>
--- a/Framework/Outputs/MultiframeDicomWriter.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Outputs/MultiframeDicomWriter.h	Tue Apr 17 15:47:47 2018 +0200
@@ -22,7 +22,7 @@
 #pragma once
 
 #include "../Enumerations.h"
-#include "../../Resources/Orthanc/Core/ChunkedBuffer.h"
+#include <Core/ChunkedBuffer.h>
 
 #include <boost/noncopyable.hpp>
 #include <memory>
--- a/Framework/Outputs/PyramidWriterBase.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Outputs/PyramidWriterBase.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -23,8 +23,8 @@
 #include "PyramidWriterBase.h"
 
 #include "../ImageToolbox.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
+#include <Core/OrthancException.h>
+#include <Core/Logging.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Outputs/TruncatedPyramidWriter.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Outputs/TruncatedPyramidWriter.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,7 +22,7 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "TruncatedPyramidWriter.h"
 
-#include "../../Resources/Orthanc/Core/OrthancException.h"
+#include <Core/OrthancException.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Targets/FolderTarget.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Targets/FolderTarget.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -22,8 +22,8 @@
 #include "../PrecompiledHeadersWSI.h"
 #include "FolderTarget.h"
 
-#include "../../Resources/Orthanc/Core/SystemToolbox.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
+#include <Core/SystemToolbox.h>
+#include <Core/Logging.h>
 
 #include <stdio.h>
 
--- a/Framework/Targets/OrthancTarget.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Targets/OrthancTarget.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -23,9 +23,9 @@
 #include "OrthancTarget.h"
 
 #include "../DicomToolbox.h"
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../../Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.h"
+#include <Core/OrthancException.h>
+#include <Core/Logging.h>
+#include <Plugins/Samples/Common/OrthancHttpConnection.h>
 
 namespace OrthancWSI
 {
--- a/Framework/Targets/OrthancTarget.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/Framework/Targets/OrthancTarget.h	Tue Apr 17 15:47:47 2018 +0200
@@ -22,8 +22,8 @@
 #pragma once
 
 #include "IFileTarget.h"
-#include "../../Resources/Orthanc/Core/WebServiceParameters.h"
-#include "../../Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h"
+#include <Core/WebServiceParameters.h>
+#include <Plugins/Samples/Common/IOrthancConnection.h>
 
 #include <memory>
 
--- a/NEWS	Wed Apr 11 16:24:26 2018 +0200
+++ b/NEWS	Tue Apr 17 15:47:47 2018 +0200
@@ -5,6 +5,7 @@
 * Support more colorspaces with JPEG2k
 * SSL is enabled by default for HTTPS transfers
 * Fix Debian #876807 (orthanc-wsi FTBFS with libopenjp2-7-dev 2.2.0-1)
+* Resort to Orthanc framework
 * Support of OpenBSD and FreeBSD
 * Support of Linux Standard Base
 
--- a/Resources/CMake/BoostExtendedConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ b/Resources/CMake/BoostExtendedConfiguration.cmake	Tue Apr 17 15:47:47 2018 +0200
@@ -3,7 +3,7 @@
 include(${ORTHANC_ROOT}/Resources/CMake/BoostConfiguration.cmake)
 
 if (BOOST_STATIC)
-  list(APPEND BOOST_SOURCES
+  set(BOOST_EXTENDED_SOURCES
     ${BOOST_SOURCES_DIR}/libs/program_options/src/cmdline.cpp
     ${BOOST_SOURCES_DIR}/libs/program_options/src/config_file.cpp
     ${BOOST_SOURCES_DIR}/libs/program_options/src/convert.cpp
--- a/Resources/CMake/LinuxStandardBaseToolchain.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-# LSB_CC=gcc-4.8 LSB_CXX=g++-4.8 cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../Resources/LinuxStandardBaseToolchain.cmake -DUSE_LEGACY_JSONCPP=ON
-
-INCLUDE(CMakeForceCompiler)
-
-SET(LSB_PATH $ENV{LSB_PATH})
-SET(LSB_CC $ENV{LSB_CC})
-SET(LSB_CXX $ENV{LSB_CXX})
-SET(LSB_TARGET_VERSION "4.0")
-
-IF ("${LSB_PATH}" STREQUAL "")
-  SET(LSB_PATH "/opt/lsb")
-ENDIF()
-
-IF (EXISTS ${LSB_PATH}/lib64)
-  SET(LSB_TARGET_PROCESSOR "x86_64")
-  SET(LSB_LIBPATH ${LSB_PATH}/lib64-${LSB_TARGET_VERSION})
-ELSEIF (EXISTS ${LSB_PATH}/lib)
-  SET(LSB_TARGET_PROCESSOR "x86")
-  SET(LSB_LIBPATH ${LSB_PATH}/lib-${LSB_TARGET_VERSION})
-ELSE()
-  MESSAGE(FATAL_ERROR "Unable to detect the target processor architecture. Check the LSB_PATH environment variable.")
-ENDIF()
-
-SET(LSB_CPPPATH ${LSB_PATH}/include)
-SET(PKG_CONFIG_PATH ${LSB_LIBPATH}/pkgconfig/)
-
-# the name of the target operating system
-SET(CMAKE_SYSTEM_NAME Linux)
-SET(CMAKE_SYSTEM_VERSION LinuxStandardBase)
-SET(CMAKE_SYSTEM_PROCESSOR ${LSB_TARGET_PROCESSOR})
-
-# which compilers to use for C and C++
-SET(CMAKE_C_COMPILER ${LSB_PATH}/bin/lsbcc)
-CMAKE_FORCE_CXX_COMPILER(${LSB_PATH}/bin/lsbc++ GNU)
-
-# here is the target environment located
-SET(CMAKE_FIND_ROOT_PATH ${LSB_PATH})
-
-# adjust the default behaviour of the FIND_XXX() commands:
-# search headers and libraries in the target environment, search 
-# programs in the host environment
-SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
-SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
-
-SET(CMAKE_CROSSCOMPILING OFF)
-
-
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -I${LSB_PATH}/include" CACHE INTERNAL "" FORCE)
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -nostdinc++ -I${LSB_PATH}/include -I${LSB_PATH}/include/c++ -I${LSB_PATH}/include/c++/backward" CACHE INTERNAL "" FORCE)
-SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH} --lsb-besteffort" CACHE INTERNAL "" FORCE)
-SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH} --lsb-besteffort" CACHE INTERNAL "" FORCE)
-
-if (NOT "${LSB_CXX}" STREQUAL "")
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-cxx=${LSB_CXX}")
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-cxx=${LSB_CXX}")
-  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-cxx=${LSB_CXX}")
-endif()
-
-if (NOT "${LSB_CC}" STREQUAL "")
-  SET(CMAKE_C_FLAGS "${CMAKE_CC_FLAGS} --lsb-cc=${LSB_CC}")
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-cc=${LSB_CC}")
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-cc=${LSB_CC}")
-  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-cc=${LSB_CC}")
-endif()
-
--- a/Resources/CMake/Version.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ b/Resources/CMake/Version.cmake	Tue Apr 17 15:47:47 2018 +0200
@@ -1,5 +1,17 @@
 set(ORTHANC_WSI_VERSION "mainline")
 
+if (ORTHANC_WSI_VERSION STREQUAL "mainline")
+  set(ORTHANC_FRAMEWORK_VERSION "mainline")
+  set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg")
+else()
+  set(ORTHANC_FRAMEWORK_VERSION "1.3.1")
+  set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web")
+endif()
+
 add_definitions(
   -DORTHANC_WSI_VERSION="${ORTHANC_WSI_VERSION}"
   )
+
+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\"")
--- a/Resources/Orthanc/Core/Cache/LeastRecentlyUsedIndex.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,347 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 <map>
-#include <boost/noncopyable.hpp>
-#include <cassert>
-
-#include "../OrthancException.h"
-#include "../Toolbox.h"
-
-namespace Orthanc
-{
-  /**
-   * This class implements the index of a cache with least recently
-   * used (LRU) recycling policy. All the items of the cache index
-   * can be associated with a payload.
-   * Reference: http://stackoverflow.com/a/2504317
-   **/
-  template <typename T, typename Payload = NullType>
-  class LeastRecentlyUsedIndex : public boost::noncopyable
-  {
-  private:
-    typedef std::list< std::pair<T, Payload> >  Queue;
-    typedef std::map<T, typename Queue::iterator>  Index;
-
-    Index  index_;
-    Queue  queue_;
-
-    /**
-     * Internal method for debug builds to check whether the internal
-     * data structures are not corrupted.
-     **/
-    void CheckInvariants() const;
-
-  public:
-    /**
-     * Add a new element to the cache index, and make it the most
-     * recent element.
-     * \param id The ID of the element.
-     * \param payload The payload of the element.
-     **/
-    void Add(T id, Payload payload = Payload());
-
-    void AddOrMakeMostRecent(T id, Payload payload = Payload());
-
-    /**
-     * When accessing an element of the cache, this method tags the
-     * element as the most recently used.
-     * \param id The most recently accessed item.
-     **/
-    void MakeMostRecent(T id);
-
-    void MakeMostRecent(T id, Payload updatedPayload);
-
-    /**
-     * Remove an element from the cache index.
-     * \param id The item to remove.
-     **/
-    Payload Invalidate(T id);
-
-    /**
-     * Get the oldest element in the cache and remove it.
-     * \return The oldest item.
-     **/
-    T RemoveOldest();
-
-    /**
-     * Get the oldest element in the cache, remove it and return the
-     * associated payload.
-     * \param payload Where to store the associated payload.
-     * \return The oldest item.
-     **/
-    T RemoveOldest(Payload& payload);
-
-    /**
-     * Check whether an element is contained in the cache.
-     * \param id The item.
-     * \return \c true iff the item is indexed by the cache.
-     **/
-    bool Contains(T id) const
-    {
-      return index_.find(id) != index_.end();
-    }
-
-    bool Contains(T id, Payload& payload) const
-    {
-      typename Index::const_iterator it = index_.find(id);
-      if (it == index_.end())
-      {
-        return false;
-      }
-      else
-      {
-        payload = it->second->second;
-        return true;
-      }
-    }
-
-    /**
-     * Return the number of elements in the cache.
-     * \return The number of elements.
-     **/
-    size_t GetSize() const
-    {
-      assert(index_.size() == queue_.size());
-      return queue_.size();
-    }
-
-    /**
-     * Check whether the cache index is empty.
-     * \return \c true iff the cache is empty.
-     **/
-    bool IsEmpty() const
-    {
-      return index_.empty();
-    }
-
-    const T& GetOldest() const;
-    
-    const Payload& GetOldestPayload() const;
-  };
-
-
-
-
-  /******************************************************************
-   ** Implementation of the template
-   ******************************************************************/
-
-  template <typename T, typename Payload>
-  void LeastRecentlyUsedIndex<T, Payload>::CheckInvariants() const
-  {
-#ifndef NDEBUG
-    assert(index_.size() == queue_.size());
-
-    for (typename Index::const_iterator 
-           it = index_.begin(); it != index_.end(); it++)
-    {
-      assert(it->second != queue_.end());
-      assert(it->second->first == it->first);
-    }
-#endif
-  }
-
-
-  template <typename T, typename Payload>
-  void LeastRecentlyUsedIndex<T, Payload>::Add(T id, Payload payload)
-  {
-    if (Contains(id))
-    {
-      throw OrthancException(ErrorCode_BadSequenceOfCalls);
-    }
-
-    queue_.push_front(std::make_pair(id, payload));
-    index_[id] = queue_.begin();
-
-    CheckInvariants();
-  }
-
-
-  template <typename T, typename Payload>
-  void LeastRecentlyUsedIndex<T, Payload>::MakeMostRecent(T id)
-  {
-    if (!Contains(id))
-    {
-      throw OrthancException(ErrorCode_InexistentItem);
-    }
-
-    typename Index::iterator it = index_.find(id);
-    assert(it != index_.end());
-
-    std::pair<T, Payload> item = *(it->second);
-    
-    queue_.erase(it->second);
-    queue_.push_front(item);
-    index_[id] = queue_.begin();
-
-    CheckInvariants();
-  }
-
-
-  template <typename T, typename Payload>
-  void LeastRecentlyUsedIndex<T, Payload>::AddOrMakeMostRecent(T id, Payload payload)
-  {
-    typename Index::iterator it = index_.find(id);
-
-    if (it != index_.end())
-    {
-      // Already existing. Make it most recent.
-      std::pair<T, Payload> item = *(it->second);
-      item.second = payload;
-      queue_.erase(it->second);
-      queue_.push_front(item);
-    }
-    else
-    {
-      // New item
-      queue_.push_front(std::make_pair(id, payload));
-    }
-
-    index_[id] = queue_.begin();
-
-    CheckInvariants();
-  }
-
-
-  template <typename T, typename Payload>
-  void LeastRecentlyUsedIndex<T, Payload>::MakeMostRecent(T id, Payload updatedPayload)
-  {
-    if (!Contains(id))
-    {
-      throw OrthancException(ErrorCode_InexistentItem);
-    }
-
-    typename Index::iterator it = index_.find(id);
-    assert(it != index_.end());
-
-    std::pair<T, Payload> item = *(it->second);
-    item.second = updatedPayload;
-    
-    queue_.erase(it->second);
-    queue_.push_front(item);
-    index_[id] = queue_.begin();
-
-    CheckInvariants();
-  }
-
-
-  template <typename T, typename Payload>
-  Payload LeastRecentlyUsedIndex<T, Payload>::Invalidate(T id)
-  {
-    if (!Contains(id))
-    {
-      throw OrthancException(ErrorCode_InexistentItem);
-    }
-
-    typename Index::iterator it = index_.find(id);
-    assert(it != index_.end());
-
-    Payload payload = it->second->second;
-    queue_.erase(it->second);
-    index_.erase(it);
-
-    CheckInvariants();
-    return payload;
-  }
-
-
-  template <typename T, typename Payload>
-  T LeastRecentlyUsedIndex<T, Payload>::RemoveOldest(Payload& payload)
-  {
-    if (IsEmpty())
-    {
-      throw OrthancException(ErrorCode_BadSequenceOfCalls);
-    }
-
-    std::pair<T, Payload> item = queue_.back();
-    T oldest = item.first;
-    payload = item.second;
-
-    queue_.pop_back();
-    assert(index_.find(oldest) != index_.end());
-    index_.erase(oldest);
-
-    CheckInvariants();
-
-    return oldest;
-  }
-
-
-  template <typename T, typename Payload>
-  T LeastRecentlyUsedIndex<T, Payload>::RemoveOldest()
-  {
-    if (IsEmpty())
-    {
-      throw OrthancException(ErrorCode_BadSequenceOfCalls);
-    }
-
-    std::pair<T, Payload> item = queue_.back();
-    T oldest = item.first;
-
-    queue_.pop_back();
-    assert(index_.find(oldest) != index_.end());
-    index_.erase(oldest);
-
-    CheckInvariants();
-
-    return oldest;
-  }
-
-
-  template <typename T, typename Payload>
-  const T& LeastRecentlyUsedIndex<T, Payload>::GetOldest() const
-  {
-    if (IsEmpty())
-    {
-      throw OrthancException(ErrorCode_BadSequenceOfCalls);
-    }
-
-    return queue_.back().first;
-  }
-
-
-  template <typename T, typename Payload>
-  const Payload& LeastRecentlyUsedIndex<T, Payload>::GetOldestPayload() const
-  {
-    if (IsEmpty())
-    {
-      throw OrthancException(ErrorCode_BadSequenceOfCalls);
-    }
-
-    return queue_.back().second;
-  }
-}
--- a/Resources/Orthanc/Core/ChunkedBuffer.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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;
-  }
-}
--- a/Resources/Orthanc/Core/ChunkedBuffer.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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);
-  };
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomArray.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomArray.h"
-
-#include <stdio.h>
-
-namespace Orthanc
-{
-  DicomArray::DicomArray(const DicomMap& map)
-  {
-    elements_.reserve(map.map_.size());
-    
-    for (DicomMap::Map::const_iterator it = 
-           map.map_.begin(); it != map.map_.end(); ++it)
-    {
-      elements_.push_back(new DicomElement(it->first, *it->second));
-    }
-  }
-
-
-  DicomArray::~DicomArray()
-  {
-    for (size_t i = 0; i < elements_.size(); i++)
-    {
-      delete elements_[i];
-    }
-  }
-
-
-  void DicomArray::Print(FILE* fp) const
-  {
-    for (size_t  i = 0; i < elements_.size(); i++)
-    {
-      DicomTag t = elements_[i]->GetTag();
-      const DicomValue& v = elements_[i]->GetValue();
-      std::string s = v.IsNull() ? "(null)" : v.GetContent();
-      printf("0x%04x 0x%04x [%s]\n", t.GetGroup(), t.GetElement(), s.c_str());
-    }
-  }
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomArray.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomElement.h"
-#include "DicomMap.h"
-
-#include <vector>
-
-namespace Orthanc
-{
-  class DicomArray : public boost::noncopyable
-  {
-  private:
-    typedef std::vector<DicomElement*>  Elements;
-
-    Elements  elements_;
-
-  public:
-    explicit DicomArray(const DicomMap& map);
-
-    ~DicomArray();
-
-    size_t GetSize() const
-    {
-      return elements_.size();
-    }
-
-    const DicomElement& GetElement(size_t i) const
-    {
-      return *elements_[i];
-    }
-
-    void Print(FILE* fp) const;
-  };
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomElement.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomValue.h"
-#include "DicomTag.h"
-
-namespace Orthanc
-{
-  class DicomElement : public boost::noncopyable
-  {
-  private:
-    DicomTag tag_;
-    DicomValue* value_;
-
-  public:
-    DicomElement(uint16_t group,
-                 uint16_t element,
-                 const DicomValue& value) :
-      tag_(group, element),
-      value_(value.Clone())
-    {
-    }
-
-    DicomElement(const DicomTag& tag,
-                 const DicomValue& value) :
-      tag_(tag),
-      value_(value.Clone())
-    {
-    }
-
-    ~DicomElement()
-    {
-      delete value_;
-    }
-
-    const DicomTag& GetTag() const
-    {
-      return tag_;
-    }
-
-    const DicomValue& GetValue() const
-    {
-      return *value_;
-    }
-
-    uint16_t GetTagGroup() const
-    {
-      return tag_.GetGroup();
-    }
-
-    uint16_t GetTagElement() const
-    {
-      return tag_.GetElement();
-    }
-
-    bool operator< (const DicomElement& other) const
-    {
-      return GetTag() < other.GetTag();
-    }
-  };
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomMap.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,975 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomMap.h"
-
-#include <stdio.h>
-#include <memory>
-
-#include "../Endianness.h"
-#include "../Logging.h"
-#include "../OrthancException.h"
-
-
-namespace Orthanc
-{
-  static DicomTag patientTags[] =
-  {
-    //DicomTag(0x0010, 0x1010), // PatientAge
-    //DicomTag(0x0010, 0x1040)  // PatientAddress
-    DicomTag(0x0010, 0x0010),   // PatientName
-    DicomTag(0x0010, 0x0030),   // PatientBirthDate
-    DicomTag(0x0010, 0x0040),   // PatientSex
-    DicomTag(0x0010, 0x1000),   // OtherPatientIDs
-    DICOM_TAG_PATIENT_ID
-  };
-
-  static DicomTag studyTags[] =
-  {
-    //DicomTag(0x0010, 0x1020), // PatientSize
-    //DicomTag(0x0010, 0x1030)  // PatientWeight
-    DICOM_TAG_STUDY_DATE,
-    DicomTag(0x0008, 0x0030),   // StudyTime
-    DicomTag(0x0020, 0x0010),   // StudyID
-    DICOM_TAG_STUDY_DESCRIPTION,
-    DICOM_TAG_ACCESSION_NUMBER,
-    DICOM_TAG_STUDY_INSTANCE_UID,
-    DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION,   // New in db v6
-    DICOM_TAG_INSTITUTION_NAME,                  // New in db v6
-    DICOM_TAG_REQUESTING_PHYSICIAN,              // New in db v6
-    DICOM_TAG_REFERRING_PHYSICIAN_NAME           // New in db v6
-  };
-
-  static DicomTag seriesTags[] =
-  {
-    //DicomTag(0x0010, 0x1080), // MilitaryRank
-    DicomTag(0x0008, 0x0021),   // SeriesDate
-    DicomTag(0x0008, 0x0031),   // SeriesTime
-    DICOM_TAG_MODALITY,
-    DicomTag(0x0008, 0x0070),   // Manufacturer
-    DicomTag(0x0008, 0x1010),   // StationName
-    DICOM_TAG_SERIES_DESCRIPTION,
-    DicomTag(0x0018, 0x0015),   // BodyPartExamined
-    DicomTag(0x0018, 0x0024),   // SequenceName
-    DicomTag(0x0018, 0x1030),   // ProtocolName
-    DicomTag(0x0020, 0x0011),   // SeriesNumber
-    DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES,
-    DICOM_TAG_IMAGES_IN_ACQUISITION,
-    DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS,
-    DICOM_TAG_NUMBER_OF_SLICES,
-    DICOM_TAG_NUMBER_OF_TIME_SLICES,
-    DICOM_TAG_SERIES_INSTANCE_UID,
-    DICOM_TAG_IMAGE_ORIENTATION_PATIENT,                  // New in db v6
-    DICOM_TAG_SERIES_TYPE,                                // New in db v6
-    DICOM_TAG_OPERATOR_NAME,                              // New in db v6
-    DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION,       // New in db v6
-    DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION,  // New in db v6
-    DICOM_TAG_CONTRAST_BOLUS_AGENT                        // New in db v6
-  };
-
-  static DicomTag instanceTags[] =
-  {
-    DicomTag(0x0008, 0x0012),   // InstanceCreationDate
-    DicomTag(0x0008, 0x0013),   // InstanceCreationTime
-    DicomTag(0x0020, 0x0012),   // AcquisitionNumber
-    DICOM_TAG_IMAGE_INDEX,
-    DICOM_TAG_INSTANCE_NUMBER,
-    DICOM_TAG_NUMBER_OF_FRAMES,
-    DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER,
-    DICOM_TAG_SOP_INSTANCE_UID,
-    DICOM_TAG_IMAGE_POSITION_PATIENT,    // New in db v6
-    DICOM_TAG_IMAGE_COMMENTS             // New in db v6
-  };
-
-
-  void DicomMap::LoadMainDicomTags(const DicomTag*& tags,
-                                   size_t& size,
-                                   ResourceType level)
-  {
-    switch (level)
-    {
-      case ResourceType_Patient:
-        tags = patientTags;
-        size = sizeof(patientTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Study:
-        tags = studyTags;
-        size = sizeof(studyTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Series:
-        tags = seriesTags;
-        size = sizeof(seriesTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Instance:
-        tags = instanceTags;
-        size = sizeof(instanceTags) / sizeof(DicomTag);
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  void DicomMap::SetValue(uint16_t group, 
-                          uint16_t element, 
-                          DicomValue* value)
-  {
-    DicomTag tag(group, element);
-    Map::iterator it = map_.find(tag);
-
-    if (it != map_.end())
-    {
-      delete it->second;
-      it->second = value;
-    }
-    else
-    {
-      map_.insert(std::make_pair(tag, value));
-    }
-  }
-
-  void DicomMap::SetValue(DicomTag tag, 
-                          DicomValue* value)
-  {
-    SetValue(tag.GetGroup(), tag.GetElement(), value);
-  }
-
-
-
-
-  void DicomMap::Clear()
-  {
-    for (Map::iterator it = map_.begin(); it != map_.end(); ++it)
-    {
-      delete it->second;
-    }
-
-    map_.clear();
-  }
-
-
-  void DicomMap::ExtractTags(DicomMap& result,
-                             const DicomTag* tags,
-                             size_t count) const
-  {
-    result.Clear();
-
-    for (unsigned int i = 0; i < count; i++)
-    {
-      Map::const_iterator it = map_.find(tags[i]);
-      if (it != map_.end())
-      {
-        result.SetValue(it->first, it->second->Clone());
-      }
-    }
-  }
-
-
-  void DicomMap::ExtractPatientInformation(DicomMap& result) const
-  {
-    ExtractTags(result, patientTags, sizeof(patientTags) / sizeof(DicomTag));
-  }
-
-  void DicomMap::ExtractStudyInformation(DicomMap& result) const
-  {
-    ExtractTags(result, studyTags, sizeof(studyTags) / sizeof(DicomTag));
-  }
-
-  void DicomMap::ExtractSeriesInformation(DicomMap& result) const
-  {
-    ExtractTags(result, seriesTags, sizeof(seriesTags) / sizeof(DicomTag));
-  }
-
-  void DicomMap::ExtractInstanceInformation(DicomMap& result) const
-  {
-    ExtractTags(result, instanceTags, sizeof(instanceTags) / sizeof(DicomTag));
-  }
-
-
-
-  DicomMap* DicomMap::Clone() const
-  {
-    std::auto_ptr<DicomMap> result(new DicomMap);
-
-    for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it)
-    {
-      result->map_.insert(std::make_pair(it->first, it->second->Clone()));
-    }
-
-    return result.release();
-  }
-
-
-  void DicomMap::Assign(const DicomMap& other)
-  {
-    Clear();
-
-    for (Map::const_iterator it = other.map_.begin(); it != other.map_.end(); ++it)
-    {
-      map_.insert(std::make_pair(it->first, it->second->Clone()));
-    }
-  }
-
-
-  const DicomValue& DicomMap::GetValue(const DicomTag& tag) const
-  {
-    const DicomValue* value = TestAndGetValue(tag);
-
-    if (value)
-    {
-      return *value;
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_InexistentTag);
-    }
-  }
-
-
-  const DicomValue* DicomMap::TestAndGetValue(const DicomTag& tag) const
-  {
-    Map::const_iterator it = map_.find(tag);
-
-    if (it == map_.end())
-    {
-      return NULL;
-    }
-    else
-    {
-      return it->second;
-    }
-  }
-
-
-  void DicomMap::Remove(const DicomTag& tag) 
-  {
-    Map::iterator it = map_.find(tag);
-    if (it != map_.end())
-    {
-      delete it->second;
-      map_.erase(it);
-    }
-  }
-
-
-  static void SetupFindTemplate(DicomMap& result,
-                                const DicomTag* tags,
-                                size_t count) 
-  {
-    result.Clear();
-
-    for (size_t i = 0; i < count; i++)
-    {
-      result.SetValue(tags[i], "", false);
-    }
-  }
-
-  void DicomMap::SetupFindPatientTemplate(DicomMap& result)
-  {
-    SetupFindTemplate(result, patientTags, sizeof(patientTags) / sizeof(DicomTag));
-  }
-
-  void DicomMap::SetupFindStudyTemplate(DicomMap& result)
-  {
-    SetupFindTemplate(result, studyTags, sizeof(studyTags) / sizeof(DicomTag));
-    result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
-    result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
-
-    // These main DICOM tags are only indirectly related to the
-    // General Study Module, remove them
-    result.Remove(DICOM_TAG_INSTITUTION_NAME);
-    result.Remove(DICOM_TAG_REQUESTING_PHYSICIAN);
-    result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION);
-  }
-
-  void DicomMap::SetupFindSeriesTemplate(DicomMap& result)
-  {
-    SetupFindTemplate(result, seriesTags, sizeof(seriesTags) / sizeof(DicomTag));
-    result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
-    result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
-    result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false);
-
-    // These tags are considered as "main" by Orthanc, but are not in the Series module
-    result.Remove(DicomTag(0x0008, 0x0070));  // Manufacturer
-    result.Remove(DicomTag(0x0008, 0x1010));  // Station name
-    result.Remove(DicomTag(0x0018, 0x0024));  // Sequence name
-    result.Remove(DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES);
-    result.Remove(DICOM_TAG_IMAGES_IN_ACQUISITION);
-    result.Remove(DICOM_TAG_NUMBER_OF_SLICES);
-    result.Remove(DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS);
-    result.Remove(DICOM_TAG_NUMBER_OF_TIME_SLICES);
-    result.Remove(DICOM_TAG_IMAGE_ORIENTATION_PATIENT);
-    result.Remove(DICOM_TAG_SERIES_TYPE);
-    result.Remove(DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION);
-    result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT);
-  }
-
-  void DicomMap::SetupFindInstanceTemplate(DicomMap& result)
-  {
-    SetupFindTemplate(result, instanceTags, sizeof(instanceTags) / sizeof(DicomTag));
-    result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
-    result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
-    result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false);
-    result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false);
-  }
-
-
-  void DicomMap::CopyTagIfExists(const DicomMap& source,
-                                 const DicomTag& tag)
-  {
-    if (source.HasTag(tag))
-    {
-      SetValue(tag, source.GetValue(tag));
-    }
-  }
-
-
-  bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level)
-  {
-    DicomTag *tags = NULL;
-    size_t size;
-
-    switch (level)
-    {
-      case ResourceType_Patient:
-        tags = patientTags;
-        size = sizeof(patientTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Study:
-        tags = studyTags;
-        size = sizeof(studyTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Series:
-        tags = seriesTags;
-        size = sizeof(seriesTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Instance:
-        tags = instanceTags;
-        size = sizeof(instanceTags) / sizeof(DicomTag);
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    for (size_t i = 0; i < size; i++)
-    {
-      if (tags[i] == tag)
-      {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  bool DicomMap::IsMainDicomTag(const DicomTag& tag)
-  {
-    return (IsMainDicomTag(tag, ResourceType_Patient) ||
-            IsMainDicomTag(tag, ResourceType_Study) ||
-            IsMainDicomTag(tag, ResourceType_Series) ||
-            IsMainDicomTag(tag, ResourceType_Instance));
-  }
-
-
-  void DicomMap::GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level)
-  {
-    DicomTag *tags = NULL;
-    size_t size;
-
-    switch (level)
-    {
-      case ResourceType_Patient:
-        tags = patientTags;
-        size = sizeof(patientTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Study:
-        tags = studyTags;
-        size = sizeof(studyTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Series:
-        tags = seriesTags;
-        size = sizeof(seriesTags) / sizeof(DicomTag);
-        break;
-
-      case ResourceType_Instance:
-        tags = instanceTags;
-        size = sizeof(instanceTags) / sizeof(DicomTag);
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    for (size_t i = 0; i < size; i++)
-    {
-      result.insert(tags[i]);
-    }
-  }
-
-
-  void DicomMap::GetMainDicomTags(std::set<DicomTag>& result, ResourceType level)
-  {
-    result.clear();
-    GetMainDicomTagsInternal(result, level);
-  }
-
-
-  void DicomMap::GetMainDicomTags(std::set<DicomTag>& result)
-  {
-    result.clear();
-    GetMainDicomTagsInternal(result, ResourceType_Patient);
-    GetMainDicomTagsInternal(result, ResourceType_Study);
-    GetMainDicomTagsInternal(result, ResourceType_Series);
-    GetMainDicomTagsInternal(result, ResourceType_Instance);
-  }
-
-
-  void DicomMap::GetTags(std::set<DicomTag>& tags) const
-  {
-    tags.clear();
-
-    for (Map::const_iterator it = map_.begin();
-         it != map_.end(); ++it)
-    {
-      tags.insert(it->first);
-    }
-  }
-
-
-  static uint16_t ReadUnsignedInteger16(const char* dicom)
-  {
-    return le16toh(*reinterpret_cast<const uint16_t*>(dicom));
-  }
-
-
-  static uint32_t ReadUnsignedInteger32(const char* dicom)
-  {
-    return le32toh(*reinterpret_cast<const uint32_t*>(dicom));
-  }
-
-
-  static bool ValidateTag(const ValueRepresentation& vr,
-                          const std::string& value)
-  {
-    switch (vr)
-    {
-      case ValueRepresentation_ApplicationEntity:
-        return value.size() <= 16;
-
-      case ValueRepresentation_AgeString:
-        return (value.size() == 4 &&
-                isdigit(value[0]) &&
-                isdigit(value[1]) &&
-                isdigit(value[2]) &&
-                (value[3] == 'D' || value[3] == 'W' || value[3] == 'M' || value[3] == 'Y'));
-
-      case ValueRepresentation_AttributeTag:
-        return value.size() == 4;
-
-      case ValueRepresentation_CodeString:
-        return value.size() <= 16;
-
-      case ValueRepresentation_Date:
-        return value.size() <= 18;
-
-      case ValueRepresentation_DecimalString:
-        return value.size() <= 16;
-
-      case ValueRepresentation_DateTime:
-        return value.size() <= 54;
-
-      case ValueRepresentation_FloatingPointSingle:
-        return value.size() == 4;
-
-      case ValueRepresentation_FloatingPointDouble:
-        return value.size() == 8;
-
-      case ValueRepresentation_IntegerString:
-        return value.size() <= 12;
-
-      case ValueRepresentation_LongString:
-        return value.size() <= 64;
-
-      case ValueRepresentation_LongText:
-        return value.size() <= 10240;
-
-      case ValueRepresentation_OtherByte:
-        return true;
-      
-      case ValueRepresentation_OtherDouble:
-        return value.size() <= (static_cast<uint64_t>(1) << 32) - 8;
-
-      case ValueRepresentation_OtherFloat:
-        return value.size() <= (static_cast<uint64_t>(1) << 32) - 4;
-
-      case ValueRepresentation_OtherLong:
-        return true;
-
-      case ValueRepresentation_OtherWord:
-        return true;
-
-      case ValueRepresentation_PersonName:
-        return true;
-
-      case ValueRepresentation_ShortString:
-        return value.size() <= 16;
-
-      case ValueRepresentation_SignedLong:
-        return value.size() == 4;
-
-      case ValueRepresentation_Sequence:
-        return true;
-
-      case ValueRepresentation_SignedShort:
-        return value.size() == 2;
-
-      case ValueRepresentation_ShortText:
-        return value.size() <= 1024;
-
-      case ValueRepresentation_Time:
-        return value.size() <= 28;
-
-      case ValueRepresentation_UnlimitedCharacters:
-        return value.size() <= (static_cast<uint64_t>(1) << 32) - 2;
-
-      case ValueRepresentation_UniqueIdentifier:
-        return value.size() <= 64;
-
-      case ValueRepresentation_UnsignedLong:
-        return value.size() == 4;
-
-      case ValueRepresentation_Unknown:
-        return true;
-
-      case ValueRepresentation_UniversalResource:
-        return value.size() <= (static_cast<uint64_t>(1) << 32) - 2;
-
-      case ValueRepresentation_UnsignedShort:
-        return value.size() == 2;
-
-      case ValueRepresentation_UnlimitedText:
-        return value.size() <= (static_cast<uint64_t>(1) << 32) - 2;
-
-      default:
-        // Assume unsupported tags are OK
-        return true;
-    }
-  }
-
-
-  static void RemoveTagPadding(std::string& value,
-                               const ValueRepresentation& vr)
-  {
-    /**
-     * Remove padding from character strings, if need be. For the time
-     * being, only the UI VR is supported.
-     * http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html
-     **/
-
-    switch (vr)
-    {
-      case ValueRepresentation_UniqueIdentifier:
-      {
-        /**
-         * "Values with a VR of UI shall be padded with a single
-         * trailing NULL (00H) character when necessary to achieve even
-         * length."
-         **/
-
-        if (!value.empty() &&
-            value[value.size() - 1] == '\0')
-        {
-          value.resize(value.size() - 1);
-        }
-
-        break;
-      }
-
-      /**
-       * TODO implement other VR
-       **/
-
-      default:
-        // No padding is applicable to this VR
-        break;
-    }
-  }
-
-
-  static bool ReadNextTag(DicomTag& tag,
-                          ValueRepresentation& vr,
-                          std::string& value,
-                          const char* dicom,
-                          size_t size,
-                          size_t& position)
-  {
-    /**
-     * http://dicom.nema.org/medical/dicom/current/output/chtml/part05/chapter_7.html#sect_7.1.2
-     * This function reads a data element with Explicit VR encoded using Little-Endian.
-     **/
-
-    if (position + 6 > size)
-    {
-      return false;
-    }
-
-    tag = DicomTag(ReadUnsignedInteger16(dicom + position),
-                   ReadUnsignedInteger16(dicom + position + 2));
-
-    vr = StringToValueRepresentation(std::string(dicom + position + 4, 2), true);
-    if (vr == ValueRepresentation_NotSupported)
-    {
-      return false;
-    }
-
-    if (vr == ValueRepresentation_OtherByte ||
-        vr == ValueRepresentation_OtherDouble ||
-        vr == ValueRepresentation_OtherFloat ||
-        vr == ValueRepresentation_OtherLong ||
-        vr == ValueRepresentation_OtherWord ||
-        vr == ValueRepresentation_Sequence ||
-        vr == ValueRepresentation_UnlimitedCharacters ||
-        vr == ValueRepresentation_UniversalResource ||
-        vr == ValueRepresentation_UnlimitedText ||
-        vr == ValueRepresentation_Unknown)    // Note that "UN" should never appear in the Meta Information
-    {
-      if (position + 12 > size)
-      {
-        return false;
-      }
-
-      uint32_t length = ReadUnsignedInteger32(dicom + position + 8);
-
-      if (position + 12 + length > size)
-      {
-        return false;
-      }
-
-      value.assign(dicom + position + 12, length);
-      position += (12 + length);
-    }
-    else
-    {
-      if (position + 8 > size)
-      {
-        return false;
-      }
-
-      uint16_t length = ReadUnsignedInteger16(dicom + position + 6);
-
-      if (position + 8 + length > size)
-      {
-        return false;
-      }
-
-      value.assign(dicom + position + 8, length);
-      position += (8 + length);
-    }
-
-    if (!ValidateTag(vr, value))
-    {
-      return false;
-    }
-
-    RemoveTagPadding(value, vr);
-
-    return true;
-  }
-
-
-  bool DicomMap::ParseDicomMetaInformation(DicomMap& result,
-                                           const char* dicom,
-                                           size_t size)
-  {
-    /**
-     * http://dicom.nema.org/medical/dicom/current/output/chtml/part10/chapter_7.html
-     * According to Table 7.1-1, besides the "DICM" DICOM prefix, the
-     * file preamble (i.e. dicom[0..127]) should not be taken into
-     * account to determine whether the file is or is not a DICOM file.
-     **/
-
-    if (size < 132 ||
-        dicom[128] != 'D' ||
-        dicom[129] != 'I' ||
-        dicom[130] != 'C' ||
-        dicom[131] != 'M')
-    {
-      return false;
-    }
-
-
-    /**
-     * The DICOM File Meta Information must be encoded using the
-     * Explicit VR Little Endian Transfer Syntax
-     * (UID=1.2.840.10008.1.2.1).
-     **/
-
-    result.Clear();
-
-    // First, we read the "File Meta Information Group Length" tag
-    // (0002,0000) to know where to stop reading the meta header
-    size_t position = 132;
-
-    DicomTag tag(0x0000, 0x0000);  // Dummy initialization
-    ValueRepresentation vr;
-    std::string value;
-    if (!ReadNextTag(tag, vr, value, dicom, size, position) ||
-        tag.GetGroup() != 0x0002 ||
-        tag.GetElement() != 0x0000 ||
-        vr != ValueRepresentation_UnsignedLong ||
-        value.size() != 4)
-    {
-      return false;
-    }
-
-    size_t stopPosition = position + ReadUnsignedInteger32(value.c_str());
-    if (stopPosition > size)
-    {
-      return false;
-    }
-
-    while (position < stopPosition)
-    {
-      if (ReadNextTag(tag, vr, value, dicom, size, position))
-      {
-        result.SetValue(tag, value, IsBinaryValueRepresentation(vr));
-      }
-      else
-      {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-
-  static std::string ValueAsString(const DicomMap& summary,
-                                   const DicomTag& tag)
-  {
-    const DicomValue& value = summary.GetValue(tag);
-    if (value.IsNull())
-    {
-      return "(null)";
-    }
-    else
-    {
-      return value.GetContent();
-    }
-  }
-
-
-  void DicomMap::LogMissingTagsForStore() const
-  {
-    std::string s, t;
-
-    if (HasTag(DICOM_TAG_PATIENT_ID))
-    {
-      if (t.size() > 0)
-        t += ", ";
-      t += "PatientID=" + ValueAsString(*this, DICOM_TAG_PATIENT_ID);
-    }
-    else
-    {
-      if (s.size() > 0)
-        s += ", ";
-      s += "PatientID";
-    }
-
-    if (HasTag(DICOM_TAG_STUDY_INSTANCE_UID))
-    {
-      if (t.size() > 0)
-        t += ", ";
-      t += "StudyInstanceUID=" + ValueAsString(*this, DICOM_TAG_STUDY_INSTANCE_UID);
-    }
-    else
-    {
-      if (s.size() > 0)
-        s += ", ";
-      s += "StudyInstanceUID";
-    }
-
-    if (HasTag(DICOM_TAG_SERIES_INSTANCE_UID))
-    {
-      if (t.size() > 0)
-        t += ", ";
-      t += "SeriesInstanceUID=" + ValueAsString(*this, DICOM_TAG_SERIES_INSTANCE_UID);
-    }
-    else
-    {
-      if (s.size() > 0)
-        s += ", ";
-      s += "SeriesInstanceUID";
-    }
-
-    if (HasTag(DICOM_TAG_SOP_INSTANCE_UID))
-    {
-      if (t.size() > 0)
-        t += ", ";
-      t += "SOPInstanceUID=" + ValueAsString(*this, DICOM_TAG_SOP_INSTANCE_UID);
-    }
-    else
-    {
-      if (s.size() > 0)
-        s += ", ";
-      s += "SOPInstanceUID";
-    }
-
-    if (t.size() == 0)
-    {
-      LOG(ERROR) << "Store has failed because all the required tags (" << s << ") are missing (is it a DICOMDIR file?)";
-    }
-    else
-    {
-      LOG(ERROR) << "Store has failed because required tags (" << s << ") are missing for the following instance: " << t;
-    }
-  }
-
-
-  bool DicomMap::CopyToString(std::string& result,
-                              const DicomTag& tag,
-                              bool allowBinary) const
-  {
-    const DicomValue* value = TestAndGetValue(tag);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      return value->CopyToString(result, allowBinary);
-    }
-  }
-    
-  bool DicomMap::ParseInteger32(int32_t& result,
-                                const DicomTag& tag) const
-  {
-    const DicomValue* value = TestAndGetValue(tag);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      return value->ParseInteger32(result);
-    }
-  }
-
-  bool DicomMap::ParseInteger64(int64_t& result,
-                                const DicomTag& tag) const
-  {
-    const DicomValue* value = TestAndGetValue(tag);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      return value->ParseInteger64(result);
-    }
-  }
-
-  bool DicomMap::ParseUnsignedInteger32(uint32_t& result,
-                                        const DicomTag& tag) const
-  {
-    const DicomValue* value = TestAndGetValue(tag);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      return value->ParseUnsignedInteger32(result);
-    }
-  }
-
-  bool DicomMap::ParseUnsignedInteger64(uint64_t& result,
-                                        const DicomTag& tag) const
-  {
-    const DicomValue* value = TestAndGetValue(tag);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      return value->ParseUnsignedInteger64(result);
-    }
-  }
-
-  bool DicomMap::ParseFloat(float& result,
-                            const DicomTag& tag) const
-  {
-    const DicomValue* value = TestAndGetValue(tag);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      return value->ParseFloat(result);
-    }
-  }
-
-  bool DicomMap::ParseDouble(double& result,
-                             const DicomTag& tag) const
-  {
-    const DicomValue* value = TestAndGetValue(tag);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      return value->ParseDouble(result);
-    }
-  }
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomMap.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomTag.h"
-#include "DicomValue.h"
-#include "../Enumerations.h"
-
-#include <set>
-#include <map>
-#include <json/json.h>
-
-namespace Orthanc
-{
-  class DicomMap : public boost::noncopyable
-  {
-  private:
-    friend class DicomArray;
-    friend class FromDcmtkBridge;
-    friend class ParsedDicomFile;
-
-    typedef std::map<DicomTag, DicomValue*>  Map;
-
-    Map map_;
-
-    // Warning: This takes the ownership of "value"
-    void SetValue(uint16_t group, 
-                  uint16_t element, 
-                  DicomValue* value);
-
-    void SetValue(DicomTag tag, 
-                  DicomValue* value);
-
-    void ExtractTags(DicomMap& source,
-                     const DicomTag* tags,
-                     size_t count) const;
-   
-    static void GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level);
-
-  public:
-    DicomMap()
-    {
-    }
-
-    ~DicomMap()
-    {
-      Clear();
-    }
-
-    size_t GetSize() const
-    {
-      return map_.size();
-    }
-    
-    DicomMap* Clone() const;
-
-    void Assign(const DicomMap& other);
-
-    void Clear();
-
-    void SetValue(uint16_t group, 
-                  uint16_t element, 
-                  const DicomValue& value)
-    {
-      SetValue(group, element, value.Clone());
-    }
-
-    void SetValue(const DicomTag& tag,
-                  const DicomValue& value)
-    {
-      SetValue(tag, value.Clone());
-    }
-
-    void SetValue(const DicomTag& tag,
-                  const std::string& str,
-                  bool isBinary)
-    {
-      SetValue(tag, new DicomValue(str, isBinary));
-    }
-
-    void SetValue(uint16_t group, 
-                  uint16_t element, 
-                  const std::string& str,
-                  bool isBinary)
-    {
-      SetValue(group, element, new DicomValue(str, isBinary));
-    }
-
-    bool HasTag(uint16_t group, uint16_t element) const
-    {
-      return HasTag(DicomTag(group, element));
-    }
-
-    bool HasTag(const DicomTag& tag) const
-    {
-      return map_.find(tag) != map_.end();
-    }
-
-    const DicomValue& GetValue(uint16_t group, uint16_t element) const
-    {
-      return GetValue(DicomTag(group, element));
-    }
-
-    const DicomValue& GetValue(const DicomTag& tag) const;
-
-    // DO NOT delete the returned value!
-    const DicomValue* TestAndGetValue(uint16_t group, uint16_t element) const
-    {
-      return TestAndGetValue(DicomTag(group, element));
-    }       
-
-    // DO NOT delete the returned value!
-    const DicomValue* TestAndGetValue(const DicomTag& tag) const;
-
-    void Remove(const DicomTag& tag);
-
-    void ExtractPatientInformation(DicomMap& result) const;
-
-    void ExtractStudyInformation(DicomMap& result) const;
-
-    void ExtractSeriesInformation(DicomMap& result) const;
-
-    void ExtractInstanceInformation(DicomMap& result) const;
-
-    static void SetupFindPatientTemplate(DicomMap& result);
-
-    static void SetupFindStudyTemplate(DicomMap& result);
-
-    static void SetupFindSeriesTemplate(DicomMap& result);
-
-    static void SetupFindInstanceTemplate(DicomMap& result);
-
-    void CopyTagIfExists(const DicomMap& source,
-                         const DicomTag& tag);
-
-    static bool IsMainDicomTag(const DicomTag& tag, ResourceType level);
-
-    static bool IsMainDicomTag(const DicomTag& tag);
-
-    static void GetMainDicomTags(std::set<DicomTag>& result, ResourceType level);
-
-    static void GetMainDicomTags(std::set<DicomTag>& result);
-
-    void GetTags(std::set<DicomTag>& tags) const;
-
-    static void LoadMainDicomTags(const DicomTag*& tags,
-                                  size_t& size,
-                                  ResourceType level);
-
-    static bool ParseDicomMetaInformation(DicomMap& result,
-                                          const char* dicom,
-                                          size_t size);
-
-    void LogMissingTagsForStore() const;
-
-    bool CopyToString(std::string& result,
-                      const DicomTag& tag,
-                      bool allowBinary) const;
-    
-    bool ParseInteger32(int32_t& result,
-                        const DicomTag& tag) const;
-
-    bool ParseInteger64(int64_t& result,
-                        const DicomTag& tag) const;                                
-
-    bool ParseUnsignedInteger32(uint32_t& result,
-                                const DicomTag& tag) const;
-
-    bool ParseUnsignedInteger64(uint64_t& result,
-                                const DicomTag& tag) const;                                
-
-    bool ParseFloat(float& result,
-                    const DicomTag& tag) const;                                
-
-    bool ParseDouble(double& result,
-                     const DicomTag& tag) const;                                
-  };
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomTag.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomTag.h"
-
-#include "../OrthancException.h"
-
-#include <iostream>
-#include <iomanip>
-#include <stdio.h>
-
-namespace Orthanc
-{
-  bool DicomTag::operator< (const DicomTag& other) const
-  {
-    if (group_ < other.group_)
-      return true;
-
-    if (group_ > other.group_)
-      return false;
-
-    return element_ < other.element_;
-  }
-
-
-  std::ostream& operator<< (std::ostream& o, const DicomTag& tag)
-  {
-    using namespace std;
-    ios_base::fmtflags state = o.flags();
-    o.flags(ios::right | ios::hex);
-    o << "(" << setfill('0') << setw(4) << tag.GetGroup()
-      << "," << setw(4) << tag.GetElement() << ")";
-    o.flags(state);
-    return o;
-  }
-
-
-  std::string DicomTag::Format() const
-  {
-    char b[16];
-    sprintf(b, "%04x,%04x", group_, element_);
-    return std::string(b);
-  }
-
-
-  const char* DicomTag::GetMainTagsName() const
-  {
-    if (*this == DICOM_TAG_ACCESSION_NUMBER)
-      return "AccessionNumber";
-
-    if (*this == DICOM_TAG_SOP_INSTANCE_UID)
-      return "SOPInstanceUID";
-
-    if (*this == DICOM_TAG_PATIENT_ID)
-      return "PatientID";
-
-    if (*this == DICOM_TAG_SERIES_INSTANCE_UID)
-      return "SeriesInstanceUID";
-
-    if (*this == DICOM_TAG_STUDY_INSTANCE_UID)
-      return "StudyInstanceUID"; 
-
-    if (*this == DICOM_TAG_PIXEL_DATA)
-      return "PixelData";
-
-    if (*this == DICOM_TAG_IMAGE_INDEX)
-      return "ImageIndex";
-
-    if (*this == DICOM_TAG_INSTANCE_NUMBER)
-      return "InstanceNumber";
-
-    if (*this == DICOM_TAG_NUMBER_OF_SLICES)
-      return "NumberOfSlices";
-
-    if (*this == DICOM_TAG_NUMBER_OF_FRAMES)
-      return "NumberOfFrames";
-
-    if (*this == DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)
-      return "CardiacNumberOfImages";
-
-    if (*this == DICOM_TAG_IMAGES_IN_ACQUISITION)
-      return "ImagesInAcquisition";
-
-    if (*this == DICOM_TAG_PATIENT_NAME)
-      return "PatientName";
-
-    if (*this == DICOM_TAG_IMAGE_POSITION_PATIENT)
-      return "ImagePositionPatient";
-
-    if (*this == DICOM_TAG_IMAGE_ORIENTATION_PATIENT)
-      return "ImageOrientationPatient";
-
-    return "";
-  }
-
-
-  void DicomTag::AddTagsForModule(std::set<DicomTag>& target,
-                                  DicomModule module)
-  {
-    // REFERENCE: 11_03pu.pdf, DICOM PS 3.3 2011 - Information Object Definitions
-
-    switch (module)
-    {
-      case DicomModule_Patient:
-        // This is Table C.7-1 "Patient Module Attributes" (p. 373)
-        target.insert(DicomTag(0x0010, 0x0010));   // Patient's name
-        target.insert(DicomTag(0x0010, 0x0020));   // Patient ID
-        target.insert(DicomTag(0x0010, 0x0030));   // Patient's birth date
-        target.insert(DicomTag(0x0010, 0x0040));   // Patient's sex
-        target.insert(DicomTag(0x0008, 0x1120));   // Referenced patient sequence
-        target.insert(DicomTag(0x0010, 0x0032));   // Patient's birth time
-        target.insert(DicomTag(0x0010, 0x1000));   // Other patient IDs
-        target.insert(DicomTag(0x0010, 0x1002));   // Other patient IDs sequence
-        target.insert(DicomTag(0x0010, 0x1001));   // Other patient names
-        target.insert(DicomTag(0x0010, 0x2160));   // Ethnic group
-        target.insert(DicomTag(0x0010, 0x4000));   // Patient comments
-        target.insert(DicomTag(0x0010, 0x2201));   // Patient species description
-        target.insert(DicomTag(0x0010, 0x2202));   // Patient species code sequence
-        target.insert(DicomTag(0x0010, 0x2292));   // Patient breed description
-        target.insert(DicomTag(0x0010, 0x2293));   // Patient breed code sequence
-        target.insert(DicomTag(0x0010, 0x2294));   // Breed registration sequence
-        target.insert(DicomTag(0x0010, 0x2297));   // Responsible person
-        target.insert(DicomTag(0x0010, 0x2298));   // Responsible person role
-        target.insert(DicomTag(0x0010, 0x2299));   // Responsible organization
-        target.insert(DicomTag(0x0012, 0x0062));   // Patient identity removed
-        target.insert(DicomTag(0x0012, 0x0063));   // De-identification method
-        target.insert(DicomTag(0x0012, 0x0064));   // De-identification method code sequence
-
-        // Table 10-18 ISSUER OF PATIENT ID MACRO (p. 112)
-        target.insert(DicomTag(0x0010, 0x0021));   // Issuer of Patient ID
-        target.insert(DicomTag(0x0010, 0x0024));   // Issuer of Patient ID qualifiers sequence
-        break;
-
-      case DicomModule_Study:
-        // This is Table C.7-3 "General Study Module Attributes" (p. 378)
-        target.insert(DicomTag(0x0020, 0x000d));   // Study instance UID
-        target.insert(DicomTag(0x0008, 0x0020));   // Study date
-        target.insert(DicomTag(0x0008, 0x0030));   // Study time
-        target.insert(DicomTag(0x0008, 0x0090));   // Referring physician's name
-        target.insert(DicomTag(0x0008, 0x0096));   // Referring physician identification sequence
-        target.insert(DicomTag(0x0020, 0x0010));   // Study ID
-        target.insert(DicomTag(0x0008, 0x0050));   // Accession number
-        target.insert(DicomTag(0x0008, 0x0051));   // Issuer of accession number sequence
-        target.insert(DicomTag(0x0008, 0x1030));   // Study description
-        target.insert(DicomTag(0x0008, 0x1048));   // Physician(s) of record
-        target.insert(DicomTag(0x0008, 0x1049));   // Physician(s) of record identification sequence
-        target.insert(DicomTag(0x0008, 0x1060));   // Name of physician(s) reading study
-        target.insert(DicomTag(0x0008, 0x1062));   // Physician(s) reading study identification sequence
-        target.insert(DicomTag(0x0032, 0x1034));   // Requesting service code sequence
-        target.insert(DicomTag(0x0008, 0x1110));   // Referenced study sequence
-        target.insert(DicomTag(0x0008, 0x1032));   // Procedure code sequence
-        target.insert(DicomTag(0x0040, 0x1012));   // Reason for performed procedure code sequence
-        break;
-
-      case DicomModule_Series:
-        // This is Table C.7-5 "General Series Module Attributes" (p. 385)
-        target.insert(DicomTag(0x0008, 0x0060));   // Modality 
-        target.insert(DicomTag(0x0020, 0x000e));   // Series Instance UID 
-        target.insert(DicomTag(0x0020, 0x0011));   // Series Number 
-        target.insert(DicomTag(0x0020, 0x0060));   // Laterality 
-        target.insert(DicomTag(0x0008, 0x0021));   // Series Date 
-        target.insert(DicomTag(0x0008, 0x0031));   // Series Time 
-        target.insert(DicomTag(0x0008, 0x1050));   // Performing Physicians’ Name 
-        target.insert(DicomTag(0x0008, 0x1052));   // Performing Physician Identification Sequence 
-        target.insert(DicomTag(0x0018, 0x1030));   // Protocol Name
-        target.insert(DicomTag(0x0008, 0x103e));   // Series Description 
-        target.insert(DicomTag(0x0008, 0x103f));   // Series Description Code Sequence 
-        target.insert(DicomTag(0x0008, 0x1070));   // Operators' Name 
-        target.insert(DicomTag(0x0008, 0x1072));   // Operator Identification Sequence 
-        target.insert(DicomTag(0x0008, 0x1111));   // Referenced Performed Procedure Step Sequence
-        target.insert(DicomTag(0x0008, 0x1250));   // Related Series Sequence
-        target.insert(DicomTag(0x0018, 0x0015));   // Body Part Examined
-        target.insert(DicomTag(0x0018, 0x5100));   // Patient Position
-        target.insert(DicomTag(0x0028, 0x0108));   // Smallest Pixel Value in Series 
-        target.insert(DicomTag(0x0029, 0x0109));   // Largest Pixel Value in Series 
-        target.insert(DicomTag(0x0040, 0x0275));   // Request Attributes Sequence 
-        target.insert(DicomTag(0x0010, 0x2210));   // Anatomical Orientation Type
-
-        // Table 10-16 PERFORMED PROCEDURE STEP SUMMARY MACRO ATTRIBUTES
-        target.insert(DicomTag(0x0040, 0x0253));   // Performed Procedure Step ID 
-        target.insert(DicomTag(0x0040, 0x0244));   // Performed Procedure Step Start Date 
-        target.insert(DicomTag(0x0040, 0x0245));   // Performed Procedure Step Start Time 
-        target.insert(DicomTag(0x0040, 0x0254));   // Performed Procedure Step Description 
-        target.insert(DicomTag(0x0040, 0x0260));   // Performed Protocol Code Sequence 
-        target.insert(DicomTag(0x0040, 0x0280));   // Comments on the Performed Procedure Step
-        break;
-
-      case DicomModule_Instance:
-        // This is Table C.12-1 "SOP Common Module Attributes" (p. 1207)
-        target.insert(DicomTag(0x0008, 0x0016));   // SOP Class UID
-        target.insert(DicomTag(0x0008, 0x0018));   // SOP Instance UID 
-        target.insert(DicomTag(0x0008, 0x0005));   // Specific Character Set 
-        target.insert(DicomTag(0x0008, 0x0012));   // Instance Creation Date 
-        target.insert(DicomTag(0x0008, 0x0013));   // Instance Creation Time 
-        target.insert(DicomTag(0x0008, 0x0014));   // Instance Creator UID 
-        target.insert(DicomTag(0x0008, 0x001a));   // Related General SOP Class UID 
-        target.insert(DicomTag(0x0008, 0x001b));   // Original Specialized SOP Class UID 
-        target.insert(DicomTag(0x0008, 0x0110));   // Coding Scheme Identification Sequence 
-        target.insert(DicomTag(0x0008, 0x0201));   // Timezone Offset From UTC 
-        target.insert(DicomTag(0x0018, 0xa001));   // Contributing Equipment Sequence
-        target.insert(DicomTag(0x0020, 0x0013));   // Instance Number 
-        target.insert(DicomTag(0x0100, 0x0410));   // SOP Instance Status 
-        target.insert(DicomTag(0x0100, 0x0420));   // SOP Authorization DateTime 
-        target.insert(DicomTag(0x0100, 0x0424));   // SOP Authorization Comment 
-        target.insert(DicomTag(0x0100, 0x0426));   // Authorization Equipment Certification Number
-        target.insert(DicomTag(0x0400, 0x0500));   // Encrypted Attributes Sequence
-        target.insert(DicomTag(0x0400, 0x0561));   // Original Attributes Sequence 
-        target.insert(DicomTag(0x0040, 0xa390));   // HL7 Structured Document Reference Sequence
-        target.insert(DicomTag(0x0028, 0x0303));   // Longitudinal Temporal Information Modified 
-
-        // Table C.12-6 "DIGITAL SIGNATURES MACRO ATTRIBUTES" (p. 1216)
-        target.insert(DicomTag(0x4ffe, 0x0001));   // MAC Parameters sequence
-        target.insert(DicomTag(0xfffa, 0xfffa));   // Digital signatures sequence
-        break;
-
-        // TODO IMAGE MODULE?
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomTag.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 <string>
-#include <set>
-#include <stdint.h>
-
-#include "../Enumerations.h"
-
-namespace Orthanc
-{
-  class DicomTag
-  {
-    // This must stay a POD (plain old data structure) 
-
-  private:
-    uint16_t group_;
-    uint16_t element_;
-
-  public:
-    DicomTag(uint16_t group,
-             uint16_t element) :
-      group_(group),
-      element_(element)
-    {
-    }
-
-    uint16_t GetGroup() const
-    {
-      return group_;
-    }
-
-    uint16_t GetElement() const
-    {
-      return element_;
-    }
-
-    bool IsPrivate() const
-    {
-      return group_ % 2 == 1;
-    }
-
-    const char* GetMainTagsName() const;
-
-    bool operator< (const DicomTag& other) const;
-
-    bool operator== (const DicomTag& other) const
-    {
-      return group_ == other.group_ && element_ == other.element_;
-    }
-
-    bool operator!= (const DicomTag& other) const
-    {
-      return !(*this == other);
-    }
-
-    std::string Format() const;
-
-    friend std::ostream& operator<< (std::ostream& o, const DicomTag& tag);
-
-    static void AddTagsForModule(std::set<DicomTag>& target,
-                                 DicomModule module);
-  };
-
-  // Aliases for the most useful tags
-  static const DicomTag DICOM_TAG_ACCESSION_NUMBER(0x0008, 0x0050);
-  static const DicomTag DICOM_TAG_SOP_INSTANCE_UID(0x0008, 0x0018);
-  static const DicomTag DICOM_TAG_PATIENT_ID(0x0010, 0x0020);
-  static const DicomTag DICOM_TAG_SERIES_INSTANCE_UID(0x0020, 0x000e);
-  static const DicomTag DICOM_TAG_STUDY_INSTANCE_UID(0x0020, 0x000d);
-  static const DicomTag DICOM_TAG_PIXEL_DATA(0x7fe0, 0x0010);
-  static const DicomTag DICOM_TAG_TRANSFER_SYNTAX_UID(0x0002, 0x0010);
-
-  static const DicomTag DICOM_TAG_IMAGE_INDEX(0x0054, 0x1330);
-  static const DicomTag DICOM_TAG_INSTANCE_NUMBER(0x0020, 0x0013);
-
-  static const DicomTag DICOM_TAG_NUMBER_OF_SLICES(0x0054, 0x0081);
-  static const DicomTag DICOM_TAG_NUMBER_OF_TIME_SLICES(0x0054, 0x0101);
-  static const DicomTag DICOM_TAG_NUMBER_OF_FRAMES(0x0028, 0x0008);
-  static const DicomTag DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES(0x0018, 0x1090);
-  static const DicomTag DICOM_TAG_IMAGES_IN_ACQUISITION(0x0020, 0x1002);
-  static const DicomTag DICOM_TAG_PATIENT_NAME(0x0010, 0x0010);
-  static const DicomTag DICOM_TAG_ENCAPSULATED_DOCUMENT(0x0042, 0x0011);
-
-  static const DicomTag DICOM_TAG_STUDY_DESCRIPTION(0x0008, 0x1030);
-  static const DicomTag DICOM_TAG_SERIES_DESCRIPTION(0x0008, 0x103e);
-  static const DicomTag DICOM_TAG_MODALITY(0x0008, 0x0060);
-
-  // The following is used for "modify/anonymize" operations
-  static const DicomTag DICOM_TAG_SOP_CLASS_UID(0x0008, 0x0016);
-  static const DicomTag DICOM_TAG_MEDIA_STORAGE_SOP_CLASS_UID(0x0002, 0x0002);
-  static const DicomTag DICOM_TAG_MEDIA_STORAGE_SOP_INSTANCE_UID(0x0002, 0x0003);
-  static const DicomTag DICOM_TAG_DEIDENTIFICATION_METHOD(0x0012, 0x0063);
-
-  // DICOM tags used for fMRI (thanks to Will Ryder)
-  static const DicomTag DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS(0x0020, 0x0105);
-  static const DicomTag DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER(0x0020, 0x0100);
-
-  // Tags for C-FIND and C-MOVE
-  static const DicomTag DICOM_TAG_MESSAGE_ID(0x0000, 0x0110);
-  static const DicomTag DICOM_TAG_SPECIFIC_CHARACTER_SET(0x0008, 0x0005);
-  static const DicomTag DICOM_TAG_QUERY_RETRIEVE_LEVEL(0x0008, 0x0052);
-  static const DicomTag DICOM_TAG_MODALITIES_IN_STUDY(0x0008, 0x0061);
-
-  // Tags for images
-  static const DicomTag DICOM_TAG_COLUMNS(0x0028, 0x0011);
-  static const DicomTag DICOM_TAG_ROWS(0x0028, 0x0010);
-  static const DicomTag DICOM_TAG_SAMPLES_PER_PIXEL(0x0028, 0x0002);
-  static const DicomTag DICOM_TAG_BITS_ALLOCATED(0x0028, 0x0100);
-  static const DicomTag DICOM_TAG_BITS_STORED(0x0028, 0x0101);
-  static const DicomTag DICOM_TAG_HIGH_BIT(0x0028, 0x0102);
-  static const DicomTag DICOM_TAG_PIXEL_REPRESENTATION(0x0028, 0x0103);
-  static const DicomTag DICOM_TAG_PLANAR_CONFIGURATION(0x0028, 0x0006);
-  static const DicomTag DICOM_TAG_PHOTOMETRIC_INTERPRETATION(0x0028, 0x0004);
-  static const DicomTag DICOM_TAG_IMAGE_ORIENTATION_PATIENT(0x0020, 0x0037);
-  static const DicomTag DICOM_TAG_IMAGE_POSITION_PATIENT(0x0020, 0x0032);
-
-  // Tags related to date and time
-  static const DicomTag DICOM_TAG_ACQUISITION_DATE(0x0008, 0x0022);
-  static const DicomTag DICOM_TAG_ACQUISITION_TIME(0x0008, 0x0032);
-  static const DicomTag DICOM_TAG_CONTENT_DATE(0x0008, 0x0023);
-  static const DicomTag DICOM_TAG_CONTENT_TIME(0x0008, 0x0033);
-  static const DicomTag DICOM_TAG_INSTANCE_CREATION_DATE(0x0008, 0x0012);
-  static const DicomTag DICOM_TAG_INSTANCE_CREATION_TIME(0x0008, 0x0013);
-  static const DicomTag DICOM_TAG_PATIENT_BIRTH_DATE(0x0010, 0x0030);
-  static const DicomTag DICOM_TAG_PATIENT_BIRTH_TIME(0x0010, 0x0032);
-  static const DicomTag DICOM_TAG_SERIES_DATE(0x0008, 0x0021);
-  static const DicomTag DICOM_TAG_SERIES_TIME(0x0008, 0x0031);
-  static const DicomTag DICOM_TAG_STUDY_DATE(0x0008, 0x0020);
-  static const DicomTag DICOM_TAG_STUDY_TIME(0x0008, 0x0030);
-
-  // Various tags
-  static const DicomTag DICOM_TAG_SERIES_TYPE(0x0054, 0x1000);
-  static const DicomTag DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION(0x0032, 0x1060);
-  static const DicomTag DICOM_TAG_INSTITUTION_NAME(0x0008, 0x0080);
-  static const DicomTag DICOM_TAG_REQUESTING_PHYSICIAN(0x0032, 0x1032);
-  static const DicomTag DICOM_TAG_REFERRING_PHYSICIAN_NAME(0x0008, 0x0090);
-  static const DicomTag DICOM_TAG_OPERATOR_NAME(0x0008, 0x1070);
-  static const DicomTag DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION(0x0040, 0x0254);
-  static const DicomTag DICOM_TAG_IMAGE_COMMENTS(0x0020, 0x4000);
-  static const DicomTag DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION(0x0018, 0x1400);
-  static const DicomTag DICOM_TAG_CONTRAST_BOLUS_AGENT(0x0018, 0x0010);
-
-  // Tags used within the Stone of Orthanc
-  static const DicomTag DICOM_TAG_FRAME_INCREMENT_POINTER(0x0028, 0x0009);
-  static const DicomTag DICOM_TAG_GRID_FRAME_OFFSET_VECTOR(0x3004, 0x000c);
-  static const DicomTag DICOM_TAG_PIXEL_SPACING(0x0028, 0x0030);
-  static const DicomTag DICOM_TAG_RESCALE_INTERCEPT(0x0028, 0x1052);
-  static const DicomTag DICOM_TAG_RESCALE_SLOPE(0x0028, 0x1053);
-  static const DicomTag DICOM_TAG_SLICE_THICKNESS(0x0018, 0x0050);
-  static const DicomTag DICOM_TAG_WINDOW_CENTER(0x0028, 0x1050);
-  static const DicomTag DICOM_TAG_WINDOW_WIDTH(0x0028, 0x1051);
-  static const DicomTag DICOM_TAG_DOSE_GRID_SCALING(0x3004, 0x000e);
-                                    
-  // Counting patients, studies and series
-  // https://www.medicalconnections.co.uk/kb/Counting_Studies_Series_and_Instances
-  static const DicomTag DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES(0x0020, 0x1200);  
-  static const DicomTag DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES(0x0020, 0x1202);  
-  static const DicomTag DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES(0x0020, 0x1204);  
-  static const DicomTag DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES(0x0020, 0x1206);  
-  static const DicomTag DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES(0x0020, 0x1208);  
-  static const DicomTag DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES(0x0020, 0x1209);  
-  static const DicomTag DICOM_TAG_SOP_CLASSES_IN_STUDY(0x0008, 0x0062);  
-
-  // Tags to preserve relationships during anonymization
-  static const DicomTag DICOM_TAG_REFERENCED_IMAGE_SEQUENCE(0x0008, 0x1140);
-  static const DicomTag DICOM_TAG_REFERENCED_SOP_INSTANCE_UID(0x0008, 0x1155);
-  static const DicomTag DICOM_TAG_SOURCE_IMAGE_SEQUENCE(0x0008, 0x2112);
-  static const DicomTag DICOM_TAG_FRAME_OF_REFERENCE_UID(0x0020, 0x0052);
-  static const DicomTag DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_UID(0x3006, 0x0024);
-  static const DicomTag DICOM_TAG_RELATED_FRAME_OF_REFERENCE_UID(0x3006, 0x00c2);
-  static const DicomTag DICOM_TAG_CURRENT_REQUESTED_PROCEDURE_EVIDENCE_SEQUENCE(0x0040, 0xa375);
-  static const DicomTag DICOM_TAG_REFERENCED_SERIES_SEQUENCE(0x0008, 0x1115);
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomValue.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomValue.h"
-
-#include "../OrthancException.h"
-#include "../Toolbox.h"
-
-#include <boost/lexical_cast.hpp>
-
-namespace Orthanc
-{
-  DicomValue::DicomValue(const DicomValue& other) : 
-    type_(other.type_),
-    content_(other.content_)
-  {
-  }
-
-
-  DicomValue::DicomValue(const std::string& content,
-                         bool isBinary) :
-    type_(isBinary ? Type_Binary : Type_String),
-    content_(content)
-  {
-  }
-  
-  
-  DicomValue::DicomValue(const char* data,
-                         size_t size,
-                         bool isBinary) :
-    type_(isBinary ? Type_Binary : Type_String)
-  {
-    content_.assign(data, size);
-  }
-    
-  
-  const std::string& DicomValue::GetContent() const
-  {
-    if (type_ == Type_Null)
-    {
-      throw OrthancException(ErrorCode_BadParameterType);
-    }
-    else
-    {
-      return content_;
-    }
-  }
-
-
-  DicomValue* DicomValue::Clone() const
-  {
-    return new DicomValue(*this);
-  }
-
-  
-#if ORTHANC_ENABLE_BASE64 == 1
-  void DicomValue::FormatDataUriScheme(std::string& target,
-                                       const std::string& mime) const
-  {
-    Toolbox::EncodeBase64(target, GetContent());
-    target.insert(0, "data:" + mime + ";base64,");
-  }
-#endif
-
-
-  template <typename T,
-            bool allowSigned>
-  static bool ParseValue(T& result,
-                         const DicomValue& source)
-  {
-    if (source.IsBinary() ||
-        source.IsNull())
-    {
-      return false;
-    }
-    
-    try
-    {
-      std::string value = Toolbox::StripSpaces(source.GetContent());
-      if (value.empty())
-      {
-        return false;
-      }
-
-      if (!allowSigned &&
-          value[0] == '-')
-      {
-        return false;
-      }
-      
-      result = boost::lexical_cast<T>(value);
-      return true;
-    }
-    catch (boost::bad_lexical_cast&)
-    {
-      return false;
-    }
-  }
-
-  bool DicomValue::ParseInteger32(int32_t& result) const
-  {
-    int64_t tmp;
-    if (ParseValue<int64_t, true>(tmp, *this))
-    {
-      result = static_cast<int32_t>(tmp);
-      return (tmp == static_cast<int64_t>(result));  // Check no overflow occurs
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-  bool DicomValue::ParseInteger64(int64_t& result) const
-  {
-    return ParseValue<int64_t, true>(result, *this);
-  }
-
-  bool DicomValue::ParseUnsignedInteger32(uint32_t& result) const
-  {
-    uint64_t tmp;
-    if (ParseValue<uint64_t, false>(tmp, *this))
-    {
-      result = static_cast<uint32_t>(tmp);
-      return (tmp == static_cast<uint64_t>(result));  // Check no overflow occurs
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-  bool DicomValue::ParseUnsignedInteger64(uint64_t& result) const
-  {
-    return ParseValue<uint64_t, false>(result, *this);
-  }
-
-  bool DicomValue::ParseFloat(float& result) const
-  {
-    return ParseValue<float, true>(result, *this);
-  }
-
-  bool DicomValue::ParseDouble(double& result) const
-  {
-    return ParseValue<double, true>(result, *this);
-  }
-
-  bool DicomValue::CopyToString(std::string& result,
-                                bool allowBinary) const
-  {
-    if (IsNull())
-    {
-      return false;
-    }
-    else if (IsBinary() && !allowBinary)
-    {
-      return false;
-    }
-    else
-    {
-      result.assign(content_);
-      return true;
-    }
-  }    
-}
--- a/Resources/Orthanc/Core/DicomFormat/DicomValue.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 <boost/noncopyable.hpp>
-
-#if !defined(ORTHANC_ENABLE_BASE64)
-#  error The macro ORTHANC_ENABLE_BASE64 must be defined
-#endif
-
-
-namespace Orthanc
-{
-  class DicomValue : public boost::noncopyable
-  {
-  private:
-    enum Type
-    {
-      Type_Null,
-      Type_String,
-      Type_Binary
-    };
-
-    Type         type_;
-    std::string  content_;
-
-    DicomValue(const DicomValue& other);
-
-  public:
-    DicomValue() : type_(Type_Null)
-    {
-    }
-    
-    DicomValue(const std::string& content,
-               bool isBinary);
-    
-    DicomValue(const char* data,
-               size_t size,
-               bool isBinary);
-    
-    const std::string& GetContent() const;
-
-    bool IsNull() const
-    {
-      return type_ == Type_Null;
-    }
-
-    bool IsBinary() const
-    {
-      return type_ == Type_Binary;
-    }
-    
-    DicomValue* Clone() const;
-
-#if ORTHANC_ENABLE_BASE64 == 1
-    void FormatDataUriScheme(std::string& target,
-                             const std::string& mime) const;
-
-    void FormatDataUriScheme(std::string& target) const
-    {
-      FormatDataUriScheme(target, "application/octet-stream");
-    }
-#endif
-
-    bool CopyToString(std::string& result,
-                      bool allowBinary) const;
-    
-    bool ParseInteger32(int32_t& result) const;
-
-    bool ParseInteger64(int64_t& result) const;                                
-
-    bool ParseUnsignedInteger32(uint32_t& result) const;
-
-    bool ParseUnsignedInteger64(uint64_t& result) const;                                
-
-    bool ParseFloat(float& result) const;                                
-
-    bool ParseDouble(double& result) const;                                
-  };
-}
--- a/Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2432 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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"
-
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-
-#if !defined(ORTHANC_SANDBOXED)
-#  error The macro ORTHANC_SANDBOXED must be defined
-#endif
-
-#include "FromDcmtkBridge.h"
-#include "ToDcmtkBridge.h"
-#include "../Logging.h"
-#include "../Toolbox.h"
-#include "../OrthancException.h"
-
-#if ORTHANC_SANDBOXED == 0
-#  include "../TemporaryFile.h"
-#endif
-
-#include <list>
-#include <limits>
-
-#include <boost/lexical_cast.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/algorithm/string/predicate.hpp>
-
-#include <dcmtk/dcmdata/dcdeftag.h>
-#include <dcmtk/dcmdata/dcdicent.h>
-#include <dcmtk/dcmdata/dcdict.h>
-#include <dcmtk/dcmdata/dcfilefo.h>
-#include <dcmtk/dcmdata/dcostrmb.h>
-#include <dcmtk/dcmdata/dcpixel.h>
-#include <dcmtk/dcmdata/dcuid.h>
-#include <dcmtk/dcmdata/dcistrmb.h>
-
-#include <dcmtk/dcmdata/dcvrae.h>
-#include <dcmtk/dcmdata/dcvras.h>
-#include <dcmtk/dcmdata/dcvrat.h>
-#include <dcmtk/dcmdata/dcvrcs.h>
-#include <dcmtk/dcmdata/dcvrda.h>
-#include <dcmtk/dcmdata/dcvrds.h>
-#include <dcmtk/dcmdata/dcvrdt.h>
-#include <dcmtk/dcmdata/dcvrfd.h>
-#include <dcmtk/dcmdata/dcvrfl.h>
-#include <dcmtk/dcmdata/dcvris.h>
-#include <dcmtk/dcmdata/dcvrlo.h>
-#include <dcmtk/dcmdata/dcvrlt.h>
-#include <dcmtk/dcmdata/dcvrpn.h>
-#include <dcmtk/dcmdata/dcvrsh.h>
-#include <dcmtk/dcmdata/dcvrsl.h>
-#include <dcmtk/dcmdata/dcvrss.h>
-#include <dcmtk/dcmdata/dcvrst.h>
-#include <dcmtk/dcmdata/dcvrtm.h>
-#include <dcmtk/dcmdata/dcvrui.h>
-#include <dcmtk/dcmdata/dcvrul.h>
-#include <dcmtk/dcmdata/dcvrus.h>
-#include <dcmtk/dcmdata/dcvrut.h>
-
-#if DCMTK_USE_EMBEDDED_DICTIONARIES == 1
-#  include <EmbeddedResources.h>
-#endif
-
-#if ORTHANC_ENABLE_DCMTK_JPEG == 1
-#  include <dcmtk/dcmjpeg/djdecode.h>
-#endif
-
-#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
-#  include <dcmtk/dcmjpls/djdecode.h>
-#endif
-
-
-namespace Orthanc
-{
-  static inline uint16_t GetCharValue(char c)
-  {
-    if (c >= '0' && c <= '9')
-      return c - '0';
-    else if (c >= 'a' && c <= 'f')
-      return c - 'a' + 10;
-    else if (c >= 'A' && c <= 'F')
-      return c - 'A' + 10;
-    else
-      return 0;
-  }
-
-  static inline uint16_t GetTagValue(const char* c)
-  {
-    return ((GetCharValue(c[0]) << 12) + 
-            (GetCharValue(c[1]) << 8) + 
-            (GetCharValue(c[2]) << 4) + 
-            GetCharValue(c[3]));
-  }
-
-
-#if DCMTK_USE_EMBEDDED_DICTIONARIES == 1
-  static void LoadEmbeddedDictionary(DcmDataDictionary& dictionary,
-                                     EmbeddedResources::FileResourceId resource)
-  {
-    std::string content;
-    EmbeddedResources::GetFileResource(content, resource);
-
-#if ORTHANC_SANDBOXED == 0
-    TemporaryFile tmp;
-    tmp.Write(content);
-
-    if (!dictionary.loadDictionary(tmp.GetPath().c_str()))
-    {
-      LOG(ERROR) << "Cannot read embedded dictionary. Under Windows, make sure that " 
-                 << "your TEMP directory does not contain special characters.";
-      throw OrthancException(ErrorCode_InternalError);
-    }
-#else
-    if (!dictionary.loadFromMemory(content))
-    {
-      LOG(ERROR) << "Cannot read embedded dictionary. Under Windows, make sure that " 
-                 << "your TEMP directory does not contain special characters.";
-      throw OrthancException(ErrorCode_InternalError);
-    }
-#endif
-  }
-                             
-#else
-  static void LoadExternalDictionary(DcmDataDictionary& dictionary,
-                                     const std::string& directory,
-                                     const std::string& filename)
-  {
-    boost::filesystem::path p = directory;
-    p = p / filename;
-
-    LOG(WARNING) << "Loading the external DICOM dictionary " << p;
-
-    if (!dictionary.loadDictionary(p.string().c_str()))
-    {
-      throw OrthancException(ErrorCode_InternalError);
-    }
-  }
-#endif
-
-
-  namespace
-  {
-    class DictionaryLocker
-    {
-    private:
-      DcmDataDictionary& dictionary_;
-
-    public:
-      DictionaryLocker() : dictionary_(dcmDataDict.wrlock())
-      {
-      }
-
-      ~DictionaryLocker()
-      {
-        dcmDataDict.unlock();
-      }
-
-      DcmDataDictionary& operator*()
-      {
-        return dictionary_;
-      }
-
-      DcmDataDictionary* operator->()
-      {
-        return &dictionary_;
-      }
-    };
-  }
-
-
-  void FromDcmtkBridge::InitializeDictionary(bool loadPrivateDictionary)
-  {
-    LOG(INFO) << "Using DCTMK version: " << DCMTK_VERSION_NUMBER;
-    
-    {
-      DictionaryLocker locker;
-
-      locker->clear();
-
-#if DCMTK_USE_EMBEDDED_DICTIONARIES == 1
-      LOG(WARNING) << "Loading the embedded dictionaries";
-      /**
-       * Do not load DICONDE dictionary, it breaks the other tags. The
-       * command "strace storescu 2>&1 |grep dic" shows that DICONDE
-       * dictionary is not loaded by storescu.
-       **/
-      //LoadEmbeddedDictionary(*locker, EmbeddedResources::DICTIONARY_DICONDE);
-
-      LoadEmbeddedDictionary(*locker, EmbeddedResources::DICTIONARY_DICOM);
-
-      if (loadPrivateDictionary)
-      {
-        LOG(INFO) << "Loading the embedded dictionary of private tags";
-        LoadEmbeddedDictionary(*locker, EmbeddedResources::DICTIONARY_PRIVATE);
-      }
-      else
-      {
-        LOG(INFO) << "The dictionary of private tags has not been loaded";
-      }
-
-#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-      std::string path = DCMTK_DICTIONARY_DIR;
-
-      const char* env = std::getenv(DCM_DICT_ENVIRONMENT_VARIABLE);
-      if (env != NULL)
-      {
-        path = std::string(env);
-      }
-
-      LoadExternalDictionary(*locker, path, "dicom.dic");
-
-      if (loadPrivateDictionary)
-      {
-        LoadExternalDictionary(*locker, path, "private.dic");
-      }
-      else
-      {
-        LOG(INFO) << "The dictionary of private tags has not been loaded";
-      }
-
-#else
-#error Support your platform here
-#endif
-    }
-
-    /* make sure data dictionary is loaded */
-    if (!dcmDataDict.isDictionaryLoaded())
-    {
-      LOG(ERROR) << "No DICOM dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE;
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-    {
-      // Test the dictionary with a simple DICOM tag
-      DcmTag key(0x0010, 0x1030); // This is PatientWeight
-      if (key.getEVR() != EVR_DS)
-      {
-        LOG(ERROR) << "The DICOM dictionary has not been correctly read";
-        throw OrthancException(ErrorCode_InternalError);
-      }
-    }
-  }
-
-
-  void FromDcmtkBridge::RegisterDictionaryTag(const DicomTag& tag,
-                                              ValueRepresentation vr,
-                                              const std::string& name,
-                                              unsigned int minMultiplicity,
-                                              unsigned int maxMultiplicity,
-                                              const std::string& privateCreator)
-  {
-    if (minMultiplicity < 1)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    bool arbitrary = false;
-    if (maxMultiplicity == 0)
-    {
-      maxMultiplicity = DcmVariableVM;
-      arbitrary = true;
-    }
-    else if (maxMultiplicity < minMultiplicity)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-    
-    DcmEVR evr = ToDcmtkBridge::Convert(vr);
-
-    LOG(INFO) << "Registering tag in dictionary: " << tag << " " << (DcmVR(evr).getValidVRName()) << " " 
-              << name << " (multiplicity: " << minMultiplicity << "-" 
-              << (arbitrary ? "n" : boost::lexical_cast<std::string>(maxMultiplicity)) << ")";
-
-    std::auto_ptr<DcmDictEntry>  entry;
-    if (privateCreator.empty())
-    {
-      if (tag.GetGroup() % 2 == 1)
-      {
-        char buf[128];
-        sprintf(buf, "Warning: You are registering a private tag (%04x,%04x), "
-                "but no private creator was associated with it", 
-                tag.GetGroup(), tag.GetElement());
-        LOG(WARNING) << buf;
-      }
-
-      entry.reset(new DcmDictEntry(tag.GetGroup(),
-                                   tag.GetElement(),
-                                   evr, name.c_str(),
-                                   static_cast<int>(minMultiplicity),
-                                   static_cast<int>(maxMultiplicity),
-                                   NULL    /* version */,
-                                   OFTrue  /* doCopyString */,
-                                   NULL    /* private creator */));
-    }
-    else
-    {
-      // "Private Data Elements have an odd Group Number that is not
-      // (0001,eeee), (0003,eeee), (0005,eeee), (0007,eeee), or
-      // (FFFF,eeee)."
-      if (tag.GetGroup() % 2 == 0 /* even */ ||
-          tag.GetGroup() == 0x0001 ||
-          tag.GetGroup() == 0x0003 ||
-          tag.GetGroup() == 0x0005 ||
-          tag.GetGroup() == 0x0007 ||
-          tag.GetGroup() == 0xffff)
-      {
-        char buf[128];
-        sprintf(buf, "Trying to register private tag (%04x,%04x), but it must have an odd group >= 0x0009",
-                tag.GetGroup(), tag.GetElement());
-        LOG(ERROR) << buf;
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-      }
-
-      entry.reset(new DcmDictEntry(tag.GetGroup(),
-                                   tag.GetElement(),
-                                   evr, name.c_str(),
-                                   static_cast<int>(minMultiplicity),
-                                   static_cast<int>(maxMultiplicity),
-                                   "private" /* version */,
-                                   OFTrue    /* doCopyString */,
-                                   privateCreator.c_str()));
-    }
-
-    entry->setGroupRangeRestriction(DcmDictRange_Unspecified);
-    entry->setElementRangeRestriction(DcmDictRange_Unspecified);
-
-    {
-      DictionaryLocker locker;
-
-      if (locker->findEntry(name.c_str()))
-      {
-        LOG(ERROR) << "Cannot register two tags with the same symbolic name \"" << name << "\"";
-        throw OrthancException(ErrorCode_AlreadyExistingTag);
-      }
-
-      locker->addEntry(entry.release());
-    }
-  }
-
-
-  Encoding FromDcmtkBridge::DetectEncoding(DcmItem& dataset,
-                                           Encoding defaultEncoding)
-  {
-    Encoding encoding = defaultEncoding;
-
-    OFString tmp;
-    if (dataset.findAndGetOFString(DCM_SpecificCharacterSet, tmp).good())
-    {
-      std::string characterSet = Toolbox::StripSpaces(std::string(tmp.c_str()));
-
-      if (characterSet.empty())
-      {
-        // Empty specific character set tag: Use the default encoding
-      }
-      else if (GetDicomEncoding(encoding, characterSet.c_str()))
-      {
-        // The specific character set is supported by the Orthanc core
-      }
-      else
-      {
-        LOG(WARNING) << "Value of Specific Character Set (0008,0005) is not supported: " << characterSet
-                     << ", fallback to ASCII (remove all special characters)";
-        encoding = Encoding_Ascii;
-      }
-    }
-    else
-    {
-      // No specific character set tag: Use the default encoding
-    }
-
-    return encoding;
-  }
-
-
-  void FromDcmtkBridge::ExtractDicomSummary(DicomMap& target, 
-                                            DcmItem& dataset,
-                                            unsigned int maxStringLength,
-                                            Encoding defaultEncoding)
-  {
-    std::set<DicomTag> ignoreTagLength;
-    
-    Encoding encoding = DetectEncoding(dataset, defaultEncoding);
-
-    target.Clear();
-    for (unsigned long i = 0; i < dataset.card(); i++)
-    {
-      DcmElement* element = dataset.getElement(i);
-      if (element && element->isLeaf())
-      {
-        target.SetValue(element->getTag().getGTag(),
-                        element->getTag().getETag(),
-                        ConvertLeafElement(*element, DicomToJsonFlags_Default,
-                                           maxStringLength, encoding, ignoreTagLength));
-      }
-    }
-  }
-
-
-  DicomTag FromDcmtkBridge::Convert(const DcmTag& tag)
-  {
-    return DicomTag(tag.getGTag(), tag.getETag());
-  }
-
-
-  DicomTag FromDcmtkBridge::GetTag(const DcmElement& element)
-  {
-    return DicomTag(element.getGTag(), element.getETag());
-  }
-
-
-  DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element,
-                                                  DicomToJsonFlags flags,
-                                                  unsigned int maxStringLength,
-                                                  Encoding encoding,
-                                                  const std::set<DicomTag>& ignoreTagLength)
-  {
-    if (!element.isLeaf())
-    {
-      // This function is only applicable to leaf elements
-      throw OrthancException(ErrorCode_BadParameterType);
-    }
-
-    char *c = NULL;
-    if (element.isaString() &&
-        element.getString(c).good())
-    {
-      if (c == NULL)  // This case corresponds to the empty string
-      {
-        return new DicomValue("", false);
-      }
-      else
-      {
-        std::string s(c);
-        std::string utf8 = Toolbox::ConvertToUtf8(s, encoding);
-
-        if (maxStringLength != 0 &&
-            utf8.size() > maxStringLength &&
-            ignoreTagLength.find(GetTag(element)) == ignoreTagLength.end())
-        {
-          return new DicomValue;  // Too long, create a NULL value
-        }
-        else
-        {
-          return new DicomValue(utf8, false);
-        }
-      }
-    }
-
-
-    if (element.getVR() == EVR_UN)
-    {
-      // Unknown value representation: Lookup in the dictionary. This
-      // is notably the case for private tags registered with the
-      // "Dictionary" configuration option.
-      DictionaryLocker locker;
-      
-      const DcmDictEntry* entry = locker->findEntry(element.getTag().getXTag(), 
-                                                    element.getTag().getPrivateCreator());
-      if (entry != NULL && 
-          entry->getVR().isaString())
-      {
-        Uint8* data = NULL;
-
-        // At (*), we do not try and convert to UTF-8, as nothing says
-        // the encoding of the private tag is the same as that of the
-        // remaining of the DICOM dataset. Only go for ASCII strings.
-
-        if (element.getUint8Array(data) == EC_Normal &&
-            Toolbox::IsAsciiString(data, element.getLength()))   // (*)
-        {
-          if (data == NULL)
-          {
-            return new DicomValue("", false);   // Empty string
-          }
-          else if (maxStringLength != 0 &&
-                   element.getLength() > maxStringLength &&
-                   ignoreTagLength.find(GetTag(element)) == ignoreTagLength.end())
-          {
-            return new DicomValue;  // Too long, create a NULL value
-          }
-          else
-          {
-            std::string s(reinterpret_cast<const char*>(data), element.getLength());
-            return new DicomValue(s, false);
-          }
-        }
-      }
-    }
-
-    
-    try
-    {
-      // http://support.dcmtk.org/docs/dcvr_8h-source.html
-      switch (element.getVR())
-      {
-
-        /**
-         * Deal with binary data (including PixelData).
-         **/
-
-        case EVR_OB:  // other byte
-        case EVR_OF:  // other float
-        case EVR_OW:  // other word
-        case EVR_UN:  // unknown value representation
-        case EVR_ox:  // OB or OW depending on context
-        case EVR_DS:  // decimal string
-        case EVR_IS:  // integer string
-        case EVR_AS:  // age string
-        case EVR_DA:  // date string
-        case EVR_DT:  // date time string
-        case EVR_TM:  // time string
-        case EVR_AE:  // application entity title
-        case EVR_CS:  // code string
-        case EVR_SH:  // short string
-        case EVR_LO:  // long string
-        case EVR_ST:  // short text
-        case EVR_LT:  // long text
-        case EVR_UT:  // unlimited text
-        case EVR_PN:  // person name
-        case EVR_UI:  // unique identifier
-        case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
-        case EVR_UNKNOWN2B:  // used internally for elements with unknown VR with 2-byte length field in explicit VR
-        {
-          if (!(flags & DicomToJsonFlags_ConvertBinaryToNull))
-          {
-            Uint8* data = NULL;
-            if (element.getUint8Array(data) == EC_Normal)
-            {
-              return new DicomValue(reinterpret_cast<const char*>(data), element.getLength(), true);
-            }
-          }
-
-          return new DicomValue;
-        }
-    
-        /**
-         * Numeric types
-         **/ 
-      
-        case EVR_SL:  // signed long
-        {
-          Sint32 f;
-          if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
-        }
-
-        case EVR_SS:  // signed short
-        {
-          Sint16 f;
-          if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
-        }
-
-        case EVR_UL:  // unsigned long
-        {
-          Uint32 f;
-          if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
-        }
-
-        case EVR_US:  // unsigned short
-        {
-          Uint16 f;
-          if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
-        }
-
-        case EVR_FL:  // float single-precision
-        {
-          Float32 f;
-          if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
-        }
-
-        case EVR_FD:  // float double-precision
-        {
-          Float64 f;
-          if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good())
-            return new DicomValue(boost::lexical_cast<std::string>(f), false);
-          else
-            return new DicomValue;
-        }
-
-
-        /**
-         * Attribute tag.
-         **/
-
-        case EVR_AT:
-        {
-          DcmTagKey tag;
-          if (dynamic_cast<DcmAttributeTag&>(element).getTagVal(tag, 0).good())
-          {
-            DicomTag t(tag.getGroup(), tag.getElement());
-            return new DicomValue(t.Format(), false);
-          }
-          else
-          {
-            return new DicomValue;
-          }
-        }
-
-
-        /**
-         * Sequence types, should never occur at this point because of
-         * "element.isLeaf()".
-         **/
-
-        case EVR_SQ:  // sequence of items
-          return new DicomValue;
-
-
-          /**
-           * Internal to DCMTK.
-           **/ 
-
-        case EVR_xs:  // SS or US depending on context
-        case EVR_lt:  // US, SS or OW depending on context, used for LUT Data (thus the name)
-        case EVR_na:  // na="not applicable", for data which has no VR
-        case EVR_up:  // up="unsigned pointer", used internally for DICOMDIR suppor
-        case EVR_item:  // used internally for items
-        case EVR_metainfo:  // used internally for meta info datasets
-        case EVR_dataset:  // used internally for datasets
-        case EVR_fileFormat:  // used internally for DICOM files
-        case EVR_dicomDir:  // used internally for DICOMDIR objects
-        case EVR_dirRecord:  // used internally for DICOMDIR records
-        case EVR_pixelSQ:  // used internally for pixel sequences in a compressed image
-        case EVR_pixelItem:  // used internally for pixel items in a compressed image
-        case EVR_PixelData:  // used internally for uncompressed pixeld data
-        case EVR_OverlayData:  // used internally for overlay data
-          return new DicomValue;
-
-
-          /**
-           * Default case.
-           **/ 
-
-        default:
-          return new DicomValue;
-      }
-    }
-    catch (boost::bad_lexical_cast&)
-    {
-      return new DicomValue;
-    }
-    catch (std::bad_cast&)
-    {
-      return new DicomValue;
-    }
-  }
-
-
-  static Json::Value& PrepareNode(Json::Value& parent,
-                                  DcmElement& element,
-                                  DicomToJsonFormat format)
-  {
-    assert(parent.type() == Json::objectValue);
-
-    DicomTag tag(FromDcmtkBridge::GetTag(element));
-    const std::string formattedTag = tag.Format();
-
-    if (format == DicomToJsonFormat_Short)
-    {
-      parent[formattedTag] = Json::nullValue;
-      return parent[formattedTag];
-    }
-
-    // This code gives access to the name of the private tags
-    std::string tagName = FromDcmtkBridge::GetTagName(element);
-    
-    switch (format)
-    {
-      case DicomToJsonFormat_Human:
-        parent[tagName] = Json::nullValue;
-        return parent[tagName];
-
-      case DicomToJsonFormat_Full:
-      {
-        parent[formattedTag] = Json::objectValue;
-        Json::Value& node = parent[formattedTag];
-
-        if (element.isLeaf())
-        {
-          node["Name"] = tagName;
-
-          if (element.getTag().getPrivateCreator() != NULL)
-          {
-            node["PrivateCreator"] = element.getTag().getPrivateCreator();
-          }
-
-          return node;
-        }
-        else
-        {
-          node["Name"] = tagName;
-          node["Type"] = "Sequence";
-          node["Value"] = Json::nullValue;
-          return node["Value"];
-        }
-      }
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  static void LeafValueToJson(Json::Value& target,
-                              const DicomValue& value,
-                              DicomToJsonFormat format,
-                              DicomToJsonFlags flags,
-                              unsigned int maxStringLength)
-  {
-    Json::Value* targetValue = NULL;
-    Json::Value* targetType = NULL;
-
-    switch (format)
-    {
-      case DicomToJsonFormat_Short:
-      case DicomToJsonFormat_Human:
-      {
-        assert(target.type() == Json::nullValue);
-        targetValue = &target;
-        break;
-      }      
-
-      case DicomToJsonFormat_Full:
-      {
-        assert(target.type() == Json::objectValue);
-        target["Value"] = Json::nullValue;
-        target["Type"] = Json::nullValue;
-        targetType = &target["Type"];
-        targetValue = &target["Value"];
-        break;
-      }
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    assert(targetValue != NULL);
-    assert(targetValue->type() == Json::nullValue);
-    assert(targetType == NULL || targetType->type() == Json::nullValue);
-
-    if (value.IsNull())
-    {
-      if (targetType != NULL)
-      {
-        *targetType = "Null";
-      }
-    }
-    else if (value.IsBinary())
-    {
-      if (flags & DicomToJsonFlags_ConvertBinaryToAscii)
-      {
-        *targetValue = Toolbox::ConvertToAscii(value.GetContent());
-      }
-      else
-      {
-        std::string s;
-        value.FormatDataUriScheme(s);
-        *targetValue = s;
-      }
-
-      if (targetType != NULL)
-      {
-        *targetType = "Binary";
-      }
-    }
-    else if (maxStringLength == 0 ||
-             value.GetContent().size() <= maxStringLength)
-    {
-      *targetValue = value.GetContent();
-
-      if (targetType != NULL)
-      {
-        *targetType = "String";
-      }
-    }
-    else
-    {
-      if (targetType != NULL)
-      {
-        *targetType = "TooLong";
-      }
-    }
-  }                              
-
-
-  void FromDcmtkBridge::ElementToJson(Json::Value& parent,
-                                      DcmElement& element,
-                                      DicomToJsonFormat format,
-                                      DicomToJsonFlags flags,
-                                      unsigned int maxStringLength,
-                                      Encoding encoding,
-                                      const std::set<DicomTag>& ignoreTagLength)
-  {
-    if (parent.type() == Json::nullValue)
-    {
-      parent = Json::objectValue;
-    }
-
-    assert(parent.type() == Json::objectValue);
-    Json::Value& target = PrepareNode(parent, element, format);
-
-    if (element.isLeaf())
-    {
-      // The "0" below lets "LeafValueToJson()" take care of "TooLong" values
-      std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement
-                                  (element, flags, 0, encoding, ignoreTagLength));
-
-      if (ignoreTagLength.find(GetTag(element)) == ignoreTagLength.end())
-      {
-        LeafValueToJson(target, *v, format, flags, maxStringLength);
-      }
-      else
-      {
-        LeafValueToJson(target, *v, format, flags, 0);
-      }
-    }
-    else
-    {
-      assert(target.type() == Json::nullValue);
-      target = Json::arrayValue;
-
-      // "All subclasses of DcmElement except for DcmSequenceOfItems
-      // are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset
-      // etc. are not." The following dynamic_cast is thus OK.
-      DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(element);
-
-      for (unsigned long i = 0; i < sequence.card(); i++)
-      {
-        DcmItem* child = sequence.getItem(i);
-        Json::Value& v = target.append(Json::objectValue);
-        DatasetToJson(v, *child, format, flags, maxStringLength, encoding, ignoreTagLength);
-      }
-    }
-  }
-
-
-  void FromDcmtkBridge::DatasetToJson(Json::Value& parent,
-                                      DcmItem& item,
-                                      DicomToJsonFormat format,
-                                      DicomToJsonFlags flags,
-                                      unsigned int maxStringLength,
-                                      Encoding encoding,
-                                      const std::set<DicomTag>& ignoreTagLength)
-  {
-    assert(parent.type() == Json::objectValue);
-
-    for (unsigned long i = 0; i < item.card(); i++)
-    {
-      DcmElement* element = item.getElement(i);
-      if (element == NULL)
-      {
-        throw OrthancException(ErrorCode_InternalError);
-      }
-
-      DicomTag tag(FromDcmtkBridge::Convert(element->getTag()));
-
-      /*element->getTag().isPrivate()*/
-      if (tag.IsPrivate() &&
-          !(flags & DicomToJsonFlags_IncludePrivateTags))    
-      {
-        continue;
-      }
-
-      if (!(flags & DicomToJsonFlags_IncludeUnknownTags))
-      {
-        DictionaryLocker locker;
-        if (locker->findEntry(element->getTag(), NULL) == NULL)
-        {
-          continue;
-        }
-      }
-
-      DcmEVR evr = element->getTag().getEVR();
-      if (evr == EVR_OB ||
-          evr == EVR_OF ||
-          evr == EVR_OW ||
-          evr == EVR_UN ||
-          evr == EVR_ox)
-      {
-        // This is a binary tag
-        if ((tag == DICOM_TAG_PIXEL_DATA && !(flags & DicomToJsonFlags_IncludePixelData)) ||
-            (tag != DICOM_TAG_PIXEL_DATA && !(flags & DicomToJsonFlags_IncludeBinary)))
-        {
-          continue;
-        }
-      }
-
-      FromDcmtkBridge::ElementToJson(parent, *element, format, flags,
-                                     maxStringLength, encoding, ignoreTagLength);
-    }
-  }
-
-
-  void FromDcmtkBridge::ExtractDicomAsJson(Json::Value& target, 
-                                           DcmDataset& dataset,
-                                           DicomToJsonFormat format,
-                                           DicomToJsonFlags flags,
-                                           unsigned int maxStringLength,
-                                           Encoding defaultEncoding,
-                                           const std::set<DicomTag>& ignoreTagLength)
-  {
-    Encoding encoding = DetectEncoding(dataset, defaultEncoding);
-
-    target = Json::objectValue;
-    DatasetToJson(target, dataset, format, flags, maxStringLength, encoding, ignoreTagLength);
-  }
-
-
-  void FromDcmtkBridge::ExtractHeaderAsJson(Json::Value& target, 
-                                            DcmMetaInfo& dataset,
-                                            DicomToJsonFormat format,
-                                            DicomToJsonFlags flags,
-                                            unsigned int maxStringLength)
-  {
-    std::set<DicomTag> ignoreTagLength;
-    target = Json::objectValue;
-    DatasetToJson(target, dataset, format, flags, maxStringLength, Encoding_Ascii, ignoreTagLength);
-  }
-
-
-
-  static std::string GetTagNameInternal(DcmTag& tag)
-  {
-    {
-      // Some patches for important tags because of different DICOM
-      // dictionaries between DCMTK versions
-      DicomTag tmp(tag.getGroup(), tag.getElement());
-      std::string n = tmp.GetMainTagsName();
-      if (n.size() != 0)
-      {
-        return n;
-      }
-      // End of patches
-    }
-
-#if 0
-    // This version explicitly calls the dictionary
-    const DcmDataDictionary& dict = dcmDataDict.rdlock();
-    const DcmDictEntry* entry = dict.findEntry(tag, NULL);
-
-    std::string s(DcmTag_ERROR_TagName);
-    if (entry != NULL)
-    {
-      s = std::string(entry->getTagName());
-    }
-
-    dcmDataDict.unlock();
-    return s;
-#else
-    const char* name = tag.getTagName();
-    if (name == NULL)
-    {
-      return DcmTag_ERROR_TagName;
-    }
-    else
-    {
-      return std::string(name);
-    }
-#endif
-  }
-
-
-  std::string FromDcmtkBridge::GetTagName(const DicomTag& t,
-                                          const std::string& privateCreator)
-  {
-    DcmTag tag(t.GetGroup(), t.GetElement());
-
-    if (!privateCreator.empty())
-    {
-      tag.setPrivateCreator(privateCreator.c_str());
-    }
-
-    return GetTagNameInternal(tag);
-  }
-
-
-  std::string FromDcmtkBridge::GetTagName(const DcmElement& element)
-  {
-    // Copy the tag to ensure const-correctness of DcmElement. Note
-    // that the private creator information is also copied.
-    DcmTag tag(element.getTag());  
-
-    return GetTagNameInternal(tag);
-  }
-
-
-
-  DicomTag FromDcmtkBridge::ParseTag(const char* name)
-  {
-    if (strlen(name) == 9 &&
-        isxdigit(name[0]) &&
-        isxdigit(name[1]) &&
-        isxdigit(name[2]) &&
-        isxdigit(name[3]) &&
-        (name[4] == '-' || name[4] == ',') &&
-        isxdigit(name[5]) &&
-        isxdigit(name[6]) &&
-        isxdigit(name[7]) &&
-        isxdigit(name[8]))        
-    {
-      uint16_t group = GetTagValue(name);
-      uint16_t element = GetTagValue(name + 5);
-      return DicomTag(group, element);
-    }
-
-    if (strlen(name) == 8 &&
-        isxdigit(name[0]) &&
-        isxdigit(name[1]) &&
-        isxdigit(name[2]) &&
-        isxdigit(name[3]) &&
-        isxdigit(name[4]) &&
-        isxdigit(name[5]) &&
-        isxdigit(name[6]) &&
-        isxdigit(name[7]))        
-    {
-      uint16_t group = GetTagValue(name);
-      uint16_t element = GetTagValue(name + 4);
-      return DicomTag(group, element);
-    }
-
-#if 0
-    const DcmDataDictionary& dict = dcmDataDict.rdlock();
-    const DcmDictEntry* entry = dict.findEntry(name);
-
-    if (entry == NULL)
-    {
-      dcmDataDict.unlock();
-      throw OrthancException(ErrorCode_UnknownDicomTag);
-    }
-    else
-    {
-      DcmTagKey key = entry->getKey();
-      DicomTag tag(key.getGroup(), key.getElement());
-      dcmDataDict.unlock();
-      return tag;
-    }
-#else
-    DcmTag tag;
-    if (DcmTag::findTagFromName(name, tag).good())
-    {
-      return DicomTag(tag.getGTag(), tag.getETag());
-    }
-    else
-    {
-      LOG(INFO) << "Unknown DICOM tag: \"" << name << "\"";
-      throw OrthancException(ErrorCode_UnknownDicomTag);
-    }
-#endif
-  }
-
-
-  bool FromDcmtkBridge::IsUnknownTag(const DicomTag& tag)
-  {
-    DcmTag tmp(tag.GetGroup(), tag.GetElement());
-    return tmp.isUnknownVR();
-  }
-
-
-  void FromDcmtkBridge::ToJson(Json::Value& result,
-                               const DicomMap& values,
-                               bool simplify)
-  {
-    if (result.type() != Json::objectValue)
-    {
-      throw OrthancException(ErrorCode_BadParameterType);
-    }
-
-    result.clear();
-
-    for (DicomMap::Map::const_iterator 
-           it = values.map_.begin(); it != values.map_.end(); ++it)
-    {
-      // TODO Inject PrivateCreator if some is available in the DicomMap?
-      const std::string tagName = GetTagName(it->first, "");
-
-      if (simplify)
-      {
-        if (it->second->IsNull())
-        {
-          result[tagName] = Json::nullValue;
-        }
-        else
-        {
-          // TODO IsBinary
-          result[tagName] = it->second->GetContent();
-        }
-      }
-      else
-      {
-        Json::Value value = Json::objectValue;
-
-        value["Name"] = tagName;
-
-        if (it->second->IsNull())
-        {
-          value["Type"] = "Null";
-          value["Value"] = Json::nullValue;
-        }
-        else
-        {
-          // TODO IsBinary
-          value["Type"] = "String";
-          value["Value"] = it->second->GetContent();
-        }
-
-        result[it->first.Format()] = value;
-      }
-    }
-  }
-
-
-  std::string FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType level)
-  {
-    char uid[100];
-
-    switch (level)
-    {
-      case ResourceType_Patient:
-        // The "PatientID" field is of type LO (Long String), 64
-        // Bytes Maximum. An UUID is of length 36, thus it can be used
-        // as a random PatientID.
-        return Toolbox::GenerateUuid();
-
-      case ResourceType_Instance:
-        return dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT);
-
-      case ResourceType_Series:
-        return dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT);
-
-      case ResourceType_Study:
-        return dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT);
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-  bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer,
-                                           DcmDataset& dataSet)
-  {
-    // Determine the transfer syntax which shall be used to write the
-    // information to the file. We always switch to the Little Endian
-    // syntax, with explicit length.
-
-    // http://support.dcmtk.org/docs/dcxfer_8h-source.html
-
-
-    /**
-     * Note that up to Orthanc 0.7.1 (inclusive), the
-     * "EXS_LittleEndianExplicit" was always used to save the DICOM
-     * dataset into memory. We now keep the original transfer syntax
-     * (if available).
-     **/
-    E_TransferSyntax xfer = dataSet.getOriginalXfer();
-    if (xfer == EXS_Unknown)
-    {
-      // No information about the original transfer syntax: This is
-      // most probably a DICOM dataset that was read from memory.
-      xfer = EXS_LittleEndianExplicit;
-    }
-
-    E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength;
-
-    // Create the meta-header information
-    DcmFileFormat ff(&dataSet);
-    ff.validateMetaInfo(xfer);
-    ff.removeInvalidGroups();
-
-    // Create a memory buffer with the proper size
-    {
-      const uint32_t estimatedSize = ff.calcElementLength(xfer, encodingType);  // (*)
-      buffer.resize(estimatedSize);
-    }
-
-    DcmOutputBufferStream ob(&buffer[0], buffer.size());
-
-    // Fill the memory buffer with the meta-header and the dataset
-    ff.transferInit();
-    OFCondition c = ff.write(ob, xfer, encodingType, NULL,
-                             /*opt_groupLength*/ EGL_recalcGL,
-                             /*opt_paddingType*/ EPD_withoutPadding);
-    ff.transferEnd();
-
-    if (c.good())
-    {
-      // The DICOM file is successfully written, truncate the target
-      // buffer if its size was overestimated by (*)
-      ob.flush();
-
-      size_t effectiveSize = static_cast<size_t>(ob.tell());
-      if (effectiveSize < buffer.size())
-      {
-        buffer.resize(effectiveSize);
-      }
-
-      return true;
-    }
-    else
-    {
-      // Error
-      buffer.clear();
-      return false;
-    }
-  }
-
-
-  ValueRepresentation FromDcmtkBridge::LookupValueRepresentation(const DicomTag& tag)
-  {
-    DcmTag t(tag.GetGroup(), tag.GetElement());
-    return Convert(t.getEVR());
-  }
-
-  ValueRepresentation FromDcmtkBridge::Convert(const DcmEVR vr)
-  {
-    switch (vr)
-    {
-      case EVR_AE:
-        return ValueRepresentation_ApplicationEntity;
-
-      case EVR_AS:
-        return ValueRepresentation_AgeString;
-
-      case EVR_AT:
-        return ValueRepresentation_AttributeTag;
-
-      case EVR_CS:
-        return ValueRepresentation_CodeString;
-
-      case EVR_DA:
-        return ValueRepresentation_Date;
-
-      case EVR_DS:
-        return ValueRepresentation_DecimalString;
-
-      case EVR_DT:
-        return ValueRepresentation_DateTime;
-
-      case EVR_FL:
-        return ValueRepresentation_FloatingPointSingle;
-
-      case EVR_FD:
-        return ValueRepresentation_FloatingPointDouble;
-
-      case EVR_IS:
-        return ValueRepresentation_IntegerString;
-
-      case EVR_LO:
-        return ValueRepresentation_LongString;
-
-      case EVR_LT:
-        return ValueRepresentation_LongText;
-
-      case EVR_OB:
-        return ValueRepresentation_OtherByte;
-
-        // Not supported as of DCMTK 3.6.0
-        /*case EVR_OD:
-          return ValueRepresentation_OtherDouble;*/
-
-      case EVR_OF:
-        return ValueRepresentation_OtherFloat;
-
-        // Not supported as of DCMTK 3.6.0
-        /*case EVR_OL:
-          return ValueRepresentation_OtherLong;*/
-
-      case EVR_OW:
-        return ValueRepresentation_OtherWord;
-
-      case EVR_PN:
-        return ValueRepresentation_PersonName;
-
-      case EVR_SH:
-        return ValueRepresentation_ShortString;
-
-      case EVR_SL:
-        return ValueRepresentation_SignedLong;
-
-      case EVR_SQ:
-        return ValueRepresentation_Sequence;
-
-      case EVR_SS:
-        return ValueRepresentation_SignedShort;
-
-      case EVR_ST:
-        return ValueRepresentation_ShortText;
-
-      case EVR_TM:
-        return ValueRepresentation_Time;
-
-        // Not supported as of DCMTK 3.6.0
-        /*case EVR_UC:
-          return ValueRepresentation_UnlimitedCharacters;*/
-
-      case EVR_UI:
-        return ValueRepresentation_UniqueIdentifier;
-
-      case EVR_UL:
-        return ValueRepresentation_UnsignedLong;
-
-      case EVR_UN:
-        return ValueRepresentation_Unknown;
-
-        // Not supported as of DCMTK 3.6.0
-        /*case EVR_UR:
-          return ValueRepresentation_UniversalResource;*/
-
-      case EVR_US:
-        return ValueRepresentation_UnsignedShort;
-
-      case EVR_UT:
-        return ValueRepresentation_UnlimitedText;
-
-      default:
-        return ValueRepresentation_NotSupported;
-    }
-  }
-
-
-  static bool IsBinaryTag(const DcmTag& key)
-  {
-    return (key.isUnknownVR() || 
-            key.getEVR() == EVR_OB ||
-            key.getEVR() == EVR_OF ||
-            key.getEVR() == EVR_OW ||
-            key.getEVR() == EVR_UN ||
-            key.getEVR() == EVR_ox);
-  }
-
-
-  DcmElement* FromDcmtkBridge::CreateElementForTag(const DicomTag& tag)
-  {
-    DcmTag key(tag.GetGroup(), tag.GetElement());
-
-    if (tag.IsPrivate() ||
-        IsBinaryTag(key))
-    {
-      return new DcmOtherByteOtherWord(key);
-    }
-
-    switch (key.getEVR())
-    {
-      // http://support.dcmtk.org/docs/dcvr_8h-source.html
-
-      /**
-       * Binary types, handled above
-       **/
-    
-      case EVR_OB:  // other byte
-      case EVR_OF:  // other float
-      case EVR_OW:  // other word
-      case EVR_UN:  // unknown value representation
-      case EVR_ox:  // OB or OW depending on context
-        throw OrthancException(ErrorCode_InternalError);
-
-
-      /**
-       * String types.
-       * http://support.dcmtk.org/docs/classDcmByteString.html
-       **/
-      
-      case EVR_AS:  // age string
-        return new DcmAgeString(key);
-
-      case EVR_AE:  // application entity title
-        return new DcmApplicationEntity(key);
-
-      case EVR_CS:  // code string
-        return new DcmCodeString(key);        
-
-      case EVR_DA:  // date string
-        return new DcmDate(key);
-        
-      case EVR_DT:  // date time string
-        return new DcmDateTime(key);
-
-      case EVR_DS:  // decimal string
-        return new DcmDecimalString(key);
-
-      case EVR_IS:  // integer string
-        return new DcmIntegerString(key);
-
-      case EVR_TM:  // time string
-        return new DcmTime(key);
-
-      case EVR_UI:  // unique identifier
-        return new DcmUniqueIdentifier(key);
-
-      case EVR_ST:  // short text
-        return new DcmShortText(key);
-
-      case EVR_LO:  // long string
-        return new DcmLongString(key);
-
-      case EVR_LT:  // long text
-        return new DcmLongText(key);
-
-      case EVR_UT:  // unlimited text
-        return new DcmUnlimitedText(key);
-
-      case EVR_SH:  // short string
-        return new DcmShortString(key);
-
-      case EVR_PN:  // person name
-        return new DcmPersonName(key);
-
-        
-      /**
-       * Numerical types
-       **/ 
-      
-      case EVR_SL:  // signed long
-        return new DcmSignedLong(key);
-
-      case EVR_SS:  // signed short
-        return new DcmSignedShort(key);
-
-      case EVR_UL:  // unsigned long
-        return new DcmUnsignedLong(key);
-
-      case EVR_US:  // unsigned short
-        return new DcmUnsignedShort(key);
-
-      case EVR_FL:  // float single-precision
-        return new DcmFloatingPointSingle(key);
-
-      case EVR_FD:  // float double-precision
-        return new DcmFloatingPointDouble(key);
-
-
-      /**
-       * Sequence types, should never occur at this point.
-       **/
-
-      case EVR_SQ:  // sequence of items
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-
-
-      /**
-       * TODO
-       **/
-
-      case EVR_AT:  // attribute tag
-        throw OrthancException(ErrorCode_NotImplemented);
-
-
-      /**
-       * Internal to DCMTK.
-       **/ 
-
-      case EVR_xs:  // SS or US depending on context
-      case EVR_lt:  // US, SS or OW depending on context, used for LUT Data (thus the name)
-      case EVR_na:  // na="not applicable", for data which has no VR
-      case EVR_up:  // up="unsigned pointer", used internally for DICOMDIR suppor
-      case EVR_item:  // used internally for items
-      case EVR_metainfo:  // used internally for meta info datasets
-      case EVR_dataset:  // used internally for datasets
-      case EVR_fileFormat:  // used internally for DICOM files
-      case EVR_dicomDir:  // used internally for DICOMDIR objects
-      case EVR_dirRecord:  // used internally for DICOMDIR records
-      case EVR_pixelSQ:  // used internally for pixel sequences in a compressed image
-      case EVR_pixelItem:  // used internally for pixel items in a compressed image
-      case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
-      case EVR_PixelData:  // used internally for uncompressed pixeld data
-      case EVR_OverlayData:  // used internally for overlay data
-      case EVR_UNKNOWN2B:  // used internally for elements with unknown VR with 2-byte length field in explicit VR
-      default:
-        break;
-    }
-
-    throw OrthancException(ErrorCode_InternalError);          
-  }
-
-
-
-  void FromDcmtkBridge::FillElementWithString(DcmElement& element,
-                                              const DicomTag& tag,
-                                              const std::string& utf8Value,
-                                              bool decodeDataUriScheme,
-                                              Encoding dicomEncoding)
-  {
-    std::string binary;
-    const std::string* decoded = &utf8Value;
-
-    if (decodeDataUriScheme &&
-        boost::starts_with(utf8Value, "data:application/octet-stream;base64,"))
-    {
-      std::string mime;
-      if (!Toolbox::DecodeDataUriScheme(mime, binary, utf8Value))
-      {
-        throw OrthancException(ErrorCode_BadFileFormat);
-      }
-
-      decoded = &binary;
-    }
-    else if (dicomEncoding != Encoding_Utf8)
-    {
-      binary = Toolbox::ConvertFromUtf8(utf8Value, dicomEncoding);
-      decoded = &binary;
-    }
-
-    DcmTag key(tag.GetGroup(), tag.GetElement());
-
-    if (tag.IsPrivate() ||
-        IsBinaryTag(key))
-    {
-      if (element.putUint8Array((const Uint8*) decoded->c_str(), decoded->size()).good())
-      {
-        return;
-      }
-      else
-      {
-        throw OrthancException(ErrorCode_InternalError);
-      }
-    }
-
-    bool ok = false;
-    
-    try
-    {
-      switch (key.getEVR())
-      {
-        // http://support.dcmtk.org/docs/dcvr_8h-source.html
-
-        /**
-         * TODO.
-         **/
-
-        case EVR_OB:  // other byte
-        case EVR_OF:  // other float
-        case EVR_OW:  // other word
-        case EVR_AT:  // attribute tag
-          throw OrthancException(ErrorCode_NotImplemented);
-    
-        case EVR_UN:  // unknown value representation
-          throw OrthancException(ErrorCode_ParameterOutOfRange);
-
-
-        /**
-         * String types.
-         **/
-      
-        case EVR_DS:  // decimal string
-        case EVR_IS:  // integer string
-        case EVR_AS:  // age string
-        case EVR_DA:  // date string
-        case EVR_DT:  // date time string
-        case EVR_TM:  // time string
-        case EVR_AE:  // application entity title
-        case EVR_CS:  // code string
-        case EVR_SH:  // short string
-        case EVR_LO:  // long string
-        case EVR_ST:  // short text
-        case EVR_LT:  // long text
-        case EVR_UT:  // unlimited text
-        case EVR_PN:  // person name
-        case EVR_UI:  // unique identifier
-        {
-          ok = element.putString(decoded->c_str()).good();
-          break;
-        }
-
-        
-        /**
-         * Numerical types
-         **/ 
-      
-        case EVR_SL:  // signed long
-        {
-          ok = element.putSint32(boost::lexical_cast<Sint32>(*decoded)).good();
-          break;
-        }
-
-        case EVR_SS:  // signed short
-        {
-          ok = element.putSint16(boost::lexical_cast<Sint16>(*decoded)).good();
-          break;
-        }
-
-        case EVR_UL:  // unsigned long
-        {
-          ok = element.putUint32(boost::lexical_cast<Uint32>(*decoded)).good();
-          break;
-        }
-
-        case EVR_US:  // unsigned short
-        {
-          ok = element.putUint16(boost::lexical_cast<Uint16>(*decoded)).good();
-          break;
-        }
-
-        case EVR_FL:  // float single-precision
-        {
-          ok = element.putFloat32(boost::lexical_cast<float>(*decoded)).good();
-          break;
-        }
-
-        case EVR_FD:  // float double-precision
-        {
-          ok = element.putFloat64(boost::lexical_cast<double>(*decoded)).good();
-          break;
-        }
-
-
-        /**
-         * Sequence types, should never occur at this point.
-         **/
-
-        case EVR_SQ:  // sequence of items
-        {
-          ok = false;
-          break;
-        }
-
-
-        /**
-         * Internal to DCMTK.
-         **/ 
-
-        case EVR_ox:  // OB or OW depending on context
-        case EVR_xs:  // SS or US depending on context
-        case EVR_lt:  // US, SS or OW depending on context, used for LUT Data (thus the name)
-        case EVR_na:  // na="not applicable", for data which has no VR
-        case EVR_up:  // up="unsigned pointer", used internally for DICOMDIR suppor
-        case EVR_item:  // used internally for items
-        case EVR_metainfo:  // used internally for meta info datasets
-        case EVR_dataset:  // used internally for datasets
-        case EVR_fileFormat:  // used internally for DICOM files
-        case EVR_dicomDir:  // used internally for DICOMDIR objects
-        case EVR_dirRecord:  // used internally for DICOMDIR records
-        case EVR_pixelSQ:  // used internally for pixel sequences in a compressed image
-        case EVR_pixelItem:  // used internally for pixel items in a compressed image
-        case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
-        case EVR_PixelData:  // used internally for uncompressed pixeld data
-        case EVR_OverlayData:  // used internally for overlay data
-        case EVR_UNKNOWN2B:  // used internally for elements with unknown VR with 2-byte length field in explicit VR
-        default:
-          break;
-      }
-    }
-    catch (boost::bad_lexical_cast&)
-    {
-      ok = false;
-    }
-
-    if (!ok)
-    {
-      LOG(ERROR) << "While creating a DICOM instance, tag (" << tag.Format()
-                 << ") has out-of-range value: \"" << *decoded << "\"";
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-  }
-
-
-  DcmElement* FromDcmtkBridge::FromJson(const DicomTag& tag,
-                                        const Json::Value& value,
-                                        bool decodeDataUriScheme,
-                                        Encoding dicomEncoding)
-  {
-    std::auto_ptr<DcmElement> element;
-
-    switch (value.type())
-    {
-      case Json::stringValue:
-        element.reset(CreateElementForTag(tag));
-        FillElementWithString(*element, tag, value.asString(), decodeDataUriScheme, dicomEncoding);
-        break;
-
-      case Json::nullValue:
-        element.reset(CreateElementForTag(tag));
-        FillElementWithString(*element, tag, "", decodeDataUriScheme, dicomEncoding);
-        break;
-
-      case Json::arrayValue:
-      {
-        DcmTag key(tag.GetGroup(), tag.GetElement());
-        if (key.getEVR() != EVR_SQ)
-        {
-          throw OrthancException(ErrorCode_BadParameterType);
-        }
-
-        DcmSequenceOfItems* sequence = new DcmSequenceOfItems(key);
-        element.reset(sequence);
-        
-        for (Json::Value::ArrayIndex i = 0; i < value.size(); i++)
-        {
-          std::auto_ptr<DcmItem> item(new DcmItem);
-
-          Json::Value::Members members = value[i].getMemberNames();
-          for (Json::Value::ArrayIndex j = 0; j < members.size(); j++)
-          {
-            item->insert(FromJson(ParseTag(members[j]), value[i][members[j]], decodeDataUriScheme, dicomEncoding));
-          }
-
-          sequence->append(item.release());
-        }
-
-        break;
-      }
-
-      default:
-        throw OrthancException(ErrorCode_BadParameterType);
-    }
-
-    return element.release();
-  }
-
-
-  DcmPixelSequence* FromDcmtkBridge::GetPixelSequence(DcmDataset& dataset)
-  {
-    DcmElement *element = NULL;
-    if (!dataset.findAndGetElement(DCM_PixelData, element).good())
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    DcmPixelData& pixelData = dynamic_cast<DcmPixelData&>(*element);
-    DcmPixelSequence* pixelSequence = NULL;
-    if (!pixelData.getEncapsulatedRepresentation
-        (dataset.getOriginalXfer(), NULL, pixelSequence).good())
-    {
-      return NULL;
-    }
-    else
-    {
-      return pixelSequence;
-    }
-  }
-
-
-  Encoding FromDcmtkBridge::ExtractEncoding(const Json::Value& json,
-                                            Encoding defaultEncoding)
-  {
-    if (json.type() != Json::objectValue)
-    {
-      throw OrthancException(ErrorCode_BadParameterType);
-    }
-
-    Encoding encoding = defaultEncoding;
-
-    const Json::Value::Members tags = json.getMemberNames();
-    
-    // Look for SpecificCharacterSet (0008,0005) in the JSON file
-    for (size_t i = 0; i < tags.size(); i++)
-    {
-      DicomTag tag = FromDcmtkBridge::ParseTag(tags[i]);
-      if (tag == DICOM_TAG_SPECIFIC_CHARACTER_SET)
-      {
-        const Json::Value& value = json[tags[i]];
-        if (value.type() != Json::stringValue ||
-            (value.asString().length() != 0 &&
-             !GetDicomEncoding(encoding, value.asCString())))
-        {
-          LOG(ERROR) << "Unknown encoding while creating DICOM from JSON: " << value;
-          throw OrthancException(ErrorCode_BadRequest);
-        }
-
-        if (value.asString().length() == 0)
-        {
-          return defaultEncoding;
-        }
-      }
-    }
-
-    return encoding;
-  } 
-
-
-  static void SetString(DcmDataset& target,
-                        const DcmTag& tag,
-                        const std::string& value)
-  {
-    if (!target.putAndInsertString(tag, value.c_str()).good())
-    {
-      throw OrthancException(ErrorCode_InternalError);
-    }
-  }
-
-
-  DcmDataset* FromDcmtkBridge::FromJson(const Json::Value& json,  // Encoded using UTF-8
-                                        bool generateIdentifiers,
-                                        bool decodeDataUriScheme,
-                                        Encoding defaultEncoding)
-  {
-    std::auto_ptr<DcmDataset> result(new DcmDataset);
-    Encoding encoding = ExtractEncoding(json, defaultEncoding);
-
-    SetString(*result, DCM_SpecificCharacterSet, GetDicomSpecificCharacterSet(encoding));
-
-    const Json::Value::Members tags = json.getMemberNames();
-    
-    bool hasPatientId = false;
-    bool hasStudyInstanceUid = false;
-    bool hasSeriesInstanceUid = false;
-    bool hasSopInstanceUid = false;
-
-    for (size_t i = 0; i < tags.size(); i++)
-    {
-      DicomTag tag = FromDcmtkBridge::ParseTag(tags[i]);
-      const Json::Value& value = json[tags[i]];
-
-      if (tag == DICOM_TAG_PATIENT_ID)
-      {
-        hasPatientId = true;
-      }
-      else if (tag == DICOM_TAG_STUDY_INSTANCE_UID)
-      {
-        hasStudyInstanceUid = true;
-      }
-      else if (tag == DICOM_TAG_SERIES_INSTANCE_UID)
-      {
-        hasSeriesInstanceUid = true;
-      }
-      else if (tag == DICOM_TAG_SOP_INSTANCE_UID)
-      {
-        hasSopInstanceUid = true;
-      }
-
-      if (tag != DICOM_TAG_SPECIFIC_CHARACTER_SET)
-      {
-        std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeDataUriScheme, encoding));
-        const DcmTagKey& tag = element->getTag();
-
-        result->findAndDeleteElement(tag);
-
-        DcmElement* tmp = element.release();
-        if (!result->insert(tmp, false, false).good())
-        {
-          delete tmp;
-          throw OrthancException(ErrorCode_InternalError);
-        }
-      }
-    }
-
-    if (!hasPatientId &&
-        generateIdentifiers)
-    {
-      SetString(*result, DCM_PatientID, GenerateUniqueIdentifier(ResourceType_Patient));
-    }
-
-    if (!hasStudyInstanceUid &&
-        generateIdentifiers)
-    {
-      SetString(*result, DCM_StudyInstanceUID, GenerateUniqueIdentifier(ResourceType_Study));
-    }
-
-    if (!hasSeriesInstanceUid &&
-        generateIdentifiers)
-    {
-      SetString(*result, DCM_SeriesInstanceUID, GenerateUniqueIdentifier(ResourceType_Series));
-    }
-
-    if (!hasSopInstanceUid &&
-        generateIdentifiers)
-    {
-      SetString(*result, DCM_SOPInstanceUID, GenerateUniqueIdentifier(ResourceType_Instance));
-    }
-
-    return result.release();
-  }
-
-
-  DcmFileFormat* FromDcmtkBridge::LoadFromMemoryBuffer(const void* buffer,
-                                                       size_t size)
-  {
-    DcmInputBufferStream is;
-    if (size > 0)
-    {
-      is.setBuffer(buffer, size);
-    }
-    is.setEos();
-
-    std::auto_ptr<DcmFileFormat> result(new DcmFileFormat);
-
-    result->transferInit();
-    if (!result->read(is).good())
-    {
-      LOG(ERROR) << "Cannot parse an invalid DICOM file (size: " << size << " bytes)";
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    result->loadAllDataIntoMemory();
-    result->transferEnd();
-
-    return result.release();
-  }
-
-
-  void FromDcmtkBridge::FromJson(DicomMap& target,
-                                 const Json::Value& source)
-  {
-    if (source.type() != Json::objectValue)
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    target.Clear();
-
-    Json::Value::Members members = source.getMemberNames();
-
-    for (size_t i = 0; i < members.size(); i++)
-    {
-      const Json::Value& value = source[members[i]];
-
-      if (value.type() != Json::stringValue)
-      {
-        throw OrthancException(ErrorCode_BadFileFormat);
-      }
-      
-      target.SetValue(ParseTag(members[i]), value.asString(), false);
-    }
-  }
-
-
-  void FromDcmtkBridge::ChangeStringEncoding(DcmItem& dataset,
-                                             Encoding source,
-                                             Encoding target)
-  {
-    // Recursive exploration of a dataset to change the encoding of
-    // each string-like element
-
-    if (source == target)
-    {
-      return;
-    }
-
-    for (unsigned long i = 0; i < dataset.card(); i++)
-    {
-      DcmElement* element = dataset.getElement(i);
-      if (element)
-      {
-        if (element->isLeaf())
-        {
-          char *c = NULL;
-          if (element->isaString() &&
-              element->getString(c).good() && 
-              c != NULL)
-          {
-            std::string a = Toolbox::ConvertToUtf8(c, source);
-            std::string b = Toolbox::ConvertFromUtf8(a, target);
-            element->putString(b.c_str());
-          }
-        }
-        else
-        {
-          // "All subclasses of DcmElement except for DcmSequenceOfItems
-          // are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset
-          // etc. are not." The following dynamic_cast is thus OK.
-          DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(*element);
-
-          for (unsigned long j = 0; j < sequence.card(); j++)
-          {
-            ChangeStringEncoding(*sequence.getItem(j), source, target);
-          }
-        }
-      }
-    }
-  }
-
-
-  bool FromDcmtkBridge::LookupTransferSyntax(std::string& result,
-                                             DcmFileFormat& dicom)
-  {
-    const char* value = NULL;
-
-    if (dicom.getMetaInfo() != NULL &&
-        dicom.getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() &&
-        value != NULL)
-    {
-      result.assign(value);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-#if ORTHANC_ENABLE_LUA == 1
-  void FromDcmtkBridge::ExecuteToDicom(DicomMap& target,
-                                       LuaFunctionCall& call)
-  {
-    Json::Value output;
-    call.ExecuteToJson(output, true /* keep strings */);
-
-    target.Clear();
-
-    if (output.type() == Json::arrayValue &&
-        output.size() == 0)
-    {
-      // This case happens for empty tables
-      return;
-    }
-
-    if (output.type() != Json::objectValue)
-    {
-      LOG(ERROR) << "Lua: IncomingFindRequestFilter must return a table";
-      throw OrthancException(ErrorCode_LuaBadOutput);
-    }
-
-    Json::Value::Members members = output.getMemberNames();
-
-    for (size_t i = 0; i < members.size(); i++)
-    {
-      if (output[members[i]].type() != Json::stringValue)
-      {
-        LOG(ERROR) << "Lua: IncomingFindRequestFilter must return a table mapping names of DICOM tags to strings";
-        throw OrthancException(ErrorCode_LuaBadOutput);
-      }
-
-      DicomTag tag(ParseTag(members[i]));
-      target.SetValue(tag, output[members[i]].asString(), false);
-    }
-  }
-#endif
-
-
-  void FromDcmtkBridge::ExtractDicomSummary(DicomMap& target, 
-                                            DcmItem& dataset)
-  {
-    ExtractDicomSummary(target, dataset,
-                        ORTHANC_MAXIMUM_TAG_LENGTH,
-                        GetDefaultDicomEncoding());
-  }
-
-  
-  void FromDcmtkBridge::ExtractDicomAsJson(Json::Value& target, 
-                                           DcmDataset& dataset,
-                                           const std::set<DicomTag>& ignoreTagLength)
-  {
-    ExtractDicomAsJson(target, dataset, 
-                       DicomToJsonFormat_Full,
-                       DicomToJsonFlags_Default, 
-                       ORTHANC_MAXIMUM_TAG_LENGTH,
-                       GetDefaultDicomEncoding(),
-                       ignoreTagLength);
-  }
-
-
-  void FromDcmtkBridge::InitializeCodecs()
-  {
-#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
-    LOG(WARNING) << "Registering JPEG Lossless codecs in DCMTK";
-    DJLSDecoderRegistration::registerCodecs();    
-#endif
-
-#if ORTHANC_ENABLE_DCMTK_JPEG == 1
-    LOG(WARNING) << "Registering JPEG codecs in DCMTK";
-    DJDecoderRegistration::registerCodecs(); 
-#endif
-  }
-
-
-  void FromDcmtkBridge::FinalizeCodecs()
-  {
-#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
-    // Unregister JPEG-LS codecs
-    DJLSDecoderRegistration::cleanup();
-#endif
-
-#if ORTHANC_ENABLE_DCMTK_JPEG == 1
-    // Unregister JPEG codecs
-    DJDecoderRegistration::cleanup();
-#endif
-  }
-
-
-
-  // Forward declaration
-  static void ApplyVisitorToElement(DcmElement& element,
-                                    ITagVisitor& visitor,
-                                    const std::vector<DicomTag>& parentTags,
-                                    const std::vector<size_t>& parentIndexes,
-                                    Encoding encoding);
- 
-  static void ApplyVisitorToDataset(DcmItem& dataset,
-                                    ITagVisitor& visitor,
-                                    const std::vector<DicomTag>& parentTags,
-                                    const std::vector<size_t>& parentIndexes,
-                                    Encoding encoding)
-  {
-    assert(parentTags.size() == parentIndexes.size());
-
-    for (unsigned long i = 0; i < dataset.card(); i++)
-    {
-      DcmElement* element = dataset.getElement(i);
-      if (element == NULL)
-      {
-        throw OrthancException(ErrorCode_InternalError);
-      }
-      else
-      {
-        ApplyVisitorToElement(*element, visitor, parentTags, parentIndexes, encoding);
-      }      
-    }
-  }
-
-
-  static void ApplyVisitorToLeaf(DcmElement& element,
-                                 ITagVisitor& visitor,
-                                 const std::vector<DicomTag>& parentTags,
-                                 const std::vector<size_t>& parentIndexes,
-                                 const DicomTag& tag,
-                                 Encoding encoding)
-  {
-    // TODO - Merge this function with ConvertLeafElement()
-
-    assert(element.isLeaf());
-
-    DcmEVR evr = element.getTag().getEVR();
-    ValueRepresentation vr = FromDcmtkBridge::Convert(evr);
-
-    char *c = NULL;
-    if (element.isaString() &&
-        element.getString(c).good())
-    {
-      std::string utf8;
-
-      if (c != NULL)  // This case corresponds to the empty string
-      {
-        std::string s(c);
-        utf8 = Toolbox::ConvertToUtf8(s, encoding);
-      }
-
-      std::string newValue;
-      ITagVisitor::Action action = visitor.VisitString
-        (newValue, parentTags, parentIndexes, tag, vr, utf8);
-
-      switch (action)
-      {
-        case ITagVisitor::Action_None:
-          break;
-
-        case ITagVisitor::Action_Replace:
-        {
-          std::string s = Toolbox::ConvertFromUtf8(newValue, encoding);
-          if (element.putString(s.c_str()) != EC_Normal)
-          {
-            LOG(ERROR) << "Cannot replace value of tag: " << tag.Format();
-            throw OrthancException(ErrorCode_InternalError);
-          }
-
-          break;
-        }
-
-        default:
-          throw OrthancException(ErrorCode_InternalError);
-      }
-
-      return;  // We're done
-    }
-
-
-    try
-    {
-      // http://support.dcmtk.org/docs/dcvr_8h-source.html
-      switch (element.getVR())
-      {
-
-        /**
-         * Deal with binary data (including PixelData).
-         **/
-
-        case EVR_OB:  // other byte
-        case EVR_OF:  // other float
-        case EVR_OW:  // other word
-        case EVR_UN:  // unknown value representation
-        case EVR_ox:  // OB or OW depending on context
-        case EVR_DS:  // decimal string
-        case EVR_IS:  // integer string
-        case EVR_AS:  // age string
-        case EVR_DA:  // date string
-        case EVR_DT:  // date time string
-        case EVR_TM:  // time string
-        case EVR_AE:  // application entity title
-        case EVR_CS:  // code string
-        case EVR_SH:  // short string
-        case EVR_LO:  // long string
-        case EVR_ST:  // short text
-        case EVR_LT:  // long text
-        case EVR_UT:  // unlimited text
-        case EVR_PN:  // person name
-        case EVR_UI:  // unique identifier
-        case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
-        case EVR_UNKNOWN2B:  // used internally for elements with unknown VR with 2-byte length field in explicit VR
-        {
-          Uint8* data = NULL;
-
-          if (element.getUint8Array(data) == EC_Normal)
-          {
-            visitor.VisitBinary(parentTags, parentIndexes, tag, vr, data, element.getLength());
-          }
-          else
-          {
-            visitor.VisitUnknown(parentTags, parentIndexes, tag, vr);
-          }
-
-          break;
-        }
-    
-        /**
-         * Numeric types
-         **/ 
-      
-        case EVR_SL:  // signed long
-        {
-          Sint32 f;
-          if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good())
-          {
-            visitor.VisitInteger(parentTags, parentIndexes, tag, vr, f);
-          }
-
-          break;
-        }
-
-        case EVR_SS:  // signed short
-        {
-          Sint16 f;
-          if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good())
-          {
-            visitor.VisitInteger(parentTags, parentIndexes, tag, vr, f);
-          }
-
-          break;
-        }
-
-        case EVR_UL:  // unsigned long
-        {
-          Uint32 f;
-          if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good())
-          {
-            visitor.VisitInteger(parentTags, parentIndexes, tag, vr, f);
-          }
-
-          break;
-        }
-
-        case EVR_US:  // unsigned short
-        {
-          Uint16 f;
-          if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good())
-          {
-            visitor.VisitInteger(parentTags, parentIndexes, tag, vr, f);
-          }
-
-          break;
-        }
-
-        case EVR_FL:  // float single-precision
-        {
-          Float32 f;
-          if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good())
-          {
-            visitor.VisitDouble(parentTags, parentIndexes, tag, vr, f);
-          }
-
-          break;
-        }
-
-        case EVR_FD:  // float double-precision
-        {
-          Float64 f;
-          if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good())
-          {
-            visitor.VisitDouble(parentTags, parentIndexes, tag, vr, f);
-          }
-
-          break;
-        }
-
-
-        /**
-         * Attribute tag.
-         **/
-
-        case EVR_AT:
-        {
-          DcmTagKey tagKey;
-          if (dynamic_cast<DcmAttributeTag&>(element).getTagVal(tagKey, 0).good())
-          {
-            DicomTag t(tagKey.getGroup(), tagKey.getElement());
-            visitor.VisitAttribute(parentTags, parentIndexes, tag, vr, t);
-          }
-
-          break;
-        }
-
-
-        /**
-         * Sequence types, should never occur at this point because of
-         * "element.isLeaf()".
-         **/
-
-        case EVR_SQ:  // sequence of items
-          return;
-
-
-          /**
-           * Internal to DCMTK.
-           **/ 
-
-        case EVR_xs:  // SS or US depending on context
-        case EVR_lt:  // US, SS or OW depending on context, used for LUT Data (thus the name)
-        case EVR_na:  // na="not applicable", for data which has no VR
-        case EVR_up:  // up="unsigned pointer", used internally for DICOMDIR suppor
-        case EVR_item:  // used internally for items
-        case EVR_metainfo:  // used internally for meta info datasets
-        case EVR_dataset:  // used internally for datasets
-        case EVR_fileFormat:  // used internally for DICOM files
-        case EVR_dicomDir:  // used internally for DICOMDIR objects
-        case EVR_dirRecord:  // used internally for DICOMDIR records
-        case EVR_pixelSQ:  // used internally for pixel sequences in a compressed image
-        case EVR_pixelItem:  // used internally for pixel items in a compressed image
-        case EVR_PixelData:  // used internally for uncompressed pixeld data
-        case EVR_OverlayData:  // used internally for overlay data
-          visitor.VisitUnknown(parentTags, parentIndexes, tag, vr);
-          return;
-
-
-          /**
-           * Default case.
-           **/ 
-
-        default:
-          return;
-      }
-    }
-    catch (boost::bad_lexical_cast&)
-    {
-      return;
-    }
-    catch (std::bad_cast&)
-    {
-      return;
-    }
-  }
-
-
-  static void ApplyVisitorToElement(DcmElement& element,
-                                    ITagVisitor& visitor,
-                                    const std::vector<DicomTag>& parentTags,
-                                    const std::vector<size_t>& parentIndexes,
-                                    Encoding encoding)
-  {
-    assert(parentTags.size() == parentIndexes.size());
-
-    DicomTag tag(FromDcmtkBridge::Convert(element.getTag()));
-
-    if (element.isLeaf())
-    {
-      ApplyVisitorToLeaf(element, visitor, parentTags, parentIndexes, tag, encoding);
-    }
-    else
-    {
-      // "All subclasses of DcmElement except for DcmSequenceOfItems
-      // are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset
-      // etc. are not." The following dynamic_cast is thus OK.
-      DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(element);
-
-      std::vector<DicomTag> tags = parentTags;
-      std::vector<size_t> indexes = parentIndexes;
-      tags.push_back(tag);
-      indexes.push_back(0);
-
-      for (unsigned long i = 0; i < sequence.card(); i++)
-      {
-        indexes.back() = static_cast<size_t>(i);
-        DcmItem* child = sequence.getItem(i);
-        ApplyVisitorToDataset(*child, visitor, tags, indexes, encoding);
-      }
-    }
-  }
-
-
-  void FromDcmtkBridge::Apply(DcmItem& dataset,
-                              ITagVisitor& visitor,
-                              Encoding defaultEncoding)
-  {
-    std::vector<DicomTag> parentTags;
-    std::vector<size_t> parentIndexes;
-    Encoding encoding = DetectEncoding(dataset, defaultEncoding);
-    ApplyVisitorToDataset(dataset, visitor, parentTags, parentIndexes, encoding);
-  }
-}
--- a/Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ITagVisitor.h"
-#include "../DicomFormat/DicomElement.h"
-#include "../DicomFormat/DicomMap.h"
-
-#include <dcmtk/dcmdata/dcdatset.h>
-#include <dcmtk/dcmdata/dcmetinf.h>
-#include <dcmtk/dcmdata/dcpixseq.h>
-#include <dcmtk/dcmdata/dcfilefo.h>
-#include <json/json.h>
-
-#if !defined(ORTHANC_ENABLE_LUA)
-#  error The macro ORTHANC_ENABLE_LUA must be defined
-#endif
-
-#if ORTHANC_ENABLE_DCMTK != 1
-#  error The macro ORTHANC_ENABLE_DCMTK must be set to 1
-#endif
-
-#if ORTHANC_BUILD_UNIT_TESTS == 1
-#  include <gtest/gtest_prod.h>
-#endif
-
-#if ORTHANC_ENABLE_LUA == 1
-#  include "../Lua/LuaFunctionCall.h"
-#endif
-
-#if !defined(ORTHANC_ENABLE_DCMTK_JPEG)
-#  error The macro ORTHANC_ENABLE_DCMTK_JPEG must be defined
-#endif
-
-#if !defined(ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS)
-#  error The macro ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS must be defined
-#endif
-
-
-namespace Orthanc
-{
-  class FromDcmtkBridge : public boost::noncopyable
-  {
-#if ORTHANC_BUILD_UNIT_TESTS == 1
-    FRIEND_TEST(FromDcmtkBridge, FromJson);
-#endif
-
-    friend class ParsedDicomFile;
-
-  private:
-    FromDcmtkBridge();  // Pure static class
-
-    static void ExtractDicomSummary(DicomMap& target, 
-                                    DcmItem& dataset,
-                                    unsigned int maxStringLength,
-                                    Encoding defaultEncoding);
-
-    static void DatasetToJson(Json::Value& parent,
-                              DcmItem& item,
-                              DicomToJsonFormat format,
-                              DicomToJsonFlags flags,
-                              unsigned int maxStringLength,
-                              Encoding encoding,
-                              const std::set<DicomTag>& ignoreTagLength);
-
-    static void ElementToJson(Json::Value& parent,
-                              DcmElement& element,
-                              DicomToJsonFormat format,
-                              DicomToJsonFlags flags,
-                              unsigned int maxStringLength,
-                              Encoding dicomEncoding,
-                              const std::set<DicomTag>& ignoreTagLength);
-
-    static void ExtractDicomAsJson(Json::Value& target, 
-                                   DcmDataset& dataset,
-                                   DicomToJsonFormat format,
-                                   DicomToJsonFlags flags,
-                                   unsigned int maxStringLength,
-                                   Encoding defaultEncoding,
-                                   const std::set<DicomTag>& ignoreTagLength);
-
-    static void ChangeStringEncoding(DcmItem& dataset,
-                                     Encoding source,
-                                     Encoding target);
-
-  public:
-    static void InitializeDictionary(bool loadPrivateDictionary);
-
-    static void RegisterDictionaryTag(const DicomTag& tag,
-                                      ValueRepresentation vr,
-                                      const std::string& name,
-                                      unsigned int minMultiplicity,
-                                      unsigned int maxMultiplicity,
-                                      const std::string& privateCreator);
-
-    static Encoding DetectEncoding(DcmItem& dataset,
-                                   Encoding defaultEncoding);
-
-    static DicomTag Convert(const DcmTag& tag);
-
-    static DicomTag GetTag(const DcmElement& element);
-
-    static bool IsUnknownTag(const DicomTag& tag);
-
-    static DicomValue* ConvertLeafElement(DcmElement& element,
-                                          DicomToJsonFlags flags,
-                                          unsigned int maxStringLength,
-                                          Encoding encoding,
-                                          const std::set<DicomTag>& ignoreTagLength);
-
-    static void ExtractHeaderAsJson(Json::Value& target, 
-                                    DcmMetaInfo& header,
-                                    DicomToJsonFormat format,
-                                    DicomToJsonFlags flags,
-                                    unsigned int maxStringLength);
-
-    static std::string GetTagName(const DicomTag& tag,
-                                  const std::string& privateCreator);
-
-    static std::string GetTagName(const DcmElement& element);
-
-    static std::string GetTagName(const DicomElement& element)
-    {
-      return GetTagName(element.GetTag(), "");
-    }
-
-    static DicomTag ParseTag(const char* name);
-
-    static DicomTag ParseTag(const std::string& name)
-    {
-      return ParseTag(name.c_str());
-    }
-
-    static bool HasTag(const DicomMap& fields,
-                       const std::string& tagName)
-    {
-      return fields.HasTag(ParseTag(tagName));
-    }
-
-    static const DicomValue& GetValue(const DicomMap& fields,
-                                      const std::string& tagName)
-    {
-      return fields.GetValue(ParseTag(tagName));
-    }
-
-    static void SetValue(DicomMap& target,
-                         const std::string& tagName,
-                         DicomValue* value)
-    {
-      target.SetValue(ParseTag(tagName), value);
-    }
-
-    static void ToJson(Json::Value& result,
-                       const DicomMap& values,
-                       bool simplify);
-
-    static std::string GenerateUniqueIdentifier(ResourceType level);
-
-    static bool SaveToMemoryBuffer(std::string& buffer,
-                                   DcmDataset& dataSet);
-
-    static ValueRepresentation Convert(DcmEVR vr);
-
-    static ValueRepresentation LookupValueRepresentation(const DicomTag& tag);
-
-    static DcmElement* CreateElementForTag(const DicomTag& tag);
-    
-    static void FillElementWithString(DcmElement& element,
-                                      const DicomTag& tag,
-                                      const std::string& utf8alue,  // Encoded using UTF-8
-                                      bool decodeDataUriScheme,
-                                      Encoding dicomEncoding);
-
-    static DcmElement* FromJson(const DicomTag& tag,
-                                const Json::Value& element,  // Encoded using UTF-8
-                                bool decodeDataUriScheme,
-                                Encoding dicomEncoding);
-
-    static DcmPixelSequence* GetPixelSequence(DcmDataset& dataset);
-
-    static Encoding ExtractEncoding(const Json::Value& json,
-                                    Encoding defaultEncoding);
-
-    static DcmDataset* FromJson(const Json::Value& json,  // Encoded using UTF-8
-                                bool generateIdentifiers,
-                                bool decodeDataUriScheme,
-                                Encoding defaultEncoding);
-
-    static DcmFileFormat* LoadFromMemoryBuffer(const void* buffer,
-                                               size_t size);
-
-    static void FromJson(DicomMap& values,
-                         const Json::Value& result);
-
-    static bool LookupTransferSyntax(std::string& result,
-                                     DcmFileFormat& dicom);
-
-#if ORTHANC_ENABLE_LUA == 1
-    static void ExecuteToDicom(DicomMap& target,
-                               LuaFunctionCall& call);
-#endif
-
-    static void ExtractDicomSummary(DicomMap& target, 
-                                    DcmItem& dataset);
-
-    static void ExtractDicomAsJson(Json::Value& target, 
-                                   DcmDataset& dataset,
-                                   const std::set<DicomTag>& ignoreTagLength);
-
-    static void InitializeCodecs();
-
-    static void FinalizeCodecs();
-
-    static void Apply(DcmItem& dataset,
-                      ITagVisitor& visitor,
-                      Encoding defaultEncoding);
-  };
-}
--- a/Resources/Orthanc/Core/DicomParsing/ITagVisitor.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "../DicomFormat/DicomTag.h"
-
-#include <vector>
-#include <boost/noncopyable.hpp>
-
-namespace Orthanc
-{
-  class ITagVisitor : public boost::noncopyable
-  {
-  public:
-    enum Action
-    {
-      Action_Replace,
-      Action_None
-    };
-
-    virtual ~ITagVisitor()
-    {
-    }
-
-    virtual void VisitUnknown(const std::vector<DicomTag>& parentTags,
-                              const std::vector<size_t>& parentIndexes,
-                              const DicomTag& tag,
-                              ValueRepresentation vr) = 0;
-
-    virtual void VisitBinary(const std::vector<DicomTag>& parentTags,
-                             const std::vector<size_t>& parentIndexes,
-                             const DicomTag& tag,
-                             ValueRepresentation vr,
-                             const void* data,
-                             size_t size) = 0;
-
-    virtual void VisitInteger(const std::vector<DicomTag>& parentTags,
-                              const std::vector<size_t>& parentIndexes,
-                              const DicomTag& tag,
-                              ValueRepresentation vr,
-                              int64_t value) = 0;
-
-    virtual void VisitDouble(const std::vector<DicomTag>& parentTags,
-                             const std::vector<size_t>& parentIndexes,
-                             const DicomTag& tag,
-                             ValueRepresentation vr,
-                             double value) = 0;
-
-    virtual void VisitAttribute(const std::vector<DicomTag>& parentTags,
-                                const std::vector<size_t>& parentIndexes,
-                                const DicomTag& tag,
-                                ValueRepresentation vr,
-                                const DicomTag& value) = 0;
-
-    virtual Action VisitString(std::string& newValue,
-                               const std::vector<DicomTag>& parentTags,
-                               const std::vector<size_t>& parentIndexes,
-                               const DicomTag& tag,
-                               ValueRepresentation vr,
-                               const std::string& value) = 0;
-  };
-}
--- a/Resources/Orthanc/Core/DicomParsing/ToDcmtkBridge.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ToDcmtkBridge.h"
-
-#include <memory>
-
-#include "../OrthancException.h"
-
-
-namespace Orthanc
-{
-  DcmEVR ToDcmtkBridge::Convert(ValueRepresentation vr)
-  {
-    switch (vr)
-    {
-      case ValueRepresentation_ApplicationEntity:
-        return EVR_AE;
-
-      case ValueRepresentation_AgeString:
-        return EVR_AS;
-
-      case ValueRepresentation_AttributeTag:
-        return EVR_AT;
-
-      case ValueRepresentation_CodeString:
-        return EVR_CS;
-
-      case ValueRepresentation_Date:
-        return EVR_DA;
-
-      case ValueRepresentation_DecimalString:
-        return EVR_DS;
-
-      case ValueRepresentation_DateTime:
-        return EVR_DT;
-
-      case ValueRepresentation_FloatingPointSingle:
-        return EVR_FL;
-
-      case ValueRepresentation_FloatingPointDouble:
-        return EVR_FD;
-
-      case ValueRepresentation_IntegerString:
-        return EVR_IS;
-
-      case ValueRepresentation_LongString:
-        return EVR_LO;
-
-      case ValueRepresentation_LongText:
-        return EVR_LT;
-
-      case ValueRepresentation_OtherByte:
-        return EVR_OB;
-
-        // Not supported as of DCMTK 3.6.0
-        /*case ValueRepresentation_OtherDouble:
-          return EVR_OD;*/
-
-      case ValueRepresentation_OtherFloat:
-        return EVR_OF;
-
-        // Not supported as of DCMTK 3.6.0
-        /*case ValueRepresentation_OtherLong:
-          return EVR_OL;*/
-
-      case ValueRepresentation_OtherWord:
-        return EVR_OW;
-
-      case ValueRepresentation_PersonName:
-        return EVR_PN;
-
-      case ValueRepresentation_ShortString:
-        return EVR_SH;
-
-      case ValueRepresentation_SignedLong:
-        return EVR_SL;
-
-      case ValueRepresentation_Sequence:
-        return EVR_SQ;
-
-      case ValueRepresentation_SignedShort:
-        return EVR_SS;
-
-      case ValueRepresentation_ShortText:
-        return EVR_ST;
-
-      case ValueRepresentation_Time:
-        return EVR_TM;
-
-        // Not supported as of DCMTK 3.6.0
-        /*case ValueRepresentation_UnlimitedCharacters:
-          return EVR_UC;*/
-
-      case ValueRepresentation_UniqueIdentifier:
-        return EVR_UI;
-
-      case ValueRepresentation_UnsignedLong:
-        return EVR_UL;
-
-      case ValueRepresentation_Unknown:
-        return EVR_UN;
-
-        // Not supported as of DCMTK 3.6.0
-        /*case ValueRepresentation_UniversalResource:
-          return EVR_UR;*/
-
-      case ValueRepresentation_UnsignedShort:
-        return EVR_US;
-
-      case ValueRepresentation_UnlimitedText:
-        return EVR_UT;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-}
--- a/Resources/Orthanc/Core/DicomParsing/ToDcmtkBridge.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 ORTHANC_ENABLE_DCMTK != 1
-#  error The macro ORTHANC_ENABLE_DCMTK must be set to 1
-#endif
-
-#include "../DicomFormat/DicomMap.h"
-#include <dcmtk/dcmdata/dcdatset.h>
-
-namespace Orthanc
-{
-  class ToDcmtkBridge
-  {
-  public:
-    static DcmTagKey Convert(const DicomTag& tag)
-    {
-      return DcmTagKey(tag.GetGroup(), tag.GetElement());
-    }
-
-    static DcmEVR Convert(ValueRepresentation vr);
-  };
-}
--- a/Resources/Orthanc/Core/Endianness.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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
-
-
-/********************************************************************
- ** LINUX-LIKE ARCHITECTURES
- ********************************************************************/
-
-#if defined(__LSB_VERSION__)
-// Linux Standard Base (LSB) does not come with be16toh, be32toh, and
-// be64toh
-#  define ORTHANC_HAS_BUILTIN_BYTE_SWAP 0
-#  include <endian.h>
-#elif defined(__linux__) || defined(__EMSCRIPTEN__)
-#  define ORTHANC_HAS_BUILTIN_BYTE_SWAP 1
-#  include <endian.h>
-#endif
-
-
-/********************************************************************
- ** WINDOWS ARCHITECTURES
- **
- ** On Windows x86, "host" will always be little-endian ("le").
- ********************************************************************/
-
-#if defined(_WIN32)
-#  if defined(_MSC_VER)
-//   Visual Studio - http://msdn.microsoft.com/en-us/library/a3140177.aspx
-#    define ORTHANC_HAS_BUILTIN_BYTE_SWAP 1
-#    define be16toh(x) _byteswap_ushort(x)
-#    define be32toh(x) _byteswap_ulong(x)
-#    define be64toh(x) _byteswap_uint64(x)
-#  elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
-//   MinGW >= 4.3 - Use builtin intrinsic for byte swapping
-#    define ORTHANC_HAS_BUILTIN_BYTE_SWAP 1
-#    define be16toh(x) __builtin_bswap16(x)
-#    define be32toh(x) __builtin_bswap32(x)
-#    define be64toh(x) __builtin_bswap64(x)
-#  else
-//   MinGW <= 4.2, we must manually implement the byte swapping
-#    define ORTHANC_HAS_BUILTIN_BYTE_SWAP 0
-#    define be16toh(x) __orthanc_bswap16(x)
-#    define be32toh(x) __orthanc_bswap32(x)
-#    define be64toh(x) __orthanc_bswap64(x)
-#  endif
-
-#  define htobe16(x) be16toh(x)
-#  define htobe32(x) be32toh(x)
-#  define htobe64(x) be64toh(x)
-
-#  define htole16(x) x
-#  define htole32(x) x
-#  define htole64(x) x
-
-#  define le16toh(x) x
-#  define le32toh(x) x
-#  define le64toh(x) x
-#endif
-
-
-/********************************************************************
- ** FREEBSD ARCHITECTURES
- ********************************************************************/
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#  define ORTHANC_HAS_BUILTIN_BYTE_SWAP 1
-#  include <arpa/inet.h>
-#endif
-
-
-/********************************************************************
- ** OPENBSD ARCHITECTURES
- ********************************************************************/
-
-#if defined(__OpenBSD__)
-#  define ORTHANC_HAS_BUILTIN_BYTE_SWAP 1
-#  include <endian.h>
-#endif
-
-
-/********************************************************************
- ** APPLE ARCHITECTURES (including OS X)
- ********************************************************************/
-
-#if defined(__APPLE__)
-#  define ORTHANC_HAS_BUILTIN_BYTE_SWAP 1
-#  include <libkern/OSByteOrder.h>
-#  define be16toh(x) OSSwapBigToHostInt16(x)
-#  define be32toh(x) OSSwapBigToHostInt32(x)
-#  define be64toh(x) OSSwapBigToHostInt64(x)
-
-#  define htobe16(x) OSSwapHostToBigInt16(x)
-#  define htobe32(x) OSSwapHostToBigInt32(x)
-#  define htobe64(x) OSSwapHostToBigInt64(x)
-
-#  define htole16(x) OSSwapHostToLittleInt16(x)
-#  define htole32(x) OSSwapHostToLittleInt32(x)
-#  define htole64(x) OSSwapHostToLittleInt64(x)
-
-#  define le16toh(x) OSSwapLittleToHostInt16(x)
-#  define le32toh(x) OSSwapLittleToHostInt32(x)
-#  define le64toh(x) OSSwapLittleToHostInt64(x)
-#endif
-
-
-/********************************************************************
- ** PORTABLE (BUT SLOW) IMPLEMENTATION OF BYTE-SWAPPING
- ********************************************************************/
-
-#if ORTHANC_HAS_BUILTIN_BYTE_SWAP != 1
-
-#include <stdint.h>
-
-static inline uint16_t __orthanc_bswap16(uint16_t a)
-{
-  return (a << 8) | (a >> 8);
-}
-
-static inline uint32_t __orthanc_bswap32(uint32_t a)
-{
-  const uint8_t* p = reinterpret_cast<const uint8_t*>(&a);
-  return (static_cast<uint32_t>(p[0]) << 24 |
-          static_cast<uint32_t>(p[1]) << 16 |
-          static_cast<uint32_t>(p[2]) << 8 |
-          static_cast<uint32_t>(p[3]));
-}
-
-static inline uint64_t __orthanc_bswap64(uint64_t a)
-{
-  const uint8_t* p = reinterpret_cast<const uint8_t*>(&a);
-  return (static_cast<uint64_t>(p[0]) << 56 |
-          static_cast<uint64_t>(p[1]) << 48 |
-          static_cast<uint64_t>(p[2]) << 40 |
-          static_cast<uint64_t>(p[3]) << 32 |
-          static_cast<uint64_t>(p[4]) << 24 |
-          static_cast<uint64_t>(p[5]) << 16 |
-          static_cast<uint64_t>(p[6]) << 8 |
-          static_cast<uint64_t>(p[7]));
-}
-
-#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
-#  if __BYTE_ORDER == __LITTLE_ENDIAN
-#    define be16toh(x) __orthanc_bswap16(x)
-#    define be32toh(x) __orthanc_bswap32(x)
-#    define be64toh(x) __orthanc_bswap64(x)
-#    define htobe16(x) __orthanc_bswap16(x)
-#    define htobe32(x) __orthanc_bswap32(x)
-#    define htobe64(x) __orthanc_bswap64(x)
-#    define htole16(x) x
-#    define htole32(x) x
-#    define htole64(x) x
-#    define le16toh(x) x
-#    define le32toh(x) x
-#    define le64toh(x) x
-#  elif __BYTE_ORDER == __BIG_ENDIAN
-#    define be16toh(x) x
-#    define be32toh(x) x
-#    define be64toh(x) x
-#    define htobe16(x) x
-#    define htobe32(x) x
-#    define htobe64(x) x
-#    define htole16(x) __orthanc_bswap16(x)
-#    define htole32(x) __orthanc_bswap32(x)
-#    define htole64(x) __orthanc_bswap64(x)
-#    define le16toh(x) __orthanc_bswap16(x)
-#    define le32toh(x) __orthanc_bswap32(x)
-#    define le64toh(x) __orthanc_bswap64(x)
-#  else
-#    error Please support your platform here
-#  endif
-#else
-#  error Please support your platform here
-#endif
-
-#endif
--- a/Resources/Orthanc/Core/EnumerationDictionary.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "OrthancException.h"
-
-#include "Toolbox.h"
-#include <boost/lexical_cast.hpp>
-#include <string>
-#include <map>
-
-namespace Orthanc
-{
-  namespace Toolbox
-  {
-    template <typename Enumeration>
-    class EnumerationDictionary
-    {
-    private:
-      typedef std::map<Enumeration, std::string>  EnumerationToString;
-      typedef std::map<std::string, Enumeration>  StringToEnumeration;
-
-      EnumerationToString enumerationToString_;
-      StringToEnumeration stringToEnumeration_;
-
-    public:
-      void Clear()
-      {
-        enumerationToString_.clear();
-        stringToEnumeration_.clear();
-      }
-
-      bool Contains(Enumeration value) const
-      {
-        return enumerationToString_.find(value) != enumerationToString_.end();
-      }
-
-      void Add(Enumeration value, const std::string& str)
-      {
-        // Check if these values are free
-        if (enumerationToString_.find(value) != enumerationToString_.end() ||
-            stringToEnumeration_.find(str) != stringToEnumeration_.end() ||
-            Toolbox::IsInteger(str) /* Prevent the registration of a number */)
-        {
-          throw OrthancException(ErrorCode_BadRequest);
-        }
-
-        // OK, the string is free and is not a number
-        enumerationToString_[value] = str;
-        stringToEnumeration_[str] = value;
-        stringToEnumeration_[boost::lexical_cast<std::string>(static_cast<int>(value))] = value;
-      }
-
-      Enumeration Translate(const std::string& str) const
-      {
-        try
-        {
-          int value = boost::lexical_cast<int>(str);
-          return static_cast<Enumeration>(value);
-        }
-        catch (boost::bad_lexical_cast)
-        {
-        }
-
-        typename StringToEnumeration::const_iterator
-          found = stringToEnumeration_.find(str);
-
-        if (found == stringToEnumeration_.end())
-        {
-          throw OrthancException(ErrorCode_InexistentItem);
-        }
-        else
-        {
-          return found->second;
-        }
-      }
-
-      std::string Translate(Enumeration e) const
-      {
-        typename EnumerationToString::const_iterator
-          found = enumerationToString_.find(e);
-
-        if (found == enumerationToString_.end())
-        {
-          // No name for this item
-          return boost::lexical_cast<std::string>(static_cast<int>(e));
-        }
-        else
-        {
-          return found->second;
-        }
-      }
-    };
-  }
-}
--- a/Resources/Orthanc/Core/Enumerations.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1822 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "Enumerations.h"
-
-#include "OrthancException.h"
-#include "Toolbox.h"
-#include "Logging.h"
-
-#include <boost/thread/mutex.hpp>
-#include <string.h>
-#include <cassert>
-
-namespace Orthanc
-{
-  // This function is autogenerated by the script
-  // "Resources/GenerateErrorCodes.py"
-  const char* EnumerationToString(ErrorCode error)
-  {
-    switch (error)
-    {
-      case ErrorCode_InternalError:
-        return "Internal error";
-
-      case ErrorCode_Success:
-        return "Success";
-
-      case ErrorCode_Plugin:
-        return "Error encountered within the plugin engine";
-
-      case ErrorCode_NotImplemented:
-        return "Not implemented yet";
-
-      case ErrorCode_ParameterOutOfRange:
-        return "Parameter out of range";
-
-      case ErrorCode_NotEnoughMemory:
-        return "The server hosting Orthanc is running out of memory";
-
-      case ErrorCode_BadParameterType:
-        return "Bad type for a parameter";
-
-      case ErrorCode_BadSequenceOfCalls:
-        return "Bad sequence of calls";
-
-      case ErrorCode_InexistentItem:
-        return "Accessing an inexistent item";
-
-      case ErrorCode_BadRequest:
-        return "Bad request";
-
-      case ErrorCode_NetworkProtocol:
-        return "Error in the network protocol";
-
-      case ErrorCode_SystemCommand:
-        return "Error while calling a system command";
-
-      case ErrorCode_Database:
-        return "Error with the database engine";
-
-      case ErrorCode_UriSyntax:
-        return "Badly formatted URI";
-
-      case ErrorCode_InexistentFile:
-        return "Inexistent file";
-
-      case ErrorCode_CannotWriteFile:
-        return "Cannot write to file";
-
-      case ErrorCode_BadFileFormat:
-        return "Bad file format";
-
-      case ErrorCode_Timeout:
-        return "Timeout";
-
-      case ErrorCode_UnknownResource:
-        return "Unknown resource";
-
-      case ErrorCode_IncompatibleDatabaseVersion:
-        return "Incompatible version of the database";
-
-      case ErrorCode_FullStorage:
-        return "The file storage is full";
-
-      case ErrorCode_CorruptedFile:
-        return "Corrupted file (e.g. inconsistent MD5 hash)";
-
-      case ErrorCode_InexistentTag:
-        return "Inexistent tag";
-
-      case ErrorCode_ReadOnly:
-        return "Cannot modify a read-only data structure";
-
-      case ErrorCode_IncompatibleImageFormat:
-        return "Incompatible format of the images";
-
-      case ErrorCode_IncompatibleImageSize:
-        return "Incompatible size of the images";
-
-      case ErrorCode_SharedLibrary:
-        return "Error while using a shared library (plugin)";
-
-      case ErrorCode_UnknownPluginService:
-        return "Plugin invoking an unknown service";
-
-      case ErrorCode_UnknownDicomTag:
-        return "Unknown DICOM tag";
-
-      case ErrorCode_BadJson:
-        return "Cannot parse a JSON document";
-
-      case ErrorCode_Unauthorized:
-        return "Bad credentials were provided to an HTTP request";
-
-      case ErrorCode_BadFont:
-        return "Badly formatted font file";
-
-      case ErrorCode_DatabasePlugin:
-        return "The plugin implementing a custom database back-end does not fulfill the proper interface";
-
-      case ErrorCode_StorageAreaPlugin:
-        return "Error in the plugin implementing a custom storage area";
-
-      case ErrorCode_EmptyRequest:
-        return "The request is empty";
-
-      case ErrorCode_NotAcceptable:
-        return "Cannot send a response which is acceptable according to the Accept HTTP header";
-
-      case ErrorCode_NullPointer:
-        return "Cannot handle a NULL pointer";
-
-      case ErrorCode_DatabaseUnavailable:
-        return "The database is currently not available (probably a transient situation)";
-
-      case ErrorCode_SQLiteNotOpened:
-        return "SQLite: The database is not opened";
-
-      case ErrorCode_SQLiteAlreadyOpened:
-        return "SQLite: Connection is already open";
-
-      case ErrorCode_SQLiteCannotOpen:
-        return "SQLite: Unable to open the database";
-
-      case ErrorCode_SQLiteStatementAlreadyUsed:
-        return "SQLite: This cached statement is already being referred to";
-
-      case ErrorCode_SQLiteExecute:
-        return "SQLite: Cannot execute a command";
-
-      case ErrorCode_SQLiteRollbackWithoutTransaction:
-        return "SQLite: Rolling back a nonexistent transaction (have you called Begin()?)";
-
-      case ErrorCode_SQLiteCommitWithoutTransaction:
-        return "SQLite: Committing a nonexistent transaction";
-
-      case ErrorCode_SQLiteRegisterFunction:
-        return "SQLite: Unable to register a function";
-
-      case ErrorCode_SQLiteFlush:
-        return "SQLite: Unable to flush the database";
-
-      case ErrorCode_SQLiteCannotRun:
-        return "SQLite: Cannot run a cached statement";
-
-      case ErrorCode_SQLiteCannotStep:
-        return "SQLite: Cannot step over a cached statement";
-
-      case ErrorCode_SQLiteBindOutOfRange:
-        return "SQLite: Bing a value while out of range (serious error)";
-
-      case ErrorCode_SQLitePrepareStatement:
-        return "SQLite: Cannot prepare a cached statement";
-
-      case ErrorCode_SQLiteTransactionAlreadyStarted:
-        return "SQLite: Beginning the same transaction twice";
-
-      case ErrorCode_SQLiteTransactionCommit:
-        return "SQLite: Failure when committing the transaction";
-
-      case ErrorCode_SQLiteTransactionBegin:
-        return "SQLite: Cannot start a transaction";
-
-      case ErrorCode_DirectoryOverFile:
-        return "The directory to be created is already occupied by a regular file";
-
-      case ErrorCode_FileStorageCannotWrite:
-        return "Unable to create a subdirectory or a file in the file storage";
-
-      case ErrorCode_DirectoryExpected:
-        return "The specified path does not point to a directory";
-
-      case ErrorCode_HttpPortInUse:
-        return "The TCP port of the HTTP server is privileged or already in use";
-
-      case ErrorCode_DicomPortInUse:
-        return "The TCP port of the DICOM server is privileged or already in use";
-
-      case ErrorCode_BadHttpStatusInRest:
-        return "This HTTP status is not allowed in a REST API";
-
-      case ErrorCode_RegularFileExpected:
-        return "The specified path does not point to a regular file";
-
-      case ErrorCode_PathToExecutable:
-        return "Unable to get the path to the executable";
-
-      case ErrorCode_MakeDirectory:
-        return "Cannot create a directory";
-
-      case ErrorCode_BadApplicationEntityTitle:
-        return "An application entity title (AET) cannot be empty or be longer than 16 characters";
-
-      case ErrorCode_NoCFindHandler:
-        return "No request handler factory for DICOM C-FIND SCP";
-
-      case ErrorCode_NoCMoveHandler:
-        return "No request handler factory for DICOM C-MOVE SCP";
-
-      case ErrorCode_NoCStoreHandler:
-        return "No request handler factory for DICOM C-STORE SCP";
-
-      case ErrorCode_NoApplicationEntityFilter:
-        return "No application entity filter";
-
-      case ErrorCode_NoSopClassOrInstance:
-        return "DicomUserConnection: Unable to find the SOP class and instance";
-
-      case ErrorCode_NoPresentationContext:
-        return "DicomUserConnection: No acceptable presentation context for modality";
-
-      case ErrorCode_DicomFindUnavailable:
-        return "DicomUserConnection: The C-FIND command is not supported by the remote SCP";
-
-      case ErrorCode_DicomMoveUnavailable:
-        return "DicomUserConnection: The C-MOVE command is not supported by the remote SCP";
-
-      case ErrorCode_CannotStoreInstance:
-        return "Cannot store an instance";
-
-      case ErrorCode_CreateDicomNotString:
-        return "Only string values are supported when creating DICOM instances";
-
-      case ErrorCode_CreateDicomOverrideTag:
-        return "Trying to override a value inherited from a parent module";
-
-      case ErrorCode_CreateDicomUseContent:
-        return "Use \"Content\" to inject an image into a new DICOM instance";
-
-      case ErrorCode_CreateDicomNoPayload:
-        return "No payload is present for one instance in the series";
-
-      case ErrorCode_CreateDicomUseDataUriScheme:
-        return "The payload of the DICOM instance must be specified according to Data URI scheme";
-
-      case ErrorCode_CreateDicomBadParent:
-        return "Trying to attach a new DICOM instance to an inexistent resource";
-
-      case ErrorCode_CreateDicomParentIsInstance:
-        return "Trying to attach a new DICOM instance to an instance (must be a series, study or patient)";
-
-      case ErrorCode_CreateDicomParentEncoding:
-        return "Unable to get the encoding of the parent resource";
-
-      case ErrorCode_UnknownModality:
-        return "Unknown modality";
-
-      case ErrorCode_BadJobOrdering:
-        return "Bad ordering of filters in a job";
-
-      case ErrorCode_JsonToLuaTable:
-        return "Cannot convert the given JSON object to a Lua table";
-
-      case ErrorCode_CannotCreateLua:
-        return "Cannot create the Lua context";
-
-      case ErrorCode_CannotExecuteLua:
-        return "Cannot execute a Lua command";
-
-      case ErrorCode_LuaAlreadyExecuted:
-        return "Arguments cannot be pushed after the Lua function is executed";
-
-      case ErrorCode_LuaBadOutput:
-        return "The Lua function does not give the expected number of outputs";
-
-      case ErrorCode_NotLuaPredicate:
-        return "The Lua function is not a predicate (only true/false outputs allowed)";
-
-      case ErrorCode_LuaReturnsNoString:
-        return "The Lua function does not return a string";
-
-      case ErrorCode_StorageAreaAlreadyRegistered:
-        return "Another plugin has already registered a custom storage area";
-
-      case ErrorCode_DatabaseBackendAlreadyRegistered:
-        return "Another plugin has already registered a custom database back-end";
-
-      case ErrorCode_DatabaseNotInitialized:
-        return "Plugin trying to call the database during its initialization";
-
-      case ErrorCode_SslDisabled:
-        return "Orthanc has been built without SSL support";
-
-      case ErrorCode_CannotOrderSlices:
-        return "Unable to order the slices of the series";
-
-      case ErrorCode_NoWorklistHandler:
-        return "No request handler factory for DICOM C-Find Modality SCP";
-
-      case ErrorCode_AlreadyExistingTag:
-        return "Cannot override the value of a tag that already exists";
-
-      default:
-        if (error >= ErrorCode_START_PLUGINS)
-        {
-          return "Error encountered within some plugin";
-        }
-        else
-        {
-          return "Unknown error code";
-        }
-    }
-  }
-
-
-  const char* EnumerationToString(HttpMethod method)
-  {
-    switch (method)
-    {
-      case HttpMethod_Get:
-        return "GET";
-
-      case HttpMethod_Post:
-        return "POST";
-
-      case HttpMethod_Delete:
-        return "DELETE";
-
-      case HttpMethod_Put:
-        return "PUT";
-
-      default:
-        return "?";
-    }
-  }
-
-
-  const char* EnumerationToString(HttpStatus status)
-  {
-    switch (status)
-    {
-    case HttpStatus_100_Continue:
-      return "Continue";
-
-    case HttpStatus_101_SwitchingProtocols:
-      return "Switching Protocols";
-
-    case HttpStatus_102_Processing:
-      return "Processing";
-
-    case HttpStatus_200_Ok:
-      return "OK";
-
-    case HttpStatus_201_Created:
-      return "Created";
-
-    case HttpStatus_202_Accepted:
-      return "Accepted";
-
-    case HttpStatus_203_NonAuthoritativeInformation:
-      return "Non-Authoritative Information";
-
-    case HttpStatus_204_NoContent:
-      return "No Content";
-
-    case HttpStatus_205_ResetContent:
-      return "Reset Content";
-
-    case HttpStatus_206_PartialContent:
-      return "Partial Content";
-
-    case HttpStatus_207_MultiStatus:
-      return "Multi-Status";
-
-    case HttpStatus_208_AlreadyReported:
-      return "Already Reported";
-
-    case HttpStatus_226_IMUsed:
-      return "IM Used";
-
-    case HttpStatus_300_MultipleChoices:
-      return "Multiple Choices";
-
-    case HttpStatus_301_MovedPermanently:
-      return "Moved Permanently";
-
-    case HttpStatus_302_Found:
-      return "Found";
-
-    case HttpStatus_303_SeeOther:
-      return "See Other";
-
-    case HttpStatus_304_NotModified:
-      return "Not Modified";
-
-    case HttpStatus_305_UseProxy:
-      return "Use Proxy";
-
-    case HttpStatus_307_TemporaryRedirect:
-      return "Temporary Redirect";
-
-    case HttpStatus_400_BadRequest:
-      return "Bad Request";
-
-    case HttpStatus_401_Unauthorized:
-      return "Unauthorized";
-
-    case HttpStatus_402_PaymentRequired:
-      return "Payment Required";
-
-    case HttpStatus_403_Forbidden:
-      return "Forbidden";
-
-    case HttpStatus_404_NotFound:
-      return "Not Found";
-
-    case HttpStatus_405_MethodNotAllowed:
-      return "Method Not Allowed";
-
-    case HttpStatus_406_NotAcceptable:
-      return "Not Acceptable";
-
-    case HttpStatus_407_ProxyAuthenticationRequired:
-      return "Proxy Authentication Required";
-
-    case HttpStatus_408_RequestTimeout:
-      return "Request Timeout";
-
-    case HttpStatus_409_Conflict:
-      return "Conflict";
-
-    case HttpStatus_410_Gone:
-      return "Gone";
-
-    case HttpStatus_411_LengthRequired:
-      return "Length Required";
-
-    case HttpStatus_412_PreconditionFailed:
-      return "Precondition Failed";
-
-    case HttpStatus_413_RequestEntityTooLarge:
-      return "Request Entity Too Large";
-
-    case HttpStatus_414_RequestUriTooLong:
-      return "Request-URI Too Long";
-
-    case HttpStatus_415_UnsupportedMediaType:
-      return "Unsupported Media Type";
-
-    case HttpStatus_416_RequestedRangeNotSatisfiable:
-      return "Requested Range Not Satisfiable";
-
-    case HttpStatus_417_ExpectationFailed:
-      return "Expectation Failed";
-
-    case HttpStatus_422_UnprocessableEntity:
-      return "Unprocessable Entity";
-
-    case HttpStatus_423_Locked:
-      return "Locked";
-
-    case HttpStatus_424_FailedDependency:
-      return "Failed Dependency";
-
-    case HttpStatus_426_UpgradeRequired:
-      return "Upgrade Required";
-
-    case HttpStatus_500_InternalServerError:
-      return "Internal Server Error";
-
-    case HttpStatus_501_NotImplemented:
-      return "Not Implemented";
-
-    case HttpStatus_502_BadGateway:
-      return "Bad Gateway";
-
-    case HttpStatus_503_ServiceUnavailable:
-      return "Service Unavailable";
-
-    case HttpStatus_504_GatewayTimeout:
-      return "Gateway Timeout";
-
-    case HttpStatus_505_HttpVersionNotSupported:
-      return "HTTP Version Not Supported";
-
-    case HttpStatus_506_VariantAlsoNegotiates:
-      return "Variant Also Negotiates";
-
-    case HttpStatus_507_InsufficientStorage:
-      return "Insufficient Storage";
-
-    case HttpStatus_509_BandwidthLimitExceeded:
-      return "Bandwidth Limit Exceeded";
-
-    case HttpStatus_510_NotExtended:
-      return "Not Extended";
-
-    default:
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(ResourceType type)
-  {
-    switch (type)
-    {
-      case ResourceType_Patient:
-        return "Patient";
-
-      case ResourceType_Study:
-        return "Study";
-
-      case ResourceType_Series:
-        return "Series";
-
-      case ResourceType_Instance:
-        return "Instance";
-      
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(ImageFormat format)
-  {
-    switch (format)
-    {
-      case ImageFormat_Png:
-        return "Png";
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(Encoding encoding)
-  {
-    switch (encoding)
-    {
-      case Encoding_Ascii:
-        return "Ascii";
-
-      case Encoding_Utf8:
-        return "Utf8";
-
-      case Encoding_Latin1:
-        return "Latin1";
-
-      case Encoding_Latin2:
-        return "Latin2";
-
-      case Encoding_Latin3:
-        return "Latin3";
-
-      case Encoding_Latin4:
-        return "Latin4";
-
-      case Encoding_Latin5:
-        return "Latin5";
-
-      case Encoding_Cyrillic:
-        return "Cyrillic";
-
-      case Encoding_Windows1251:
-        return "Windows1251";
-
-      case Encoding_Arabic:
-        return "Arabic";
-
-      case Encoding_Greek:
-        return "Greek";
-
-      case Encoding_Hebrew:
-        return "Hebrew";
-
-      case Encoding_Thai:
-        return "Thai";
-
-      case Encoding_Japanese:
-        return "Japanese";
-
-      case Encoding_Chinese:
-        return "Chinese";
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(PhotometricInterpretation photometric)
-  {
-    switch (photometric)
-    {
-      case PhotometricInterpretation_RGB:
-        return "RGB";
-
-      case PhotometricInterpretation_Monochrome1:
-        return "MONOCHROME1";
-
-      case PhotometricInterpretation_Monochrome2:
-        return "MONOCHROME2";
-
-      case PhotometricInterpretation_ARGB:
-        return "ARGB";
-
-      case PhotometricInterpretation_CMYK:
-        return "CMYK";
-
-      case PhotometricInterpretation_HSV:
-        return "HSV";
-
-      case PhotometricInterpretation_Palette:
-        return "PALETTE COLOR";
-
-      case PhotometricInterpretation_YBRFull:
-        return "YBR_FULL";
-
-      case PhotometricInterpretation_YBRFull422:
-        return "YBR_FULL_422";
-
-      case PhotometricInterpretation_YBRPartial420:
-        return "YBR_PARTIAL_420"; 
-
-      case PhotometricInterpretation_YBRPartial422:
-        return "YBR_PARTIAL_422"; 
-
-      case PhotometricInterpretation_YBR_ICT:
-        return "YBR_ICT"; 
-
-      case PhotometricInterpretation_YBR_RCT:
-        return "YBR_RCT"; 
-
-      case PhotometricInterpretation_Unknown:
-        return "Unknown";
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(RequestOrigin origin)
-  {
-    switch (origin)
-    {
-      case RequestOrigin_Unknown:
-        return "Unknown";
-
-      case RequestOrigin_DicomProtocol:
-        return "DicomProtocol";
-
-      case RequestOrigin_RestApi:
-        return "RestApi";
-
-      case RequestOrigin_Plugins:
-        return "Plugins";
-
-      case RequestOrigin_Lua:
-        return "Lua";
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(LogLevel level)
-  {
-    switch (level)
-    {
-      case LogLevel_Error:
-        return "ERROR";
-
-      case LogLevel_Warning:
-        return "WARNING";
-
-      case LogLevel_Info:
-        return "INFO";
-
-      case LogLevel_Trace:
-        return "TRACE";
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(PixelFormat format)
-  {
-    switch (format)
-    {
-      case PixelFormat_RGB24:
-        return "RGB24";
-
-      case PixelFormat_RGBA32:
-        return "RGBA32";
-
-      case PixelFormat_BGRA32:
-        return "BGRA32";
-
-      case PixelFormat_Grayscale8:
-        return "Grayscale (unsigned 8bpp)";
-
-      case PixelFormat_Grayscale16:
-        return "Grayscale (unsigned 16bpp)";
-
-      case PixelFormat_SignedGrayscale16:
-        return "Grayscale (signed 16bpp)";
-
-      case PixelFormat_Float32:
-        return "Grayscale (float 32bpp)";
-
-      case PixelFormat_Grayscale32:
-        return "Grayscale (unsigned 32bpp)";
-
-      case PixelFormat_RGB48:
-        return "RGB48";
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(ModalityManufacturer manufacturer)
-  {
-    switch (manufacturer)
-    {
-      case ModalityManufacturer_Generic:
-        return "Generic";
-
-      case ModalityManufacturer_GenericNoWildcardInDates:
-        return "GenericNoWildcardInDates";
-
-      case ModalityManufacturer_GenericNoUniversalWildcard:
-        return "GenericNoUniversalWildcard";
-
-      case ModalityManufacturer_StoreScp:
-        return "StoreScp";
-      
-      case ModalityManufacturer_ClearCanvas:
-        return "ClearCanvas";
-      
-      case ModalityManufacturer_Dcm4Chee:
-        return "Dcm4Chee";
-      
-      case ModalityManufacturer_Vitrea:
-        return "Vitrea";
-      
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(DicomRequestType type)
-  {
-    switch (type)
-    {
-      case DicomRequestType_Echo:
-        return "Echo";
-        break;
-
-      case DicomRequestType_Find:
-        return "Find";
-        break;
-
-      case DicomRequestType_Get:
-        return "Get";
-        break;
-
-      case DicomRequestType_Move:
-        return "Move";
-        break;
-
-      case DicomRequestType_Store:
-        return "Store";
-        break;
-
-      default: 
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(TransferSyntax syntax)
-  {
-    switch (syntax)
-    {
-      case TransferSyntax_Deflated:
-        return "Deflated";
-
-      case TransferSyntax_Jpeg:
-        return "JPEG";
-
-      case TransferSyntax_Jpeg2000:
-        return "JPEG2000";
-
-      case TransferSyntax_JpegLossless:
-        return "JPEG Lossless";
-
-      case TransferSyntax_Jpip:
-        return "JPIP";
-
-      case TransferSyntax_Mpeg2:
-        return "MPEG2";
-
-      case TransferSyntax_Rle:
-        return "RLE";
-
-      default: 
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(DicomVersion version)
-  {
-    switch (version)
-    {
-      case DicomVersion_2008:
-        return "2008";
-        break;
-
-      case DicomVersion_2017c:
-        return "2017c";
-        break;
-
-      default: 
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  const char* EnumerationToString(ValueRepresentation vr)
-  {
-    switch (vr)
-    {
-      case ValueRepresentation_ApplicationEntity:     // AE
-        return "AE";
-
-      case ValueRepresentation_AgeString:             // AS
-        return "AS";
-
-      case ValueRepresentation_AttributeTag:          // AT (2 x uint16_t)
-        return "AT";
-
-      case ValueRepresentation_CodeString:            // CS
-        return "CS";
-
-      case ValueRepresentation_Date:                  // DA
-        return "DA";
-
-      case ValueRepresentation_DecimalString:         // DS
-        return "DS";
-
-      case ValueRepresentation_DateTime:              // DT
-        return "DT";
-
-      case ValueRepresentation_FloatingPointSingle:   // FL (float)
-        return "FL";
-
-      case ValueRepresentation_FloatingPointDouble:   // FD (double)
-        return "FD";
-
-      case ValueRepresentation_IntegerString:         // IS
-        return "IS";
-
-      case ValueRepresentation_LongString:            // LO
-        return "LO";
-
-      case ValueRepresentation_LongText:              // LT
-        return "LT";
-
-      case ValueRepresentation_OtherByte:             // OB
-        return "OB";
-
-      case ValueRepresentation_OtherDouble:           // OD
-        return "OD";
-
-      case ValueRepresentation_OtherFloat:            // OF
-        return "OF";
-
-      case ValueRepresentation_OtherLong:             // OL
-        return "OL";
-
-      case ValueRepresentation_OtherWord:             // OW
-        return "OW";
-
-      case ValueRepresentation_PersonName:            // PN
-        return "PN";
-
-      case ValueRepresentation_ShortString:           // SH
-        return "SH";
-
-      case ValueRepresentation_SignedLong:            // SL (int32_t)
-        return "SL";
-
-      case ValueRepresentation_Sequence:              // SQ
-        return "SQ";
-
-      case ValueRepresentation_SignedShort:           // SS (int16_t)
-        return "SS";
-
-      case ValueRepresentation_ShortText:             // ST
-        return "ST";
-
-      case ValueRepresentation_Time:                  // TM
-        return "TM";
-
-      case ValueRepresentation_UnlimitedCharacters:   // UC
-        return "UC";
-
-      case ValueRepresentation_UniqueIdentifier:      // UI (UID)
-        return "UI";
-
-      case ValueRepresentation_UnsignedLong:          // UL (uint32_t)
-        return "UL";
-
-      case ValueRepresentation_Unknown:               // UN
-        return "UN";
-
-      case ValueRepresentation_UniversalResource:     // UR (URI or URL)
-        return "UR";
-
-      case ValueRepresentation_UnsignedShort:         // US (uint16_t)
-        return "US";
-
-      case ValueRepresentation_UnlimitedText:         // UT
-        return "UT";
-
-      case ValueRepresentation_NotSupported:
-        return "Not supported";
-
-      default: 
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  Encoding StringToEncoding(const char* encoding)
-  {
-    std::string s(encoding);
-    Toolbox::ToUpperCase(s);
-
-    if (s == "UTF8")
-    {
-      return Encoding_Utf8;
-    }
-
-    if (s == "ASCII")
-    {
-      return Encoding_Ascii;
-    }
-
-    if (s == "LATIN1")
-    {
-      return Encoding_Latin1;
-    }
-
-    if (s == "LATIN2")
-    {
-      return Encoding_Latin2;
-    }
-
-    if (s == "LATIN3")
-    {
-      return Encoding_Latin3;
-    }
-
-    if (s == "LATIN4")
-    {
-      return Encoding_Latin4;
-    }
-
-    if (s == "LATIN5")
-    {
-      return Encoding_Latin5;
-    }
-
-    if (s == "CYRILLIC")
-    {
-      return Encoding_Cyrillic;
-    }
-
-    if (s == "WINDOWS1251")
-    {
-      return Encoding_Windows1251;
-    }
-
-    if (s == "ARABIC")
-    {
-      return Encoding_Arabic;
-    }
-
-    if (s == "GREEK")
-    {
-      return Encoding_Greek;
-    }
-
-    if (s == "HEBREW")
-    {
-      return Encoding_Hebrew;
-    }
-
-    if (s == "THAI")
-    {
-      return Encoding_Thai;
-    }
-
-    if (s == "JAPANESE")
-    {
-      return Encoding_Japanese;
-    }
-
-    if (s == "CHINESE")
-    {
-      return Encoding_Chinese;
-    }
-
-    throw OrthancException(ErrorCode_ParameterOutOfRange);
-  }
-
-
-  ResourceType StringToResourceType(const char* type)
-  {
-    std::string s(type);
-    Toolbox::ToUpperCase(s);
-
-    if (s == "PATIENT" || s == "PATIENTS")
-    {
-      return ResourceType_Patient;
-    }
-    else if (s == "STUDY" || s == "STUDIES")
-    {
-      return ResourceType_Study;
-    }
-    else if (s == "SERIES")
-    {
-      return ResourceType_Series;
-    }
-    else if (s == "INSTANCE"  || s == "IMAGE" || 
-             s == "INSTANCES" || s == "IMAGES")
-    {
-      return ResourceType_Instance;
-    }
-
-    throw OrthancException(ErrorCode_ParameterOutOfRange);
-  }
-
-
-  ImageFormat StringToImageFormat(const char* format)
-  {
-    std::string s(format);
-    Toolbox::ToUpperCase(s);
-
-    if (s == "PNG")
-    {
-      return ImageFormat_Png;
-    }
-
-    throw OrthancException(ErrorCode_ParameterOutOfRange);
-  }
-
-
-  LogLevel StringToLogLevel(const char *level)
-  {
-    if (strcmp(level, "ERROR") == 0)
-    {
-      return LogLevel_Error;
-    }
-    else if (strcmp(level, "WARNING") == 0)
-    {
-      return LogLevel_Warning;
-    }
-    else if (strcmp(level, "INFO") == 0)
-    {
-      return LogLevel_Info;
-    }
-    else if (strcmp(level, "TRACE") == 0)
-    {
-      return LogLevel_Trace;
-    }
-    else 
-    {
-      throw OrthancException(ErrorCode_InternalError);
-    }
-  }
-
-
-  ValueRepresentation StringToValueRepresentation(const std::string& vr,
-                                                  bool throwIfUnsupported)
-  {
-    if (vr == "AE")
-    {
-      return ValueRepresentation_ApplicationEntity;
-    }
-    else if (vr == "AS")
-    {
-      return ValueRepresentation_AgeString;
-    }
-    else if (vr == "AT")
-    {
-      return ValueRepresentation_AttributeTag;
-    }
-    else if (vr == "CS")
-    {
-      return ValueRepresentation_CodeString;
-    }
-    else if (vr == "DA")
-    {
-      return ValueRepresentation_Date;
-    }
-    else if (vr == "DS")
-    {
-      return ValueRepresentation_DecimalString;
-    }
-    else if (vr == "DT")
-    {
-      return ValueRepresentation_DateTime;
-    }
-    else if (vr == "FL")
-    {
-      return ValueRepresentation_FloatingPointSingle;
-    }
-    else if (vr == "FD")
-    {
-      return ValueRepresentation_FloatingPointDouble;
-    }
-    else if (vr == "IS")
-    {
-      return ValueRepresentation_IntegerString;
-    }
-    else if (vr == "LO")
-    {
-      return ValueRepresentation_LongString;
-    }
-    else if (vr == "LT")
-    {
-      return ValueRepresentation_LongText;
-    }
-    else if (vr == "OB")
-    {
-      return ValueRepresentation_OtherByte;
-    }
-    else if (vr == "OD")
-    {
-      return ValueRepresentation_OtherDouble;
-    }
-    else if (vr == "OF")
-    {
-      return ValueRepresentation_OtherFloat;
-    }
-    else if (vr == "OL")
-    {
-      return ValueRepresentation_OtherLong;
-    }
-    else if (vr == "OW")
-    {
-      return ValueRepresentation_OtherWord;
-    }
-    else if (vr == "PN")
-    {
-      return ValueRepresentation_PersonName;
-    }
-    else if (vr == "SH")
-    {
-      return ValueRepresentation_ShortString;
-    }
-    else if (vr == "SL")
-    {
-      return ValueRepresentation_SignedLong;
-    }
-    else if (vr == "SQ")
-    {
-      return ValueRepresentation_Sequence;
-    }
-    else if (vr == "SS")
-    {
-      return ValueRepresentation_SignedShort;
-    }
-    else if (vr == "ST")
-    {
-      return ValueRepresentation_ShortText;
-    }
-    else if (vr == "TM")
-    {
-      return ValueRepresentation_Time;
-    }
-    else if (vr == "UC")
-    {
-      return ValueRepresentation_UnlimitedCharacters;
-    }
-    else if (vr == "UI")
-    {
-      return ValueRepresentation_UniqueIdentifier;
-    }
-    else if (vr == "UL")
-    {
-      return ValueRepresentation_UnsignedLong;
-    }
-    else if (vr == "UN")
-    {
-      return ValueRepresentation_Unknown;
-    }
-    else if (vr == "UR")
-    {
-      return ValueRepresentation_UniversalResource;
-    }
-    else if (vr == "US")
-    {
-      return ValueRepresentation_UnsignedShort;
-    }
-    else if (vr == "UT")
-    {
-      return ValueRepresentation_UnlimitedText;
-    }
-    else
-    {
-      std::string s = "Unsupported value representation encountered: " + vr;
-
-      if (throwIfUnsupported)
-      {
-        LOG(ERROR) << s;
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-      }
-      else
-      {
-        LOG(INFO) << s;
-        return ValueRepresentation_NotSupported;
-      }
-    }
-  }
-
-
-  PhotometricInterpretation StringToPhotometricInterpretation(const char* value)
-  {
-    // http://dicom.nema.org/medical/dicom/2017a/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2
-    std::string s(value);
-
-    if (s == "MONOCHROME1")
-    {
-      return PhotometricInterpretation_Monochrome1;
-    }
-    
-    if (s == "MONOCHROME2")
-    {
-      return PhotometricInterpretation_Monochrome2;
-    }
-
-    if (s == "PALETTE COLOR")
-    {
-      return PhotometricInterpretation_Palette;
-    }
-    
-    if (s == "RGB")
-    {
-      return PhotometricInterpretation_RGB;
-    }
-    
-    if (s == "HSV")
-    {
-      return PhotometricInterpretation_HSV;
-    }
-    
-    if (s == "ARGB")
-    {
-      return PhotometricInterpretation_ARGB;
-    }    
-
-    if (s == "CMYK")
-    {
-      return PhotometricInterpretation_CMYK;
-    }    
-
-    if (s == "YBR_FULL")
-    {
-      return PhotometricInterpretation_YBRFull;
-    }
-    
-    if (s == "YBR_FULL_422")
-    {
-      return PhotometricInterpretation_YBRFull422;
-    }
-    
-    if (s == "YBR_PARTIAL_422")
-    {
-      return PhotometricInterpretation_YBRPartial422;
-    }
-    
-    if (s == "YBR_PARTIAL_420")
-    {
-      return PhotometricInterpretation_YBRPartial420;
-    }
-    
-    if (s == "YBR_ICT")
-    {
-      return PhotometricInterpretation_YBR_ICT;
-    }
-    
-    if (s == "YBR_RCT")
-    {
-      return PhotometricInterpretation_YBR_RCT;
-    }
-
-    throw OrthancException(ErrorCode_ParameterOutOfRange);
-  }
-  
-
-  ModalityManufacturer StringToModalityManufacturer(const std::string& manufacturer)
-  {
-    ModalityManufacturer result;
-    bool obsolete = false;
-    
-    if (manufacturer == "Generic")
-    {
-      return ModalityManufacturer_Generic;
-    }
-    else if (manufacturer == "GenericNoWildcardInDates")
-    {
-      return ModalityManufacturer_GenericNoWildcardInDates;
-    }
-    else if (manufacturer == "GenericNoUniversalWildcard")
-    {
-      return ModalityManufacturer_GenericNoUniversalWildcard;
-    }
-    else if (manufacturer == "ClearCanvas")
-    {
-      return ModalityManufacturer_ClearCanvas;
-    }
-    else if (manufacturer == "StoreScp")
-    {
-      return ModalityManufacturer_StoreScp;
-    }
-    else if (manufacturer == "Dcm4Chee")
-    {
-      return ModalityManufacturer_Dcm4Chee;
-    }
-    else if (manufacturer == "Vitrea")
-    {
-      return ModalityManufacturer_Vitrea;
-    }
-    else if (manufacturer == "AgfaImpax" ||
-             manufacturer == "SyngoVia")
-    {
-      result = ModalityManufacturer_GenericNoWildcardInDates;
-      obsolete = true;
-    }
-    else if (manufacturer == "EFilm2" ||
-             manufacturer == "MedInria")
-    {
-      result = ModalityManufacturer_Generic;
-      obsolete = true;
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    if (obsolete)
-    {
-      LOG(WARNING) << "The \"" << manufacturer << "\" manufacturer is obsolete since "
-                   << "Orthanc 1.3.0. To guarantee compatibility with future Orthanc "
-                   << "releases, you should replace it by \""
-                   << EnumerationToString(result)
-                   << "\" in your configuration file.";
-    }
-
-    return result;
-  }
-
-
-  DicomVersion StringToDicomVersion(const std::string& version)
-  {
-    if (version == "2008")
-    {
-      return DicomVersion_2008;
-    }
-    else if (version == "2017c")
-    {
-      return DicomVersion_2017c;
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  unsigned int GetBytesPerPixel(PixelFormat format)
-  {
-    switch (format)
-    {
-      case PixelFormat_Grayscale8:
-        return 1;
-
-      case PixelFormat_Grayscale16:
-      case PixelFormat_SignedGrayscale16:
-        return 2;
-
-      case PixelFormat_RGB24:
-        return 3;
-
-      case PixelFormat_RGBA32:
-      case PixelFormat_BGRA32:
-      case PixelFormat_Grayscale32:
-        return 4;
-
-      case PixelFormat_Float32:
-        assert(sizeof(float) == 4);
-        return 4;
-
-      case PixelFormat_RGB48:
-        return 6;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  bool GetDicomEncoding(Encoding& encoding,
-                        const char* specificCharacterSet)
-  {
-    std::string s = Toolbox::StripSpaces(specificCharacterSet);
-    Toolbox::ToUpperCase(s);
-
-    // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2
-    // https://github.com/dcm4che/dcm4che/blob/master/dcm4che-core/src/main/java/org/dcm4che3/data/SpecificCharacterSet.java
-    if (s == "ISO_IR 6" ||
-        s == "ISO 2022 IR 6")
-    {
-      encoding = Encoding_Ascii;
-    }
-    else if (s == "ISO_IR 192")
-    {
-      encoding = Encoding_Utf8;
-    }
-    else if (s == "ISO_IR 100" ||
-             s == "ISO 2022 IR 100")
-    {
-      encoding = Encoding_Latin1;
-    }
-    else if (s == "ISO_IR 101" ||
-             s == "ISO 2022 IR 101")
-    {
-      encoding = Encoding_Latin2;
-    }
-    else if (s == "ISO_IR 109" ||
-             s == "ISO 2022 IR 109")
-    {
-      encoding = Encoding_Latin3;
-    }
-    else if (s == "ISO_IR 110" ||
-             s == "ISO 2022 IR 110")
-    {
-      encoding = Encoding_Latin4;
-    }
-    else if (s == "ISO_IR 148" ||
-             s == "ISO 2022 IR 148")
-    {
-      encoding = Encoding_Latin5;
-    }
-    else if (s == "ISO_IR 144" ||
-             s == "ISO 2022 IR 144")
-    {
-      encoding = Encoding_Cyrillic;
-    }
-    else if (s == "ISO_IR 127" ||
-             s == "ISO 2022 IR 127")
-    {
-      encoding = Encoding_Arabic;
-    }
-    else if (s == "ISO_IR 126" ||
-             s == "ISO 2022 IR 126")
-    {
-      encoding = Encoding_Greek;
-    }
-    else if (s == "ISO_IR 138" ||
-             s == "ISO 2022 IR 138")
-    {
-      encoding = Encoding_Hebrew;
-    }
-    else if (s == "ISO_IR 166" || s == "ISO 2022 IR 166")
-    {
-      encoding = Encoding_Thai;
-    }
-    else if (s == "ISO_IR 13" || s == "ISO 2022 IR 13")
-    {
-      encoding = Encoding_Japanese;
-    }
-    else if (s == "GB18030" || s == "GBK")
-    {
-      /**
-       * According to tumashu@163.com, "In China, many dicom file's
-       * 0008,0005 tag is set as "GBK", instead of "GB18030", GBK is a
-       * subset of GB18030, and which is used frequently in China,
-       * suggest support it."
-       * https://groups.google.com/d/msg/orthanc-users/WMM8LMbjpUc/02-1f_yFCgAJ
-       **/
-      encoding = Encoding_Chinese;
-    }
-    /*
-      else if (s == "ISO 2022 IR 149")
-      {
-      TODO
-      }
-      else if (s == "ISO 2022 IR 159")
-      {
-      TODO
-      }
-      else if (s == "ISO 2022 IR 87")
-      {
-      TODO
-      }
-    */
-    else
-    {
-      return false;
-    }
-
-    // The encoding was properly detected
-    return true;
-  }
-
-
-  ResourceType GetChildResourceType(ResourceType type)
-  {
-    switch (type)
-    {
-      case ResourceType_Patient:
-        return ResourceType_Study;
-
-      case ResourceType_Study:
-        return ResourceType_Series;
-        
-      case ResourceType_Series:
-        return ResourceType_Instance;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  ResourceType GetParentResourceType(ResourceType type)
-  {
-    switch (type)
-    {
-      case ResourceType_Study:
-        return ResourceType_Patient;
-        
-      case ResourceType_Series:
-        return ResourceType_Study;
-
-      case ResourceType_Instance:
-        return ResourceType_Series;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  DicomModule GetModule(ResourceType type)
-  {
-    switch (type)
-    {
-      case ResourceType_Patient:
-        return DicomModule_Patient;
-
-      case ResourceType_Study:
-        return DicomModule_Study;
-        
-      case ResourceType_Series:
-        return DicomModule_Series;
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-
-  const char* GetDicomSpecificCharacterSet(Encoding encoding)
-  {
-    // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2
-    switch (encoding)
-    {
-      case Encoding_Ascii:
-        return "ISO_IR 6";
-
-      case Encoding_Utf8:
-        return "ISO_IR 192";
-
-      case Encoding_Latin1:
-        return "ISO_IR 100";
-
-      case Encoding_Latin2:
-        return "ISO_IR 101";
-
-      case Encoding_Latin3:
-        return "ISO_IR 109";
-
-      case Encoding_Latin4:
-        return "ISO_IR 110";
-
-      case Encoding_Latin5:
-        return "ISO_IR 148";
-
-      case Encoding_Cyrillic:
-        return "ISO_IR 144";
-
-      case Encoding_Arabic:
-        return "ISO_IR 127";
-
-      case Encoding_Greek:
-        return "ISO_IR 126";
-
-      case Encoding_Hebrew:
-        return "ISO_IR 138";
-
-      case Encoding_Japanese:
-        return "ISO_IR 13";
-
-      case Encoding_Chinese:
-        return "GB18030";
-
-      case Encoding_Thai:
-        return "ISO_IR 166";
-
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  // This function is autogenerated by the script
-  // "Resources/GenerateErrorCodes.py"
-  HttpStatus ConvertErrorCodeToHttpStatus(ErrorCode error)
-  {
-    switch (error)
-    {
-      case ErrorCode_Success:
-        return HttpStatus_200_Ok;
-
-      case ErrorCode_ParameterOutOfRange:
-        return HttpStatus_400_BadRequest;
-
-      case ErrorCode_BadParameterType:
-        return HttpStatus_400_BadRequest;
-
-      case ErrorCode_InexistentItem:
-        return HttpStatus_404_NotFound;
-
-      case ErrorCode_BadRequest:
-        return HttpStatus_400_BadRequest;
-
-      case ErrorCode_UriSyntax:
-        return HttpStatus_400_BadRequest;
-
-      case ErrorCode_InexistentFile:
-        return HttpStatus_404_NotFound;
-
-      case ErrorCode_BadFileFormat:
-        return HttpStatus_400_BadRequest;
-
-      case ErrorCode_UnknownResource:
-        return HttpStatus_404_NotFound;
-
-      case ErrorCode_InexistentTag:
-        return HttpStatus_404_NotFound;
-
-      case ErrorCode_BadJson:
-        return HttpStatus_400_BadRequest;
-
-      case ErrorCode_Unauthorized:
-        return HttpStatus_401_Unauthorized;
-
-      case ErrorCode_NotAcceptable:
-        return HttpStatus_406_NotAcceptable;
-
-      case ErrorCode_DatabaseUnavailable:
-        return HttpStatus_503_ServiceUnavailable;
-
-      default:
-        return HttpStatus_500_InternalServerError;
-    }
-  }
-
-
-  bool IsUserContentType(FileContentType type)
-  {
-    return (type >= FileContentType_StartUser &&
-            type <= FileContentType_EndUser);
-  }
-
-
-  bool IsBinaryValueRepresentation(ValueRepresentation vr)
-  {
-    // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html
-
-    switch (vr)
-    {
-      case ValueRepresentation_ApplicationEntity:     // AE
-      case ValueRepresentation_AgeString:             // AS
-      case ValueRepresentation_CodeString:            // CS
-      case ValueRepresentation_Date:                  // DA
-      case ValueRepresentation_DecimalString:         // DS
-      case ValueRepresentation_DateTime:              // DT
-      case ValueRepresentation_IntegerString:         // IS
-      case ValueRepresentation_LongString:            // LO
-      case ValueRepresentation_LongText:              // LT
-      case ValueRepresentation_PersonName:            // PN
-      case ValueRepresentation_ShortString:           // SH
-      case ValueRepresentation_ShortText:             // ST
-      case ValueRepresentation_Time:                  // TM
-      case ValueRepresentation_UnlimitedCharacters:   // UC
-      case ValueRepresentation_UniqueIdentifier:      // UI (UID)
-      case ValueRepresentation_UniversalResource:     // UR (URI or URL)
-      case ValueRepresentation_UnlimitedText:         // UT
-      {
-        return false;
-      }
-
-      /**
-       * Below are all the VR whose character repertoire is tagged as
-       * "not applicable"
-       **/
-      case ValueRepresentation_AttributeTag:          // AT (2 x uint16_t)
-      case ValueRepresentation_FloatingPointSingle:   // FL (float)
-      case ValueRepresentation_FloatingPointDouble:   // FD (double)
-      case ValueRepresentation_OtherByte:             // OB
-      case ValueRepresentation_OtherDouble:           // OD
-      case ValueRepresentation_OtherFloat:            // OF
-      case ValueRepresentation_OtherLong:             // OL
-      case ValueRepresentation_OtherWord:             // OW
-      case ValueRepresentation_SignedLong:            // SL (int32_t)
-      case ValueRepresentation_Sequence:              // SQ
-      case ValueRepresentation_SignedShort:           // SS (int16_t)
-      case ValueRepresentation_UnsignedLong:          // UL (uint32_t)
-      case ValueRepresentation_Unknown:               // UN
-      case ValueRepresentation_UnsignedShort:         // US (uint16_t)
-      {
-        return true;
-      }
-
-      case ValueRepresentation_NotSupported:
-      default:
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }  
-
-
-  static boost::mutex  defaultEncodingMutex_;  // Should not be necessary
-  static Encoding      defaultEncoding_ = ORTHANC_DEFAULT_DICOM_ENCODING;
-  
-  Encoding GetDefaultDicomEncoding()
-  {
-    boost::mutex::scoped_lock lock(defaultEncodingMutex_);
-    return defaultEncoding_;
-  }
-
-  void SetDefaultDicomEncoding(Encoding encoding)
-  {
-    std::string name = EnumerationToString(encoding);
-    
-    {
-      boost::mutex::scoped_lock lock(defaultEncodingMutex_);
-      defaultEncoding_ = encoding;
-    }
-
-    LOG(INFO) << "Default encoding for DICOM was changed to: " << name;
-  }
-
-}
--- a/Resources/Orthanc/Core/Enumerations.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,664 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 <string>
-
-
-#if defined(_MSC_VER)
-#  define ORTHANC_FORCE_INLINE __forceinline
-#elif defined(__GNUC__) || defined(__clang__) || defined(__EMSCRIPTEN__)
-#  define ORTHANC_FORCE_INLINE inline __attribute((always_inline))
-#else
-#  error Please support your compiler here
-#endif
-
-
-namespace Orthanc
-{
-  enum Endianness
-  {
-    Endianness_Unknown,
-    Endianness_Big,
-    Endianness_Little
-  };
-
-  // This enumeration is autogenerated by the script
-  // "Resources/GenerateErrorCodes.py"
-  enum ErrorCode
-  {
-    ErrorCode_InternalError = -1    /*!< Internal error */,
-    ErrorCode_Success = 0    /*!< Success */,
-    ErrorCode_Plugin = 1    /*!< Error encountered within the plugin engine */,
-    ErrorCode_NotImplemented = 2    /*!< Not implemented yet */,
-    ErrorCode_ParameterOutOfRange = 3    /*!< Parameter out of range */,
-    ErrorCode_NotEnoughMemory = 4    /*!< The server hosting Orthanc is running out of memory */,
-    ErrorCode_BadParameterType = 5    /*!< Bad type for a parameter */,
-    ErrorCode_BadSequenceOfCalls = 6    /*!< Bad sequence of calls */,
-    ErrorCode_InexistentItem = 7    /*!< Accessing an inexistent item */,
-    ErrorCode_BadRequest = 8    /*!< Bad request */,
-    ErrorCode_NetworkProtocol = 9    /*!< Error in the network protocol */,
-    ErrorCode_SystemCommand = 10    /*!< Error while calling a system command */,
-    ErrorCode_Database = 11    /*!< Error with the database engine */,
-    ErrorCode_UriSyntax = 12    /*!< Badly formatted URI */,
-    ErrorCode_InexistentFile = 13    /*!< Inexistent file */,
-    ErrorCode_CannotWriteFile = 14    /*!< Cannot write to file */,
-    ErrorCode_BadFileFormat = 15    /*!< Bad file format */,
-    ErrorCode_Timeout = 16    /*!< Timeout */,
-    ErrorCode_UnknownResource = 17    /*!< Unknown resource */,
-    ErrorCode_IncompatibleDatabaseVersion = 18    /*!< Incompatible version of the database */,
-    ErrorCode_FullStorage = 19    /*!< The file storage is full */,
-    ErrorCode_CorruptedFile = 20    /*!< Corrupted file (e.g. inconsistent MD5 hash) */,
-    ErrorCode_InexistentTag = 21    /*!< Inexistent tag */,
-    ErrorCode_ReadOnly = 22    /*!< Cannot modify a read-only data structure */,
-    ErrorCode_IncompatibleImageFormat = 23    /*!< Incompatible format of the images */,
-    ErrorCode_IncompatibleImageSize = 24    /*!< Incompatible size of the images */,
-    ErrorCode_SharedLibrary = 25    /*!< Error while using a shared library (plugin) */,
-    ErrorCode_UnknownPluginService = 26    /*!< Plugin invoking an unknown service */,
-    ErrorCode_UnknownDicomTag = 27    /*!< Unknown DICOM tag */,
-    ErrorCode_BadJson = 28    /*!< Cannot parse a JSON document */,
-    ErrorCode_Unauthorized = 29    /*!< Bad credentials were provided to an HTTP request */,
-    ErrorCode_BadFont = 30    /*!< Badly formatted font file */,
-    ErrorCode_DatabasePlugin = 31    /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */,
-    ErrorCode_StorageAreaPlugin = 32    /*!< Error in the plugin implementing a custom storage area */,
-    ErrorCode_EmptyRequest = 33    /*!< The request is empty */,
-    ErrorCode_NotAcceptable = 34    /*!< Cannot send a response which is acceptable according to the Accept HTTP header */,
-    ErrorCode_NullPointer = 35    /*!< Cannot handle a NULL pointer */,
-    ErrorCode_DatabaseUnavailable = 36    /*!< The database is currently not available (probably a transient situation) */,
-    ErrorCode_SQLiteNotOpened = 1000    /*!< SQLite: The database is not opened */,
-    ErrorCode_SQLiteAlreadyOpened = 1001    /*!< SQLite: Connection is already open */,
-    ErrorCode_SQLiteCannotOpen = 1002    /*!< SQLite: Unable to open the database */,
-    ErrorCode_SQLiteStatementAlreadyUsed = 1003    /*!< SQLite: This cached statement is already being referred to */,
-    ErrorCode_SQLiteExecute = 1004    /*!< SQLite: Cannot execute a command */,
-    ErrorCode_SQLiteRollbackWithoutTransaction = 1005    /*!< SQLite: Rolling back a nonexistent transaction (have you called Begin()?) */,
-    ErrorCode_SQLiteCommitWithoutTransaction = 1006    /*!< SQLite: Committing a nonexistent transaction */,
-    ErrorCode_SQLiteRegisterFunction = 1007    /*!< SQLite: Unable to register a function */,
-    ErrorCode_SQLiteFlush = 1008    /*!< SQLite: Unable to flush the database */,
-    ErrorCode_SQLiteCannotRun = 1009    /*!< SQLite: Cannot run a cached statement */,
-    ErrorCode_SQLiteCannotStep = 1010    /*!< SQLite: Cannot step over a cached statement */,
-    ErrorCode_SQLiteBindOutOfRange = 1011    /*!< SQLite: Bing a value while out of range (serious error) */,
-    ErrorCode_SQLitePrepareStatement = 1012    /*!< SQLite: Cannot prepare a cached statement */,
-    ErrorCode_SQLiteTransactionAlreadyStarted = 1013    /*!< SQLite: Beginning the same transaction twice */,
-    ErrorCode_SQLiteTransactionCommit = 1014    /*!< SQLite: Failure when committing the transaction */,
-    ErrorCode_SQLiteTransactionBegin = 1015    /*!< SQLite: Cannot start a transaction */,
-    ErrorCode_DirectoryOverFile = 2000    /*!< The directory to be created is already occupied by a regular file */,
-    ErrorCode_FileStorageCannotWrite = 2001    /*!< Unable to create a subdirectory or a file in the file storage */,
-    ErrorCode_DirectoryExpected = 2002    /*!< The specified path does not point to a directory */,
-    ErrorCode_HttpPortInUse = 2003    /*!< The TCP port of the HTTP server is privileged or already in use */,
-    ErrorCode_DicomPortInUse = 2004    /*!< The TCP port of the DICOM server is privileged or already in use */,
-    ErrorCode_BadHttpStatusInRest = 2005    /*!< This HTTP status is not allowed in a REST API */,
-    ErrorCode_RegularFileExpected = 2006    /*!< The specified path does not point to a regular file */,
-    ErrorCode_PathToExecutable = 2007    /*!< Unable to get the path to the executable */,
-    ErrorCode_MakeDirectory = 2008    /*!< Cannot create a directory */,
-    ErrorCode_BadApplicationEntityTitle = 2009    /*!< An application entity title (AET) cannot be empty or be longer than 16 characters */,
-    ErrorCode_NoCFindHandler = 2010    /*!< No request handler factory for DICOM C-FIND SCP */,
-    ErrorCode_NoCMoveHandler = 2011    /*!< No request handler factory for DICOM C-MOVE SCP */,
-    ErrorCode_NoCStoreHandler = 2012    /*!< No request handler factory for DICOM C-STORE SCP */,
-    ErrorCode_NoApplicationEntityFilter = 2013    /*!< No application entity filter */,
-    ErrorCode_NoSopClassOrInstance = 2014    /*!< DicomUserConnection: Unable to find the SOP class and instance */,
-    ErrorCode_NoPresentationContext = 2015    /*!< DicomUserConnection: No acceptable presentation context for modality */,
-    ErrorCode_DicomFindUnavailable = 2016    /*!< DicomUserConnection: The C-FIND command is not supported by the remote SCP */,
-    ErrorCode_DicomMoveUnavailable = 2017    /*!< DicomUserConnection: The C-MOVE command is not supported by the remote SCP */,
-    ErrorCode_CannotStoreInstance = 2018    /*!< Cannot store an instance */,
-    ErrorCode_CreateDicomNotString = 2019    /*!< Only string values are supported when creating DICOM instances */,
-    ErrorCode_CreateDicomOverrideTag = 2020    /*!< Trying to override a value inherited from a parent module */,
-    ErrorCode_CreateDicomUseContent = 2021    /*!< Use \"Content\" to inject an image into a new DICOM instance */,
-    ErrorCode_CreateDicomNoPayload = 2022    /*!< No payload is present for one instance in the series */,
-    ErrorCode_CreateDicomUseDataUriScheme = 2023    /*!< The payload of the DICOM instance must be specified according to Data URI scheme */,
-    ErrorCode_CreateDicomBadParent = 2024    /*!< Trying to attach a new DICOM instance to an inexistent resource */,
-    ErrorCode_CreateDicomParentIsInstance = 2025    /*!< Trying to attach a new DICOM instance to an instance (must be a series, study or patient) */,
-    ErrorCode_CreateDicomParentEncoding = 2026    /*!< Unable to get the encoding of the parent resource */,
-    ErrorCode_UnknownModality = 2027    /*!< Unknown modality */,
-    ErrorCode_BadJobOrdering = 2028    /*!< Bad ordering of filters in a job */,
-    ErrorCode_JsonToLuaTable = 2029    /*!< Cannot convert the given JSON object to a Lua table */,
-    ErrorCode_CannotCreateLua = 2030    /*!< Cannot create the Lua context */,
-    ErrorCode_CannotExecuteLua = 2031    /*!< Cannot execute a Lua command */,
-    ErrorCode_LuaAlreadyExecuted = 2032    /*!< Arguments cannot be pushed after the Lua function is executed */,
-    ErrorCode_LuaBadOutput = 2033    /*!< The Lua function does not give the expected number of outputs */,
-    ErrorCode_NotLuaPredicate = 2034    /*!< The Lua function is not a predicate (only true/false outputs allowed) */,
-    ErrorCode_LuaReturnsNoString = 2035    /*!< The Lua function does not return a string */,
-    ErrorCode_StorageAreaAlreadyRegistered = 2036    /*!< Another plugin has already registered a custom storage area */,
-    ErrorCode_DatabaseBackendAlreadyRegistered = 2037    /*!< Another plugin has already registered a custom database back-end */,
-    ErrorCode_DatabaseNotInitialized = 2038    /*!< Plugin trying to call the database during its initialization */,
-    ErrorCode_SslDisabled = 2039    /*!< Orthanc has been built without SSL support */,
-    ErrorCode_CannotOrderSlices = 2040    /*!< Unable to order the slices of the series */,
-    ErrorCode_NoWorklistHandler = 2041    /*!< No request handler factory for DICOM C-Find Modality SCP */,
-    ErrorCode_AlreadyExistingTag = 2042    /*!< Cannot override the value of a tag that already exists */,
-    ErrorCode_START_PLUGINS = 1000000
-  };
-
-  enum LogLevel
-  {
-    LogLevel_Error,
-    LogLevel_Warning,
-    LogLevel_Info,
-    LogLevel_Trace
-  };
-
-
-  /**
-   * {summary}{The memory layout of the pixels (resp. voxels) of a 2D (resp. 3D) image.}
-   **/
-  enum PixelFormat
-  {
-    /**
-     * {summary}{Color image in RGB24 format.}
-     * {description}{This format describes a color image. The pixels are stored in 3
-     * consecutive bytes. The memory layout is RGB.}
-     **/
-    PixelFormat_RGB24 = 1,
-
-    /**
-     * {summary}{Color image in RGBA32 format.}
-     * {description}{This format describes a color image. The pixels are stored in 4
-     * consecutive bytes. The memory layout is RGBA.}
-     **/
-    PixelFormat_RGBA32 = 2,
-
-    /**
-     * {summary}{Graylevel 8bpp image.}
-     * {description}{The image is graylevel. Each pixel is unsigned and stored in one byte.}
-     **/
-    PixelFormat_Grayscale8 = 3,
-      
-    /**
-     * {summary}{Graylevel, unsigned 16bpp image.}
-     * {description}{The image is graylevel. Each pixel is unsigned and stored in two bytes.}
-     **/
-    PixelFormat_Grayscale16 = 4,
-      
-    /**
-     * {summary}{Graylevel, signed 16bpp image.}
-     * {description}{The image is graylevel. Each pixel is signed and stored in two bytes.}
-     **/
-    PixelFormat_SignedGrayscale16 = 5,
-      
-    /**
-     * {summary}{Graylevel, floating-point image.}
-     * {description}{The image is graylevel. Each pixel is floating-point and stored in 4 bytes.}
-     **/
-    PixelFormat_Float32 = 6,
-
-    // This is the memory layout for Cairo (for internal use in Stone of Orthanc)
-    PixelFormat_BGRA32 = 7,
-
-    /**
-     * {summary}{Graylevel, unsigned 32bpp image.}
-     * {description}{The image is graylevel. Each pixel is unsigned and stored in 4 bytes.}
-     **/
-    PixelFormat_Grayscale32 = 8,
-    
-    /**
-     * {summary}{Color image in RGB48 format.}
-     * {description}{This format describes a color image. The pixels are stored in 6
-     * consecutive bytes. The memory layout is RGB.}
-     **/
-    PixelFormat_RGB48 = 9
-  };
-
-
-  /**
-   * {summary}{The extraction mode specifies the way the values of the pixels are scaled when downloading a 2D image.}
-   **/
-  enum ImageExtractionMode
-  {
-    /**
-     * {summary}{Rescaled to 8bpp.}
-     * {description}{The minimum value of the image is set to 0, and its maximum value is set to 255.}
-     **/
-    ImageExtractionMode_Preview = 1,
-
-    /**
-     * {summary}{Truncation to the [0, 255] range.}
-     **/
-    ImageExtractionMode_UInt8 = 2,
-
-    /**
-     * {summary}{Truncation to the [0, 65535] range.}
-     **/
-    ImageExtractionMode_UInt16 = 3,
-
-    /**
-     * {summary}{Truncation to the [-32768, 32767] range.}
-     **/
-    ImageExtractionMode_Int16 = 4
-  };
-
-
-  /**
-   * Most common, non-joke and non-experimental HTTP status codes
-   * http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
-   **/
-  enum HttpStatus
-  {
-    HttpStatus_None = -1,
-
-    // 1xx Informational
-    HttpStatus_100_Continue = 100,
-    HttpStatus_101_SwitchingProtocols = 101,
-    HttpStatus_102_Processing = 102,
-
-    // 2xx Success
-    HttpStatus_200_Ok = 200,
-    HttpStatus_201_Created = 201,
-    HttpStatus_202_Accepted = 202,
-    HttpStatus_203_NonAuthoritativeInformation = 203,
-    HttpStatus_204_NoContent = 204,
-    HttpStatus_205_ResetContent = 205,
-    HttpStatus_206_PartialContent = 206,
-    HttpStatus_207_MultiStatus = 207,
-    HttpStatus_208_AlreadyReported = 208,
-    HttpStatus_226_IMUsed = 226,
-
-    // 3xx Redirection
-    HttpStatus_300_MultipleChoices = 300,
-    HttpStatus_301_MovedPermanently = 301,
-    HttpStatus_302_Found = 302,
-    HttpStatus_303_SeeOther = 303,
-    HttpStatus_304_NotModified = 304,
-    HttpStatus_305_UseProxy = 305,
-    HttpStatus_307_TemporaryRedirect = 307,
-
-    // 4xx Client Error
-    HttpStatus_400_BadRequest = 400,
-    HttpStatus_401_Unauthorized = 401,
-    HttpStatus_402_PaymentRequired = 402,
-    HttpStatus_403_Forbidden = 403,
-    HttpStatus_404_NotFound = 404,
-    HttpStatus_405_MethodNotAllowed = 405,
-    HttpStatus_406_NotAcceptable = 406,
-    HttpStatus_407_ProxyAuthenticationRequired = 407,
-    HttpStatus_408_RequestTimeout = 408,
-    HttpStatus_409_Conflict = 409,
-    HttpStatus_410_Gone = 410,
-    HttpStatus_411_LengthRequired = 411,
-    HttpStatus_412_PreconditionFailed = 412,
-    HttpStatus_413_RequestEntityTooLarge = 413,
-    HttpStatus_414_RequestUriTooLong = 414,
-    HttpStatus_415_UnsupportedMediaType = 415,
-    HttpStatus_416_RequestedRangeNotSatisfiable = 416,
-    HttpStatus_417_ExpectationFailed = 417,
-    HttpStatus_422_UnprocessableEntity = 422,
-    HttpStatus_423_Locked = 423,
-    HttpStatus_424_FailedDependency = 424,
-    HttpStatus_426_UpgradeRequired = 426,
-
-    // 5xx Server Error
-    HttpStatus_500_InternalServerError = 500,
-    HttpStatus_501_NotImplemented = 501,
-    HttpStatus_502_BadGateway = 502,
-    HttpStatus_503_ServiceUnavailable = 503,
-    HttpStatus_504_GatewayTimeout = 504,
-    HttpStatus_505_HttpVersionNotSupported = 505,
-    HttpStatus_506_VariantAlsoNegotiates = 506,
-    HttpStatus_507_InsufficientStorage = 507,
-    HttpStatus_509_BandwidthLimitExceeded = 509,
-    HttpStatus_510_NotExtended = 510
-  };
-
-
-  enum HttpMethod
-  {
-    HttpMethod_Get = 0,
-    HttpMethod_Post = 1,
-    HttpMethod_Delete = 2,
-    HttpMethod_Put = 3
-  };
-
-
-  enum ImageFormat
-  {
-    ImageFormat_Png = 1
-  };
-
-
-  // https://en.wikipedia.org/wiki/HTTP_compression
-  enum HttpCompression
-  {
-    HttpCompression_None,
-    HttpCompression_Deflate,
-    HttpCompression_Gzip
-  };
-
-
-  // Specific Character Sets
-  // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2
-  enum Encoding
-  {
-    Encoding_Ascii,
-    Encoding_Utf8,
-    Encoding_Latin1,
-    Encoding_Latin2,
-    Encoding_Latin3,
-    Encoding_Latin4,
-    Encoding_Latin5,                        // Turkish
-    Encoding_Cyrillic,
-    Encoding_Windows1251,                   // Windows-1251 (commonly used for Cyrillic)
-    Encoding_Arabic,
-    Encoding_Greek,
-    Encoding_Hebrew,
-    Encoding_Thai,                          // TIS 620-2533
-    Encoding_Japanese,                      // JIS X 0201 (Shift JIS): Katakana
-    Encoding_Chinese                        // GB18030 - Chinese simplified
-    //Encoding_JapaneseKanji,               // Multibyte - JIS X 0208: Kanji
-    //Encoding_JapaneseSupplementaryKanji,  // Multibyte - JIS X 0212: Supplementary Kanji set
-    //Encoding_Korean,                      // Multibyte - KS X 1001: Hangul and Hanja
-  };
-
-
-  // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.7.6.3.1.2
-  enum PhotometricInterpretation
-  {
-    PhotometricInterpretation_ARGB,  // Retired
-    PhotometricInterpretation_CMYK,  // Retired
-    PhotometricInterpretation_HSV,   // Retired
-    PhotometricInterpretation_Monochrome1,
-    PhotometricInterpretation_Monochrome2,
-    PhotometricInterpretation_Palette,
-    PhotometricInterpretation_RGB,
-    PhotometricInterpretation_YBRFull,
-    PhotometricInterpretation_YBRFull422,
-    PhotometricInterpretation_YBRPartial420,
-    PhotometricInterpretation_YBRPartial422,
-    PhotometricInterpretation_YBR_ICT,
-    PhotometricInterpretation_YBR_RCT,
-    PhotometricInterpretation_Unknown
-  };
-
-  enum DicomModule
-  {
-    DicomModule_Patient,
-    DicomModule_Study,
-    DicomModule_Series,
-    DicomModule_Instance,
-    DicomModule_Image
-  };
-
-  enum RequestOrigin
-  {
-    RequestOrigin_Unknown,
-    RequestOrigin_DicomProtocol,
-    RequestOrigin_RestApi,
-    RequestOrigin_Plugins,
-    RequestOrigin_Lua
-  };
-
-  enum ServerBarrierEvent
-  {
-    ServerBarrierEvent_Stop,
-    ServerBarrierEvent_Reload  // SIGHUP signal: reload configuration file
-  };
-
-  enum FileMode
-  {
-    FileMode_ReadBinary,
-    FileMode_WriteBinary
-  };
-
-  /**
-   * The value representations Orthanc knows about. They correspond to
-   * the DICOM 2016b version of the standard.
-   * http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html
-   **/
-  enum ValueRepresentation
-  {
-    ValueRepresentation_ApplicationEntity = 1,     // AE
-    ValueRepresentation_AgeString = 2,             // AS
-    ValueRepresentation_AttributeTag = 3,          // AT (2 x uint16_t)
-    ValueRepresentation_CodeString = 4,            // CS
-    ValueRepresentation_Date = 5,                  // DA
-    ValueRepresentation_DecimalString = 6,         // DS
-    ValueRepresentation_DateTime = 7,              // DT
-    ValueRepresentation_FloatingPointSingle = 8,   // FL (float)
-    ValueRepresentation_FloatingPointDouble = 9,   // FD (double)
-    ValueRepresentation_IntegerString = 10,        // IS
-    ValueRepresentation_LongString = 11,           // LO
-    ValueRepresentation_LongText = 12,             // LT
-    ValueRepresentation_OtherByte = 13,            // OB
-    ValueRepresentation_OtherDouble = 14,          // OD
-    ValueRepresentation_OtherFloat = 15,           // OF
-    ValueRepresentation_OtherLong = 16,            // OL
-    ValueRepresentation_OtherWord = 17,            // OW
-    ValueRepresentation_PersonName = 18,           // PN
-    ValueRepresentation_ShortString = 19,          // SH
-    ValueRepresentation_SignedLong = 20,           // SL (int32_t)
-    ValueRepresentation_Sequence = 21,             // SQ
-    ValueRepresentation_SignedShort = 22,          // SS (int16_t)
-    ValueRepresentation_ShortText = 23,            // ST
-    ValueRepresentation_Time = 24,                 // TM
-    ValueRepresentation_UnlimitedCharacters = 25,  // UC
-    ValueRepresentation_UniqueIdentifier = 26,     // UI (UID)
-    ValueRepresentation_UnsignedLong = 27,         // UL (uint32_t)
-    ValueRepresentation_Unknown = 28,              // UN
-    ValueRepresentation_UniversalResource = 29,    // UR (URI or URL)
-    ValueRepresentation_UnsignedShort = 30,        // US (uint16_t)
-    ValueRepresentation_UnlimitedText = 31,        // UT
-    ValueRepresentation_NotSupported               // Not supported by Orthanc, or tag not in dictionary
-  };
-
-  enum DicomReplaceMode
-  {
-    DicomReplaceMode_InsertIfAbsent,
-    DicomReplaceMode_ThrowIfAbsent,
-    DicomReplaceMode_IgnoreIfAbsent
-  };
-
-  enum DicomToJsonFormat
-  {
-    DicomToJsonFormat_Full,
-    DicomToJsonFormat_Short,
-    DicomToJsonFormat_Human
-  };
-
-  enum DicomToJsonFlags
-  {
-    DicomToJsonFlags_IncludeBinary         = (1 << 0),
-    DicomToJsonFlags_IncludePrivateTags    = (1 << 1),
-    DicomToJsonFlags_IncludeUnknownTags    = (1 << 2),
-    DicomToJsonFlags_IncludePixelData      = (1 << 3),
-    DicomToJsonFlags_ConvertBinaryToAscii  = (1 << 4),
-    DicomToJsonFlags_ConvertBinaryToNull   = (1 << 5),
-
-    // Some predefined combinations
-    DicomToJsonFlags_None     = 0,
-    DicomToJsonFlags_Default  = (DicomToJsonFlags_IncludeBinary |
-                                 DicomToJsonFlags_IncludePixelData | 
-                                 DicomToJsonFlags_IncludePrivateTags | 
-                                 DicomToJsonFlags_IncludeUnknownTags | 
-                                 DicomToJsonFlags_ConvertBinaryToNull)
-  };
-  
-  enum DicomFromJsonFlags
-  {
-    DicomFromJsonFlags_DecodeDataUriScheme = (1 << 0),
-    DicomFromJsonFlags_GenerateIdentifiers = (1 << 1)
-  };
-  
-  enum DicomVersion
-  {
-    DicomVersion_2008,
-    DicomVersion_2017c
-  };
-
-  enum ModalityManufacturer
-  {
-    ModalityManufacturer_Generic,
-    ModalityManufacturer_GenericNoWildcardInDates,
-    ModalityManufacturer_GenericNoUniversalWildcard,
-    ModalityManufacturer_StoreScp,
-    ModalityManufacturer_ClearCanvas,
-    ModalityManufacturer_Dcm4Chee,
-    ModalityManufacturer_Vitrea
-  };
-
-  enum DicomRequestType
-  {
-    DicomRequestType_Echo,
-    DicomRequestType_Find,
-    DicomRequestType_Get,
-    DicomRequestType_Move,
-    DicomRequestType_Store
-  };
-
-  enum TransferSyntax
-  {
-    TransferSyntax_Deflated,
-    TransferSyntax_Jpeg,
-    TransferSyntax_Jpeg2000,
-    TransferSyntax_JpegLossless,
-    TransferSyntax_Jpip,
-    TransferSyntax_Mpeg2,
-    TransferSyntax_Rle
-  };
-
-
-  /**
-   * WARNING: Do not change the explicit values in the enumerations
-   * below this point. This would result in incompatible databases
-   * between versions of Orthanc!
-   **/
-
-  enum CompressionType
-  {
-    /**
-     * Buffer/file that is stored as-is, in a raw fashion, without
-     * compression.
-     **/
-    CompressionType_None = 1,
-
-    /**
-     * Buffer that is compressed using the "deflate" algorithm (RFC
-     * 1951), wrapped inside the zlib data format (RFC 1950), prefixed
-     * with a "uint64_t" (8 bytes) that encodes the size of the
-     * uncompressed buffer. If the compressed buffer is empty, its
-     * represents an empty uncompressed buffer. This format is
-     * internal to Orthanc. If the 8 first bytes are skipped AND the
-     * buffer is non-empty, the buffer is compatible with the
-     * "deflate" HTTP compression.
-     **/
-    CompressionType_ZlibWithSize = 2
-  };
-
-  enum FileContentType
-  {
-    // If you add a value below, insert it in "PluginStorageArea" in
-    // the file "Plugins/Engine/OrthancPlugins.cpp"
-    FileContentType_Unknown = 0,
-    FileContentType_Dicom = 1,
-    FileContentType_DicomAsJson = 2,
-
-    // Make sure that the value "65535" can be stored into this enumeration
-    FileContentType_StartUser = 1024,
-    FileContentType_EndUser = 65535
-  };
-
-  enum ResourceType
-  {
-    ResourceType_Patient = 1,
-    ResourceType_Study = 2,
-    ResourceType_Series = 3,
-    ResourceType_Instance = 4
-  };
-
-
-  const char* EnumerationToString(ErrorCode code);
-
-  const char* EnumerationToString(HttpMethod method);
-
-  const char* EnumerationToString(HttpStatus status);
-
-  const char* EnumerationToString(ResourceType type);
-
-  const char* EnumerationToString(ImageFormat format);
-
-  const char* EnumerationToString(Encoding encoding);
-
-  const char* EnumerationToString(PhotometricInterpretation photometric);
-
-  const char* EnumerationToString(LogLevel level);
-
-  const char* EnumerationToString(RequestOrigin origin);
-
-  const char* EnumerationToString(PixelFormat format);
-
-  const char* EnumerationToString(ModalityManufacturer manufacturer);
-
-  const char* EnumerationToString(DicomRequestType type);
-
-  const char* EnumerationToString(TransferSyntax syntax);
-
-  const char* EnumerationToString(DicomVersion version);
-
-  const char* EnumerationToString(ValueRepresentation vr);
-
-  Encoding StringToEncoding(const char* encoding);
-
-  ResourceType StringToResourceType(const char* type);
-
-  ImageFormat StringToImageFormat(const char* format);
-
-  LogLevel StringToLogLevel(const char* level);
-
-  ValueRepresentation StringToValueRepresentation(const std::string& vr,
-                                                  bool throwIfUnsupported);
-
-  PhotometricInterpretation StringToPhotometricInterpretation(const char* value);
-
-  ModalityManufacturer StringToModalityManufacturer(const std::string& manufacturer);
-
-  DicomVersion StringToDicomVersion(const std::string& version);
-  
-  unsigned int GetBytesPerPixel(PixelFormat format);
-
-  bool GetDicomEncoding(Encoding& encoding,
-                        const char* specificCharacterSet);
-
-  ResourceType GetChildResourceType(ResourceType type);
-
-  ResourceType GetParentResourceType(ResourceType type);
-
-  DicomModule GetModule(ResourceType type);
-
-  const char* GetDicomSpecificCharacterSet(Encoding encoding);
-
-  HttpStatus ConvertErrorCodeToHttpStatus(ErrorCode error);
-
-  bool IsUserContentType(FileContentType type);
-
-  bool IsBinaryValueRepresentation(ValueRepresentation vr);
-  
-  Encoding GetDefaultDicomEncoding();
-
-  void SetDefaultDicomEncoding(Encoding encoding);
-}
--- a/Resources/Orthanc/Core/HttpClient.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,845 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "HttpClient.h"
-
-#include "Toolbox.h"
-#include "OrthancException.h"
-#include "Logging.h"
-#include "ChunkedBuffer.h"
-#include "SystemToolbox.h"
-
-#include <string.h>
-#include <curl/curl.h>
-#include <boost/algorithm/string/predicate.hpp>
-#include <boost/thread/mutex.hpp>
-
-
-#if ORTHANC_ENABLE_SSL == 1
-// For OpenSSL initialization and finalization
-#  include <openssl/conf.h>
-#  include <openssl/engine.h>
-#  include <openssl/err.h>
-#  include <openssl/evp.h>
-#  include <openssl/ssl.h>
-#endif
-
-
-#if ORTHANC_ENABLE_PKCS11 == 1
-#  include "Pkcs11.h"
-#endif
-
-
-extern "C"
-{
-  static CURLcode GetHttpStatus(CURLcode code, CURL* curl, long* status)
-  {
-    if (code == CURLE_OK)
-    {
-      code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, status);
-      return code;
-    }
-    else
-    {
-      *status = 0;
-      return code;
-    }
-  }
-
-  // This is a dummy wrapper function to suppress any OpenSSL-related
-  // problem in valgrind. Inlining is prevented.
-#if defined(__GNUC__) || defined(__clang__)
-    __attribute__((noinline)) 
-#endif
-    static CURLcode OrthancHttpClientPerformSSL(CURL* curl, long* status)
-  {
-#if ORTHANC_ENABLE_SSL == 1
-    return GetHttpStatus(curl_easy_perform(curl), curl, status);
-#else
-    LOG(ERROR) << "Orthanc was compiled without SSL support, cannot make HTTPS request";
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-#endif
-  }
-}
-
-
-
-namespace Orthanc
-{
-  class HttpClient::GlobalParameters
-  {
-  private:
-    boost::mutex    mutex_;
-    bool            httpsVerifyPeers_;
-    std::string     httpsCACertificates_;
-    std::string     proxy_;
-    long            timeout_;
-
-    GlobalParameters() : 
-      httpsVerifyPeers_(true),
-      timeout_(0)
-    {
-    }
-
-  public:
-    // Singleton pattern
-    static GlobalParameters& GetInstance()
-    {
-      static GlobalParameters parameters;
-      return parameters;
-    }
-
-    void ConfigureSsl(bool httpsVerifyPeers,
-                      const std::string& httpsCACertificates)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      httpsVerifyPeers_ = httpsVerifyPeers;
-      httpsCACertificates_ = httpsCACertificates;
-    }
-
-    void GetSslConfiguration(bool& httpsVerifyPeers,
-                             std::string& httpsCACertificates)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      httpsVerifyPeers = httpsVerifyPeers_;
-      httpsCACertificates = httpsCACertificates_;
-    }
-
-    void SetDefaultProxy(const std::string& proxy)
-    {
-      LOG(INFO) << "Setting the default proxy for HTTP client connections: " << proxy;
-
-      {
-        boost::mutex::scoped_lock lock(mutex_);
-        proxy_ = proxy;
-      }
-    }
-
-    void GetDefaultProxy(std::string& target)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      target = proxy_;
-    }
-
-    void SetDefaultTimeout(long seconds)
-    {
-      LOG(INFO) << "Setting the default timeout for HTTP client connections: " << seconds << " seconds";
-
-      {
-        boost::mutex::scoped_lock lock(mutex_);
-        timeout_ = seconds;
-      }
-    }
-
-    long GetDefaultTimeout()
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      return timeout_;
-    }
-
-#if ORTHANC_ENABLE_PKCS11 == 1
-    bool IsPkcs11Initialized()
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      return Pkcs11::IsInitialized();
-    }
-
-    void InitializePkcs11(const std::string& module,
-                          const std::string& pin,
-                          bool verbose)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      Pkcs11::Initialize(module, pin, verbose);
-    }
-#endif
-  };
-
-
-  struct HttpClient::PImpl
-  {
-    CURL* curl_;
-    struct curl_slist *defaultPostHeaders_;
-    struct curl_slist *userHeaders_;
-  };
-
-
-  static void ThrowException(HttpStatus status)
-  {
-    switch (status)
-    {
-      case HttpStatus_400_BadRequest:
-        throw OrthancException(ErrorCode_BadRequest);
-
-      case HttpStatus_401_Unauthorized:
-      case HttpStatus_403_Forbidden:
-        throw OrthancException(ErrorCode_Unauthorized);
-
-      case HttpStatus_404_NotFound:
-        throw OrthancException(ErrorCode_UnknownResource);
-
-      default:
-        throw OrthancException(ErrorCode_NetworkProtocol);
-    }
-  }
-
-
-  static CURLcode CheckCode(CURLcode code)
-  {
-    if (code == CURLE_NOT_BUILT_IN)
-    {
-      LOG(ERROR) << "Your libcurl does not contain a required feature, "
-                 << "please recompile Orthanc with -DUSE_SYSTEM_CURL=OFF";
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-    if (code != CURLE_OK)
-    {
-      LOG(ERROR) << "libCURL error: " + std::string(curl_easy_strerror(code));
-      throw OrthancException(ErrorCode_NetworkProtocol);
-    }
-
-    return code;
-  }
-
-
-  static size_t CurlBodyCallback(void *buffer, size_t size, size_t nmemb, void *payload)
-  {
-    ChunkedBuffer& target = *(static_cast<ChunkedBuffer*>(payload));
-
-    size_t length = size * nmemb;
-    if (length == 0)
-    {
-      return 0;
-    }
-    else
-    {
-      target.AddChunk(buffer, length);
-      return length;
-    }
-  }
-
-
-  struct CurlHeaderParameters
-  {
-    bool lowerCase_;
-    HttpClient::HttpHeaders* headers_;
-  };
-
-
-  static size_t CurlHeaderCallback(void *buffer, size_t size, size_t nmemb, void *payload)
-  {
-    CurlHeaderParameters& parameters = *(static_cast<CurlHeaderParameters*>(payload));
-    assert(parameters.headers_ != NULL);
-
-    size_t length = size * nmemb;
-    if (length == 0)
-    {
-      return 0;
-    }
-    else
-    {
-      std::string s(reinterpret_cast<const char*>(buffer), length);
-      std::size_t colon = s.find(':');
-      std::size_t eol = s.find("\r\n");
-      if (colon != std::string::npos &&
-          eol != std::string::npos)
-      {
-        std::string tmp(s.substr(0, colon));
-
-        if (parameters.lowerCase_)
-        {
-          Toolbox::ToLowerCase(tmp);
-        }
-
-        std::string key = Toolbox::StripSpaces(tmp);
-
-        if (!key.empty())
-        {
-          std::string value = Toolbox::StripSpaces(s.substr(colon + 1, eol));
-          (*parameters.headers_) [key] = value;
-        }
-      }
-
-      return length;
-    }
-  }
-
-
-  void HttpClient::Setup()
-  {
-    pimpl_->userHeaders_ = NULL;
-    pimpl_->defaultPostHeaders_ = NULL;
-    if ((pimpl_->defaultPostHeaders_ = curl_slist_append(pimpl_->defaultPostHeaders_, "Expect:")) == NULL)
-    {
-      throw OrthancException(ErrorCode_NotEnoughMemory);
-    }
-
-    pimpl_->curl_ = curl_easy_init();
-    if (!pimpl_->curl_)
-    {
-      curl_slist_free_all(pimpl_->defaultPostHeaders_);
-      throw OrthancException(ErrorCode_NotEnoughMemory);
-    }
-
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEFUNCTION, &CurlBodyCallback));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADER, 0));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 1));
-
-    // This fixes the "longjmp causes uninitialized stack frame" crash
-    // that happens on modern Linux versions.
-    // http://stackoverflow.com/questions/9191668/error-longjmp-causes-uninitialized-stack-frame
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOSIGNAL, 1));
-
-    url_ = "";
-    method_ = HttpMethod_Get;
-    lastStatus_ = HttpStatus_200_Ok;
-    SetVerbose(false);
-    timeout_ = GlobalParameters::GetInstance().GetDefaultTimeout();
-    GlobalParameters::GetInstance().GetDefaultProxy(proxy_);
-    GlobalParameters::GetInstance().GetSslConfiguration(verifyPeers_, caCertificates_);    
-  }
-
-
-  HttpClient::HttpClient() : 
-    pimpl_(new PImpl), 
-    verifyPeers_(true),
-    pkcs11Enabled_(false),
-    headersToLowerCase_(true),
-    redirectionFollowed_(true)
-  {
-    Setup();
-  }
-
-
-  HttpClient::HttpClient(const WebServiceParameters& service,
-                         const std::string& uri) : 
-    pimpl_(new PImpl), 
-    verifyPeers_(true),
-    headersToLowerCase_(true),
-    redirectionFollowed_(true)
-  {
-    Setup();
-
-    if (service.GetUsername().size() != 0 && 
-        service.GetPassword().size() != 0)
-    {
-      SetCredentials(service.GetUsername().c_str(), 
-                     service.GetPassword().c_str());
-    }
-
-    if (!service.GetCertificateFile().empty())
-    {
-      SetClientCertificate(service.GetCertificateFile(),
-                           service.GetCertificateKeyFile(),
-                           service.GetCertificateKeyPassword());
-    }
-
-    SetPkcs11Enabled(service.IsPkcs11Enabled());
-
-    SetUrl(service.GetUrl() + uri);
-  }
-
-
-  HttpClient::~HttpClient()
-  {
-    curl_easy_cleanup(pimpl_->curl_);
-    curl_slist_free_all(pimpl_->defaultPostHeaders_);
-    ClearHeaders();
-  }
-
-
-  void HttpClient::SetVerbose(bool isVerbose)
-  {
-    isVerbose_ = isVerbose;
-
-    if (isVerbose_)
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 1));
-    }
-    else
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 0));
-    }
-  }
-
-
-  void HttpClient::AddHeader(const std::string& key,
-                             const std::string& value)
-  {
-    if (key.empty())
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    std::string s = key + ": " + value;
-
-    if ((pimpl_->userHeaders_ = curl_slist_append(pimpl_->userHeaders_, s.c_str())) == NULL)
-    {
-      throw OrthancException(ErrorCode_NotEnoughMemory);
-    }
-  }
-
-
-  void HttpClient::ClearHeaders()
-  {
-    if (pimpl_->userHeaders_ != NULL)
-    {
-      curl_slist_free_all(pimpl_->userHeaders_);
-      pimpl_->userHeaders_ = NULL;
-    }
-  }
-
-
-  bool HttpClient::ApplyInternal(std::string& answerBody,
-                                 HttpHeaders* answerHeaders)
-  {
-    answerBody.clear();
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str()));
-
-    CurlHeaderParameters headerParameters;
-
-    if (answerHeaders == NULL)
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERFUNCTION, NULL));
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERDATA, NULL));
-    }
-    else
-    {
-      headerParameters.lowerCase_ = headersToLowerCase_;
-      headerParameters.headers_ = answerHeaders;
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERFUNCTION, &CurlHeaderCallback));
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERDATA, &headerParameters));
-    }
-
-#if ORTHANC_ENABLE_SSL == 1
-    // Setup HTTPS-related options
-
-    if (verifyPeers_)
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CAINFO, caCertificates_.c_str()));
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYHOST, 2));  // libcurl default is strict verifyhost
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 1)); 
-    }
-    else
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYHOST, 0)); 
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 0)); 
-    }
-#endif
-
-    // Setup the HTTPS client certificate
-    if (!clientCertificateFile_.empty() &&
-        pkcs11Enabled_)
-    {
-      LOG(ERROR) << "Cannot enable both client certificates and PKCS#11 authentication";
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    if (pkcs11Enabled_)
-    {
-#if ORTHANC_ENABLE_PKCS11 == 1
-      if (GlobalParameters::GetInstance().IsPkcs11Initialized())
-      {
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSLENGINE, Pkcs11::GetEngineIdentifier()));
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSLKEYTYPE, "ENG"));
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSLCERTTYPE, "ENG"));
-      }
-      else
-      {
-        LOG(ERROR) << "Cannot use PKCS#11 for a HTTPS request, because it has not been initialized";
-        throw OrthancException(ErrorCode_BadSequenceOfCalls);
-      }
-#else
-      LOG(ERROR) << "This version of Orthanc is compiled without support for PKCS#11";
-      throw OrthancException(ErrorCode_InternalError);
-#endif
-    }
-    else if (!clientCertificateFile_.empty())
-    {
-#if ORTHANC_ENABLE_SSL == 1
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSLCERTTYPE, "PEM"));
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSLCERT, clientCertificateFile_.c_str()));
-
-      if (!clientCertificateKeyPassword_.empty())
-      {
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_KEYPASSWD, clientCertificateKeyPassword_.c_str()));
-      }
-
-      // NB: If no "clientKeyFile_" is provided, the key must be
-      // prepended to the certificate file
-      if (!clientCertificateKeyFile_.empty())
-      {
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSLKEYTYPE, "PEM"));
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSLKEY, clientCertificateKeyFile_.c_str()));
-      }
-#else
-      LOG(ERROR) << "This version of Orthanc is compiled without OpenSSL support, cannot use HTTPS client authentication";
-      throw OrthancException(ErrorCode_InternalError);
-#endif
-    }
-
-    // Reset the parameters from previous calls to Apply()
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, pimpl_->userHeaders_));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPGET, 0L));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 0L));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOBODY, 0L));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CUSTOMREQUEST, NULL));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, NULL));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, 0L));
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_PROXY, NULL));
-
-    if (redirectionFollowed_)
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 1L));
-    }
-    else
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 0L));
-    }
-
-    // Set timeouts
-    if (timeout_ <= 0)
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_TIMEOUT, 10));  /* default: 10 seconds */
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CONNECTTIMEOUT, 10));  /* default: 10 seconds */
-    }
-    else
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_TIMEOUT, timeout_));
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CONNECTTIMEOUT, timeout_));
-    }
-
-    if (credentials_.size() != 0)
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_USERPWD, credentials_.c_str()));
-    }
-
-    if (proxy_.size() != 0)
-    {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_PROXY, proxy_.c_str()));
-    }
-
-    switch (method_)
-    {
-    case HttpMethod_Get:
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPGET, 1L));
-      break;
-
-    case HttpMethod_Post:
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 1L));
-
-      if (pimpl_->userHeaders_ == NULL)
-      {
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, pimpl_->defaultPostHeaders_));
-      }
-
-      break;
-
-    case HttpMethod_Delete:
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOBODY, 1L));
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CUSTOMREQUEST, "DELETE"));
-      break;
-
-    case HttpMethod_Put:
-      // http://stackoverflow.com/a/7570281/881731: Don't use
-      // CURLOPT_PUT if there is a body
-
-      // CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_PUT, 1L));
-
-      curl_easy_setopt(pimpl_->curl_, CURLOPT_CUSTOMREQUEST, "PUT"); /* !!! */
-
-      if (pimpl_->userHeaders_ == NULL)
-      {
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, pimpl_->defaultPostHeaders_));
-      }
-
-      break;
-
-    default:
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-
-    if (method_ == HttpMethod_Post ||
-        method_ == HttpMethod_Put)
-    {
-      if (body_.size() > 0)
-      {
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, body_.c_str()));
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, body_.size()));
-      }
-      else
-      {
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, NULL));
-        CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, 0));
-      }
-    }
-
-
-    // Do the actual request
-    CURLcode code;
-    long status = 0;
-
-    ChunkedBuffer buffer;
-    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &buffer));
-
-    if (boost::starts_with(url_, "https://"))
-    {
-      code = OrthancHttpClientPerformSSL(pimpl_->curl_, &status);
-    }
-    else
-    {
-      code = GetHttpStatus(curl_easy_perform(pimpl_->curl_), pimpl_->curl_, &status);
-    }
-
-    CheckCode(code);
-
-    if (status == 0)
-    {
-      // This corresponds to a call to an inexistent host
-      lastStatus_ = HttpStatus_500_InternalServerError;
-    }
-    else
-    {
-      lastStatus_ = static_cast<HttpStatus>(status);
-    }
-
-    bool success = (status >= 200 && status < 300);
-
-    if (success)
-    {
-      buffer.Flatten(answerBody);
-    }
-    else
-    {
-      answerBody.clear();
-      LOG(INFO) << "Error in HTTP request, received HTTP status " << status 
-                << " (" << EnumerationToString(lastStatus_) << ")";
-    }
-
-    return success;
-  }
-
-
-  bool HttpClient::ApplyInternal(Json::Value& answerBody,
-                                 HttpClient::HttpHeaders* answerHeaders)
-  {
-    std::string s;
-    if (ApplyInternal(s, answerHeaders))
-    {
-      Json::Reader reader;
-      return reader.parse(s, answerBody);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  void HttpClient::SetCredentials(const char* username,
-                                  const char* password)
-  {
-    credentials_ = std::string(username) + ":" + std::string(password);
-  }
-
-
-  void HttpClient::ConfigureSsl(bool httpsVerifyPeers,
-                                const std::string& httpsVerifyCertificates)
-  {
-#if ORTHANC_ENABLE_SSL == 1
-    if (httpsVerifyPeers)
-    {
-      if (httpsVerifyCertificates.empty())
-      {
-        LOG(WARNING) << "No certificates are provided to validate peers, "
-                     << "set \"HttpsCACertificates\" if you need to do HTTPS requests";
-      }
-      else
-      {
-        LOG(WARNING) << "HTTPS will use the CA certificates from this file: " << httpsVerifyCertificates;
-      }
-    }
-    else
-    {
-      LOG(WARNING) << "The verification of the peers in HTTPS requests is disabled";
-    }
-#endif
-
-    GlobalParameters::GetInstance().ConfigureSsl(httpsVerifyPeers, httpsVerifyCertificates);
-  }
-
-  
-  void HttpClient::GlobalInitialize()
-  {
-#if ORTHANC_ENABLE_SSL == 1
-    CheckCode(curl_global_init(CURL_GLOBAL_ALL));
-#else
-    CheckCode(curl_global_init(CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL));
-#endif
-  }
-
-
-  void HttpClient::GlobalFinalize()
-  {
-    curl_global_cleanup();
-
-#if ORTHANC_ENABLE_PKCS11 == 1
-    Pkcs11::Finalize();
-#endif
-  }
-  
-
-  void HttpClient::SetDefaultProxy(const std::string& proxy)
-  {
-    GlobalParameters::GetInstance().SetDefaultProxy(proxy);
-  }
-
-
-  void HttpClient::SetDefaultTimeout(long timeout)
-  {
-    GlobalParameters::GetInstance().SetDefaultTimeout(timeout);
-  }
-
-
-  void HttpClient::ApplyAndThrowException(std::string& answerBody)
-  {
-    if (!Apply(answerBody))
-    {
-      ThrowException(GetLastStatus());
-    }
-  }
-
-  
-  void HttpClient::ApplyAndThrowException(Json::Value& answerBody)
-  {
-    if (!Apply(answerBody))
-    {
-      ThrowException(GetLastStatus());
-    }
-  }
-
-
-  void HttpClient::ApplyAndThrowException(std::string& answerBody,
-                                          HttpHeaders& answerHeaders)
-  {
-    if (!Apply(answerBody, answerHeaders))
-    {
-      ThrowException(GetLastStatus());
-    }
-  }
-  
-
-  void HttpClient::ApplyAndThrowException(Json::Value& answerBody,
-                                          HttpHeaders& answerHeaders)
-  {
-    if (!Apply(answerBody, answerHeaders))
-    {
-      ThrowException(GetLastStatus());
-    }
-  }
-
-
-  void HttpClient::SetClientCertificate(const std::string& certificateFile,
-                                        const std::string& certificateKeyFile,
-                                        const std::string& certificateKeyPassword)
-  {
-    if (certificateFile.empty())
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    if (!SystemToolbox::IsRegularFile(certificateFile))
-    {
-      LOG(ERROR) << "Cannot open certificate file: " << certificateFile;
-      throw OrthancException(ErrorCode_InexistentFile);
-    }
-
-    if (!certificateKeyFile.empty() && 
-        !SystemToolbox::IsRegularFile(certificateKeyFile))
-    {
-      LOG(ERROR) << "Cannot open key file: " << certificateKeyFile;
-      throw OrthancException(ErrorCode_InexistentFile);
-    }
-
-    clientCertificateFile_ = certificateFile;
-    clientCertificateKeyFile_ = certificateKeyFile;
-    clientCertificateKeyPassword_ = certificateKeyPassword;
-  }
-
-
-  void HttpClient::InitializePkcs11(const std::string& module,
-                                    const std::string& pin,
-                                    bool verbose)
-  {
-#if ORTHANC_ENABLE_PKCS11 == 1
-    LOG(INFO) << "Initializing PKCS#11 using " << module 
-              << (pin.empty() ? " (no PIN provided)" : " (PIN is provided)");
-    GlobalParameters::GetInstance().InitializePkcs11(module, pin, verbose);    
-#else
-    LOG(ERROR) << "This version of Orthanc is compiled without support for PKCS#11";
-    throw OrthancException(ErrorCode_InternalError);
-#endif
-  }
-
-
-  void HttpClient::InitializeOpenSsl()
-  {
-#if ORTHANC_ENABLE_SSL == 1
-    // https://wiki.openssl.org/index.php/Library_Initialization
-    SSL_library_init();
-    SSL_load_error_strings();
-    OpenSSL_add_all_algorithms();
-    ERR_load_crypto_strings();
-#endif
-  }
-
-
-  void HttpClient::FinalizeOpenSsl()
-  {
-#if ORTHANC_ENABLE_SSL == 1
-    // Finalize OpenSSL
-    // https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
-#ifdef FIPS_mode_set
-    FIPS_mode_set(0);
-#endif
-    ENGINE_cleanup();
-    CONF_modules_unload(1);
-    EVP_cleanup();
-    CRYPTO_cleanup_all_ex_data();
-    ERR_remove_state(0);
-    ERR_free_strings();
-#endif
-  }
-}
--- a/Resources/Orthanc/Core/HttpClient.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "WebServiceParameters.h"
-
-#include <string>
-#include <boost/shared_ptr.hpp>
-#include <json/json.h>
-
-#if !defined(ORTHANC_ENABLE_SSL)
-#  error The macro ORTHANC_ENABLE_SSL must be defined
-#endif
-
-#if !defined(ORTHANC_ENABLE_PKCS11)
-#  error The macro ORTHANC_ENABLE_PKCS11 must be defined
-#endif
-
-
-namespace Orthanc
-{
-  class HttpClient
-  {
-  public:
-    typedef std::map<std::string, std::string>  HttpHeaders;
-
-  private:
-    class GlobalParameters;
-
-    struct PImpl;
-    boost::shared_ptr<PImpl> pimpl_;
-
-    std::string url_;
-    std::string credentials_;
-    HttpMethod method_;
-    HttpStatus lastStatus_;
-    std::string body_;  // This only makes sense for POST and PUT requests
-    bool isVerbose_;
-    long timeout_;
-    std::string proxy_;
-    bool verifyPeers_;
-    std::string caCertificates_;
-    std::string clientCertificateFile_;
-    std::string clientCertificateKeyFile_;
-    std::string clientCertificateKeyPassword_;
-    bool pkcs11Enabled_;
-    bool headersToLowerCase_;
-    bool redirectionFollowed_;
-
-    void Setup();
-
-    void operator= (const HttpClient&);  // Assignment forbidden
-    HttpClient(const HttpClient& base);  // Copy forbidden
-
-    bool ApplyInternal(std::string& answerBody,
-                       HttpHeaders* answerHeaders);
-
-    bool ApplyInternal(Json::Value& answerBody,
-                       HttpHeaders* answerHeaders);
-
-  public:
-    HttpClient();
-
-    HttpClient(const WebServiceParameters& service,
-               const std::string& uri);
-
-    ~HttpClient();
-
-    void SetUrl(const char* url)
-    {
-      url_ = std::string(url);
-    }
-
-    void SetUrl(const std::string& url)
-    {
-      url_ = url;
-    }
-
-    const std::string& GetUrl() const
-    {
-      return url_;
-    }
-
-    void SetMethod(HttpMethod method)
-    {
-      method_ = method;
-    }
-
-    HttpMethod GetMethod() const
-    {
-      return method_;
-    }
-
-    void SetTimeout(long seconds)
-    {
-      timeout_ = seconds;
-    }
-
-    long GetTimeout() const
-    {
-      return timeout_;
-    }
-
-    void SetBody(const std::string& data)
-    {
-      body_ = data;
-    }
-
-    std::string& GetBody()
-    {
-      return body_;
-    }
-
-    const std::string& GetBody() const
-    {
-      return body_;
-    }
-
-    void SetVerbose(bool isVerbose);
-
-    bool IsVerbose() const
-    {
-      return isVerbose_;
-    }
-
-    void AddHeader(const std::string& key,
-                   const std::string& value);
-
-    void ClearHeaders();
-
-    bool Apply(std::string& answerBody)
-    {
-      return ApplyInternal(answerBody, NULL);
-    }
-
-    bool Apply(Json::Value& answerBody)
-    {
-      return ApplyInternal(answerBody, NULL);
-    }
-
-    bool Apply(std::string& answerBody,
-               HttpHeaders& answerHeaders)
-    {
-      return ApplyInternal(answerBody, &answerHeaders);
-    }
-
-    bool Apply(Json::Value& answerBody,
-               HttpHeaders& answerHeaders)
-    {
-      return ApplyInternal(answerBody, &answerHeaders);
-    }
-
-    HttpStatus GetLastStatus() const
-    {
-      return lastStatus_;
-    }
-
-    void SetCredentials(const char* username,
-                        const char* password);
-
-    void SetProxy(const std::string& proxy)
-    {
-      proxy_ = proxy;
-    }
-
-    void SetHttpsVerifyPeers(bool verify)
-    {
-      verifyPeers_ = verify;
-    }
-
-    bool IsHttpsVerifyPeers() const
-    {
-      return verifyPeers_;
-    }
-
-    void SetHttpsCACertificates(const std::string& certificates)
-    {
-      caCertificates_ = certificates;
-    }
-
-    const std::string& GetHttpsCACertificates() const
-    {
-      return caCertificates_;
-    }
-
-    void SetClientCertificate(const std::string& certificateFile,
-                              const std::string& certificateKeyFile,
-                              const std::string& certificateKeyPassword);
-
-    void SetPkcs11Enabled(bool enabled)
-    {
-      pkcs11Enabled_ = enabled;
-    }
-
-    bool IsPkcs11Enabled() const
-    {
-      return pkcs11Enabled_;
-    }
-
-    const std::string& GetClientCertificateFile() const
-    {
-      return clientCertificateFile_;
-    }
-
-    const std::string& GetClientCertificateKeyFile() const
-    {
-      return clientCertificateKeyFile_;
-    }
-
-    const std::string& GetClientCertificateKeyPassword() const
-    {
-      return clientCertificateKeyPassword_;
-    }
-
-    void SetConvertHeadersToLowerCase(bool lowerCase)
-    {
-      headersToLowerCase_ = lowerCase;
-    }
-
-    bool IsConvertHeadersToLowerCase() const
-    {
-      return headersToLowerCase_;
-    }
-
-    void SetRedirectionFollowed(bool follow)
-    {
-      redirectionFollowed_ = follow;
-    }
-
-    bool IsRedirectionFollowed() const
-    {
-      return redirectionFollowed_;
-    }
-
-    static void GlobalInitialize();
-  
-    static void GlobalFinalize();
-
-    static void InitializeOpenSsl();
-
-    static void FinalizeOpenSsl();
-
-    static void InitializePkcs11(const std::string& module,
-                                 const std::string& pin,
-                                 bool verbose);
-
-    static void ConfigureSsl(bool httpsVerifyPeers,
-                             const std::string& httpsCACertificates);
-
-    static void SetDefaultProxy(const std::string& proxy);
-
-    static void SetDefaultTimeout(long timeout);
-
-    void ApplyAndThrowException(std::string& answerBody);
-
-    void ApplyAndThrowException(Json::Value& answerBody);
-
-    void ApplyAndThrowException(std::string& answerBody,
-                                HttpHeaders& answerHeaders);
-
-    void ApplyAndThrowException(Json::Value& answerBody,
-                                HttpHeaders& answerHeaders);
-  };
-}
--- a/Resources/Orthanc/Core/ICommand.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "IDynamicObject.h"
-
-namespace Orthanc
-{
-  /**
-   * This class is the base class for the "Command" design pattern.
-   * http://en.wikipedia.org/wiki/Command_pattern
-   **/
-  class ICommand : public IDynamicObject
-  {
-  public:
-    virtual bool Execute() = 0;
-  };
-}
--- a/Resources/Orthanc/Core/IDynamicObject.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 <boost/noncopyable.hpp>
-
-namespace Orthanc
-{
-  /**
-   * This class should be the ancestor to any class whose type is
-   * determined at the runtime, and that can be dynamically allocated.
-   * Being a child of IDynamicObject only implies the existence of a
-   * virtual destructor.
-   **/
-  class IDynamicObject : public boost::noncopyable
-  {
-  public:
-    virtual ~IDynamicObject()
-    {
-    }
-  };
-}
--- a/Resources/Orthanc/Core/Images/IImageWriter.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "IImageWriter.h"
-
-#if ORTHANC_SANDBOXED == 0
-#  include "../SystemToolbox.h"
-#endif
-
-namespace Orthanc
-{
-#if ORTHANC_SANDBOXED == 0
-  void IImageWriter::WriteToFileInternal(const std::string& path,
-                                         unsigned int width,
-                                         unsigned int height,
-                                         unsigned int pitch,
-                                         PixelFormat format,
-                                         const void* buffer)
-  {
-    std::string compressed;
-    WriteToMemoryInternal(compressed, width, height, pitch, format, buffer);
-    SystemToolbox::WriteFile(compressed, path);
-  }
-#endif
-}
--- a/Resources/Orthanc/Core/Images/IImageWriter.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ImageAccessor.h"
-
-#include <boost/noncopyable.hpp>
-
-#if !defined(ORTHANC_SANDBOXED)
-#  error The macro ORTHANC_SANDBOXED must be defined
-#endif
-
-namespace Orthanc
-{
-  class IImageWriter : public boost::noncopyable
-  {
-  protected:
-    virtual void WriteToMemoryInternal(std::string& compressed,
-                                       unsigned int width,
-                                       unsigned int height,
-                                       unsigned int pitch,
-                                       PixelFormat format,
-                                       const void* buffer) = 0;
-
-#if ORTHANC_SANDBOXED == 0
-    virtual void WriteToFileInternal(const std::string& path,
-                                     unsigned int width,
-                                     unsigned int height,
-                                     unsigned int pitch,
-                                     PixelFormat format,
-                                     const void* buffer);
-#endif
-
-  public:
-    virtual ~IImageWriter()
-    {
-    }
-
-    virtual void WriteToMemory(std::string& compressed,
-                               const ImageAccessor& accessor)
-    {
-      WriteToMemoryInternal(compressed, accessor.GetWidth(), accessor.GetHeight(),
-                            accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
-    }
-
-#if ORTHANC_SANDBOXED == 0
-    virtual void WriteToFile(const std::string& path,
-                             const ImageAccessor& accessor)
-    {
-      WriteToFileInternal(path, accessor.GetWidth(), accessor.GetHeight(),
-                          accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
-    }
-#endif
-  };
-}
--- a/Resources/Orthanc/Core/Images/Image.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "Image.h"
-
-#include "ImageProcessing.h"
-
-#include <memory>
-
-namespace Orthanc
-{
-  Image::Image(PixelFormat format,
-               unsigned int width,
-               unsigned int height,
-               bool forceMinimalPitch) :
-    image_(format, width, height, forceMinimalPitch)
-  {
-    ImageAccessor accessor = image_.GetAccessor();
-    AssignWritable(format, width, height, accessor.GetPitch(), accessor.GetBuffer());
-  }
-
-
-  Image* Image::Clone(const ImageAccessor& source)
-  {
-    std::auto_ptr<Image> target(new Image(source.GetFormat(), source.GetWidth(), source.GetHeight(), false));
-    ImageProcessing::Copy(*target, source);
-    return target.release();
-  }
-}
--- a/Resources/Orthanc/Core/Images/Image.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ImageAccessor.h"
-#include "ImageBuffer.h"
-
-namespace Orthanc
-{
-  class Image : public ImageAccessor
-  {
-  private:
-    ImageBuffer  image_;
-
-  public:
-    Image(PixelFormat format,
-          unsigned int width,
-          unsigned int height,
-          bool forceMinimalPitch);
-
-    static Image* Clone(const ImageAccessor& source);
-  };
-}
--- a/Resources/Orthanc/Core/Images/ImageAccessor.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,301 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ImageAccessor.h"
-
-#include "../Logging.h"
-#include "../OrthancException.h"
-#include "../ChunkedBuffer.h"
-
-#include <stdint.h>
-#include <cassert>
-#include <boost/lexical_cast.hpp>
-
-
-
-namespace Orthanc
-{
-  template <typename PixelType>
-  static void ToMatlabStringInternal(ChunkedBuffer& target,
-                                     const ImageAccessor& source)
-  {
-    target.AddChunk("double([ ");
-
-    for (unsigned int y = 0; y < source.GetHeight(); y++)
-    {
-      const PixelType* p = reinterpret_cast<const PixelType*>(source.GetConstRow(y));
-
-      std::string s;
-      if (y > 0)
-      {
-        s = "; ";
-      }
-
-      s.reserve(source.GetWidth() * 8);
-
-      for (unsigned int x = 0; x < source.GetWidth(); x++, p++)
-      {
-        s += boost::lexical_cast<std::string>(static_cast<double>(*p)) + " ";
-      }
-
-      target.AddChunk(s);
-    }
-
-    target.AddChunk("])");
-  }
-
-
-  static void RGB24ToMatlabString(ChunkedBuffer& target,
-                                  const ImageAccessor& source)
-  {
-    assert(source.GetFormat() == PixelFormat_RGB24);
-
-    target.AddChunk("double(permute(reshape([ ");
-
-    for (unsigned int y = 0; y < source.GetHeight(); y++)
-    {
-      const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-      
-      std::string s;
-      s.reserve(source.GetWidth() * 3 * 8);
-      
-      for (unsigned int x = 0; x < 3 * source.GetWidth(); x++, p++)
-      {
-        s += boost::lexical_cast<std::string>(static_cast<int>(*p)) + " ";
-      }
-      
-      target.AddChunk(s);
-    }
-
-    target.AddChunk("], [ 3 " + boost::lexical_cast<std::string>(source.GetHeight()) +
-                    " " + boost::lexical_cast<std::string>(source.GetWidth()) + " ]), [ 3 2 1 ]))");
-  }
-
-
-  void* ImageAccessor::GetBuffer() const
-  {
-    if (readOnly_)
-    {
-#if ORTHANC_ENABLE_LOGGING == 1
-      LOG(ERROR) << "Trying to write on a read-only image";
-#endif
-
-      throw OrthancException(ErrorCode_ReadOnly);
-    }
-
-    return buffer_;
-  }
-
-
-  const void* ImageAccessor::GetConstRow(unsigned int y) const
-  {
-    if (buffer_ != NULL)
-    {
-      return buffer_ + y * pitch_;
-    }
-    else
-    {
-      return NULL;
-    }
-  }
-
-
-  void* ImageAccessor::GetRow(unsigned int y) const
-  {
-    if (readOnly_)
-    {
-#if ORTHANC_ENABLE_LOGGING == 1
-      LOG(ERROR) << "Trying to write on a read-only image";
-#endif
-
-      throw OrthancException(ErrorCode_ReadOnly);
-    }
-
-    if (buffer_ != NULL)
-    {
-      return buffer_ + y * pitch_;
-    }
-    else
-    {
-      return NULL;
-    }
-  }
-
-
-  void ImageAccessor::AssignEmpty(PixelFormat format)
-  {
-    readOnly_ = false;
-    format_ = format;
-    width_ = 0;
-    height_ = 0;
-    pitch_ = 0;
-    buffer_ = NULL;
-  }
-
-
-  void ImageAccessor::AssignReadOnly(PixelFormat format,
-                                     unsigned int width,
-                                     unsigned int height,
-                                     unsigned int pitch,
-                                     const void *buffer)
-  {
-    readOnly_ = true;
-    format_ = format;
-    width_ = width;
-    height_ = height;
-    pitch_ = pitch;
-    buffer_ = reinterpret_cast<uint8_t*>(const_cast<void*>(buffer));
-
-    if (GetBytesPerPixel() * width_ > pitch_)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  void ImageAccessor::AssignWritable(PixelFormat format,
-                                     unsigned int width,
-                                     unsigned int height,
-                                     unsigned int pitch,
-                                     void *buffer)
-  {
-    readOnly_ = false;
-    format_ = format;
-    width_ = width;
-    height_ = height;
-    pitch_ = pitch;
-    buffer_ = reinterpret_cast<uint8_t*>(buffer);
-
-    if (GetBytesPerPixel() * width_ > pitch_)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  void ImageAccessor::ToMatlabString(std::string& target) const
-  {
-    ChunkedBuffer buffer;
-
-    switch (GetFormat())
-    {
-      case PixelFormat_Grayscale8:
-        ToMatlabStringInternal<uint8_t>(buffer, *this);
-        break;
-
-      case PixelFormat_Grayscale16:
-        ToMatlabStringInternal<uint16_t>(buffer, *this);
-        break;
-
-      case PixelFormat_Grayscale32:
-        ToMatlabStringInternal<uint32_t>(buffer, *this);
-        break;
-
-      case PixelFormat_SignedGrayscale16:
-        ToMatlabStringInternal<int16_t>(buffer, *this);
-        break;
-
-      case PixelFormat_Float32:
-        ToMatlabStringInternal<float>(buffer, *this);
-        break;
-
-      case PixelFormat_RGB24:
-        RGB24ToMatlabString(buffer, *this);
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }   
-
-    buffer.Flatten(target);
-  }
-
-
-
-  ImageAccessor ImageAccessor::GetRegion(unsigned int x,
-                                         unsigned int y,
-                                         unsigned int width,
-                                         unsigned int height) const
-  {
-    if (x + width > width_ ||
-        y + height > height_)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-    
-    ImageAccessor result;
-
-    if (width == 0 ||
-        height == 0)
-    {
-      result.AssignWritable(format_, 0, 0, 0, NULL);
-    }
-    else
-    {
-      uint8_t* p = (buffer_ + 
-                    y * pitch_ + 
-                    x * GetBytesPerPixel());
-
-      if (readOnly_)
-      {
-        result.AssignReadOnly(format_, width, height, pitch_, p);
-      }
-      else
-      {
-        result.AssignWritable(format_, width, height, pitch_, p);
-      }
-    }
-
-    return result;
-  }
-
-
-  void ImageAccessor::SetFormat(PixelFormat format)
-  {
-    if (readOnly_)
-    {
-#if ORTHANC_ENABLE_LOGGING == 1
-      LOG(ERROR) << "Trying to modify the format of a read-only image";
-#endif
-      throw OrthancException(ErrorCode_ReadOnly);
-    }
-
-    if (::Orthanc::GetBytesPerPixel(format) != ::Orthanc::GetBytesPerPixel(format_))
-    {
-      throw OrthancException(ErrorCode_IncompatibleImageFormat);
-    }
-
-    format_ = format;
-  }
-}
--- a/Resources/Orthanc/Core/Images/ImageAccessor.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 <string>
-#include <stdint.h>
-
-namespace Orthanc
-{
-  class ImageAccessor
-  {
-  private:
-    template <Orthanc::PixelFormat Format>
-    friend struct ImageTraits;
-    
-    bool readOnly_;
-    PixelFormat format_;
-    unsigned int width_;
-    unsigned int height_;
-    unsigned int pitch_;
-    uint8_t *buffer_;
-
-    template <typename T>
-    const T& GetPixelUnchecked(unsigned int x,
-                               unsigned int y) const
-    {
-      const uint8_t* row = reinterpret_cast<const uint8_t*>(buffer_) + y * pitch_;
-      return reinterpret_cast<const T*>(row) [x];
-    }
-
-
-    template <typename T>
-    T& GetPixelUnchecked(unsigned int x,
-                         unsigned int y)
-    {
-      uint8_t* row = reinterpret_cast<uint8_t*>(buffer_) + y * pitch_;
-      return reinterpret_cast<T*>(row) [x];
-    }
-
-  public:
-    ImageAccessor()
-    {
-      AssignEmpty(PixelFormat_Grayscale8);
-    }
-
-    virtual ~ImageAccessor()
-    {
-    }
-
-    bool IsReadOnly() const
-    {
-      return readOnly_;
-    }
-
-    PixelFormat GetFormat() const
-    {
-      return format_;
-    }
-
-    unsigned int GetBytesPerPixel() const
-    {
-      return ::Orthanc::GetBytesPerPixel(format_);
-    }
-
-    unsigned int GetWidth() const
-    {
-      return width_;
-    }
-
-    unsigned int GetHeight() const
-    {
-      return height_;
-    }
-
-    unsigned int GetPitch() const
-    {
-      return pitch_;
-    }
-
-    unsigned int GetSize() const
-    {
-      return GetHeight() * GetPitch();
-    }
-
-    const void* GetConstBuffer() const
-    {
-      return buffer_;
-    }
-
-    void* GetBuffer() const;
-
-    const void* GetConstRow(unsigned int y) const;
-
-    void* GetRow(unsigned int y) const;
-
-    void AssignEmpty(PixelFormat format);
-
-    void AssignReadOnly(PixelFormat format,
-                        unsigned int width,
-                        unsigned int height,
-                        unsigned int pitch,
-                        const void *buffer);
-
-    void AssignWritable(PixelFormat format,
-                        unsigned int width,
-                        unsigned int height,
-                        unsigned int pitch,
-                        void *buffer);
-
-    void ToMatlabString(std::string& target) const; 
-
-    ImageAccessor GetRegion(unsigned int x,
-                            unsigned int y,
-                            unsigned int width,
-                            unsigned int height) const;
-
-    void SetFormat(PixelFormat format);
-  };
-}
--- a/Resources/Orthanc/Core/Images/ImageBuffer.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ImageBuffer.h"
-
-#include "../OrthancException.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-namespace Orthanc
-{
-  void ImageBuffer::Allocate()
-  {
-    if (changed_)
-    {
-      Deallocate();
-
-      /*
-        if (forceMinimalPitch_)
-        {
-        TODO: Align pitch and memory buffer to optimal size for SIMD.
-        }
-      */
-
-      pitch_ = GetBytesPerPixel() * width_;
-      size_t size = pitch_ * height_;
-
-      if (size == 0)
-      {
-        buffer_ = NULL;
-      }
-      else
-      {
-        buffer_ = malloc(size);
-        if (buffer_ == NULL)
-        {
-          throw OrthancException(ErrorCode_NotEnoughMemory);
-        }
-      }
-
-      changed_ = false;
-    }
-  }
-
-
-  void ImageBuffer::Deallocate()
-  {
-    if (buffer_ != NULL)
-    {
-      free(buffer_);
-      buffer_ = NULL;
-      changed_ = true;
-    }
-  }
-
-
-  ImageBuffer::ImageBuffer(PixelFormat format,
-                           unsigned int width,
-                           unsigned int height,
-                           bool forceMinimalPitch) :
-    forceMinimalPitch_(forceMinimalPitch)
-  {
-    Initialize();
-    SetWidth(width);
-    SetHeight(height);
-    SetFormat(format);
-  }
-
-
-  void ImageBuffer::Initialize()
-  {
-    changed_ = false;
-    forceMinimalPitch_ = true;
-    format_ = PixelFormat_Grayscale8;
-    width_ = 0;
-    height_ = 0;
-    pitch_ = 0;
-    buffer_ = NULL;
-  }
-
-
-  void ImageBuffer::SetFormat(PixelFormat format)
-  {
-    if (format != format_)
-    {
-      changed_ = true;
-      format_ = format;
-    }
-  }
-
-
-  void ImageBuffer::SetWidth(unsigned int width)
-  {
-    if (width != width_)
-    {
-      changed_ = true;
-      width_ = width;     
-    }
-  }
-
-
-  void ImageBuffer::SetHeight(unsigned int height)
-  {
-    if (height != height_)
-    {
-      changed_ = true;
-      height_ = height;     
-    }
-  }
-
-
-  ImageAccessor ImageBuffer::GetAccessor()
-  {
-    Allocate();
-
-    ImageAccessor accessor;
-    accessor.AssignWritable(format_, width_, height_, pitch_, buffer_);
-    return accessor;
-  }
-
-
-  ImageAccessor ImageBuffer::GetConstAccessor()
-  {
-    Allocate();
-
-    ImageAccessor accessor;
-    accessor.AssignReadOnly(format_, width_, height_, pitch_, buffer_);
-    return accessor;
-  }
-
-
-  void ImageBuffer::AcquireOwnership(ImageBuffer& other)
-  {
-    // Remove the content of the current image
-    Deallocate();
-
-    // Force the allocation of the other image (if not already
-    // allocated)
-    other.Allocate();
-
-    // Transfer the content of the other image
-    changed_ = false;
-    forceMinimalPitch_ = other.forceMinimalPitch_;
-    format_ = other.format_;
-    width_ = other.width_;
-    height_ = other.height_;
-    pitch_ = other.pitch_;
-    buffer_ = other.buffer_;
-
-    // Force the reinitialization of the other image
-    other.Initialize();
-  }
-}
--- a/Resources/Orthanc/Core/Images/ImageBuffer.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ImageAccessor.h"
-
-#include <vector>
-#include <stdint.h>
-#include <boost/noncopyable.hpp>
-
-namespace Orthanc
-{
-  class ImageBuffer : public boost::noncopyable
-  {
-  private:
-    bool changed_;
-
-    bool forceMinimalPitch_;  // Currently unused
-    PixelFormat format_;
-    unsigned int width_;
-    unsigned int height_;
-    unsigned int pitch_;
-    void *buffer_;
-
-    void Initialize();
-    
-    void Allocate();
-
-    void Deallocate();
-
-  public:
-    ImageBuffer(PixelFormat format,
-                unsigned int width,
-                unsigned int height,
-                bool forceMinimalPitch);
-
-    ImageBuffer()
-    {
-      Initialize();
-    }
-
-    ~ImageBuffer()
-    {
-      Deallocate();
-    }
-
-    PixelFormat GetFormat() const
-    {
-      return format_;
-    }
-
-    void SetFormat(PixelFormat format);
-
-    unsigned int GetWidth() const
-    {
-      return width_;
-    }
-
-    void SetWidth(unsigned int width);
-
-    unsigned int GetHeight() const
-    {
-      return height_;
-    }
-
-    void SetHeight(unsigned int height);
-
-    unsigned int GetBytesPerPixel() const
-    {
-      return ::Orthanc::GetBytesPerPixel(format_);
-    }
-
-    ImageAccessor GetAccessor();
-
-    ImageAccessor GetConstAccessor();
-
-    bool IsMinimalPitchForced() const
-    {
-      return forceMinimalPitch_;
-    }
-
-    void AcquireOwnership(ImageBuffer& other);
-  };
-}
--- a/Resources/Orthanc/Core/Images/ImageProcessing.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1226 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ImageProcessing.h"
-
-#include "PixelTraits.h"
-
-#include <boost/math/special_functions/round.hpp>
-
-#include <cassert>
-#include <string.h>
-#include <limits>
-#include <stdint.h>
-
-namespace Orthanc
-{
-  template <typename TargetType, typename SourceType>
-  static void ConvertInternal(ImageAccessor& target,
-                              const ImageAccessor& source)
-  {
-    const TargetType minValue = std::numeric_limits<TargetType>::min();
-    const TargetType maxValue = std::numeric_limits<TargetType>::max();
-
-    for (unsigned int y = 0; y < source.GetHeight(); y++)
-    {
-      TargetType* t = reinterpret_cast<TargetType*>(target.GetRow(y));
-      const SourceType* s = reinterpret_cast<const SourceType*>(source.GetConstRow(y));
-
-      for (unsigned int x = 0; x < source.GetWidth(); x++, t++, s++)
-      {
-        if (static_cast<int32_t>(*s) < static_cast<int32_t>(minValue))
-        {
-          *t = minValue;
-        }
-        else if (static_cast<int32_t>(*s) > static_cast<int32_t>(maxValue))
-        {
-          *t = maxValue;
-        }
-        else
-        {
-          *t = static_cast<TargetType>(*s);
-        }
-      }
-    }
-  }
-
-
-  template <typename SourceType>
-  static void ConvertGrayscaleToFloat(ImageAccessor& target,
-                                      const ImageAccessor& source)
-  {
-    assert(sizeof(float) == 4);
-
-    for (unsigned int y = 0; y < source.GetHeight(); y++)
-    {
-      float* t = reinterpret_cast<float*>(target.GetRow(y));
-      const SourceType* s = reinterpret_cast<const SourceType*>(source.GetConstRow(y));
-
-      for (unsigned int x = 0; x < source.GetWidth(); x++, t++, s++)
-      {
-        *t = static_cast<float>(*s);
-      }
-    }
-  }
-
-
-  template <typename TargetType>
-  static void ConvertColorToGrayscale(ImageAccessor& target,
-                                      const ImageAccessor& source)
-  {
-    assert(source.GetFormat() == PixelFormat_RGB24);
-
-    const TargetType minValue = std::numeric_limits<TargetType>::min();
-    const TargetType maxValue = std::numeric_limits<TargetType>::max();
-
-    for (unsigned int y = 0; y < source.GetHeight(); y++)
-    {
-      TargetType* t = reinterpret_cast<TargetType*>(target.GetRow(y));
-      const uint8_t* s = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-
-      for (unsigned int x = 0; x < source.GetWidth(); x++, t++, s += 3)
-      {
-        // Y = 0.2126 R + 0.7152 G + 0.0722 B
-        int32_t v = (2126 * static_cast<int32_t>(s[0]) +
-                     7152 * static_cast<int32_t>(s[1]) +
-                     0722 * static_cast<int32_t>(s[2])) / 10000;
-        
-        if (static_cast<int32_t>(v) < static_cast<int32_t>(minValue))
-        {
-          *t = minValue;
-        }
-        else if (static_cast<int32_t>(v) > static_cast<int32_t>(maxValue))
-        {
-          *t = maxValue;
-        }
-        else
-        {
-          *t = static_cast<TargetType>(v);
-        }
-      }
-    }
-  }
-
-
-  template <typename PixelType>
-  static void SetInternal(ImageAccessor& image,
-                          int64_t constant)
-  {
-    for (unsigned int y = 0; y < image.GetHeight(); y++)
-    {
-      PixelType* p = reinterpret_cast<PixelType*>(image.GetRow(y));
-
-      for (unsigned int x = 0; x < image.GetWidth(); x++, p++)
-      {
-        *p = static_cast<PixelType>(constant);
-      }
-    }
-  }
-
-
-  template <typename PixelType>
-  static void GetMinMaxValueInternal(PixelType& minValue,
-                                     PixelType& maxValue,
-                                     const ImageAccessor& source)
-  {
-    // Deal with the special case of empty image
-    if (source.GetWidth() == 0 ||
-        source.GetHeight() == 0)
-    {
-      minValue = 0;
-      maxValue = 0;
-      return;
-    }
-
-    minValue = std::numeric_limits<PixelType>::max();
-    maxValue = std::numeric_limits<PixelType>::min();
-
-    const unsigned int width = source.GetWidth();
-
-    for (unsigned int y = 0; y < source.GetHeight(); y++)
-    {
-      const PixelType* p = reinterpret_cast<const PixelType*>(source.GetConstRow(y));
-
-      for (unsigned int x = 0; x < width; x++, p++)
-      {
-        if (*p < minValue)
-        {
-          minValue = *p;
-        }
-
-        if (*p > maxValue)
-        {
-          maxValue = *p;
-        }
-      }
-    }
-  }
-
-
-
-  template <typename PixelType>
-  static void AddConstantInternal(ImageAccessor& image,
-                                  int64_t constant)
-  {
-    if (constant == 0)
-    {
-      return;
-    }
-
-    const int64_t minValue = std::numeric_limits<PixelType>::min();
-    const int64_t maxValue = std::numeric_limits<PixelType>::max();
-
-    for (unsigned int y = 0; y < image.GetHeight(); y++)
-    {
-      PixelType* p = reinterpret_cast<PixelType*>(image.GetRow(y));
-
-      for (unsigned int x = 0; x < image.GetWidth(); x++, p++)
-      {
-        int64_t v = static_cast<int64_t>(*p) + constant;
-
-        if (v > maxValue)
-        {
-          *p = std::numeric_limits<PixelType>::max();
-        }
-        else if (v < minValue)
-        {
-          *p = std::numeric_limits<PixelType>::min();
-        }
-        else
-        {
-          *p = static_cast<PixelType>(v);
-        }
-      }
-    }
-  }
-
-
-
-  template <typename PixelType,
-            bool UseRound>
-  static void MultiplyConstantInternal(ImageAccessor& image,
-                                       float factor)
-  {
-    if (std::abs(factor - 1.0f) <= std::numeric_limits<float>::epsilon())
-    {
-      return;
-    }
-
-    const int64_t minValue = std::numeric_limits<PixelType>::min();
-    const int64_t maxValue = std::numeric_limits<PixelType>::max();
-    const unsigned int width = image.GetWidth();
-
-    for (unsigned int y = 0; y < image.GetHeight(); y++)
-    {
-      PixelType* p = reinterpret_cast<PixelType*>(image.GetRow(y));
-
-      for (unsigned int x = 0; x < width; x++, p++)
-      {
-        int64_t v;
-        if (UseRound)
-        {
-          // The "round" operation is very costly
-          v = boost::math::llround(static_cast<float>(*p) * factor);
-        }
-        else
-        {
-          v = static_cast<int64_t>(static_cast<float>(*p) * factor);
-        }
-
-        if (v > maxValue)
-        {
-          *p = std::numeric_limits<PixelType>::max();
-        }
-        else if (v < minValue)
-        {
-          *p = std::numeric_limits<PixelType>::min();
-        }
-        else
-        {
-          *p = static_cast<PixelType>(v);
-        }
-      }
-    }
-  }
-
-
-  template <typename PixelType,
-            bool UseRound>
-  static void ShiftScaleInternal(ImageAccessor& image,
-                                 float offset,
-                                 float scaling)
-  {
-    const float minFloatValue = static_cast<float>(std::numeric_limits<PixelType>::min());
-    const float maxFloatValue = static_cast<float>(std::numeric_limits<PixelType>::max());
-    const PixelType minPixelValue = std::numeric_limits<PixelType>::min();
-    const PixelType maxPixelValue = std::numeric_limits<PixelType>::max();
-
-    const unsigned int height = image.GetHeight();
-    const unsigned int width = image.GetWidth();
-    
-    for (unsigned int y = 0; y < height; y++)
-    {
-      PixelType* p = reinterpret_cast<PixelType*>(image.GetRow(y));
-
-      for (unsigned int x = 0; x < width; x++, p++)
-      {
-        float v = (static_cast<float>(*p) + offset) * scaling;
-
-        if (v > maxFloatValue)
-        {
-          *p = maxPixelValue;
-        }
-        else if (v < minFloatValue)
-        {
-          *p = minPixelValue;
-        }
-        else if (UseRound)
-        {
-          // The "round" operation is very costly
-          *p = static_cast<PixelType>(boost::math::iround(v));
-        }
-        else
-        {
-          *p = static_cast<PixelType>(v);
-        }
-      }
-    }
-  }
-
-
-  void ImageProcessing::Copy(ImageAccessor& target,
-                             const ImageAccessor& source)
-  {
-    if (target.GetWidth() != source.GetWidth() ||
-        target.GetHeight() != source.GetHeight())
-    {
-      throw OrthancException(ErrorCode_IncompatibleImageSize);
-    }
-
-    if (target.GetFormat() != source.GetFormat())
-    {
-      throw OrthancException(ErrorCode_IncompatibleImageFormat);
-    }
-
-    unsigned int lineSize = GetBytesPerPixel(source.GetFormat()) * source.GetWidth();
-
-    assert(source.GetPitch() >= lineSize && target.GetPitch() >= lineSize);
-
-    for (unsigned int y = 0; y < source.GetHeight(); y++)
-    {
-      memcpy(target.GetRow(y), source.GetConstRow(y), lineSize);
-    }
-  }
-
-
-  void ImageProcessing::Convert(ImageAccessor& target,
-                                const ImageAccessor& source)
-  {
-    if (target.GetWidth() != source.GetWidth() ||
-        target.GetHeight() != source.GetHeight())
-    {
-      throw OrthancException(ErrorCode_IncompatibleImageSize);
-    }
-
-    if (source.GetFormat() == target.GetFormat())
-    {
-      Copy(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Grayscale16 &&
-        source.GetFormat() == PixelFormat_Grayscale8)
-    {
-      ConvertInternal<uint16_t, uint8_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_SignedGrayscale16 &&
-        source.GetFormat() == PixelFormat_Grayscale8)
-    {
-      ConvertInternal<int16_t, uint8_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Grayscale8 &&
-        source.GetFormat() == PixelFormat_Grayscale16)
-    {
-      ConvertInternal<uint8_t, uint16_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_SignedGrayscale16 &&
-        source.GetFormat() == PixelFormat_Grayscale16)
-    {
-      ConvertInternal<int16_t, uint16_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Grayscale8 &&
-        source.GetFormat() == PixelFormat_SignedGrayscale16)
-    {
-      ConvertInternal<uint8_t, int16_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Grayscale16 &&
-        source.GetFormat() == PixelFormat_SignedGrayscale16)
-    {
-      ConvertInternal<uint16_t, int16_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Grayscale8 &&
-        source.GetFormat() == PixelFormat_RGB24)
-    {
-      ConvertColorToGrayscale<uint8_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Grayscale16 &&
-        source.GetFormat() == PixelFormat_RGB24)
-    {
-      ConvertColorToGrayscale<uint16_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_SignedGrayscale16 &&
-        source.GetFormat() == PixelFormat_RGB24)
-    {
-      ConvertColorToGrayscale<int16_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Float32 &&
-        source.GetFormat() == PixelFormat_Grayscale8)
-    {
-      ConvertGrayscaleToFloat<uint8_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Float32 &&
-        source.GetFormat() == PixelFormat_Grayscale16)
-    {
-      ConvertGrayscaleToFloat<uint16_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Float32 &&
-        source.GetFormat() == PixelFormat_Grayscale32)
-    {
-      ConvertGrayscaleToFloat<uint32_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Float32 &&
-        source.GetFormat() == PixelFormat_SignedGrayscale16)
-    {
-      ConvertGrayscaleToFloat<int16_t>(target, source);
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_Grayscale8 &&
-        source.GetFormat() == PixelFormat_RGBA32)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++, q++)
-        {
-          *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[0]) +
-                                     7152 * static_cast<uint32_t>(p[1]) +
-                                     0722 * static_cast<uint32_t>(p[2])) / 10000);
-          p += 4;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_RGB24 &&
-        source.GetFormat() == PixelFormat_RGBA32)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          q[0] = p[0];
-          q[1] = p[1];
-          q[2] = p[2];
-          p += 4;
-          q += 3;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_RGB24 &&
-        source.GetFormat() == PixelFormat_BGRA32)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          q[0] = p[2];
-          q[1] = p[1];
-          q[2] = p[0];
-          p += 4;
-          q += 3;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_RGBA32 &&
-        source.GetFormat() == PixelFormat_RGB24)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          q[0] = p[0];
-          q[1] = p[1];
-          q[2] = p[2];
-          q[3] = 255;   // Set the alpha channel to full opacity
-          p += 3;
-          q += 4;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_RGB24 &&
-        source.GetFormat() == PixelFormat_Grayscale8)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          q[0] = *p;
-          q[1] = *p;
-          q[2] = *p;
-          p += 1;
-          q += 3;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_RGBA32 &&
-        source.GetFormat() == PixelFormat_Grayscale8)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          q[0] = *p;
-          q[1] = *p;
-          q[2] = *p;
-          q[3] = 255;
-          p += 1;
-          q += 4;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_BGRA32 &&
-        source.GetFormat() == PixelFormat_Grayscale16)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint16_t* p = reinterpret_cast<const uint16_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          uint8_t value = (*p < 256 ? *p : 255);
-          q[0] = value;
-          q[1] = value;
-          q[2] = value;
-          q[3] = 255;
-          p += 1;
-          q += 4;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_BGRA32 &&
-        source.GetFormat() == PixelFormat_SignedGrayscale16)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const int16_t* p = reinterpret_cast<const int16_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          uint8_t value;
-          if (*p < 0)
-          {
-            value = 0;
-          }
-          else if (*p > 255)
-          {
-            value = 255;
-          }
-          else
-          {
-            value = static_cast<uint8_t>(*p);
-          }
-
-          q[0] = value;
-          q[1] = value;
-          q[2] = value;
-          q[3] = 255;
-          p += 1;
-          q += 4;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_BGRA32 &&
-        source.GetFormat() == PixelFormat_RGB24)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          q[0] = p[2];
-          q[1] = p[1];
-          q[2] = p[0];
-          q[3] = 255;
-          p += 3;
-          q += 4;
-        }
-      }
-
-      return;
-    }
-
-    if (target.GetFormat() == PixelFormat_RGB24 &&
-        source.GetFormat() == PixelFormat_RGB48)
-    {
-      for (unsigned int y = 0; y < source.GetHeight(); y++)
-      {
-        const uint16_t* p = reinterpret_cast<const uint16_t*>(source.GetConstRow(y));
-        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
-        for (unsigned int x = 0; x < source.GetWidth(); x++)
-        {
-          q[0] = p[0] >> 8;
-          q[1] = p[1] >> 8;
-          q[2] = p[2] >> 8;
-          p += 3;
-          q += 3;
-        }
-      }
-
-      return;
-    }
-
-    throw OrthancException(ErrorCode_NotImplemented);
-  }
-
-
-
-  void ImageProcessing::Set(ImageAccessor& image,
-                            int64_t value)
-  {
-    switch (image.GetFormat())
-    {
-      case PixelFormat_Grayscale8:
-        memset(image.GetBuffer(), static_cast<uint8_t>(value), image.GetPitch() * image.GetHeight());
-        return;
-
-      case PixelFormat_Grayscale16:
-        if (value == 0)
-        {
-          memset(image.GetBuffer(), 0, image.GetPitch() * image.GetHeight());
-        }
-        else
-        {
-          SetInternal<uint16_t>(image, value);
-        }
-        return;
-
-      case PixelFormat_Grayscale32:
-        if (value == 0)
-        {
-          memset(image.GetBuffer(), 0, image.GetPitch() * image.GetHeight());
-        }
-        else
-        {
-          SetInternal<uint32_t>(image, value);
-        }
-        return;
-
-      case PixelFormat_SignedGrayscale16:
-        if (value == 0)
-        {
-          memset(image.GetBuffer(), 0, image.GetPitch() * image.GetHeight());
-        }
-        else
-        {
-          SetInternal<int16_t>(image, value);
-        }
-        return;
-
-      case PixelFormat_Float32:
-        assert(sizeof(float) == 4);
-        SetInternal<float>(image, value);
-        return;
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-  void ImageProcessing::Set(ImageAccessor& image,
-                            uint8_t red,
-                            uint8_t green,
-                            uint8_t blue,
-                            uint8_t alpha)
-  {
-    uint8_t p[4];
-    unsigned int size;
-
-    switch (image.GetFormat())
-    {
-      case PixelFormat_RGBA32:
-        p[0] = red;
-        p[1] = green;
-        p[2] = blue;
-        p[3] = alpha;
-        size = 4;
-        break;
-
-      case PixelFormat_BGRA32:
-        p[0] = blue;
-        p[1] = green;
-        p[2] = red;
-        p[3] = alpha;
-        size = 4;
-        break;
-
-      case PixelFormat_RGB24:
-        p[0] = red;
-        p[1] = green;
-        p[2] = blue;
-        size = 3;
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }    
-
-    for (unsigned int y = 0; y < image.GetHeight(); y++)
-    {
-      uint8_t* q = reinterpret_cast<uint8_t*>(image.GetRow(y));
-
-      for (unsigned int x = 0; x < image.GetWidth(); x++)
-      {
-        for (unsigned int i = 0; i < size; i++)
-        {
-          q[i] = p[i];
-        }
-
-        q += size;
-      }
-    }
-  }
-
-
-  void ImageProcessing::ShiftRight(ImageAccessor& image,
-                                   unsigned int shift)
-  {
-    if (image.GetWidth() == 0 ||
-        image.GetHeight() == 0 ||
-        shift == 0)
-    {
-      // Nothing to do
-      return;
-    }
-
-    throw OrthancException(ErrorCode_NotImplemented);
-  }
-
-
-  void ImageProcessing::GetMinMaxIntegerValue(int64_t& minValue,
-                                              int64_t& maxValue,
-                                              const ImageAccessor& image)
-  {
-    switch (image.GetFormat())
-    {
-      case PixelFormat_Grayscale8:
-      {
-        uint8_t a, b;
-        GetMinMaxValueInternal<uint8_t>(a, b, image);
-        minValue = a;
-        maxValue = b;
-        break;
-      }
-
-      case PixelFormat_Grayscale16:
-      {
-        uint16_t a, b;
-        GetMinMaxValueInternal<uint16_t>(a, b, image);
-        minValue = a;
-        maxValue = b;
-        break;
-      }
-
-      case PixelFormat_Grayscale32:
-      {
-        uint32_t a, b;
-        GetMinMaxValueInternal<uint32_t>(a, b, image);
-        minValue = a;
-        maxValue = b;
-        break;
-      }
-
-      case PixelFormat_SignedGrayscale16:
-      {
-        int16_t a, b;
-        GetMinMaxValueInternal<int16_t>(a, b, image);
-        minValue = a;
-        maxValue = b;
-        break;
-      }
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-  void ImageProcessing::GetMinMaxFloatValue(float& minValue,
-                                            float& maxValue,
-                                            const ImageAccessor& image)
-  {
-    switch (image.GetFormat())
-    {
-      case PixelFormat_Float32:
-      {
-        assert(sizeof(float) == 32);
-        float a, b;
-        GetMinMaxValueInternal<float>(a, b, image);
-        minValue = a;
-        maxValue = b;
-        break;
-      }
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-
-  void ImageProcessing::AddConstant(ImageAccessor& image,
-                                    int64_t value)
-  {
-    switch (image.GetFormat())
-    {
-      case PixelFormat_Grayscale8:
-        AddConstantInternal<uint8_t>(image, value);
-        return;
-
-      case PixelFormat_Grayscale16:
-        AddConstantInternal<uint16_t>(image, value);
-        return;
-
-      case PixelFormat_SignedGrayscale16:
-        AddConstantInternal<int16_t>(image, value);
-        return;
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-  void ImageProcessing::MultiplyConstant(ImageAccessor& image,
-                                         float factor,
-                                         bool useRound)
-  {
-    switch (image.GetFormat())
-    {
-      case PixelFormat_Grayscale8:
-        if (useRound)
-        {
-          MultiplyConstantInternal<uint8_t, true>(image, factor);
-        }
-        else
-        {
-          MultiplyConstantInternal<uint8_t, false>(image, factor);
-        }
-        return;
-
-      case PixelFormat_Grayscale16:
-        if (useRound)
-        {
-          MultiplyConstantInternal<uint16_t, true>(image, factor);
-        }
-        else
-        {
-          MultiplyConstantInternal<uint16_t, false>(image, factor);
-        }
-        return;
-
-      case PixelFormat_SignedGrayscale16:
-        if (useRound)
-        {
-          MultiplyConstantInternal<int16_t, true>(image, factor);
-        }
-        else
-        {
-          MultiplyConstantInternal<int16_t, false>(image, factor);
-        }
-        return;
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-  void ImageProcessing::ShiftScale(ImageAccessor& image,
-                                   float offset,
-                                   float scaling,
-                                   bool useRound)
-  {
-    switch (image.GetFormat())
-    {
-      case PixelFormat_Grayscale8:
-        if (useRound)
-        {
-          ShiftScaleInternal<uint8_t, true>(image, offset, scaling);
-        }
-        else
-        {
-          ShiftScaleInternal<uint8_t, false>(image, offset, scaling);
-        }
-        return;
-
-      case PixelFormat_Grayscale16:
-        if (useRound)
-        {
-          ShiftScaleInternal<uint16_t, true>(image, offset, scaling);
-        }
-        else
-        {
-          ShiftScaleInternal<uint16_t, false>(image, offset, scaling);
-        }
-        return;
-
-      case PixelFormat_SignedGrayscale16:
-        if (useRound)
-        {
-          ShiftScaleInternal<int16_t, true>(image, offset, scaling);
-        }
-        else
-        {
-          ShiftScaleInternal<int16_t, false>(image, offset, scaling);
-        }
-        return;
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-  void ImageProcessing::Invert(ImageAccessor& image)
-  {
-    switch (image.GetFormat())
-    {
-      case PixelFormat_Grayscale8:
-      {
-        for (unsigned int y = 0; y < image.GetHeight(); y++)
-        {
-          uint8_t* p = reinterpret_cast<uint8_t*>(image.GetRow(y));
-
-          for (unsigned int x = 0; x < image.GetWidth(); x++, p++)
-          {
-            *p = 255 - (*p);
-          }
-        }
-        
-        return;
-      }
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }   
-  }
-
-
-
-  namespace
-  {
-    template <Orthanc::PixelFormat Format>
-    class BresenhamPixelWriter
-    {
-    private:
-      typedef typename PixelTraits<Format>::PixelType  PixelType;
-    
-      Orthanc::ImageAccessor&  image_;
-      PixelType                value_;
-
-      void PlotLineLow(int x0,
-                       int y0,
-                       int x1,
-                       int y1)
-      {
-        int dx = x1 - x0;
-        int dy = y1 - y0;
-        int yi = 1;
-
-        if (dy < 0)
-        {
-          yi = -1;
-          dy = -dy;
-        }
-
-        int d = 2 * dy - dx;
-        int y = y0;
-
-        for (int x = x0; x <= x1; x++)
-        {
-          Write(x, y);
-          
-          if (d > 0)
-          {
-            y = y + yi;
-            d = d - 2 * dx;
-          }
-      
-          d = d + 2*dy;
-        }
-      }
-      
-      void PlotLineHigh(int x0,
-                        int y0,
-                        int x1,
-                        int y1)
-      {
-        int dx = x1 - x0;
-        int dy = y1 - y0;
-        int xi = 1;
-    
-        if (dx < 0)
-        {
-          xi = -1;
-          dx = -dx;
-        }
-    
-        int d = 2 * dx - dy;
-        int x = x0;
-
-        for (int y = y0; y <= y1; y++)
-        {
-          Write(x, y);
-          
-          if (d > 0)
-          {
-            x = x + xi;
-            d = d - 2 * dy;
-          }
-      
-          d = d + 2 * dx;
-        }
-      }
-
-    public:
-      BresenhamPixelWriter(Orthanc::ImageAccessor& image,
-                           int64_t value) :
-        image_(image),
-        value_(PixelTraits<Format>::IntegerToPixel(value))
-      {
-      }
-
-      BresenhamPixelWriter(Orthanc::ImageAccessor& image,
-                           const PixelType& value) :
-        image_(image),
-        value_(value)
-      {
-      }
-
-      void Write(int x,
-                 int y)
-      {
-        if (x >= 0 &&
-            y >= 0 &&
-            static_cast<unsigned int>(x) < image_.GetWidth() &&
-            static_cast<unsigned int>(y) < image_.GetHeight())
-        {
-          PixelType* p = reinterpret_cast<PixelType*>(image_.GetRow(y));
-          p[x] = value_;
-        }
-      }
-
-      void DrawSegment(int x0,
-                       int y0,
-                       int x1,
-                       int y1)
-      {
-        // This is an implementation of Bresenham's line algorithm
-        // https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases
-    
-        if (abs(y1 - y0) < abs(x1 - x0))
-        {
-          if (x0 > x1)
-          {
-            PlotLineLow(x1, y1, x0, y0);
-          }
-          else
-          {
-            PlotLineLow(x0, y0, x1, y1);
-          }
-        }
-        else
-        {
-          if (y0 > y1)
-          {
-            PlotLineHigh(x1, y1, x0, y0);
-          }
-          else
-          {
-            PlotLineHigh(x0, y0, x1, y1);
-          }
-        }
-      }
-    };
-  }
-
-  
-  void ImageProcessing::DrawLineSegment(ImageAccessor& image,
-                                        int x0,
-                                        int y0,
-                                        int x1,
-                                        int y1,
-                                        int64_t value)
-  {
-    switch (image.GetFormat())
-    {       
-      case Orthanc::PixelFormat_Grayscale8:
-      {
-        BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale8> writer(image, value);
-        writer.DrawSegment(x0, y0, x1, y1);
-        break;
-      }
-
-      case Orthanc::PixelFormat_Grayscale16:
-      {
-        BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale16> writer(image, value);
-        writer.DrawSegment(x0, y0, x1, y1);
-        break;
-      }
-
-      case Orthanc::PixelFormat_SignedGrayscale16:
-      {
-        BresenhamPixelWriter<Orthanc::PixelFormat_SignedGrayscale16> writer(image, value);
-        writer.DrawSegment(x0, y0, x1, y1);
-        break;
-      }
-        
-      default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
-    }
-  }
-
-  
-  void ImageProcessing::DrawLineSegment(ImageAccessor& image,
-                                        int x0,
-                                        int y0,
-                                        int x1,
-                                        int y1,
-                                        uint8_t red,
-                                        uint8_t green,
-                                        uint8_t blue,
-                                        uint8_t alpha)
-  {
-    switch (image.GetFormat())
-    {
-      case Orthanc::PixelFormat_BGRA32:
-      {
-        PixelTraits<Orthanc::PixelFormat_BGRA32>::PixelType pixel;
-        pixel.red_ = red;
-        pixel.green_ = green;
-        pixel.blue_ = blue;
-        pixel.alpha_ = alpha;
-
-        BresenhamPixelWriter<Orthanc::PixelFormat_BGRA32> writer(image, pixel);
-        writer.DrawSegment(x0, y0, x1, y1);
-        break;
-      }
-        
-      case Orthanc::PixelFormat_RGB24:
-      {
-        PixelTraits<Orthanc::PixelFormat_RGB24>::PixelType pixel;
-        pixel.red_ = red;
-        pixel.green_ = green;
-        pixel.blue_ = blue;
-
-        BresenhamPixelWriter<Orthanc::PixelFormat_RGB24> writer(image, pixel);
-        writer.DrawSegment(x0, y0, x1, y1);
-        break;
-      }
-        
-      default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
-    }
-  }
-}
--- a/Resources/Orthanc/Core/Images/ImageProcessing.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "ImageAccessor.h"
-
-#include <stdint.h>
-
-namespace Orthanc
-{
-  namespace ImageProcessing
-  {
-    void Copy(ImageAccessor& target,
-              const ImageAccessor& source);
-
-    void Convert(ImageAccessor& target,
-                 const ImageAccessor& source);
-
-    void Set(ImageAccessor& image,
-             int64_t value);
-
-    void Set(ImageAccessor& image,
-             uint8_t red,
-             uint8_t green,
-             uint8_t blue,
-             uint8_t alpha);
-
-    void ShiftRight(ImageAccessor& target,
-                    unsigned int shift);
-
-    void GetMinMaxIntegerValue(int64_t& minValue,
-                               int64_t& maxValue,
-                               const ImageAccessor& image);
-
-    void GetMinMaxFloatValue(float& minValue,
-                             float& maxValue,
-                             const ImageAccessor& image);
-
-    void AddConstant(ImageAccessor& image,
-                     int64_t value);
-
-    // "useRound" is expensive
-    void MultiplyConstant(ImageAccessor& image,
-                          float factor,
-                          bool useRound);
-
-    // "useRound" is expensive
-    void ShiftScale(ImageAccessor& image,
-                    float offset,
-                    float scaling,
-                    bool useRound);
-
-    void Invert(ImageAccessor& image);
-
-    void DrawLineSegment(ImageAccessor& image,
-                         int x0,
-                         int y0,
-                         int x1,
-                         int y1,
-                         int64_t value);
-
-    void DrawLineSegment(ImageAccessor& image,
-                         int x0,
-                         int y0,
-                         int x1,
-                         int y1,
-                         uint8_t red,
-                         uint8_t green,
-                         uint8_t blue,
-                         uint8_t alpha);
-  };
-}
--- a/Resources/Orthanc/Core/Images/JpegErrorManager.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "JpegErrorManager.h"
-
-namespace Orthanc
-{
-  namespace Internals
-  {
-    void JpegErrorManager::OutputMessage(j_common_ptr cinfo)
-    {
-      char message[JMSG_LENGTH_MAX];
-      (*cinfo->err->format_message) (cinfo, message);
-
-      JpegErrorManager* that = reinterpret_cast<JpegErrorManager*>(cinfo->err);
-      that->message = std::string(message);
-    }
-
-
-    void JpegErrorManager::ErrorExit(j_common_ptr cinfo)
-    {
-      (*cinfo->err->output_message) (cinfo);
-
-      JpegErrorManager* that = reinterpret_cast<JpegErrorManager*>(cinfo->err);
-      longjmp(that->setjmp_buffer, 1);
-    }
-      
-
-    JpegErrorManager::JpegErrorManager()
-    {
-      memset(&pub, 0, sizeof(struct jpeg_error_mgr));
-      memset(&setjmp_buffer, 0, sizeof(jmp_buf));
-
-      jpeg_std_error(&pub);
-      pub.error_exit = ErrorExit;
-      pub.output_message = OutputMessage;
-    }
-  }
-}
--- a/Resources/Orthanc/Core/Images/JpegErrorManager.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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_ENABLE_JPEG)
-#  error The macro ORTHANC_ENABLE_JPEG must be defined
-#endif
-
-#if ORTHANC_ENABLE_JPEG != 1
-#  error JPEG support must be enabled to include this file
-#endif
-
-#include <string.h>
-#include <stdio.h>
-#include <jpeglib.h>
-#include <setjmp.h>
-#include <string>
-
-namespace Orthanc
-{
-  namespace Internals
-  {
-    class JpegErrorManager 
-    {
-    private:
-      struct jpeg_error_mgr pub;  /* "public" fields */
-      jmp_buf setjmp_buffer;      /* for return to caller */
-      std::string message;
-
-      static void OutputMessage(j_common_ptr cinfo);
-
-      static void ErrorExit(j_common_ptr cinfo);
-
-    public:
-      JpegErrorManager();
-
-      struct jpeg_error_mgr* GetPublic()
-      {
-        return &pub;
-      }
-
-      jmp_buf& GetJumpBuffer()
-      {
-        return setjmp_buffer;
-      }
-
-      const std::string& GetMessage() const
-      {
-        return message;
-      }
-    };
-  }
-}
--- a/Resources/Orthanc/Core/Images/JpegReader.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "JpegReader.h"
-
-#include "JpegErrorManager.h"
-#include "../OrthancException.h"
-#include "../Logging.h"
-
-#if ORTHANC_SANDBOXED == 0
-#  include "../SystemToolbox.h"
-#endif
-
-
-namespace Orthanc
-{
-  static void Uncompress(struct jpeg_decompress_struct& cinfo,
-                         std::string& content,
-                         ImageAccessor& accessor)
-  {
-    jpeg_read_header(&cinfo, TRUE);
-    jpeg_start_decompress(&cinfo);
-
-    PixelFormat format;
-    if (cinfo.output_components == 1 &&
-        cinfo.out_color_space == JCS_GRAYSCALE)
-    {
-      format = PixelFormat_Grayscale8;
-    }
-    else if (cinfo.output_components == 3 &&
-             cinfo.out_color_space == JCS_RGB)
-    {
-      format = PixelFormat_RGB24;
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_NotImplemented);
-    }
-
-    unsigned int pitch = cinfo.output_width * cinfo.output_components;
-
-    /* Make a one-row-high sample array that will go away when done with image */
-    JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, pitch, 1);
-
-    try
-    {
-      content.resize(pitch * cinfo.output_height);
-    }
-    catch (...)
-    {
-      throw OrthancException(ErrorCode_NotEnoughMemory);
-    }
-
-    accessor.AssignWritable(format, cinfo.output_width, cinfo.output_height, pitch, 
-                            content.empty() ? NULL : &content[0]);
-
-    uint8_t* target = reinterpret_cast<uint8_t*>(&content[0]);
-    while (cinfo.output_scanline < cinfo.output_height) 
-    {
-      jpeg_read_scanlines(&cinfo, buffer, 1);
-      memcpy(target, buffer[0], pitch);
-      target += pitch;
-    }
-
-    // Everything went fine, "setjmp()" didn't get called
-
-    jpeg_finish_decompress(&cinfo);
-  }
-
-
-#if ORTHANC_SANDBOXED == 0
-  void JpegReader::ReadFromFile(const std::string& filename)
-  {
-    FILE* fp = SystemToolbox::OpenFile(filename, FileMode_ReadBinary);
-    if (!fp)
-    {
-      throw OrthancException(ErrorCode_InexistentFile);
-    }
-
-    struct jpeg_decompress_struct cinfo;
-    memset(&cinfo, 0, sizeof(struct jpeg_decompress_struct));
-
-    Internals::JpegErrorManager jerr;
-    cinfo.err = jerr.GetPublic();
-    
-    if (setjmp(jerr.GetJumpBuffer())) 
-    {
-      jpeg_destroy_decompress(&cinfo);
-      fclose(fp);
-      LOG(ERROR) << "Error during JPEG decoding: " << jerr.GetMessage();
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-    // Below this line, we are under the scope of a "setjmp"
-
-    jpeg_create_decompress(&cinfo);
-    jpeg_stdio_src(&cinfo, fp);
-
-    try
-    {
-      Uncompress(cinfo, content_, *this);
-    }
-    catch (OrthancException&)
-    {
-      jpeg_destroy_decompress(&cinfo);
-      fclose(fp);
-      throw;
-    }
-
-    jpeg_destroy_decompress(&cinfo);
-    fclose(fp);
-  }
-#endif
-
-
-  void JpegReader::ReadFromMemory(const void* buffer,
-                                  size_t size)
-  {
-    struct jpeg_decompress_struct cinfo;
-    memset(&cinfo, 0, sizeof(struct jpeg_decompress_struct));
-
-    Internals::JpegErrorManager jerr;
-    cinfo.err = jerr.GetPublic();
-    
-    if (setjmp(jerr.GetJumpBuffer())) 
-    {
-      jpeg_destroy_decompress(&cinfo);
-      LOG(ERROR) << "Error during JPEG decoding: " << jerr.GetMessage();
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-    // Below this line, we are under the scope of a "setjmp"
-    jpeg_create_decompress(&cinfo);
-    jpeg_mem_src(&cinfo, const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer)), size);
-
-    try
-    {
-      Uncompress(cinfo, content_, *this);
-    }
-    catch (OrthancException&)
-    {
-      jpeg_destroy_decompress(&cinfo);
-      throw;
-    }
-
-    jpeg_destroy_decompress(&cinfo);
-  }
-
-
-  void JpegReader::ReadFromMemory(const std::string& buffer)
-  {
-    if (buffer.empty())
-    {
-      ReadFromMemory(NULL, 0);
-    }
-    else
-    {
-      ReadFromMemory(buffer.c_str(), buffer.size());
-    }
-  }
-}
--- a/Resources/Orthanc/Core/Images/JpegReader.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 !defined(ORTHANC_ENABLE_JPEG)
-#  error The macro ORTHANC_ENABLE_JPEG must be defined
-#endif
-
-#if ORTHANC_ENABLE_JPEG != 1
-#  error JPEG support must be enabled to include this file
-#endif
-
-#include "ImageAccessor.h"
-
-#include <string>
-#include <boost/noncopyable.hpp>
-
-namespace Orthanc
-{
-  class JpegReader : 
-    public ImageAccessor,
-    public boost::noncopyable
-  {
-  private:
-    std::string  content_;
-
-  public:
-#if ORTHANC_SANDBOXED == 0
-    void ReadFromFile(const std::string& filename);
-#endif
-
-    void ReadFromMemory(const void* buffer,
-                        size_t size);
-
-    void ReadFromMemory(const std::string& buffer);
-  };
-}
--- a/Resources/Orthanc/Core/Images/JpegWriter.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "JpegWriter.h"
-
-#include "../OrthancException.h"
-#include "../Logging.h"
-#include "JpegErrorManager.h"
-
-#if ORTHANC_SANDBOXED == 0
-#  include "../SystemToolbox.h"
-#endif
-
-#include <stdlib.h>
-#include <vector>
-
-namespace Orthanc
-{
-  static void GetLines(std::vector<uint8_t*>& lines,
-                       unsigned int height,
-                       unsigned int pitch,
-                       PixelFormat format,
-                       const void* buffer)
-  {
-    if (format != PixelFormat_Grayscale8 &&
-        format != PixelFormat_RGB24)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    lines.resize(height);
-
-    uint8_t* base = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffer));
-    for (unsigned int y = 0; y < height; y++)
-    {
-      lines[y] = base + static_cast<intptr_t>(y) * static_cast<intptr_t>(pitch);
-    }
-  }
-
-
-  static void Compress(struct jpeg_compress_struct& cinfo,
-                       std::vector<uint8_t*>& lines,
-                       unsigned int width,
-                       unsigned int height,
-                       PixelFormat format,
-                       uint8_t quality)
-  {
-    cinfo.image_width = width;
-    cinfo.image_height = height;
-
-    switch (format)
-    {
-      case PixelFormat_Grayscale8:
-        cinfo.input_components = 1;
-        cinfo.in_color_space = JCS_GRAYSCALE;
-        break;
-
-      case PixelFormat_RGB24:
-        cinfo.input_components = 3;
-        cinfo.in_color_space = JCS_RGB;
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_InternalError);
-    }
-
-    jpeg_set_defaults(&cinfo);
-    jpeg_set_quality(&cinfo, quality, TRUE);
-    jpeg_start_compress(&cinfo, TRUE);
-    jpeg_write_scanlines(&cinfo, &lines[0], height);
-    jpeg_finish_compress(&cinfo);
-    jpeg_destroy_compress(&cinfo);
-  }
-                       
-
-  void JpegWriter::SetQuality(uint8_t quality)
-  {
-    if (quality == 0 || quality > 100)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    quality_ = quality;
-  }
-
-
-#if ORTHANC_SANDBOXED == 0
-  void JpegWriter::WriteToFileInternal(const std::string& filename,
-                                       unsigned int width,
-                                       unsigned int height,
-                                       unsigned int pitch,
-                                       PixelFormat format,
-                                       const void* buffer)
-  {
-    FILE* fp = SystemToolbox::OpenFile(filename, FileMode_WriteBinary);
-    if (fp == NULL)
-    {
-      throw OrthancException(ErrorCode_CannotWriteFile);
-    }
-
-    std::vector<uint8_t*> lines;
-    GetLines(lines, height, pitch, format, buffer);
-
-    struct jpeg_compress_struct cinfo;
-    memset(&cinfo, 0, sizeof(struct jpeg_compress_struct));
-
-    Internals::JpegErrorManager jerr;
-    cinfo.err = jerr.GetPublic();
-
-    if (setjmp(jerr.GetJumpBuffer())) 
-    {
-      /* If we get here, the JPEG code has signaled an error.
-       * We need to clean up the JPEG object, close the input file, and return.
-       */
-      jpeg_destroy_compress(&cinfo);
-      fclose(fp);
-      LOG(ERROR) << "Error during JPEG encoding: " << jerr.GetMessage();
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-    // Do not allocate data on the stack below this line!
-
-    jpeg_create_compress(&cinfo);
-    jpeg_stdio_dest(&cinfo, fp);
-    Compress(cinfo, lines, width, height, format, quality_);
-
-    // Everything went fine, "setjmp()" didn't get called
-
-    fclose(fp);
-  }
-#endif
-
-
-#if ORTHANC_SANDBOXED == 0
-  void JpegWriter::WriteToMemoryInternal(std::string& jpeg,
-                                         unsigned int width,
-                                         unsigned int height,
-                                         unsigned int pitch,
-                                         PixelFormat format,
-                                         const void* buffer)
-  {
-    std::vector<uint8_t*> lines;
-    GetLines(lines, height, pitch, format, buffer);
-
-    struct jpeg_compress_struct cinfo;
-    memset(&cinfo, 0, sizeof(struct jpeg_compress_struct));
-
-    Internals::JpegErrorManager jerr;
-
-    unsigned char* data = NULL;
-    unsigned long size;
-
-    if (setjmp(jerr.GetJumpBuffer())) 
-    {
-      jpeg_destroy_compress(&cinfo);
-
-      if (data != NULL)
-      {
-        free(data);
-      }
-
-      LOG(ERROR) << "Error during JPEG encoding: " << jerr.GetMessage();
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-    // Do not allocate data on the stack below this line!
-
-    jpeg_create_compress(&cinfo);
-    cinfo.err = jerr.GetPublic();
-    jpeg_mem_dest(&cinfo, &data, &size);
-
-    Compress(cinfo, lines, width, height, format, quality_);
-
-    // Everything went fine, "setjmp()" didn't get called
-
-    jpeg.assign(reinterpret_cast<const char*>(data), size);
-    free(data);
-  }
-#endif
-}
--- a/Resources/Orthanc/Core/Images/JpegWriter.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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_ENABLE_JPEG)
-#  error The macro ORTHANC_ENABLE_JPEG must be defined
-#endif
-
-#if ORTHANC_ENABLE_JPEG != 1
-#  error JPEG support must be enabled to include this file
-#endif
-
-#include "IImageWriter.h"
-
-namespace Orthanc
-{
-  class JpegWriter : public IImageWriter
-  {
-  protected:
-    virtual void WriteToFileInternal(const std::string& filename,
-                                     unsigned int width,
-                                     unsigned int height,
-                                     unsigned int pitch,
-                                     PixelFormat format,
-                                     const void* buffer);
-
-#if ORTHANC_SANDBOXED == 0
-    virtual void WriteToMemoryInternal(std::string& jpeg,
-                                       unsigned int width,
-                                       unsigned int height,
-                                       unsigned int pitch,
-                                       PixelFormat format,
-                                       const void* buffer);
-#endif
-
-  private:
-    uint8_t  quality_;
-
-  public:
-    JpegWriter() : quality_(90)
-    {
-    }
-
-    void SetQuality(uint8_t quality);
-
-    uint8_t GetQuality() const
-    {
-      return quality_;
-    }
-  };
-}
--- a/Resources/Orthanc/Core/Images/PixelTraits.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,267 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "../OrthancException.h"
-
-#include <limits>
-
-namespace Orthanc
-{
-  template <PixelFormat format,
-            typename _PixelType>
-  struct IntegerPixelTraits
-  {
-    typedef _PixelType  PixelType;
-
-    ORTHANC_FORCE_INLINE
-    static PixelFormat GetPixelFormat()
-    {
-      return format;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static PixelType IntegerToPixel(int64_t value)
-    {
-      if (value < static_cast<int64_t>(std::numeric_limits<PixelType>::min()) ||
-          value > static_cast<int64_t>(std::numeric_limits<PixelType>::max()))
-      {
-        throw OrthancException(ErrorCode_ParameterOutOfRange);
-      }
-      else
-      {
-        return static_cast<PixelType>(value);
-      }
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void SetZero(PixelType& target)
-    {
-      target = 0;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void SetMinValue(PixelType& target)
-    {
-      target = std::numeric_limits<PixelType>::min();
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void SetMaxValue(PixelType& target)
-    {
-      target = std::numeric_limits<PixelType>::max();
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void Copy(PixelType& target,
-                     const PixelType& source)
-    {
-      target = source;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static float PixelToFloat(const PixelType& source)
-    {
-      return static_cast<float>(source);
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void FloatToPixel(PixelType& target,
-                             float value)
-    {
-      if (value < static_cast<float>(std::numeric_limits<PixelType>::min()))
-      {
-        target = std::numeric_limits<PixelType>::min();
-      }
-      else if (value > static_cast<float>(std::numeric_limits<PixelType>::max()))
-      {
-        target = std::numeric_limits<PixelType>::max();
-      }
-      else
-      {
-        target = static_cast<PixelType>(value);
-      }
-    }
-
-    ORTHANC_FORCE_INLINE
-    static bool IsEqual(const PixelType& a,
-                        const PixelType& b)
-    {
-      return a == b;
-    }
-  };
-
-
-  template <PixelFormat Format>
-  struct PixelTraits;
-
-
-  template <>
-  struct PixelTraits<PixelFormat_Grayscale8> :
-    public IntegerPixelTraits<PixelFormat_Grayscale8, uint8_t>
-  {
-  };
-
-  
-  template <>
-  struct PixelTraits<PixelFormat_Grayscale16> :
-    public IntegerPixelTraits<PixelFormat_Grayscale16, uint16_t>
-  {
-  };
-
-  
-  template <>
-  struct PixelTraits<PixelFormat_SignedGrayscale16> :
-    public IntegerPixelTraits<PixelFormat_SignedGrayscale16, int16_t>
-  {
-  };
-
-
-  template <>
-  struct PixelTraits<PixelFormat_RGB24>
-  {
-    struct PixelType
-    {
-      uint8_t  red_;
-      uint8_t  green_;
-      uint8_t  blue_;
-    };
-
-    ORTHANC_FORCE_INLINE
-    static PixelFormat GetPixelFormat()
-    {
-      return PixelFormat_RGB24;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void SetZero(PixelType& target)
-    {
-      target.red_ = 0;
-      target.green_ = 0;
-      target.blue_ = 0;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void Copy(PixelType& target,
-                     const PixelType& source)
-    {
-      target.red_ = source.red_;
-      target.green_ = source.green_;
-      target.blue_ = source.blue_;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static bool IsEqual(const PixelType& a,
-                        const PixelType& b)
-    {
-      return (a.red_ == b.red_ &&
-              a.green_ == b.green_ &&
-              a.blue_ == b.blue_);
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void FloatToPixel(PixelType& target,
-                             float value)
-    {
-      uint8_t v;
-      PixelTraits<PixelFormat_Grayscale8>::FloatToPixel(v, value);
-
-      target.red_ = v;
-      target.green_ = v;
-      target.blue_ = v;
-    }
-  };
-
-
-  template <>
-  struct PixelTraits<PixelFormat_BGRA32>
-  {
-    struct PixelType
-    {
-      uint8_t  blue_;
-      uint8_t  green_;
-      uint8_t  red_;
-      uint8_t  alpha_;
-    };
-
-    ORTHANC_FORCE_INLINE
-    static PixelFormat GetPixelFormat()
-    {
-      return PixelFormat_BGRA32;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void SetZero(PixelType& target)
-    {
-      target.blue_ = 0;
-      target.green_ = 0;
-      target.red_ = 0;
-      target.alpha_ = 0;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void Copy(PixelType& target,
-                     const PixelType& source)
-    {
-      target.blue_ = source.blue_;
-      target.green_ = source.green_;
-      target.red_ = source.red_;
-      target.alpha_ = source.alpha_;
-    }
-
-    ORTHANC_FORCE_INLINE
-    static bool IsEqual(const PixelType& a,
-                        const PixelType& b)
-    {
-      return (a.blue_ == b.blue_ &&
-              a.green_ == b.green_ &&
-              a.red_ == b.red_ &&
-              a.alpha_ == b.alpha_);
-    }
-
-    ORTHANC_FORCE_INLINE
-    static void FloatToPixel(PixelType& target,
-                             float value)
-    {
-      uint8_t v;
-      PixelTraits<PixelFormat_Grayscale8>::FloatToPixel(v, value);
-
-      target.blue_ = v;
-      target.green_ = v;
-      target.red_ = v;
-      target.alpha_ = 255;      
-    }
-  };
-}
--- a/Resources/Orthanc/Core/Images/PngReader.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,325 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "PngReader.h"
-
-#include "../OrthancException.h"
-#include "../Toolbox.h"
-
-#if ORTHANC_SANDBOXED == 0
-#  include "../SystemToolbox.h"
-#endif
-
-#include <png.h>
-#include <string.h>  // For memcpy()
-
-namespace Orthanc
-{
-#if ORTHANC_SANDBOXED == 0
-  namespace 
-  {
-    struct FileRabi
-    {
-      FILE* fp_;
-
-      FileRabi(const char* filename)
-      {
-        fp_ = SystemToolbox::OpenFile(filename, FileMode_ReadBinary);
-        if (!fp_)
-        {
-          throw OrthancException(ErrorCode_InexistentFile);
-        }
-      }
-
-      ~FileRabi()
-      {
-        if (fp_)
-        {
-          fclose(fp_);
-        }
-      }
-    };
-  }
-#endif
-
-
-  struct PngReader::PngRabi
-  {
-    png_structp png_;
-    png_infop info_;
-    png_infop endInfo_;
-
-    void Destruct()
-    {
-      if (png_)
-      {
-        png_destroy_read_struct(&png_, &info_, &endInfo_);
-
-        png_ = NULL;
-        info_ = NULL;
-        endInfo_ = NULL;
-      }
-    }
-
-    PngRabi()
-    {
-      png_ = NULL;
-      info_ = NULL;
-      endInfo_ = NULL;
-
-      png_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-      if (!png_)
-      {
-        throw OrthancException(ErrorCode_NotEnoughMemory);
-      }
-
-      info_ = png_create_info_struct(png_);
-      if (!info_)
-      {
-        png_destroy_read_struct(&png_, NULL, NULL);
-        throw OrthancException(ErrorCode_NotEnoughMemory);
-      }
-
-      endInfo_ = png_create_info_struct(png_);
-      if (!info_)
-      {
-        png_destroy_read_struct(&png_, &info_, NULL);
-        throw OrthancException(ErrorCode_NotEnoughMemory);
-      }
-    }
-
-    ~PngRabi()
-    {
-      Destruct();
-    }
-
-    static void MemoryCallback(png_structp png_ptr, 
-                               png_bytep data, 
-                               png_size_t size);
-  };
-
-
-  void PngReader::CheckHeader(const void* header)
-  {
-    int is_png = !png_sig_cmp((png_bytep) header, 0, 8);
-    if (!is_png)
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-  }
-
-  PngReader::PngReader()
-  {
-  }
-
-  void PngReader::Read(PngRabi& rabi)
-  {
-    png_set_sig_bytes(rabi.png_, 8);
-
-    png_read_info(rabi.png_, rabi.info_);
-
-    png_uint_32 width, height;
-    int bit_depth, color_type, interlace_type;
-    int compression_type, filter_method;
-    // get size and bit-depth of the PNG-image
-    png_get_IHDR(rabi.png_, rabi.info_,
-                 &width, &height,
-                 &bit_depth, &color_type, &interlace_type,
-                 &compression_type, &filter_method);
-
-    PixelFormat format;
-    unsigned int pitch;
-
-    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 8)
-    {
-      format = PixelFormat_Grayscale8;
-      pitch = width;
-    }
-    else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16)
-    {
-      format = PixelFormat_Grayscale16;
-      pitch = 2 * width;
-
-      if (Toolbox::DetectEndianness() == Endianness_Little)
-      {
-        png_set_swap(rabi.png_);
-      }
-    }
-    else if (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 8)
-    {
-      format = PixelFormat_RGB24;
-      pitch = 3 * width;
-    }
-    else if (color_type == PNG_COLOR_TYPE_RGBA && bit_depth == 8)
-    {
-      format = PixelFormat_RGBA32;
-      pitch = 4 * width;
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_NotImplemented);
-    }
-
-    data_.resize(height * pitch);
-
-    if (height == 0 || width == 0)
-    {
-      // Empty image, we are done
-      AssignEmpty(format);
-      return;
-    }
-    
-    png_read_update_info(rabi.png_, rabi.info_);
-
-    std::vector<png_bytep> rows(height);
-    for (size_t i = 0; i < height; i++)
-    {
-      rows[i] = &data_[0] + i * pitch;
-    }
-
-    png_read_image(rabi.png_, &rows[0]);
-
-    AssignWritable(format, width, height, pitch, &data_[0]);
-  }
-
-
-#if ORTHANC_SANDBOXED == 0
-  void PngReader::ReadFromFile(const std::string& filename)
-  {
-    FileRabi f(filename.c_str());
-
-    char header[8];
-    if (fread(header, 1, 8, f.fp_) != 8)
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    CheckHeader(header);
-
-    PngRabi rabi;
-
-    if (setjmp(png_jmpbuf(rabi.png_)))
-    {
-      rabi.Destruct();
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    png_init_io(rabi.png_, f.fp_);
-
-    Read(rabi);
-  }
-#endif
-
-
-  namespace
-  {
-    struct MemoryBuffer
-    {
-      const uint8_t* buffer_;
-      size_t size_;
-      size_t pos_;
-      bool ok_;
-    };
-  }
-
-
-  void PngReader::PngRabi::MemoryCallback(png_structp png_ptr, 
-                                          png_bytep outBytes, 
-                                          png_size_t byteCountToRead)
-  {
-    MemoryBuffer* from = reinterpret_cast<MemoryBuffer*>(png_get_io_ptr(png_ptr));
-
-    if (!from->ok_)
-    {
-      return;
-    }
-
-    if (from->pos_ + byteCountToRead > from->size_)
-    {
-      from->ok_ = false;
-      return;
-    }
-
-    memcpy(outBytes, from->buffer_ + from->pos_, byteCountToRead);
-
-    from->pos_ += byteCountToRead;
-  }
-
-
-  void PngReader::ReadFromMemory(const void* buffer,
-                                 size_t size)
-  {
-    if (size < 8)
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    CheckHeader(buffer);
-
-    PngRabi rabi;
-
-    if (setjmp(png_jmpbuf(rabi.png_)))
-    {
-      rabi.Destruct();
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    MemoryBuffer tmp;
-    tmp.buffer_ = reinterpret_cast<const uint8_t*>(buffer) + 8;  // We skip the header
-    tmp.size_ = size - 8;
-    tmp.pos_ = 0;
-    tmp.ok_ = true;
-
-    png_set_read_fn(rabi.png_, &tmp, PngRabi::MemoryCallback);
-
-    Read(rabi);
-
-    if (!tmp.ok_)
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-  }
-
-  void PngReader::ReadFromMemory(const std::string& buffer)
-  {
-    if (buffer.size() != 0)
-    {
-      ReadFromMemory(&buffer[0], buffer.size());
-    }
-    else
-    {
-      ReadFromMemory(NULL, 0);
-    }
-  }
-}
--- a/Resources/Orthanc/Core/Images/PngReader.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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_ENABLE_PNG)
-#  error The macro ORTHANC_ENABLE_PNG must be defined
-#endif
-
-#if ORTHANC_ENABLE_PNG != 1
-#  error PNG support must be enabled to include this file
-#endif
-
-#include "ImageAccessor.h"
-
-#include "../Enumerations.h"
-
-#include <vector>
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
-#include <boost/noncopyable.hpp>
-
-#if !defined(ORTHANC_SANDBOXED)
-#  error The macro ORTHANC_SANDBOXED must be defined
-#endif
-
-namespace Orthanc
-{
-  class PngReader : 
-    public ImageAccessor, 
-    public boost::noncopyable
-  {
-  private:
-    struct PngRabi;
-
-    std::vector<uint8_t> data_;
-
-    void CheckHeader(const void* header);
-
-    void Read(PngRabi& rabi);
-
-  public:
-    PngReader();
-
-#if ORTHANC_SANDBOXED == 0
-    void ReadFromFile(const std::string& filename);
-#endif
-
-    void ReadFromMemory(const void* buffer,
-                        size_t size);
-
-    void ReadFromMemory(const std::string& buffer);
-  };
-}
--- a/Resources/Orthanc/Core/Images/PngWriter.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "PngWriter.h"
-
-#include <vector>
-#include <stdint.h>
-#include <png.h>
-#include "../OrthancException.h"
-#include "../ChunkedBuffer.h"
-#include "../Toolbox.h"
-
-#if ORTHANC_SANDBOXED == 0
-#  include "../SystemToolbox.h"
-#endif
-
-
-// http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-4
-// http://zarb.org/~gc/html/libpng.html
-/*
-  void write_row_callback(png_ptr, png_uint_32 row, int pass)
-  {
-  }*/
-
-
-
-
-/*  bool isError_;
-
-// http://www.libpng.org/pub/png/book/chapter14.html#png.ch14.div.2
-
-static void ErrorHandler(png_structp png, png_const_charp message)
-{
-printf("** [%s]\n", message);
-
-PngWriter* that = (PngWriter*) png_get_error_ptr(png);
-that->isError_ = true;
-printf("** %d\n", (int)that);
-
-//((PngWriter*) payload)->isError_ = true;
-}
-
-static void WarningHandler(png_structp png, png_const_charp message)
-{
-  printf("++ %d\n", (int)message);
-}*/
-
-
-namespace Orthanc
-{
-  struct PngWriter::PImpl
-  {
-    png_structp png_;
-    png_infop info_;
-
-    // Filled by Prepare()
-    std::vector<uint8_t*> rows_;
-    int bitDepth_;
-    int colorType_;
-  };
-
-
-
-  PngWriter::PngWriter() : pimpl_(new PImpl)
-  {
-    pimpl_->png_ = NULL;
-    pimpl_->info_ = NULL;
-
-    pimpl_->png_ = png_create_write_struct
-      (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); //this, ErrorHandler, WarningHandler);
-    if (!pimpl_->png_)
-    {
-      throw OrthancException(ErrorCode_NotEnoughMemory);
-    }
-
-    pimpl_->info_ = png_create_info_struct(pimpl_->png_);
-    if (!pimpl_->info_)
-    {
-      png_destroy_write_struct(&pimpl_->png_, NULL);
-      throw OrthancException(ErrorCode_NotEnoughMemory);
-    }
-  }
-
-  PngWriter::~PngWriter()
-  {
-    if (pimpl_->info_)
-    {
-      png_destroy_info_struct(pimpl_->png_, &pimpl_->info_);
-    }
-
-    if (pimpl_->png_)
-    {
-      png_destroy_write_struct(&pimpl_->png_, NULL);
-    }
-  }
-
-
-
-  void PngWriter::Prepare(unsigned int width,
-                          unsigned int height,
-                          unsigned int pitch,
-                          PixelFormat format,
-                          const void* buffer)
-  {
-    pimpl_->rows_.resize(height);
-    for (unsigned int y = 0; y < height; y++)
-    {
-      pimpl_->rows_[y] = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffer)) + y * pitch;
-    }
-
-    switch (format)
-    {
-    case PixelFormat_RGB24:
-      pimpl_->bitDepth_ = 8;
-      pimpl_->colorType_ = PNG_COLOR_TYPE_RGB;
-      break;
-
-    case PixelFormat_RGBA32:
-      pimpl_->bitDepth_ = 8;
-      pimpl_->colorType_ = PNG_COLOR_TYPE_RGBA;
-      break;
-
-    case PixelFormat_Grayscale8:
-      pimpl_->bitDepth_ = 8;
-      pimpl_->colorType_ = PNG_COLOR_TYPE_GRAY;
-      break;
-
-    case PixelFormat_Grayscale16:
-    case PixelFormat_SignedGrayscale16:
-      pimpl_->bitDepth_ = 16;
-      pimpl_->colorType_ = PNG_COLOR_TYPE_GRAY;
-      break;
-
-    default:
-      throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-  void PngWriter::Compress(unsigned int width,
-                           unsigned int height,
-                           unsigned int pitch,
-                           PixelFormat format)
-  {
-    png_set_IHDR(pimpl_->png_, pimpl_->info_, width, height,
-                 pimpl_->bitDepth_, pimpl_->colorType_, PNG_INTERLACE_NONE,
-                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
-    png_write_info(pimpl_->png_, pimpl_->info_);
-
-    if (height > 0)
-    {
-      switch (format)
-      {
-      case PixelFormat_Grayscale16:
-      case PixelFormat_SignedGrayscale16:
-      {
-        int transforms = 0;
-        if (Toolbox::DetectEndianness() == Endianness_Little)
-        {
-          transforms = PNG_TRANSFORM_SWAP_ENDIAN;
-        }
-
-        png_set_rows(pimpl_->png_, pimpl_->info_, &pimpl_->rows_[0]);
-        png_write_png(pimpl_->png_, pimpl_->info_, transforms, NULL);
-
-        break;
-      }
-
-      default:
-        png_write_image(pimpl_->png_, &pimpl_->rows_[0]);
-      }
-    }
-
-    png_write_end(pimpl_->png_, NULL);
-  }
-
-
-#if ORTHANC_SANDBOXED == 0
-  void PngWriter::WriteToFileInternal(const std::string& filename,
-                                      unsigned int width,
-                                      unsigned int height,
-                                      unsigned int pitch,
-                                      PixelFormat format,
-                                      const void* buffer)
-  {
-    Prepare(width, height, pitch, format, buffer);
-
-    FILE* fp = SystemToolbox::OpenFile(filename, FileMode_WriteBinary);
-    if (!fp)
-    {
-      throw OrthancException(ErrorCode_CannotWriteFile);
-    }    
-
-    png_init_io(pimpl_->png_, fp);
-
-    if (setjmp(png_jmpbuf(pimpl_->png_)))
-    {
-      // Error during writing PNG
-      throw OrthancException(ErrorCode_CannotWriteFile);      
-    }
-
-    Compress(width, height, pitch, format);
-
-    fclose(fp);
-  }
-#endif
-
-
-  static void MemoryCallback(png_structp png_ptr, 
-                             png_bytep data, 
-                             png_size_t size)
-  {
-    ChunkedBuffer* buffer = reinterpret_cast<ChunkedBuffer*>(png_get_io_ptr(png_ptr));
-    buffer->AddChunk(reinterpret_cast<const char*>(data), size);
-  }
-
-
-
-#if ORTHANC_SANDBOXED == 0
-  void PngWriter::WriteToMemoryInternal(std::string& png,
-                                        unsigned int width,
-                                        unsigned int height,
-                                        unsigned int pitch,
-                                        PixelFormat format,
-                                        const void* buffer)
-  {
-    ChunkedBuffer chunks;
-
-    Prepare(width, height, pitch, format, buffer);
-
-    if (setjmp(png_jmpbuf(pimpl_->png_)))
-    {
-      // Error during writing PNG
-      throw OrthancException(ErrorCode_InternalError);      
-    }
-
-    png_set_write_fn(pimpl_->png_, &chunks, MemoryCallback, NULL);
-
-    Compress(width, height, pitch, format);
-
-    chunks.Flatten(png);
-  }
-#endif
-}
--- a/Resources/Orthanc/Core/Images/PngWriter.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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_ENABLE_PNG)
-#  error The macro ORTHANC_ENABLE_PNG must be defined
-#endif
-
-#if ORTHANC_ENABLE_PNG != 1
-#  error PNG support must be enabled to include this file
-#endif
-
-#include "IImageWriter.h"
-
-#include <boost/shared_ptr.hpp>
-
-namespace Orthanc
-{
-  class PngWriter : public IImageWriter
-  {
-  protected:
-    virtual void WriteToFileInternal(const std::string& filename,
-                                     unsigned int width,
-                                     unsigned int height,
-                                     unsigned int pitch,
-                                     PixelFormat format,
-                                     const void* buffer);
-
-#if ORTHANC_SANDBOXED == 0
-    virtual void WriteToMemoryInternal(std::string& png,
-                                       unsigned int width,
-                                       unsigned int height,
-                                       unsigned int pitch,
-                                       PixelFormat format,
-                                       const void* buffer);
-#endif
-
-  private:
-    struct PImpl;
-    boost::shared_ptr<PImpl> pimpl_;
-
-    void Compress(unsigned int width,
-                  unsigned int height,
-                  unsigned int pitch,
-                  PixelFormat format);
-
-    void Prepare(unsigned int width,
-                 unsigned int height,
-                 unsigned int pitch,
-                 PixelFormat format,
-                 const void* buffer);
-
-  public:
-    PngWriter();
-
-    ~PngWriter();
-  };
-}
--- a/Resources/Orthanc/Core/Logging.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,603 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "Logging.h"
-
-#if ORTHANC_ENABLE_LOGGING != 1
-
-namespace Orthanc
-{
-  namespace Logging
-  {
-    void Initialize()
-    {
-    }
-
-    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)
-    {
-    }
-  }
-}
-
-
-#elif ORTHANC_ENABLE_LOGGING_PLUGIN == 1
-
-/*********************************************************
- * Logger compatible with the Orthanc plugin SDK
- *********************************************************/
-
-#include <boost/lexical_cast.hpp>
-
-namespace Orthanc
-{
-  namespace Logging
-  {
-    static OrthancPluginContext* context_ = NULL;
-
-    void Initialize(OrthancPluginContext* context)
-    {
-      context_ = context;
-    }
-
-    InternalLogger::InternalLogger(InternalLevel level,
-                                   const char* file  /* ignored */,
-                                   int line  /* ignored */) :
-      level_(level)
-    {
-    }
-
-    InternalLogger::~InternalLogger()
-    {
-      if (context_ != NULL)
-      {
-        switch (level_)
-        {
-          case InternalLevel_ERROR:
-            OrthancPluginLogError(context_, message_.c_str());
-            break;
-
-          case InternalLevel_WARNING:
-            OrthancPluginLogWarning(context_, message_.c_str());
-            break;
-
-          case InternalLevel_INFO:
-            OrthancPluginLogInfo(context_, message_.c_str());
-            break;
-
-          case InternalLevel_TRACE:
-            // Not used by plugins
-            break;
-
-          default:
-          {
-            std::string s = ("Unknown log level (" + boost::lexical_cast<std::string>(level_) +
-                             ") for message: " + message_);
-            OrthancPluginLogError(context_, s.c_str());
-            break;
-          }
-        }
-      }
-    }
-  }
-}
-
-
-#elif ORTHANC_ENABLE_LOGGING_STDIO == 1
-
-/*********************************************************
- * Logger compatible with <stdio.h>
- *********************************************************/
-
-#include <stdio.h>
-#include <boost/lexical_cast.hpp>
-
-namespace Orthanc
-{
-  namespace Logging
-  {
-    static bool globalVerbose_ = false;
-    static bool globalTrace_ = false;
-    
-    InternalLogger::InternalLogger(InternalLevel level,
-                                   const char* file  /* ignored */,
-                                   int line  /* ignored */) :
-      level_(level)
-    {
-    }
-
-    InternalLogger::~InternalLogger()
-    {
-      switch (level_)
-      {
-        case InternalLevel_ERROR:
-          fprintf(stderr, "E: %s\n", message_.c_str());
-          break;
-
-        case InternalLevel_WARNING:
-          fprintf(stdout, "W: %s\n", message_.c_str());
-          break;
-
-        case InternalLevel_INFO:
-          if (globalVerbose_)
-          {
-            fprintf(stdout, "I: %s\n", message_.c_str());
-          }
-          break;
-
-        case InternalLevel_TRACE:
-          if (globalTrace_)
-          {
-            fprintf(stdout, "T: %s\n", message_.c_str());
-          }
-          break;
-
-        default:
-          fprintf(stderr, "Unknown log level (%d) for message: %s\n", level_, message_.c_str());
-      }
-    }
-
-    void EnableInfoLevel(bool enabled)
-    {
-      globalVerbose_ = enabled;
-    }
-
-    void EnableTraceLevel(bool enabled)
-    {
-      globalTrace_ = enabled;
-    }
-  }
-}
-
-
-#else  /* ORTHANC_ENABLE_LOGGING_PLUGIN == 0 && 
-          ORTHANC_ENABLE_LOGGING_STDIO == 0 && 
-          ORTHANC_ENABLE_LOGGING == 1 */
-
-/*********************************************************
- * Internal logger of Orthanc, that mimics some
- * behavior from Google Log.
- *********************************************************/
-
-#include "OrthancException.h"
-#include "Enumerations.h"
-#include "Toolbox.h"
-
-#if ORTHANC_SANDBOXED == 1
-#  include <stdio.h>
-#else
-#  include "SystemToolbox.h"
-#endif
-
-#include <fstream>
-#include <boost/filesystem.hpp>
-#include <boost/thread.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-
-
-namespace
-{
-  struct LoggingContext
-  {
-    bool infoEnabled_;
-    bool traceEnabled_;
-    std::string  targetFile_;
-    std::string  targetFolder_;
-
-    std::ostream* error_;
-    std::ostream* warning_;
-    std::ostream* info_;
-
-    std::auto_ptr<std::ofstream> file_;
-
-    LoggingContext() : 
-      infoEnabled_(false),
-      traceEnabled_(false),
-      error_(&std::cerr),
-      warning_(&std::cerr),
-      info_(&std::cerr)
-    {
-    }
-  };
-}
-
-
-
-static std::auto_ptr<LoggingContext> loggingContext_;
-static boost::mutex  loggingMutex_;
-
-
-
-namespace Orthanc
-{
-  namespace Logging
-  {
-    static void GetLogPath(boost::filesystem::path& log,
-                           boost::filesystem::path& link,
-                           const std::string& suffix,
-                           const std::string& directory)
-    {
-      /**
-         From Google Log documentation:
-
-         Unless otherwise specified, logs will be written to the filename
-         "<program name>.<hostname>.<user name>.log<suffix>.",
-         followed by the date, time, and pid (you can't prevent the date,
-         time, and pid from being in the filename).
-
-         In this implementation : "hostname" and "username" are not used
-      **/
-
-      boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
-      boost::filesystem::path root(directory);
-      boost::filesystem::path exe(SystemToolbox::GetPathToExecutable());
-      
-      if (!boost::filesystem::exists(root) ||
-          !boost::filesystem::is_directory(root))
-      {
-        throw OrthancException(ErrorCode_CannotWriteFile);
-      }
-
-      char date[64];
-      sprintf(date, "%04d%02d%02d-%02d%02d%02d.%d",
-              static_cast<int>(now.date().year()),
-              now.date().month().as_number(),
-              now.date().day().as_number(),
-              static_cast<int>(now.time_of_day().hours()),
-              static_cast<int>(now.time_of_day().minutes()),
-              static_cast<int>(now.time_of_day().seconds()),
-              SystemToolbox::GetProcessId());
-
-      std::string programName = exe.filename().replace_extension("").string();
-
-      log = (root / (programName + ".log" + suffix + "." + std::string(date)));
-      link = (root / (programName + ".log" + suffix));
-    }
-
-
-    static void PrepareLogFolder(std::auto_ptr<std::ofstream>& file,
-                                 const std::string& suffix,
-                                 const std::string& directory)
-    {
-      boost::filesystem::path log, link;
-      GetLogPath(log, link, suffix, directory);
-
-#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
-      boost::filesystem::remove(link);
-      boost::filesystem::create_symlink(log.filename(), link);
-#endif
-
-      file.reset(new std::ofstream(log.string().c_str()));
-    }
-
-
-    void Initialize()
-    {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      loggingContext_.reset(new LoggingContext);
-    }
-
-    void Finalize()
-    {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      loggingContext_.reset(NULL);
-    }
-
-    void Reset()
-    {
-      // Recover the old logging context
-      std::auto_ptr<LoggingContext> old;
-
-      {
-        boost::mutex::scoped_lock lock(loggingMutex_);
-        if (loggingContext_.get() == NULL)
-        {
-          return;
-        }
-        else
-        {
-          old = loggingContext_;
-
-          // Create a new logging context, 
-          loggingContext_.reset(new LoggingContext);
-        }
-      }
-      
-      EnableInfoLevel(old->infoEnabled_);
-      EnableTraceLevel(old->traceEnabled_);
-
-      if (!old->targetFolder_.empty())
-      {
-        SetTargetFolder(old->targetFolder_);
-      }
-      else if (!old->targetFile_.empty())
-      {
-        SetTargetFile(old->targetFile_);
-      }
-    }
-
-    void EnableInfoLevel(bool enabled)
-    {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      loggingContext_->infoEnabled_ = enabled;
-      
-      if (!enabled)
-      {
-        // Also disable the "TRACE" level when info-level debugging is disabled
-        loggingContext_->traceEnabled_ = false;
-      }
-    }
-
-    void EnableTraceLevel(bool enabled)
-    {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      loggingContext_->traceEnabled_ = enabled;
-      
-      if (enabled)
-      {
-        // Also enable the "INFO" level when trace-level debugging is enabled
-        loggingContext_->infoEnabled_ = true;
-      }
-    }
-
-
-    static void CheckFile(std::auto_ptr<std::ofstream>& f)
-    {
-      if (loggingContext_->file_.get() == NULL ||
-          !loggingContext_->file_->is_open())
-      {
-        throw OrthancException(ErrorCode_CannotWriteFile);
-      }
-    }
-
-    void SetTargetFolder(const std::string& path)
-    {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      PrepareLogFolder(loggingContext_->file_, "" /* no suffix */, path);
-      CheckFile(loggingContext_->file_);
-
-      loggingContext_->targetFile_.clear();
-      loggingContext_->targetFolder_ = path;
-      loggingContext_->warning_ = loggingContext_->file_.get();
-      loggingContext_->error_ = loggingContext_->file_.get();
-      loggingContext_->info_ = loggingContext_->file_.get();
-    }
-
-
-    void SetTargetFile(const std::string& path)
-    {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      loggingContext_->file_.reset(new std::ofstream(path.c_str(), std::fstream::app));
-      CheckFile(loggingContext_->file_);
-
-      loggingContext_->targetFile_ = path;
-      loggingContext_->targetFolder_.clear();
-      loggingContext_->warning_ = loggingContext_->file_.get();
-      loggingContext_->error_ = loggingContext_->file_.get();
-      loggingContext_->info_ = loggingContext_->file_.get();
-    }
-
-
-    InternalLogger::InternalLogger(const char* level,
-                                   const char* file,
-                                   int line) : 
-      lock_(loggingMutex_), 
-      stream_(&null_)  // By default, logging to "/dev/null" is simulated
-    {
-      if (loggingContext_.get() == NULL)
-      {
-        fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n");
-        return;
-      }
-
-      try
-      {
-        LogLevel l = StringToLogLevel(level);
-      
-        if ((l == LogLevel_Info  && !loggingContext_->infoEnabled_) ||
-            (l == LogLevel_Trace && !loggingContext_->traceEnabled_))
-        {
-          // This logging level is disabled, directly exit and unlock
-          // the mutex to speed-up things. The stream is set to "/dev/null"
-          lock_.unlock();
-          return;
-        }
-
-        // Compute the header of the line, temporary release the lock as
-        // this is a time-consuming operation
-        lock_.unlock();
-        std::string header;
-
-        {
-          boost::filesystem::path path(file);
-          boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
-          boost::posix_time::time_duration duration = now.time_of_day();
-
-          /**
-             From Google Log documentation:
-
-             "Log lines have this form:
-
-             Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
-
-             where the fields are defined as follows:
-
-             L                A single character, representing the log level (eg 'I' for INFO)
-             mm               The month (zero padded; ie May is '05')
-             dd               The day (zero padded)
-             hh:mm:ss.uuuuuu  Time in hours, minutes and fractional seconds
-             threadid         The space-padded thread ID as returned by GetTID() (this matches the PID on Linux)
-             file             The file name
-             line             The line number
-             msg              The user-supplied message"
-
-             In this implementation, "threadid" is not printed.
-          **/
-
-          char date[32];
-          sprintf(date, "%c%02d%02d %02d:%02d:%02d.%06d ",
-                  level[0],
-                  now.date().month().as_number(),
-                  now.date().day().as_number(),
-                  static_cast<int>(duration.hours()),
-                  static_cast<int>(duration.minutes()),
-                  static_cast<int>(duration.seconds()),
-                  static_cast<int>(duration.fractional_seconds()));
-
-          header = std::string(date) + path.filename().string() + ":" + boost::lexical_cast<std::string>(line) + "] ";
-        }
-
-
-        // The header is computed, we now re-lock the mutex to access
-        // the stream objects. Pay attention that "loggingContext_",
-        // "infoEnabled_" or "traceEnabled_" might have changed while
-        // the mutex was unlocked.
-        lock_.lock();
-
-        if (loggingContext_.get() == NULL)
-        {
-          fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n");
-          return;
-        }
-
-        switch (l)
-        {
-          case LogLevel_Error:
-            stream_ = loggingContext_->error_;
-            break;
-
-          case LogLevel_Warning:
-            stream_ = loggingContext_->warning_;
-            break;
-
-          case LogLevel_Info:
-            if (loggingContext_->infoEnabled_)
-            {
-              stream_ = loggingContext_->info_;
-            }
-
-            break;
-
-          case LogLevel_Trace:
-            if (loggingContext_->traceEnabled_)
-            {
-              stream_ = loggingContext_->info_;
-            }
-
-            break;
-
-          default:
-            throw OrthancException(ErrorCode_InternalError);
-        }
-
-        if (stream_ == &null_)
-        {
-          // The logging is disabled for this level. The stream is the
-          // "null_" member of this object, so we can release the global
-          // mutex.
-          lock_.unlock();
-        }
-
-        (*stream_) << header;
-      }
-      catch (...)
-      { 
-        // Something is going really wrong, probably running out of
-        // memory. Fallback to a degraded mode.
-        stream_ = loggingContext_->error_;
-        (*stream_) << "E???? ??:??:??.?????? ] ";
-      }
-    }
-
-
-    InternalLogger::~InternalLogger()
-    {
-      if (stream_ != &null_)
-      {
-#if defined(_WIN32)
-        *stream_ << "\r\n";
-#else
-        *stream_ << "\n";
-#endif
-
-        stream_->flush();
-      }
-    }
-      
-
-    void Flush()
-    {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-
-      if (loggingContext_.get() != NULL &&
-          loggingContext_->file_.get() != NULL)
-      {
-        loggingContext_->file_->flush();
-      }
-    }
-  }
-}
-
-#endif   // ORTHANC_ENABLE_LOGGING
--- a/Resources/Orthanc/Core/Logging.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 !defined(ORTHANC_ENABLE_LOGGING_STDIO)
-#  if ORTHANC_ENABLE_LOGGING == 1
-#    error The macro ORTHANC_ENABLE_LOGGING_STDIO must be defined
-#  else
-#    define ORTHANC_ENABLE_LOGGING_STDIO 0
-#  endif
-#endif
-
-#if ORTHANC_ENABLE_LOGGING_PLUGIN == 1
-#  include <orthanc/OrthancCPlugin.h>
-#endif
-
-#include <boost/lexical_cast.hpp>
-
-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)
-      {
-      }
-      
-      template <typename T>
-      std::ostream& operator<< (const T& 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 ||    \
-       ORTHANC_ENABLE_LOGGING_STDIO == 1)
-
-#  include <boost/noncopyable.hpp>
-#  define LOG(level)  ::Orthanc::Logging::InternalLogger \
-  (::Orthanc::Logging::InternalLevel_ ## level, __FILE__, __LINE__)
-#  define VLOG(level) ::Orthanc::Logging::InternalLogger \
-  (::Orthanc::Logging::InternalLevel_TRACE, __FILE__, __LINE__)
-
-namespace Orthanc
-{
-  namespace Logging
-  {
-    enum InternalLevel
-    {
-      InternalLevel_ERROR,
-      InternalLevel_WARNING,
-      InternalLevel_INFO,
-      InternalLevel_TRACE
-    };
-    
-    class InternalLogger : public boost::noncopyable
-    {
-    private:
-      InternalLevel  level_;
-      std::string    message_;
-
-    public:
-      InternalLogger(InternalLevel level,
-                     const char* file,
-                     int line);
-
-      ~InternalLogger();
-      
-      template <typename T>
-      InternalLogger& operator<< (const T& message)
-      {
-        message_ += boost::lexical_cast<std::string>(message);
-        return *this;
-      }
-    };
-  }
-}
-
-
-
-
-#else  /* ORTHANC_ENABLE_LOGGING_PLUGIN == 0 && 
-          ORTHANC_ENABLE_LOGGING_STDIO == 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();
-      
-      template <typename T>
-      std::ostream& operator<< (const T& message)
-      {
-        return (*stream_) << boost::lexical_cast<std::string>(message);
-      }
-    };
-  }
-}
-
-#endif  // ORTHANC_ENABLE_LOGGING
--- a/Resources/Orthanc/Core/MultiThreading/BagOfTasks.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "../ICommand.h"
-
-#include <list>
-#include <cstddef>
-
-namespace Orthanc
-{
-  class BagOfTasks : public boost::noncopyable
-  {
-  private:
-    typedef std::list<ICommand*>  Tasks;
-
-    Tasks  tasks_;
-
-  public:
-    ~BagOfTasks()
-    {
-      for (Tasks::iterator it = tasks_.begin(); it != tasks_.end(); ++it)
-      {
-        delete *it;
-      }
-    }
-
-    ICommand* Pop()
-    {
-      ICommand* task = tasks_.front();
-      tasks_.pop_front();
-      return task;
-    }
-
-    void Push(ICommand* task)   // Takes ownership
-    {
-      if (task != NULL)
-      {
-        tasks_.push_back(task);
-      }
-    }
-
-    size_t GetSize() const
-    {
-      return tasks_.size();
-    }
-
-    bool IsEmpty() const
-    {
-      return tasks_.empty();
-    }
-  };
-}
--- a/Resources/Orthanc/Core/MultiThreading/BagOfTasksProcessor.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,277 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "BagOfTasksProcessor.h"
-
-#include "../Logging.h"
-#include "../OrthancException.h"
-
-#include <stdio.h>
-
-namespace Orthanc
-{
-  class BagOfTasksProcessor::Task : public IDynamicObject
-  {
-  private:
-    uint64_t                 bag_;
-    std::auto_ptr<ICommand>  command_;
-
-  public:
-    Task(uint64_t  bag,
-         ICommand* command) :
-      bag_(bag),
-      command_(command)
-    {
-    }
-
-    bool Execute()
-    {
-      try
-      {
-        return command_->Execute();
-      }
-      catch (OrthancException& e)
-      {
-        LOG(ERROR) << "Exception while processing a bag of tasks: " << e.What();
-        return false;
-      }
-      catch (std::runtime_error& e)
-      {
-        LOG(ERROR) << "Runtime exception while processing a bag of tasks: " << e.what();
-        return false;
-      }
-      catch (...)
-      {
-        LOG(ERROR) << "Native exception while processing a bag of tasks";
-        return false;
-      }
-    }
-
-    uint64_t GetBag()
-    {
-      return bag_;
-    }
-  };
-
-
-  void BagOfTasksProcessor::SignalProgress(Task& task,
-                                           Bag& bag)
-  {
-    assert(bag.done_ < bag.size_);
-
-    bag.done_ += 1;
-
-    if (bag.done_ == bag.size_)
-    {
-      exitStatus_[task.GetBag()] = (bag.status_ == BagStatus_Running);
-      bagFinished_.notify_all();
-    }
-  }
-
-  void BagOfTasksProcessor::Worker(BagOfTasksProcessor* that)
-  {
-    while (that->continue_)
-    {
-      std::auto_ptr<IDynamicObject> obj(that->queue_.Dequeue(100));
-      if (obj.get() != NULL)
-      {
-        Task& task = *dynamic_cast<Task*>(obj.get());
-
-        {
-          boost::mutex::scoped_lock lock(that->mutex_);
-
-          Bags::iterator bag = that->bags_.find(task.GetBag());
-          assert(bag != that->bags_.end());
-          assert(bag->second.done_ < bag->second.size_);
-
-          if (bag->second.status_ != BagStatus_Running)
-          {
-            // Do not execute this task, as its parent bag of tasks
-            // has failed or is tagged as canceled
-            that->SignalProgress(task, bag->second);
-            continue;
-          }
-        }
-
-        bool success = task.Execute();
-
-        {
-          boost::mutex::scoped_lock lock(that->mutex_);
-
-          Bags::iterator bag = that->bags_.find(task.GetBag());
-          assert(bag != that->bags_.end());
-
-          if (!success)
-          {
-            bag->second.status_ = BagStatus_Failed;
-          }
-
-          that->SignalProgress(task, bag->second);
-        }
-      }
-    }
-  }
-
-
-  void BagOfTasksProcessor::Cancel(int64_t bag)
-  {
-    boost::mutex::scoped_lock  lock(mutex_);
-
-    Bags::iterator it = bags_.find(bag);
-    if (it != bags_.end())
-    {
-      it->second.status_ = BagStatus_Canceled;
-    }
-  }
-
-
-  bool BagOfTasksProcessor::Join(int64_t bag)
-  {
-    boost::mutex::scoped_lock  lock(mutex_);
-
-    while (continue_)
-    {
-      ExitStatus::iterator it = exitStatus_.find(bag);
-      if (it == exitStatus_.end())  // The bag is still running
-      {
-        bagFinished_.wait(lock);
-      }
-      else
-      {
-        bool status = it->second;
-        exitStatus_.erase(it);
-        return status;
-      }
-    }
-
-    return false;   // The processor is stopping
-  }
-
-
-  float BagOfTasksProcessor::GetProgress(int64_t bag)
-  {
-    boost::mutex::scoped_lock  lock(mutex_);
-
-    Bags::const_iterator it = bags_.find(bag);
-    if (it == bags_.end())
-    {
-      // The bag of tasks has finished
-      return 1.0f;
-    }
-    else
-    {
-      return (static_cast<float>(it->second.done_) / 
-              static_cast<float>(it->second.size_));
-    }
-  }
-
-
-  bool BagOfTasksProcessor::Handle::Join()
-  {
-    if (hasJoined_)
-    {
-      return status_;
-    }
-    else
-    {
-      status_ = that_.Join(bag_);
-      hasJoined_ = true;
-      return status_;
-    }
-  }
-
-
-  BagOfTasksProcessor::BagOfTasksProcessor(size_t countThreads) : 
-    countBags_(0),
-    continue_(true)
-  {
-    if (countThreads == 0)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    threads_.resize(countThreads);
-
-    for (size_t i = 0; i < threads_.size(); i++)
-    {
-      threads_[i] = new boost::thread(Worker, this);
-    }
-  }
-
-
-  BagOfTasksProcessor::~BagOfTasksProcessor()
-  {
-    continue_ = false;
-
-    bagFinished_.notify_all();   // Wakes up all the pending "Join()"
-
-    for (size_t i = 0; i < threads_.size(); i++)
-    {
-      if (threads_[i])
-      {
-        if (threads_[i]->joinable())
-        {
-          threads_[i]->join();
-        }
-
-        delete threads_[i];
-        threads_[i] = NULL;
-      }
-    }
-  }
-
-
-  BagOfTasksProcessor::Handle* BagOfTasksProcessor::Submit(BagOfTasks& tasks)
-  {
-    if (tasks.GetSize() == 0)
-    {
-      return new Handle(*this, 0, true);
-    }
-
-    boost::mutex::scoped_lock lock(mutex_);
-
-    uint64_t id = countBags_;
-    countBags_ += 1;
-
-    Bag bag(tasks.GetSize());
-    bags_[id] = bag;
-
-    while (!tasks.IsEmpty())
-    {
-      queue_.Enqueue(new Task(id, tasks.Pop()));
-    }
-
-    return new Handle(*this, id, false);
-  }
-}
--- a/Resources/Orthanc/Core/MultiThreading/BagOfTasksProcessor.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "BagOfTasks.h"
-#include "SharedMessageQueue.h"
-
-#include <stdint.h>
-#include <map>
-
-namespace Orthanc
-{
-  class BagOfTasksProcessor : public boost::noncopyable
-  {
-  private:
-    enum BagStatus
-    {
-      BagStatus_Running,
-      BagStatus_Canceled,
-      BagStatus_Failed
-    };
-
-
-    struct Bag
-    {
-      size_t    size_;
-      size_t    done_;
-      BagStatus status_;
-
-      Bag() :
-        size_(0),
-        done_(0),
-        status_(BagStatus_Failed)
-      {
-      }
-
-      explicit Bag(size_t size) : 
-        size_(size),
-        done_(0),
-        status_(BagStatus_Running)
-      {
-      }
-    };
-
-    class Task;
-
-
-    typedef std::map<uint64_t, Bag>   Bags;
-    typedef std::map<uint64_t, bool>  ExitStatus;
-
-    SharedMessageQueue  queue_;
-
-    boost::mutex  mutex_;
-    uint64_t  countBags_;
-    Bags bags_;
-    std::vector<boost::thread*>   threads_;
-    ExitStatus  exitStatus_;
-    bool continue_;
-
-    boost::condition_variable  bagFinished_;
-
-    static void Worker(BagOfTasksProcessor* that);
-
-    void Cancel(int64_t bag);
-
-    bool Join(int64_t bag);
-
-    float GetProgress(int64_t bag);
-
-    void SignalProgress(Task& task,
-                        Bag& bag);
-
-  public:
-    class Handle : public boost::noncopyable
-    {
-      friend class BagOfTasksProcessor;
-
-    private:
-      BagOfTasksProcessor&  that_;
-      uint64_t              bag_;
-      bool                  hasJoined_;
-      bool                  status_;
- 
-      Handle(BagOfTasksProcessor&  that,
-             uint64_t bag,
-             bool empty) : 
-        that_(that),
-        bag_(bag),
-        hasJoined_(empty)
-      {
-      }
-
-    public:
-      ~Handle()
-      {
-        Join();
-      }
-
-      void Cancel()
-      {
-        that_.Cancel(bag_);
-      }
-
-      bool Join();
-
-      float GetProgress()
-      {
-        return that_.GetProgress(bag_);
-      }
-    };
-  
-
-    explicit BagOfTasksProcessor(size_t countThreads);
-
-    ~BagOfTasksProcessor();
-
-    Handle* Submit(BagOfTasks& tasks);
-  };
-}
--- a/Resources/Orthanc/Core/MultiThreading/Semaphore.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "Semaphore.h"
-
-#include "../OrthancException.h"
-
-
-namespace Orthanc
-{
-  Semaphore::Semaphore(unsigned int count) : count_(count)
-  {
-  }
-
-  void Semaphore::Release()
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    count_++;
-    condition_.notify_one(); 
-  }
-
-  void Semaphore::Acquire()
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    while (count_ == 0)
-    {
-      condition_.wait(lock);
-    }
-
-    count_++;
-  }
-}
--- a/Resources/Orthanc/Core/MultiThreading/Semaphore.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 <boost/noncopyable.hpp>
-#include <boost/thread.hpp>
-
-namespace Orthanc
-{
-  class Semaphore : public boost::noncopyable
-  {
-  private:
-    unsigned int count_;
-    boost::mutex mutex_;
-    boost::condition_variable condition_;
-
-  public:
-    explicit Semaphore(unsigned int count);
-
-    void Release();
-
-    void Acquire();
-
-    class Locker : public boost::noncopyable
-    {
-    private:
-      Semaphore&  that_;
-
-    public:
-      explicit Locker(Semaphore& that) :
-        that_(that)
-      {
-        that_.Acquire();
-      }
-
-      ~Locker()
-      {
-        that_.Release();
-      }
-    };
-  };
-}
--- a/Resources/Orthanc/Core/MultiThreading/SharedMessageQueue.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "SharedMessageQueue.h"
-
-
-
-/**
- * FIFO (queue):
- * 
- *            back                         front
- *            +--+--+--+--+--+--+--+--+--+--+--+
- * Enqueue -> |  |  |  |  |  |  |  |  |  |  |  |
- *            |  |  |  |  |  |  |  |  |  |  |  | -> Dequeue
- *            +--+--+--+--+--+--+--+--+--+--+--+
- *                                            ^
- *                                            |
- *                                      Make room here
- *
- *
- * LIFO (stack):
- * 
- *            back                         front
- *            +--+--+--+--+--+--+--+--+--+--+--+
- *            |  |  |  |  |  |  |  |  |  |  |  | <- Enqueue
- *            |  |  |  |  |  |  |  |  |  |  |  | -> Dequeue
- *            +--+--+--+--+--+--+--+--+--+--+--+
- *              ^
- *              |
- *        Make room here
- **/
-
-
-namespace Orthanc
-{
-  SharedMessageQueue::SharedMessageQueue(unsigned int maxSize) :
-    isFifo_(true),
-    maxSize_(maxSize)
-  {
-  }
-
-
-  SharedMessageQueue::~SharedMessageQueue()
-  {
-    for (Queue::iterator it = queue_.begin(); it != queue_.end(); ++it)
-    {
-      delete *it;
-    }
-  }
-
-
-  void SharedMessageQueue::Enqueue(IDynamicObject* message)
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    if (maxSize_ != 0 && queue_.size() > maxSize_)
-    {
-      if (isFifo_)
-      {
-        // Too many elements in the queue: Make room
-        delete queue_.front();
-        queue_.pop_front();
-      }
-      else
-      {
-        // Too many elements in the stack: Make room
-        delete queue_.back();
-        queue_.pop_back();
-      }
-    }
-
-    if (isFifo_)
-    {
-      // Queue policy (FIFO)
-      queue_.push_back(message);
-    }
-    else
-    {
-      // Stack policy (LIFO)
-      queue_.push_front(message);
-    }
-
-    elementAvailable_.notify_one();
-  }
-
-
-  IDynamicObject* SharedMessageQueue::Dequeue(int32_t millisecondsTimeout)
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    // Wait for a message to arrive in the FIFO queue
-    while (queue_.empty())
-    {
-      if (millisecondsTimeout == 0)
-      {
-        elementAvailable_.wait(lock);
-      }
-      else
-      {
-        bool success = elementAvailable_.timed_wait
-          (lock, boost::posix_time::milliseconds(millisecondsTimeout));
-        if (!success)
-        {
-          return NULL;
-        }
-      }
-    }
-
-    std::auto_ptr<IDynamicObject> message(queue_.front());
-    queue_.pop_front();
-
-    if (queue_.empty())
-    {
-      emptied_.notify_all();
-    }
-
-    return message.release();
-  }
-
-
-
-  bool SharedMessageQueue::WaitEmpty(int32_t millisecondsTimeout)
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-    
-    // Wait for the queue to become empty
-    while (!queue_.empty())
-    {
-      if (millisecondsTimeout == 0)
-      {
-        emptied_.wait(lock);
-      }
-      else
-      {
-        if (!emptied_.timed_wait
-            (lock, boost::posix_time::milliseconds(millisecondsTimeout)))
-        {
-          return false;
-        }
-      }
-    }
-
-    return true;
-  }
-
-
-  void SharedMessageQueue::SetFifoPolicy()
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-    isFifo_ = true;
-  }
-
-  void SharedMessageQueue::SetLifoPolicy()
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-    isFifo_ = false;
-  }
-
-  void SharedMessageQueue::Clear()
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    if (queue_.empty())
-    {
-      return;
-    }
-    else
-    {
-      while (!queue_.empty())
-      {
-        std::auto_ptr<IDynamicObject> message(queue_.front());
-        queue_.pop_front();
-      }
-
-      emptied_.notify_all();
-    }
-  }
-}
--- a/Resources/Orthanc/Core/MultiThreading/SharedMessageQueue.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "../IDynamicObject.h"
-
-#include <stdint.h>
-#include <list>
-#include <boost/thread.hpp>
-
-namespace Orthanc
-{
-  class SharedMessageQueue : public boost::noncopyable
-  {
-  private:
-    typedef std::list<IDynamicObject*>  Queue;
-
-    bool isFifo_;
-    unsigned int maxSize_;
-    Queue queue_;
-    boost::mutex mutex_;
-    boost::condition_variable elementAvailable_;
-    boost::condition_variable emptied_;
-
-  public:
-    explicit SharedMessageQueue(unsigned int maxSize = 0);
-    
-    ~SharedMessageQueue();
-
-    // This transfers the ownership of the message
-    void Enqueue(IDynamicObject* message);
-
-    // The caller is responsible to delete the dequeud message!
-    IDynamicObject* Dequeue(int32_t millisecondsTimeout);
-
-    bool WaitEmpty(int32_t millisecondsTimeout);
-
-    bool IsFifoPolicy() const
-    {
-      return isFifo_;
-    }
-
-    bool IsLifoPolicy() const
-    {
-      return !isFifo_;
-    }
-
-    void SetFifoPolicy();
-
-    void SetLifoPolicy();
-
-    void Clear();
-  };
-}
--- a/Resources/Orthanc/Core/OrthancException.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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_);
-    }
-  };
-}
--- a/Resources/Orthanc/Core/PrecompiledHeaders.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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"
--- a/Resources/Orthanc/Core/PrecompiledHeaders.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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"
-
-#if ORTHANC_ENABLE_DCMTK == 1
-// Headers from DCMTK used in Orthanc headers 
-#  include <dcmtk/dcmdata/dcdatset.h>
-#  include <dcmtk/dcmdata/dcfilefo.h>
-#  include <dcmtk/dcmdata/dcmetinf.h>
-#  include <dcmtk/dcmdata/dcpixseq.h>
-#endif
-
-#if ORTHANC_ENABLE_DCMTK_NETWORKING == 1
-#  include "DicomNetworking/DicomServer.h"
-
-// Headers from DCMTK used in Orthanc headers 
-#  include <dcmtk/dcmnet/dimse.h>
-#endif
-
-#endif
--- a/Resources/Orthanc/Core/SharedLibrary.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "SharedLibrary.h"
-
-#include "Logging.h"
-#include "OrthancException.h"
-
-#include <boost/filesystem.hpp>
-
-#if defined(_WIN32)
-#include <windows.h>
-#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-#include <dlfcn.h>
-#else
-#error Support your platform here
-#endif
-
-namespace Orthanc
-{
-  SharedLibrary::SharedLibrary(const std::string& path) : 
-    path_(path), 
-    handle_(NULL)
-  {
-#if defined(_WIN32)
-    handle_ = ::LoadLibraryA(path_.c_str());
-    if (handle_ == NULL)
-    {
-      LOG(ERROR) << "LoadLibrary(" << path_ << ") failed: Error " << ::GetLastError();
-      throw OrthancException(ErrorCode_SharedLibrary);
-    }
-
-#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-    handle_ = ::dlopen(path_.c_str(), RTLD_NOW);
-    if (handle_ == NULL) 
-    {
-      std::string explanation;
-      const char *tmp = ::dlerror();
-      if (tmp)
-      {
-        explanation = ": Error " + std::string(tmp);
-      }
-
-      LOG(ERROR) << "dlopen(" << path_ << ") failed" << explanation;
-      throw OrthancException(ErrorCode_SharedLibrary);
-    }
-
-#else
-#error Support your platform here
-#endif   
-  }
-
-  SharedLibrary::~SharedLibrary()
-  {
-    if (handle_)
-    {
-#if defined(_WIN32)
-      ::FreeLibrary((HMODULE)handle_);
-#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-      ::dlclose(handle_);
-#else
-#error Support your platform here
-#endif
-    }
-  }
-
-
-  SharedLibrary::FunctionPointer SharedLibrary::GetFunctionInternal(const std::string& name)
-  {
-    if (!handle_)
-    {
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-#if defined(_WIN32)
-    return ::GetProcAddress((HMODULE)handle_, name.c_str());
-#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-    return ::dlsym(handle_, name.c_str());
-#else
-#error Support your platform here
-#endif
-  }
-
-
-  SharedLibrary::FunctionPointer SharedLibrary::GetFunction(const std::string& name)
-  {
-    SharedLibrary::FunctionPointer result = GetFunctionInternal(name);
-  
-    if (result == NULL)
-    {
-      LOG(ERROR) << "Shared library does not expose function \"" << name << "\"";
-      throw OrthancException(ErrorCode_SharedLibrary);
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  bool SharedLibrary::HasFunction(const std::string& name)
-  {
-    return GetFunctionInternal(name) != NULL;
-  }
-}
--- a/Resources/Orthanc/Core/SharedLibrary.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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
-
-#if defined(_WIN32)
-#include <windows.h>
-#endif
-
-#include <string>
-#include <boost/noncopyable.hpp>
-
-namespace Orthanc
-{
-  class SharedLibrary : public boost::noncopyable
-  {
-  public:
-#if defined(_WIN32)
-    typedef FARPROC FunctionPointer;
-#else
-    typedef void* FunctionPointer;
-#endif
-
-  private:
-    std::string path_;
-    void *handle_;
-
-    FunctionPointer GetFunctionInternal(const std::string& name);
-
-  public:
-    explicit SharedLibrary(const std::string& path);
-
-    ~SharedLibrary();
-
-    const std::string& GetPath() const
-    {
-      return path_;
-    }
-
-    bool HasFunction(const std::string& name);
-
-    FunctionPointer GetFunction(const std::string& name);
-  };
-}
--- a/Resources/Orthanc/Core/SystemToolbox.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,563 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 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
-
-
-#if defined(__OpenBSD__)
-#  include <sys/sysctl.h>  // For "sysctl", "CTL_KERN" and "KERN_PROC_ARGS"
-#endif
-
-
-#include "Logging.h"
-#include "OrthancException.h"
-#include "Toolbox.h"
-
-#include <boost/filesystem.hpp>
-#include <boost/filesystem/fstream.hpp>
-#include <boost/date_time/posix_time/posix_time.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(__OpenBSD__) || 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) << "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(static_cast<size_t>(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) << "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 = static_cast<size_t>(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()
-  {
-    // NOTE: For FreeBSD, using KERN_PROC_PATHNAME might be a better alternative
-
-    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);
-  }
-
-#elif defined(__OpenBSD__)
-  static std::string GetPathToExecutableInternal()
-  {
-    // This is an adapted version of the patch proposed in issue #64
-    // without an explicit call to "malloc()" to prevent memory leak
-    // https://bitbucket.org/sjodogne/orthanc/issues/64/add-openbsd-support
-    // https://stackoverflow.com/q/31494901/881731
-
-    const int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
-
-    size_t len;
-    if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1) 
-    {
-      throw OrthancException(ErrorCode_PathToExecutable);
-    }
-
-    std::string tmp;
-    tmp.resize(len);
-
-    char** buffer = reinterpret_cast<char**>(&tmp[0]);
-
-    if (sysctl(mib, 4, buffer, &len, NULL, 0) == -1) 
-    {
-      throw OrthancException(ErrorCode_PathToExecutable);
-    }
-    else
-    {
-      return std::string(buffer[0]);
-    }
-  }
-
-#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);
-  }
-
-
-  static boost::posix_time::ptime GetNow(bool utc)
-  {
-    if (utc)
-    {
-      return boost::posix_time::second_clock::universal_time();
-    }
-    else
-    {
-      return boost::posix_time::second_clock::local_time();
-    }
-  }
-
-
-  std::string SystemToolbox::GetNowIsoString(bool utc)
-  {
-    return boost::posix_time::to_iso_string(GetNow(utc));
-  }
-
-  
-  void SystemToolbox::GetNowDicom(std::string& date,
-                                  std::string& time,
-                                  bool utc)
-  {
-    boost::posix_time::ptime now = GetNow(utc);
-    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);
-  }
-}
--- a/Resources/Orthanc/Core/SystemToolbox.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 GetNowIsoString(bool utc);
-
-    void GetNowDicom(std::string& date,
-                     std::string& time,
-                     bool utc);
-  }
-}
--- a/Resources/Orthanc/Core/TemporaryFile.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "TemporaryFile.h"
-
-#include "SystemToolbox.h"
-#include "Toolbox.h"
-
-#include <boost/filesystem.hpp>
-
-namespace Orthanc
-{
-  static std::string CreateTemporaryPath(const char* extension)
-  {
-#if BOOST_HAS_FILESYSTEM_V3 == 1
-    boost::filesystem::path tmpDir = boost::filesystem::temp_directory_path();
-#elif defined(__linux__)
-    boost::filesystem::path tmpDir("/tmp");
-#else
-#error Support your platform here
-#endif
-
-    // We use UUID to create unique path to temporary files
-    std::string filename = "Orthanc-" + Orthanc::Toolbox::GenerateUuid();
-
-    if (extension != NULL)
-    {
-      filename.append(extension);
-    }
-
-    tmpDir /= filename;
-    return tmpDir.string();
-  }
-
-
-  TemporaryFile::TemporaryFile() : 
-    path_(CreateTemporaryPath(NULL))
-  {
-  }
-
-
-  TemporaryFile::TemporaryFile(const char* extension) :
-    path_(CreateTemporaryPath(extension))
-  {
-  }
-
-
-  TemporaryFile::~TemporaryFile()
-  {
-    boost::filesystem::remove(path_);
-  }
-
-
-  void TemporaryFile::Write(const std::string& content)
-  {
-    SystemToolbox::WriteFile(content, path_);
-  }
-
-
-  void TemporaryFile::Read(std::string& content) const
-  {
-    SystemToolbox::ReadFile(content, path_);
-  }
-}
--- a/Resources/Orthanc/Core/TemporaryFile.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 class TemporaryFile cannot be used in sandboxed environments
-#endif
-
-#include <string>
-
-namespace Orthanc
-{
-  class TemporaryFile
-  {
-  private:
-    std::string path_;
-
-  public:
-    TemporaryFile();
-
-    TemporaryFile(const char* extension);
-
-    ~TemporaryFile();
-
-    const std::string& GetPath() const
-    {
-      return path_;
-    }
-
-    void Write(const std::string& content);
-
-    void Read(std::string& content) const;
-  };
-}
--- a/Resources/Orthanc/Core/Toolbox.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1526 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "Toolbox.h"
-
-#include "OrthancException.h"
-#include "Logging.h"
-
-#include <boost/algorithm/string/case_conv.hpp>
-#include <boost/algorithm/string/replace.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/regex.hpp> 
-#include <boost/uuid/sha1.hpp>
- 
-#include <string>
-#include <stdint.h>
-#include <string.h>
-#include <algorithm>
-#include <ctype.h>
-
-
-#if ORTHANC_ENABLE_MD5 == 1
-#  include "../Resources/ThirdParty/md5/md5.h"
-#endif
-
-#if ORTHANC_ENABLE_BASE64 == 1
-#  include "../Resources/ThirdParty/base64/base64.h"
-#endif
-
-#if ORTHANC_ENABLE_LOCALE == 1
-#  include <boost/locale.hpp>
-#endif
-
-
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-// Patch for the missing "_strtoll" symbol when compiling with Visual Studio < 2013
-extern "C"
-{
-  int64_t _strtoi64(const char *nptr, char **endptr, int base);
-  int64_t strtoll(const char *nptr, char **endptr, int base)
-  {
-    return _strtoi64(nptr, endptr, base);
-  } 
-}
-#endif
-
-
-#if defined(_WIN32)
-#  include <windows.h>   // For ::Sleep
-#endif
-
-
-#if ORTHANC_ENABLE_PUGIXML == 1
-#  include "ChunkedBuffer.h"
-#  include <pugixml.hpp>
-#endif
-
-
-// Inclusions for UUID
-// http://stackoverflow.com/a/1626302
-
-extern "C"
-{
-#if defined(_WIN32)
-#  include <rpc.h>
-#else
-#  include <uuid/uuid.h>
-#endif
-}
-
-
-
-namespace Orthanc
-{
-  void Toolbox::LinesIterator::FindEndOfLine()
-  {
-    lineEnd_ = lineStart_;
-
-    while (lineEnd_ < content_.size() &&
-           content_[lineEnd_] != '\n' &&
-           content_[lineEnd_] != '\r')
-    {
-      lineEnd_ += 1;
-    }
-  }
-  
-
-  Toolbox::LinesIterator::LinesIterator(const std::string& content) :
-    content_(content),
-    lineStart_(0)
-  {
-    FindEndOfLine();
-  }
-
-    
-  bool Toolbox::LinesIterator::GetLine(std::string& target) const
-  {
-    assert(lineStart_ <= content_.size() &&
-           lineEnd_ <= content_.size() &&
-           lineStart_ <= lineEnd_);
-
-    if (lineStart_ == content_.size())
-    {
-      return false;
-    }
-    else
-    {
-      target = content_.substr(lineStart_, lineEnd_ - lineStart_);
-      return true;
-    }
-  }
-
-    
-  void Toolbox::LinesIterator::Next()
-  {
-    lineStart_ = lineEnd_;
-
-    if (lineStart_ != content_.size())
-    {
-      assert(content_[lineStart_] == '\r' ||
-             content_[lineStart_] == '\n');
-
-      char second;
-      
-      if (content_[lineStart_] == '\r')
-      {
-        second = '\n';
-      }
-      else
-      {
-        second = '\r';
-      }
-        
-      lineStart_ += 1;
-
-      if (lineStart_ < content_.size() &&
-          content_[lineStart_] == second)
-      {
-        lineStart_ += 1;
-      }
-
-      FindEndOfLine();
-    }
-  }
-
-  
-  void Toolbox::ToUpperCase(std::string& s)
-  {
-    std::transform(s.begin(), s.end(), s.begin(), toupper);
-  }
-
-
-  void Toolbox::ToLowerCase(std::string& s)
-  {
-    std::transform(s.begin(), s.end(), s.begin(), tolower);
-  }
-
-
-  void Toolbox::ToUpperCase(std::string& result,
-                            const std::string& source)
-  {
-    result = source;
-    ToUpperCase(result);
-  }
-
-  void Toolbox::ToLowerCase(std::string& result,
-                            const std::string& source)
-  {
-    result = source;
-    ToLowerCase(result);
-  }
-
-
-  void Toolbox::SplitUriComponents(UriComponents& components,
-                                   const std::string& uri)
-  {
-    static const char URI_SEPARATOR = '/';
-
-    components.clear();
-
-    if (uri.size() == 0 ||
-        uri[0] != URI_SEPARATOR)
-    {
-      throw OrthancException(ErrorCode_UriSyntax);
-    }
-
-    // Count the number of slashes in the URI to make an assumption
-    // about the number of components in the URI
-    unsigned int estimatedSize = 0;
-    for (unsigned int i = 0; i < uri.size(); i++)
-    {
-      if (uri[i] == URI_SEPARATOR)
-        estimatedSize++;
-    }
-
-    components.reserve(estimatedSize - 1);
-
-    unsigned int start = 1;
-    unsigned int end = 1;
-    while (end < uri.size())
-    {
-      // This is the loop invariant
-      assert(uri[start - 1] == '/' && (end >= start));
-
-      if (uri[end] == '/')
-      {
-        components.push_back(std::string(&uri[start], end - start));
-        end++;
-        start = end;
-      }
-      else
-      {
-        end++;
-      }
-    }
-
-    if (start < uri.size())
-    {
-      components.push_back(std::string(&uri[start], end - start));
-    }
-
-    for (size_t i = 0; i < components.size(); i++)
-    {
-      if (components[i].size() == 0)
-      {
-        // Empty component, as in: "/coucou//e"
-        throw OrthancException(ErrorCode_UriSyntax);
-      }
-    }
-  }
-
-
-  void Toolbox::TruncateUri(UriComponents& target,
-                            const UriComponents& source,
-                            size_t fromLevel)
-  {
-    target.clear();
-
-    if (source.size() > fromLevel)
-    {
-      target.resize(source.size() - fromLevel);
-
-      size_t j = 0;
-      for (size_t i = fromLevel; i < source.size(); i++, j++)
-      {
-        target[j] = source[i];
-      }
-
-      assert(j == target.size());
-    }
-  }
-  
-
-
-  bool Toolbox::IsChildUri(const UriComponents& baseUri,
-                           const UriComponents& testedUri)
-  {
-    if (testedUri.size() < baseUri.size())
-    {
-      return false;
-    }
-
-    for (size_t i = 0; i < baseUri.size(); i++)
-    {
-      if (baseUri[i] != testedUri[i])
-        return false;
-    }
-
-    return true;
-  }
-
-
-  std::string Toolbox::AutodetectMimeType(const std::string& path)
-  {
-    std::string contentType;
-    size_t lastDot = path.rfind('.');
-    size_t lastSlash = path.rfind('/');
-
-    if (lastDot == std::string::npos ||
-        (lastSlash != std::string::npos && lastDot < lastSlash))
-    {
-      // No trailing dot, unable to detect the content type
-    }
-    else
-    {
-      const char* extension = &path[lastDot + 1];
-    
-      // http://en.wikipedia.org/wiki/Mime_types
-      // Text types
-      if (!strcmp(extension, "txt"))
-        contentType = "text/plain";
-      else if (!strcmp(extension, "html"))
-        contentType = "text/html";
-      else if (!strcmp(extension, "xml"))
-        contentType = "text/xml";
-      else if (!strcmp(extension, "css"))
-        contentType = "text/css";
-
-      // Application types
-      else if (!strcmp(extension, "js"))
-        contentType = "application/javascript";
-      else if (!strcmp(extension, "json"))
-        contentType = "application/json";
-      else if (!strcmp(extension, "pdf"))
-        contentType = "application/pdf";
-
-      // Images types
-      else if (!strcmp(extension, "jpg") || !strcmp(extension, "jpeg"))
-        contentType = "image/jpeg";
-      else if (!strcmp(extension, "gif"))
-        contentType = "image/gif";
-      else if (!strcmp(extension, "png"))
-        contentType = "image/png";
-    }
-
-    return contentType;
-  }
-
-
-  std::string Toolbox::FlattenUri(const UriComponents& components,
-                                  size_t fromLevel)
-  {
-    if (components.size() <= fromLevel)
-    {
-      return "/";
-    }
-    else
-    {
-      std::string r;
-
-      for (size_t i = fromLevel; i < components.size(); i++)
-      {
-        r += "/" + components[i];
-      }
-
-      return r;
-    }
-  }
-
-
-#if ORTHANC_ENABLE_MD5 == 1
-  static char GetHexadecimalCharacter(uint8_t value)
-  {
-    assert(value < 16);
-
-    if (value < 10)
-    {
-      return value + '0';
-    }
-    else
-    {
-      return (value - 10) + 'a';
-    }
-  }
-
-
-  void Toolbox::ComputeMD5(std::string& result,
-                           const std::string& data)
-  {
-    if (data.size() > 0)
-    {
-      ComputeMD5(result, &data[0], data.size());
-    }
-    else
-    {
-      ComputeMD5(result, NULL, 0);
-    }
-  }
-
-
-  void Toolbox::ComputeMD5(std::string& result,
-                           const void* data,
-                           size_t size)
-  {
-    md5_state_s state;
-    md5_init(&state);
-
-    if (size > 0)
-    {
-      md5_append(&state, 
-                 reinterpret_cast<const md5_byte_t*>(data), 
-                 static_cast<int>(size));
-    }
-
-    md5_byte_t actualHash[16];
-    md5_finish(&state, actualHash);
-
-    result.resize(32);
-    for (unsigned int i = 0; i < 16; i++)
-    {
-      result[2 * i] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] / 16));
-      result[2 * i + 1] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] % 16));
-    }
-  }
-#endif
-
-
-#if ORTHANC_ENABLE_BASE64 == 1
-  void Toolbox::EncodeBase64(std::string& result, 
-                             const std::string& data)
-  {
-    result = base64_encode(data);
-  }
-
-  void Toolbox::DecodeBase64(std::string& result, 
-                             const std::string& data)
-  {
-    for (size_t i = 0; i < data.length(); i++)
-    {
-      if (!isalnum(data[i]) &&
-          data[i] != '+' &&
-          data[i] != '/' &&
-          data[i] != '=')
-      {
-        // This is not a valid character for a Base64 string
-        throw OrthancException(ErrorCode_BadFileFormat);
-      }
-    }
-
-    result = base64_decode(data);
-  }
-
-
-  bool Toolbox::DecodeDataUriScheme(std::string& mime,
-                                    std::string& content,
-                                    const std::string& source)
-  {
-    boost::regex pattern("data:([^;]+);base64,([a-zA-Z0-9=+/]*)",
-                         boost::regex::icase /* case insensitive search */);
-
-    boost::cmatch what;
-    if (regex_match(source.c_str(), what, pattern))
-    {
-      mime = what[1];
-      DecodeBase64(content, what[2]);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  void Toolbox::EncodeDataUriScheme(std::string& result,
-                                    const std::string& mime,
-                                    const std::string& content)
-  {
-    result = "data:" + mime + ";base64," + base64_encode(content);
-  }
-
-#endif
-
-
-#if ORTHANC_ENABLE_LOCALE == 1
-  static const char* GetBoostLocaleEncoding(const Encoding sourceEncoding)
-  {
-    switch (sourceEncoding)
-    {
-      case Encoding_Utf8:
-        return "UTF-8";
-
-      case Encoding_Ascii:
-        return "ASCII";
-
-      case Encoding_Latin1:
-        return "ISO-8859-1";
-        break;
-
-      case Encoding_Latin2:
-        return "ISO-8859-2";
-        break;
-
-      case Encoding_Latin3:
-        return "ISO-8859-3";
-        break;
-
-      case Encoding_Latin4:
-        return "ISO-8859-4";
-        break;
-
-      case Encoding_Latin5:
-        return "ISO-8859-9";
-        break;
-
-      case Encoding_Cyrillic:
-        return "ISO-8859-5";
-        break;
-
-      case Encoding_Windows1251:
-        return "WINDOWS-1251";
-        break;
-
-      case Encoding_Arabic:
-        return "ISO-8859-6";
-        break;
-
-      case Encoding_Greek:
-        return "ISO-8859-7";
-        break;
-
-      case Encoding_Hebrew:
-        return "ISO-8859-8";
-        break;
-        
-      case Encoding_Japanese:
-        return "SHIFT-JIS";
-        break;
-
-      case Encoding_Chinese:
-        return "GB18030";
-        break;
-
-      case Encoding_Thai:
-        return "TIS620.2533-0";
-        break;
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-#endif
-
-
-#if ORTHANC_ENABLE_LOCALE == 1
-  std::string Toolbox::ConvertToUtf8(const std::string& source,
-                                     Encoding sourceEncoding)
-  {
-    if (sourceEncoding == Encoding_Utf8)
-    {
-      // Already in UTF-8: No conversion is required
-      return source;
-    }
-
-    if (sourceEncoding == Encoding_Ascii)
-    {
-      return ConvertToAscii(source);
-    }
-
-    const char* encoding = GetBoostLocaleEncoding(sourceEncoding);
-
-    try
-    {
-      return boost::locale::conv::to_utf<char>(source, encoding);
-    }
-    catch (std::runtime_error&)
-    {
-      // Bad input string or bad encoding
-      return ConvertToAscii(source);
-    }
-  }
-#endif
-  
-
-#if ORTHANC_ENABLE_LOCALE == 1
-  std::string Toolbox::ConvertFromUtf8(const std::string& source,
-                                       Encoding targetEncoding)
-  {
-    if (targetEncoding == Encoding_Utf8)
-    {
-      // Already in UTF-8: No conversion is required
-      return source;
-    }
-
-    if (targetEncoding == Encoding_Ascii)
-    {
-      return ConvertToAscii(source);
-    }
-
-    const char* encoding = GetBoostLocaleEncoding(targetEncoding);
-
-    try
-    {
-      return boost::locale::conv::from_utf<char>(source, encoding);
-    }
-    catch (std::runtime_error&)
-    {
-      // Bad input string or bad encoding
-      return ConvertToAscii(source);
-    }
-  }
-#endif
-
-
-  bool Toolbox::IsAsciiString(const void* data,
-                              size_t size)
-  {
-    const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
-
-    for (size_t i = 0; i < size; i++, p++)
-    {
-      if (*p > 127 || *p == 0 || iscntrl(*p))
-      {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-
-  bool Toolbox::IsAsciiString(const std::string& s)
-  {
-    return IsAsciiString(s.c_str(), s.size());
-  }
-  
-
-  std::string Toolbox::ConvertToAscii(const std::string& source)
-  {
-    std::string result;
-
-    result.reserve(source.size() + 1);
-    for (size_t i = 0; i < source.size(); i++)
-    {
-      if (source[i] <= 127 && source[i] >= 0 && !iscntrl(source[i]))
-      {
-        result.push_back(source[i]);
-      }
-    }
-
-    return result;
-  }
-
-
-  void Toolbox::ComputeSHA1(std::string& result,
-                            const void* data,
-                            size_t size)
-  {
-    boost::uuids::detail::sha1 sha1;
-
-    if (size > 0)
-    {
-      sha1.process_bytes(data, size);
-    }
-
-    unsigned int digest[5];
-
-    // Sanity check for the memory layout: A SHA-1 digest is 160 bits wide
-    assert(sizeof(unsigned int) == 4 && sizeof(digest) == (160 / 8)); 
-    
-    sha1.get_digest(digest);
-
-    result.resize(8 * 5 + 4);
-    sprintf(&result[0], "%08x-%08x-%08x-%08x-%08x",
-            digest[0],
-            digest[1],
-            digest[2],
-            digest[3],
-            digest[4]);
-  }
-
-  void Toolbox::ComputeSHA1(std::string& result,
-                            const std::string& data)
-  {
-    if (data.size() > 0)
-    {
-      ComputeSHA1(result, data.c_str(), data.size());
-    }
-    else
-    {
-      ComputeSHA1(result, NULL, 0);
-    }
-  }
-
-
-  bool Toolbox::IsSHA1(const char* str,
-                       size_t size)
-  {
-    if (size == 0)
-    {
-      return false;
-    }
-
-    const char* start = str;
-    const char* end = str + size;
-
-    // Trim the beginning of the string
-    while (start < end)
-    {
-      if (*start == '\0' ||
-          isspace(*start))
-      {
-        start++;
-      }
-      else
-      {
-        break;
-      }
-    }
-
-    // Trim the trailing of the string
-    while (start < end)
-    {
-      if (*(end - 1) == '\0' ||
-          isspace(*(end - 1)))
-      {
-        end--;
-      }
-      else
-      {
-        break;
-      }
-    }
-
-    if (end - start != 44)
-    {
-      return false;
-    }
-
-    for (unsigned int i = 0; i < 44; i++)
-    {
-      if (i == 8 ||
-          i == 17 ||
-          i == 26 ||
-          i == 35)
-      {
-        if (start[i] != '-')
-          return false;
-      }
-      else
-      {
-        if (!isalnum(start[i]))
-          return false;
-      }
-    }
-
-    return true;
-  }
-
-
-  bool Toolbox::IsSHA1(const std::string& s)
-  {
-    if (s.size() == 0)
-    {
-      return false;
-    }
-    else
-    {
-      return IsSHA1(s.c_str(), s.size());
-    }
-  }
-
-
-  std::string Toolbox::StripSpaces(const std::string& source)
-  {
-    size_t first = 0;
-
-    while (first < source.length() &&
-           isspace(source[first]))
-    {
-      first++;
-    }
-
-    if (first == source.length())
-    {
-      // String containing only spaces
-      return "";
-    }
-
-    size_t last = source.length();
-    while (last > first &&
-           isspace(source[last - 1]))
-    {
-      last--;
-    }          
-    
-    assert(first <= last);
-    return source.substr(first, last - first);
-  }
-
-
-  static char Hex2Dec(char c)
-  {
-    return ((c >= '0' && c <= '9') ? c - '0' :
-            ((c >= 'a' && c <= 'f') ? c - 'a' + 10 : c - 'A' + 10));
-  }
-
-  void Toolbox::UrlDecode(std::string& s)
-  {
-    // http://en.wikipedia.org/wiki/Percent-encoding
-    // http://www.w3schools.com/tags/ref_urlencode.asp
-    // http://stackoverflow.com/questions/154536/encode-decode-urls-in-c
-
-    if (s.size() == 0)
-    {
-      return;
-    }
-
-    size_t source = 0;
-    size_t target = 0;
-
-    while (source < s.size())
-    {
-      if (s[source] == '%' &&
-          source + 2 < s.size() &&
-          isalnum(s[source + 1]) &&
-          isalnum(s[source + 2]))
-      {
-        s[target] = (Hex2Dec(s[source + 1]) << 4) | Hex2Dec(s[source + 2]);
-        source += 3;
-        target += 1;
-      }
-      else
-      {
-        if (s[source] == '+')
-          s[target] = ' ';
-        else
-          s[target] = s[source];
-
-        source++;
-        target++;
-      }
-    }
-
-    s.resize(target);
-  }
-
-
-  Endianness Toolbox::DetectEndianness()
-  {
-    // http://sourceforge.net/p/predef/wiki/Endianness/
-
-    uint8_t buffer[4];
-
-    buffer[0] = 0x00;
-    buffer[1] = 0x01;
-    buffer[2] = 0x02;
-    buffer[3] = 0x03;
-
-    switch (*((uint32_t *)buffer)) 
-    {
-      case 0x00010203: 
-        return Endianness_Big;
-
-      case 0x03020100: 
-        return Endianness_Little;
-        
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-  std::string Toolbox::WildcardToRegularExpression(const std::string& source)
-  {
-    // TODO - Speed up this with a regular expression
-
-    std::string result = source;
-
-    // Escape all special characters
-    boost::replace_all(result, "\\", "\\\\");
-    boost::replace_all(result, "^", "\\^");
-    boost::replace_all(result, ".", "\\.");
-    boost::replace_all(result, "$", "\\$");
-    boost::replace_all(result, "|", "\\|");
-    boost::replace_all(result, "(", "\\(");
-    boost::replace_all(result, ")", "\\)");
-    boost::replace_all(result, "[", "\\[");
-    boost::replace_all(result, "]", "\\]");
-    boost::replace_all(result, "+", "\\+");
-    boost::replace_all(result, "/", "\\/");
-    boost::replace_all(result, "{", "\\{");
-    boost::replace_all(result, "}", "\\}");
-
-    // Convert wildcards '*' and '?' to their regex equivalents
-    boost::replace_all(result, "?", ".");
-    boost::replace_all(result, "*", ".*");
-
-    return result;
-  }
-
-
-  void Toolbox::TokenizeString(std::vector<std::string>& result,
-                               const std::string& value,
-                               char separator)
-  {
-    result.clear();
-
-    std::string currentItem;
-
-    for (size_t i = 0; i < value.size(); i++)
-    {
-      if (value[i] == separator)
-      {
-        result.push_back(currentItem);
-        currentItem.clear();
-      }
-      else
-      {
-        currentItem.push_back(value[i]);
-      }
-    }
-
-    result.push_back(currentItem);
-  }
-
-
-#if ORTHANC_ENABLE_PUGIXML == 1
-  class ChunkedBufferWriter : public pugi::xml_writer
-  {
-  private:
-    ChunkedBuffer buffer_;
-
-  public:
-    virtual void write(const void *data, size_t size)
-    {
-      if (size > 0)
-      {
-        buffer_.AddChunk(reinterpret_cast<const char*>(data), size);
-      }
-    }
-
-    void Flatten(std::string& s)
-    {
-      buffer_.Flatten(s);
-    }
-  };
-
-
-  static void JsonToXmlInternal(pugi::xml_node& target,
-                                const Json::Value& source,
-                                const std::string& arrayElement)
-  {
-    // http://jsoncpp.sourceforge.net/value_8h_source.html#l00030
-
-    switch (source.type())
-    {
-      case Json::nullValue:
-      {
-        target.append_child(pugi::node_pcdata).set_value("null");
-        break;
-      }
-
-      case Json::intValue:
-      {
-        std::string s = boost::lexical_cast<std::string>(source.asInt());
-        target.append_child(pugi::node_pcdata).set_value(s.c_str());
-        break;
-      }
-
-      case Json::uintValue:
-      {
-        std::string s = boost::lexical_cast<std::string>(source.asUInt());
-        target.append_child(pugi::node_pcdata).set_value(s.c_str());
-        break;
-      }
-
-      case Json::realValue:
-      {
-        std::string s = boost::lexical_cast<std::string>(source.asFloat());
-        target.append_child(pugi::node_pcdata).set_value(s.c_str());
-        break;
-      }
-
-      case Json::stringValue:
-      {
-        target.append_child(pugi::node_pcdata).set_value(source.asString().c_str());
-        break;
-      }
-
-      case Json::booleanValue:
-      {
-        target.append_child(pugi::node_pcdata).set_value(source.asBool() ? "true" : "false");
-        break;
-      }
-
-      case Json::arrayValue:
-      {
-        for (Json::Value::ArrayIndex i = 0; i < source.size(); i++)
-        {
-          pugi::xml_node node = target.append_child();
-          node.set_name(arrayElement.c_str());
-          JsonToXmlInternal(node, source[i], arrayElement);
-        }
-        break;
-      }
-        
-      case Json::objectValue:
-      {
-        Json::Value::Members members = source.getMemberNames();
-
-        for (size_t i = 0; i < members.size(); i++)
-        {
-          pugi::xml_node node = target.append_child();
-          node.set_name(members[i].c_str());
-          JsonToXmlInternal(node, source[members[i]], arrayElement);          
-        }
-
-        break;
-      }
-
-      default:
-        throw OrthancException(ErrorCode_NotImplemented);
-    }
-  }
-
-
-  void Toolbox::JsonToXml(std::string& target,
-                          const Json::Value& source,
-                          const std::string& rootElement,
-                          const std::string& arrayElement)
-  {
-    pugi::xml_document doc;
-
-    pugi::xml_node n = doc.append_child(rootElement.c_str());
-    JsonToXmlInternal(n, source, arrayElement);
-
-    pugi::xml_node decl = doc.prepend_child(pugi::node_declaration);
-    decl.append_attribute("version").set_value("1.0");
-    decl.append_attribute("encoding").set_value("utf-8");
-
-    ChunkedBufferWriter writer;
-    doc.save(writer, "  ", pugi::format_default, pugi::encoding_utf8);
-    writer.Flatten(target);
-  }
-
-#endif
-
-
-  
-  bool Toolbox::IsInteger(const std::string& str)
-  {
-    std::string s = StripSpaces(str);
-
-    if (s.size() == 0)
-    {
-      return false;
-    }
-
-    size_t pos = 0;
-    if (s[0] == '-')
-    {
-      if (s.size() == 1)
-      {
-        return false;
-      }
-
-      pos = 1;
-    }
-
-    while (pos < s.size())
-    {
-      if (!isdigit(s[pos]))
-      {
-        return false;
-      }
-
-      pos++;
-    }
-
-    return true;
-  }
-
-
-  void Toolbox::CopyJsonWithoutComments(Json::Value& target,
-                                        const Json::Value& source)
-  {
-    switch (source.type())
-    {
-      case Json::nullValue:
-        target = Json::nullValue;
-        break;
-
-      case Json::intValue:
-        target = source.asInt64();
-        break;
-
-      case Json::uintValue:
-        target = source.asUInt64();
-        break;
-
-      case Json::realValue:
-        target = source.asDouble();
-        break;
-
-      case Json::stringValue:
-        target = source.asString();
-        break;
-
-      case Json::booleanValue:
-        target = source.asBool();
-        break;
-
-      case Json::arrayValue:
-      {
-        target = Json::arrayValue;
-        for (Json::Value::ArrayIndex i = 0; i < source.size(); i++)
-        {
-          Json::Value& item = target.append(Json::nullValue);
-          CopyJsonWithoutComments(item, source[i]);
-        }
-
-        break;
-      }
-
-      case Json::objectValue:
-      {
-        target = Json::objectValue;
-        Json::Value::Members members = source.getMemberNames();
-        for (Json::Value::ArrayIndex i = 0; i < members.size(); i++)
-        {
-          const std::string item = members[i];
-          CopyJsonWithoutComments(target[item], source[item]);
-        }
-
-        break;
-      }
-
-      default:
-        break;
-    }
-  }
-
-
-  bool Toolbox::StartsWith(const std::string& str,
-                           const std::string& prefix)
-  {
-    if (str.size() < prefix.size())
-    {
-      return false;
-    }
-    else
-    {
-      return str.compare(0, prefix.size(), prefix) == 0;
-    }
-  }
-  
-
-  static bool IsUnreservedCharacter(char c)
-  {
-    // This function checks whether "c" is an unserved character
-    // wrt. an URI percent-encoding
-    // https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding%5Fin%5Fa%5FURI
-
-    return ((c >= 'A' && c <= 'Z') ||
-            (c >= 'a' && c <= 'z') ||
-            (c >= '0' && c <= '9') ||
-            c == '-' ||
-            c == '_' ||
-            c == '.' ||
-            c == '~');
-  }
-
-  void Toolbox::UriEncode(std::string& target,
-                          const std::string& source)
-  {
-    // Estimate the length of the percent-encoded URI
-    size_t length = 0;
-
-    for (size_t i = 0; i < source.size(); i++)
-    {
-      if (IsUnreservedCharacter(source[i]))
-      {
-        length += 1;
-      }
-      else
-      {
-        // This character must be percent-encoded
-        length += 3;
-      }
-    }
-
-    target.clear();
-    target.reserve(length);
-
-    for (size_t i = 0; i < source.size(); i++)
-    {
-      if (IsUnreservedCharacter(source[i]))
-      {
-        target.push_back(source[i]);
-      }
-      else
-      {
-        // This character must be percent-encoded
-        uint8_t byte = static_cast<uint8_t>(source[i]);
-        uint8_t a = byte >> 4;
-        uint8_t b = byte & 0x0f;
-
-        target.push_back('%');
-        target.push_back(a < 10 ? a + '0' : a - 10 + 'A');
-        target.push_back(b < 10 ? b + '0' : b - 10 + 'A');
-      }
-    }
-  }
-
-
-  static bool HasField(const Json::Value& json,
-                       const std::string& key,
-                       Json::ValueType expectedType)
-  {
-    if (json.type() != Json::objectValue ||
-        !json.isMember(key))
-    {
-      return false;
-    }
-    else if (json[key].type() == expectedType)
-    {
-      return true;
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_BadParameterType);
-    }
-  }
-
-
-  std::string Toolbox::GetJsonStringField(const Json::Value& json,
-                                          const std::string& key,
-                                          const std::string& defaultValue)
-  {
-    if (HasField(json, key, Json::stringValue))
-    {
-      return json[key].asString();
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  bool Toolbox::GetJsonBooleanField(const ::Json::Value& json,
-                                    const std::string& key,
-                                    bool defaultValue)
-  {
-    if (HasField(json, key, Json::booleanValue))
-    {
-      return json[key].asBool();
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  int Toolbox::GetJsonIntegerField(const ::Json::Value& json,
-                                   const std::string& key,
-                                   int defaultValue)
-  {
-    if (HasField(json, key, Json::intValue))
-    {
-      return json[key].asInt();
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  unsigned int Toolbox::GetJsonUnsignedIntegerField(const ::Json::Value& json,
-                                                    const std::string& key,
-                                                    unsigned int defaultValue)
-  {
-    int v = GetJsonIntegerField(json, key, defaultValue);
-
-    if (v < 0)
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-    else
-    {
-      return static_cast<unsigned int>(v);
-    }
-  }
-
-
-  bool Toolbox::IsUuid(const std::string& str)
-  {
-    if (str.size() != 36)
-    {
-      return false;
-    }
-
-    for (size_t i = 0; i < str.length(); i++)
-    {
-      if (i == 8 || i == 13 || i == 18 || i == 23)
-      {
-        if (str[i] != '-')
-          return false;
-      }
-      else
-      {
-        if (!isalnum(str[i]))
-          return false;
-      }
-    }
-
-    return true;
-  }
-
-
-  bool Toolbox::StartsWithUuid(const std::string& str)
-  {
-    if (str.size() < 36)
-    {
-      return false;
-    }
-
-    if (str.size() == 36)
-    {
-      return IsUuid(str);
-    }
-
-    assert(str.size() > 36);
-    if (!isspace(str[36]))
-    {
-      return false;
-    }
-
-    return IsUuid(str.substr(0, 36));
-  }
-
-
-#if ORTHANC_ENABLE_LOCALE == 1
-  static std::auto_ptr<std::locale>  globalLocale_;
-
-  static bool SetGlobalLocale(const char* locale)
-  {
-    globalLocale_.reset(NULL);
-
-    try
-    {
-      if (locale == NULL)
-      {
-        LOG(WARNING) << "Falling back to system-wide default locale";
-        globalLocale_.reset(new std::locale());
-      }
-      else
-      {
-        LOG(INFO) << "Using locale: \"" << locale << "\" for case-insensitive comparison of strings";
-        globalLocale_.reset(new std::locale(locale));
-      }
-    }
-    catch (std::runtime_error&)
-    {
-    }
-
-    return (globalLocale_.get() != NULL);
-  }
-  
-  void Toolbox::InitializeGlobalLocale(const char* locale)
-  {
-    // Make Orthanc use English, United States locale
-    // Linux: use "en_US.UTF-8"
-    // Windows: use ""
-    // Wine: use NULL
-    
-#if defined(__MINGW32__)
-    // Visibly, there is no support of locales in MinGW yet
-    // http://mingw.5.n7.nabble.com/How-to-use-std-locale-global-with-MinGW-correct-td33048.html
-    static const char* DEFAULT_LOCALE = NULL;
-#elif defined(_WIN32)
-    // For Windows: use default locale (using "en_US" does not work)
-    static const char* DEFAULT_LOCALE = "";
-#else
-    // For Linux & cie
-    static const char* DEFAULT_LOCALE = "en_US.UTF-8";
-#endif
-
-    bool ok;
-    
-    if (locale == NULL)
-    {
-      ok = SetGlobalLocale(DEFAULT_LOCALE);
-
-#if defined(__MINGW32__)
-      LOG(WARNING) << "This is a MinGW build, case-insensitive comparison of "
-                   << "strings with accents will not work outside of Wine";
-#endif
-    }
-    else
-    {
-      ok = SetGlobalLocale(locale);
-    }
-
-    if (!ok &&
-        !SetGlobalLocale(NULL))
-    {
-      LOG(ERROR) << "Cannot initialize global locale";
-      throw OrthancException(ErrorCode_InternalError);
-    }
-
-  }
-
-
-  void Toolbox::FinalizeGlobalLocale()
-  {
-    globalLocale_.reset();
-  }
-
-  
-  std::string Toolbox::ToUpperCaseWithAccents(const std::string& source)
-  {
-    if (globalLocale_.get() == NULL)
-    {
-      LOG(ERROR) << "No global locale was set, call Toolbox::InitializeGlobalLocale()";
-      throw OrthancException(ErrorCode_BadSequenceOfCalls);
-    }
-
-    /**
-     * A few notes about locales:
-     *
-     * (1) We don't use "case folding":
-     * http://www.boost.org/doc/libs/1_64_0/libs/locale/doc/html/conversions.html
-     *
-     * Characters are made uppercase one by one. This is because, in
-     * static builds, we are using iconv, which is visibly not
-     * supported correctly (TODO: Understand why). Case folding seems
-     * to be working correctly if using the default backend under
-     * Linux (ICU or POSIX?). If one wishes to use case folding, one
-     * would use:
-     *
-     *   boost::locale::generator gen;
-     *   std::locale::global(gen(DEFAULT_LOCALE));
-     *   return boost::locale::to_upper(source);
-     *
-     * (2) The function "boost::algorithm::to_upper_copy" does not
-     * make use of the "std::locale::global()". We therefore create a
-     * global variable "globalLocale_".
-     * 
-     * (3) The variant of "boost::algorithm::to_upper_copy()" that
-     * uses std::string does not work properly. We need to apply it
-     * one wide strings (std::wstring). This explains the two calls to
-     * "utf_to_utf" in order to convert to/from std::wstring.
-     **/
-
-    std::wstring w = boost::locale::conv::utf_to_utf<wchar_t>(source);
-    w = boost::algorithm::to_upper_copy<std::wstring>(w, *globalLocale_);
-    return boost::locale::conv::utf_to_utf<char>(w);
-  }
-#endif
-
-
-  std::string Toolbox::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;
-  }
-}
-
-
-
-OrthancLinesIterator* OrthancLinesIterator_Create(const std::string& content)
-{
-  return reinterpret_cast<OrthancLinesIterator*>(new Orthanc::Toolbox::LinesIterator(content));
-}
-
-
-bool OrthancLinesIterator_GetLine(std::string& target,
-                                         const OrthancLinesIterator* iterator)
-{
-  if (iterator != NULL)
-  {
-    return reinterpret_cast<const Orthanc::Toolbox::LinesIterator*>(iterator)->GetLine(target);
-  }
-  else
-  {
-    return false;
-  }
-}
-
-
-void OrthancLinesIterator_Next(OrthancLinesIterator* iterator)
-{
-  if (iterator != NULL)
-  {
-    reinterpret_cast<Orthanc::Toolbox::LinesIterator*>(iterator)->Next();
-  }
-}
-
-
-void OrthancLinesIterator_Free(OrthancLinesIterator* iterator)
-{
-  if (iterator != NULL)
-  {
-    delete reinterpret_cast<const Orthanc::Toolbox::LinesIterator*>(iterator);
-  }
-}
--- a/Resources/Orthanc/Core/Toolbox.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,259 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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_LOCALE)
-#  error The macro ORTHANC_ENABLE_LOCALE 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
-
-
-/**
- * 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
-  {
-    class LinesIterator
-    {
-    private:
-      const std::string& content_;
-      size_t             lineStart_;
-      size_t             lineEnd_;
-
-      void FindEndOfLine();
-  
-    public:
-      LinesIterator(const std::string& content);
-  
-      bool GetLine(std::string& target) const;
-
-      void Next();
-    };
-    
-    
-    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);
-
-    bool DecodeDataUriScheme(std::string& mime,
-                             std::string& content,
-                             const std::string& source);
-
-    void EncodeDataUriScheme(std::string& result,
-                             const std::string& mime,
-                             const std::string& content);
-#endif
-
-#if ORTHANC_ENABLE_LOCALE == 1
-    std::string ConvertToUtf8(const std::string& source,
-                              Encoding sourceEncoding);
-
-    std::string ConvertFromUtf8(const std::string& source,
-                                Encoding targetEncoding);
-#endif
-
-    bool IsAsciiString(const void* data,
-                       size_t size);
-
-    bool IsAsciiString(const std::string& s);
-
-    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();
-
-    std::string WildcardToRegularExpression(const std::string& s);
-
-    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);
-
-#if ORTHANC_ENABLE_LOCALE == 1
-    void InitializeGlobalLocale(const char* locale);
-
-    void FinalizeGlobalLocale();
-
-    std::string ToUpperCaseWithAccents(const std::string& source);
-#endif
-
-    std::string GenerateUuid();
-  }
-}
-
-
-
-
-/**
- * The plain C, opaque data structure "OrthancLinesIterator" is a thin
- * wrapper around Orthanc::Toolbox::LinesIterator, and is only used by
- * "../Resources/WebAssembly/dcdict.cc", in order to avoid code
- * duplication
- **/
-
-struct OrthancLinesIterator;
-
-OrthancLinesIterator* OrthancLinesIterator_Create(const std::string& content);
-
-bool OrthancLinesIterator_GetLine(std::string& target,
-                                  const OrthancLinesIterator* iterator);
-
-void OrthancLinesIterator_Next(OrthancLinesIterator* iterator);
-
-void OrthancLinesIterator_Free(OrthancLinesIterator* iterator);
--- a/Resources/Orthanc/Core/WebServiceParameters.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "WebServiceParameters.h"
-
-#include "../Core/Logging.h"
-#include "../Core/OrthancException.h"
-
-#if ORTHANC_SANDBOXED == 0
-#  include "../Core/SystemToolbox.h"
-#endif
-
-#include <cassert>
-
-namespace Orthanc
-{
-  WebServiceParameters::WebServiceParameters() : 
-    advancedFormat_(false),
-    url_("http://127.0.0.1:8042/"),
-    pkcs11Enabled_(false)
-  {
-  }
-
-
-  void WebServiceParameters::ClearClientCertificate()
-  {
-    certificateFile_.clear();
-    certificateKeyFile_.clear();
-    certificateKeyPassword_.clear();
-  }
-
-
-#if ORTHANC_SANDBOXED == 0
-  void WebServiceParameters::SetClientCertificate(const std::string& certificateFile,
-                                                  const std::string& certificateKeyFile,
-                                                  const std::string& certificateKeyPassword)
-  {
-    if (certificateFile.empty())
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
-
-    if (!SystemToolbox::IsRegularFile(certificateFile))
-    {
-      LOG(ERROR) << "Cannot open certificate file: " << certificateFile;
-      throw OrthancException(ErrorCode_InexistentFile);
-    }
-
-    if (!certificateKeyFile.empty() && 
-        !SystemToolbox::IsRegularFile(certificateKeyFile))
-    {
-      LOG(ERROR) << "Cannot open key file: " << certificateKeyFile;
-      throw OrthancException(ErrorCode_InexistentFile);
-    }
-
-    advancedFormat_ = true;
-    certificateFile_ = certificateFile;
-    certificateKeyFile_ = certificateKeyFile;
-    certificateKeyPassword_ = certificateKeyPassword;
-  }
-#endif
-
-
-  static void AddTrailingSlash(std::string& url)
-  {
-    if (url.size() != 0 && 
-        url[url.size() - 1] != '/')
-    {
-      url += '/';
-    }
-  }
-
-
-  void WebServiceParameters::FromJsonArray(const Json::Value& peer)
-  {
-    assert(peer.isArray());
-
-    advancedFormat_ = false;
-    pkcs11Enabled_ = false;
-
-    if (peer.size() != 1 && 
-        peer.size() != 3)
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    std::string url = peer.get(0u, "").asString();
-    if (url.empty())
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    AddTrailingSlash(url);
-    SetUrl(url);
-
-    if (peer.size() == 1)
-    {
-      SetUsername("");
-      SetPassword("");
-    }
-    else if (peer.size() == 3)
-    {
-      SetUsername(peer.get(1u, "").asString());
-      SetPassword(peer.get(2u, "").asString());
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-  }
-
-
-  static std::string GetStringMember(const Json::Value& peer,
-                                     const std::string& key,
-                                     const std::string& defaultValue)
-  {
-    if (!peer.isMember(key))
-    {
-      return defaultValue;
-    }
-    else if (peer[key].type() != Json::stringValue)
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-    else
-    {
-      return peer[key].asString();
-    }
-  }
-
-
-  void WebServiceParameters::FromJsonObject(const Json::Value& peer)
-  {
-    assert(peer.isObject());
-    advancedFormat_ = true;
-
-    std::string url = GetStringMember(peer, "Url", "");
-    if (url.empty())
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-
-    AddTrailingSlash(url);
-    SetUrl(url);
-
-    SetUsername(GetStringMember(peer, "Username", ""));
-    SetPassword(GetStringMember(peer, "Password", ""));
-
-#if ORTHANC_SANDBOXED == 0
-    if (peer.isMember("CertificateFile"))
-    {
-      SetClientCertificate(GetStringMember(peer, "CertificateFile", ""),
-                           GetStringMember(peer, "CertificateKeyFile", ""),
-                           GetStringMember(peer, "CertificateKeyPassword", ""));
-    }
-#endif
-
-    if (peer.isMember("Pkcs11"))
-    {
-      if (peer["Pkcs11"].type() == Json::booleanValue)
-      {
-        pkcs11Enabled_ = peer["Pkcs11"].asBool();
-      }
-      else
-      {
-        throw OrthancException(ErrorCode_BadFileFormat);
-      }
-    }
-  }
-
-
-  void WebServiceParameters::FromJson(const Json::Value& peer)
-  {
-    try
-    {
-      if (peer.isArray())
-      {
-        FromJsonArray(peer);
-      }
-      else if (peer.isObject())
-      {
-        FromJsonObject(peer);
-      }
-      else
-      {
-        throw OrthancException(ErrorCode_BadFileFormat);
-      }
-    }
-    catch (OrthancException&)
-    {
-      throw;
-    }
-    catch (...)
-    {
-      throw OrthancException(ErrorCode_BadFileFormat);
-    }
-  }
-
-
-  void WebServiceParameters::ToJson(Json::Value& value) const
-  {
-    if (advancedFormat_)
-    {
-      value = Json::objectValue;
-      value["Url"] = url_;
-
-      if (!username_.empty() ||
-          !password_.empty())
-      {
-        value["Username"] = username_;
-        value["Password"] = password_;
-      }
-
-      if (!certificateFile_.empty())
-      {
-        value["CertificateFile"] = certificateFile_;
-      }
-
-      if (!certificateKeyFile_.empty())
-      {
-        value["CertificateKeyFile"] = certificateKeyFile_;
-      }
-
-      if (!certificateKeyPassword_.empty())
-      {
-        value["CertificateKeyPassword"] = certificateKeyPassword_;
-      }
-    }
-    else
-    {
-      value = Json::arrayValue;
-      value.append(url_);
-
-      if (!username_.empty() ||
-          !password_.empty())
-      {
-        value.append(username_);
-        value.append(password_);
-      }
-    }
-  }
-}
--- a/Resources/Orthanc/Core/WebServiceParameters.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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;
-  };
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/DownloadOrthancFramework.cmake	Tue Apr 17 15:47:47 2018 +0200
@@ -0,0 +1,312 @@
+# Orthanc - A Lightweight, RESTful DICOM Store
+# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+# Department, University Hospital of Liege, 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 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/>.
+
+
+
+##
+## Check whether the parent script sets the mandatory variables
+##
+
+if (NOT DEFINED ORTHANC_FRAMEWORK_SOURCE OR
+    (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" AND
+     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "web" AND
+     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" AND
+     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "path"))
+  message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_SOURCE must be set to \"hg\", \"web\", \"archive\" or \"path\"")
+endif()
+
+
+##
+## Detection of the requested version
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR
+    ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
+    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
+  if (NOT DEFINED ORTHANC_FRAMEWORK_VERSION)
+    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_VERSION must be set")
+  endif()
+
+  if (DEFINED ORTHANC_FRAMEWORK_MAJOR OR
+      DEFINED ORTHANC_FRAMEWORK_MINOR OR
+      DEFINED ORTHANC_FRAMEWORK_REVISION OR
+      DEFINED ORTHANC_FRAMEWORK_MD5)
+    message(FATAL_ERROR "Some internal variable has been set")
+  endif()
+
+  set(ORTHANC_FRAMEWORK_MD5 "")
+
+  if (ORTHANC_FRAMEWORK_VERSION STREQUAL "mainline")
+    set(ORTHANC_FRAMEWORK_BRANCH "default")
+
+  else()
+    set(ORTHANC_FRAMEWORK_BRANCH "Orthanc-${ORTHANC_FRAMEWORK_VERSION}")
+
+    set(RE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
+    string(REGEX REPLACE ${RE} "\\1" ORTHANC_FRAMEWORK_MAJOR ${ORTHANC_FRAMEWORK_VERSION})
+    string(REGEX REPLACE ${RE} "\\2" ORTHANC_FRAMEWORK_MINOR ${ORTHANC_FRAMEWORK_VERSION})
+    string(REGEX REPLACE ${RE} "\\3" ORTHANC_FRAMEWORK_REVISION ${ORTHANC_FRAMEWORK_VERSION})
+
+    if (NOT ORTHANC_FRAMEWORK_MAJOR MATCHES "^[0-9]+$" OR
+        NOT ORTHANC_FRAMEWORK_MINOR MATCHES "^[0-9]+$" OR
+        NOT ORTHANC_FRAMEWORK_REVISION MATCHES "^[0-9]+$")
+      message("Bad version of the Orthanc framework: ${ORTHANC_FRAMEWORK_VERSION}")
+    endif()
+
+    if (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.3.1")
+      set(ORTHANC_FRAMEWORK_MD5 "dac95bd6cf86fb19deaf4e612961f378")
+    endif()
+  endif()
+endif()
+
+
+
+##
+## Detection of the third-party software
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg")
+  find_program(ORTHANC_FRAMEWORK_HG hg)
+  
+  if (${ORTHANC_FRAMEWORK_HG} MATCHES "ORTHANC_FRAMEWORK_HG-NOTFOUND")
+    message(FATAL_ERROR "Please install Mercurial")
+  endif()
+endif()
+
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
+    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
+  if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
+    find_program(ORTHANC_FRAMEWORK_7ZIP 7z 
+      PATHS 
+      "$ENV{ProgramFiles}/7-Zip"
+      "$ENV{ProgramW6432}/7-Zip"
+      )
+
+    if (${ORTHANC_FRAMEWORK_7ZIP} MATCHES "ORTHANC_FRAMEWORK_7ZIP-NOTFOUND")
+      message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)")
+    endif()
+
+  else()
+    find_program(ORTHANC_FRAMEWORK_TAR tar)
+    if (${ORTHANC_FRAMEWORK_TAR} MATCHES "ORTHANC_FRAMEWORK_TAR-NOTFOUND")
+      message(FATAL_ERROR "Please install the 'tar' package")
+    endif()
+  endif()
+endif()
+
+
+
+##
+## Case of the Orthanc framework specified as a path on the filesystem
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path")
+  if (NOT DEFINED ORTHANC_FRAMEWORK_ROOT)
+    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ROOT must provide the path to the sources of Orthanc")
+  endif()
+  
+  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT})
+    message(FATAL_ERROR "Non-existing directory: ${ORTHANC_FRAMEWORK_ROOT}")
+  endif()
+  
+  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
+    message(FATAL_ERROR "Directory not containing the source code of Orthanc: ${ORTHANC_FRAMEWORK_ROOT}")
+  endif()
+  
+  set(ORTHANC_ROOT ${ORTHANC_FRAMEWORK_ROOT})
+endif()
+
+
+
+##
+## Case of the Orthanc framework cloned using Mercurial
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg")
+  if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
+    message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
+  endif()
+
+  set(ORTHANC_ROOT ${CMAKE_BINARY_DIR}/orthanc)
+
+  if (EXISTS ${ORTHANC_ROOT})
+    message("Updating the Orthanc source repository using Mercurial")
+    execute_process(
+      COMMAND ${ORTHANC_FRAMEWORK_HG} pull
+      WORKING_DIRECTORY ${ORTHANC_ROOT}
+      RESULT_VARIABLE Failure
+      )    
+  else()
+    message("Forking the Orthanc source repository using Mercurial")
+    execute_process(
+      COMMAND ${ORTHANC_FRAMEWORK_HG} clone "https://bitbucket.org/sjodogne/orthanc"
+      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+      RESULT_VARIABLE Failure
+      )    
+  endif()
+
+  if (Failure OR NOT EXISTS ${ORTHANC_ROOT})
+    message(FATAL_ERROR "Cannot fork the Orthanc repository")
+  endif()
+
+  message("Setting branch of the Orthanc repository to: ${ORTHANC_FRAMEWORK_BRANCH}")
+
+  execute_process(
+    COMMAND ${ORTHANC_FRAMEWORK_HG} update -c ${ORTHANC_FRAMEWORK_BRANCH}
+    WORKING_DIRECTORY ${ORTHANC_ROOT}
+    RESULT_VARIABLE Failure
+    )
+
+  if (Failure)
+    message(FATAL_ERROR "Error while running Mercurial")
+  endif()
+endif()
+
+
+
+##
+## Case of the Orthanc framework provided as a source archive on the
+## filesystem
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive")
+  if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE)
+    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ARCHIVE must provide the path to the sources of Orthanc")
+  endif()
+endif()
+
+
+
+##
+## Case of the Orthanc framework downloaded from the official Web site
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
+  set(ORTHANC_FRAMEMORK_FILENAME Orthanc-${ORTHANC_FRAMEWORK_VERSION}.tar.gz)
+  set(ORTHANC_FRAMEWORK_URL "https://www.orthanc-server.com/downloads/get.php?path=/orthanc/${ORTHANC_FRAMEMORK_FILENAME}")
+
+  set(ORTHANC_FRAMEWORK_ARCHIVE "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${ORTHANC_FRAMEMORK_FILENAME}")
+
+  if (NOT EXISTS "${ORTHANC_FRAMEWORK_ARCHIVE}")
+    if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
+      message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
+    endif()
+
+    message("Downloading: ${ORTHANC_FRAMEWORK_ARCHIVE}")
+
+    file(DOWNLOAD
+      "${ORTHANC_FRAMEWORK_URL}" "${ORTHANC_FRAMEWORK_ARCHIVE}" 
+      SHOW_PROGRESS EXPECTED_MD5 "${ORTHANC_FRAMEWORK_MD5}"
+      TIMEOUT 60
+      INACTIVITY_TIMEOUT 60
+      )
+  else()
+    message("Using local copy of: ${ORTHANC_FRAMEWORK_URL}")
+  endif()  
+endif()
+
+
+
+
+##
+## Uncompressing the Orthanc framework, if it was retrieved from a
+## source archive on the filesystem, or from the official Web site
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
+    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
+
+  if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE OR
+      NOT DEFINED ORTHANC_FRAMEWORK_VERSION OR
+      NOT DEFINED ORTHANC_FRAMEWORK_MD5)
+    message(FATAL_ERROR "Internal error")
+  endif()
+
+  if (ORTHANC_FRAMEWORK_MD5 STREQUAL "")
+    message(FATAL_ERROR "Unknown release of Orthanc: ${ORTHANC_FRAMEWORK_VERSION}")
+  endif()
+
+  file(MD5 ${ORTHANC_FRAMEWORK_ARCHIVE} ActualMD5)
+
+  if (NOT "${ActualMD5}" STREQUAL "${ORTHANC_FRAMEWORK_MD5}")
+    message(FATAL_ERROR "The MD5 hash of the Orthanc archive is invalid: ${ORTHANC_FRAMEWORK_ARCHIVE}")
+  endif()
+
+  set(ORTHANC_ROOT "${CMAKE_BINARY_DIR}/Orthanc-${ORTHANC_FRAMEWORK_VERSION}")
+
+  if (NOT IS_DIRECTORY "${ORTHANC_ROOT}")
+    if (NOT ORTHANC_FRAMEWORK_ARCHIVE MATCHES ".tar.gz$")
+      message(FATAL_ERROR "Archive should have the \".tar.gz\" extension: ${ORTHANC_FRAMEWORK_ARCHIVE}")
+    endif()
+    
+    message("Uncompressing: ${ORTHANC_FRAMEWORK_ARCHIVE}")
+
+    if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
+      # How to silently extract files using 7-zip
+      # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly
+
+      execute_process(
+        COMMAND ${ORTHANC_FRAMEWORK_7ZIP} e -y ${ORTHANC_FRAMEWORK_ARCHIVE}
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        RESULT_VARIABLE Failure
+        OUTPUT_QUIET
+        )
+      
+      if (Failure)
+        message(FATAL_ERROR "Error while running the uncompression tool")
+      endif()
+
+      string(REGEX REPLACE ".gz$" "" TMP "${ORTHANC_FRAMEWORK_ARCHIVE}")
+
+      execute_process(
+        COMMAND ${ORTHANC_FRAMEWORK_7ZIP} x -y ${TMP_FILENAME2}
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        RESULT_VARIABLE Failure
+        OUTPUT_QUIET
+        )
+
+    else()
+      execute_process(
+        COMMAND sh -c "${ORTHANC_FRAMEWORK_TAR} xfz ${ORTHANC_FRAMEWORK_ARCHIVE}"
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        RESULT_VARIABLE Failure
+        )
+    endif()
+   
+    if (Failure)
+      message(FATAL_ERROR "Error while running the uncompression tool")
+    endif()
+
+    if (NOT IS_DIRECTORY "${ORTHANC_ROOT}")
+      message(FATAL_ERROR "The Orthanc framework was not uncompressed at the proper location. Check the CMake instructions.")
+    endif()
+  endif()
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/LinuxStandardBaseToolchain.cmake	Tue Apr 17 15:47:47 2018 +0200
@@ -0,0 +1,66 @@
+# LSB_CC=gcc-4.8 LSB_CXX=g++-4.8 cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../Resources/LinuxStandardBaseToolchain.cmake -DUSE_LEGACY_JSONCPP=ON
+
+INCLUDE(CMakeForceCompiler)
+
+SET(LSB_PATH $ENV{LSB_PATH})
+SET(LSB_CC $ENV{LSB_CC})
+SET(LSB_CXX $ENV{LSB_CXX})
+SET(LSB_TARGET_VERSION "4.0")
+
+IF ("${LSB_PATH}" STREQUAL "")
+  SET(LSB_PATH "/opt/lsb")
+ENDIF()
+
+IF (EXISTS ${LSB_PATH}/lib64)
+  SET(LSB_TARGET_PROCESSOR "x86_64")
+  SET(LSB_LIBPATH ${LSB_PATH}/lib64-${LSB_TARGET_VERSION})
+ELSEIF (EXISTS ${LSB_PATH}/lib)
+  SET(LSB_TARGET_PROCESSOR "x86")
+  SET(LSB_LIBPATH ${LSB_PATH}/lib-${LSB_TARGET_VERSION})
+ELSE()
+  MESSAGE(FATAL_ERROR "Unable to detect the target processor architecture. Check the LSB_PATH environment variable.")
+ENDIF()
+
+SET(LSB_CPPPATH ${LSB_PATH}/include)
+SET(PKG_CONFIG_PATH ${LSB_LIBPATH}/pkgconfig/)
+
+# the name of the target operating system
+SET(CMAKE_SYSTEM_NAME Linux)
+SET(CMAKE_SYSTEM_VERSION LinuxStandardBase)
+SET(CMAKE_SYSTEM_PROCESSOR ${LSB_TARGET_PROCESSOR})
+
+# which compilers to use for C and C++
+SET(CMAKE_C_COMPILER ${LSB_PATH}/bin/lsbcc)
+CMAKE_FORCE_CXX_COMPILER(${LSB_PATH}/bin/lsbc++ GNU)
+
+# here is the target environment located
+SET(CMAKE_FIND_ROOT_PATH ${LSB_PATH})
+
+# adjust the default behaviour of the FIND_XXX() commands:
+# search headers and libraries in the target environment, search 
+# programs in the host environment
+SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
+SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
+
+SET(CMAKE_CROSSCOMPILING OFF)
+
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -I${LSB_PATH}/include" CACHE INTERNAL "" FORCE)
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -nostdinc++ -I${LSB_PATH}/include -I${LSB_PATH}/include/c++ -I${LSB_PATH}/include/c++/backward" CACHE INTERNAL "" FORCE)
+SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH} --lsb-besteffort" CACHE INTERNAL "" FORCE)
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH} --lsb-besteffort" CACHE INTERNAL "" FORCE)
+
+if (NOT "${LSB_CXX}" STREQUAL "")
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-cxx=${LSB_CXX}")
+  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-cxx=${LSB_CXX}")
+  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-cxx=${LSB_CXX}")
+endif()
+
+if (NOT "${LSB_CC}" STREQUAL "")
+  SET(CMAKE_C_FLAGS "${CMAKE_CC_FLAGS} --lsb-cc=${LSB_CC}")
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-cc=${LSB_CC}")
+  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-cc=${LSB_CC}")
+  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-cc=${LSB_CC}")
+endif()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/MinGW-W64-Toolchain32.cmake	Tue Apr 17 15:47:47 2018 +0200
@@ -0,0 +1,17 @@
+# the name of the target operating system
+set(CMAKE_SYSTEM_NAME Windows)
+
+# which compilers to use for C and C++
+set(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
+set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
+set(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
+
+# here is the target environment located
+set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
+
+# adjust the default behaviour of the FIND_XXX() commands:
+# search headers and libraries in the target environment, search 
+# programs in the host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/MinGW-W64-Toolchain64.cmake	Tue Apr 17 15:47:47 2018 +0200
@@ -0,0 +1,17 @@
+# the name of the target operating system
+set(CMAKE_SYSTEM_NAME Windows)
+
+# which compilers to use for C and C++
+set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
+set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
+set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
+
+# here is the target environment located
+set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
+
+# adjust the default behaviour of the FIND_XXX() commands:
+# search headers and libraries in the target environment, search 
+# programs in the host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/MinGWToolchain.cmake	Tue Apr 17 15:47:47 2018 +0200
@@ -0,0 +1,17 @@
+# the name of the target operating system
+set(CMAKE_SYSTEM_NAME Windows)
+
+# which compilers to use for C and C++
+set(CMAKE_C_COMPILER i586-mingw32msvc-gcc)
+set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++)
+set(CMAKE_RC_COMPILER i586-mingw32msvc-windres)
+
+# here is the target environment located
+set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc)
+
+# adjust the default behaviour of the FIND_XXX() commands:
+# search headers and libraries in the target environment, search 
+# programs in the host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--- a/Resources/Orthanc/NEWS	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,946 +0,0 @@
-Pending changes in the mainline
-===============================
-
-REST API
---------
-
-* "/system" URI returns the version of the Orthanc REST API
-* "/tools/now" returns the current UTC (universal) time
-* "/tools/now-local" returns the curent local time.
-  This was the behavior of "/tools/now" until release 1.3.1.
-* Added "?expand" GET argument to "/peers" and "/modalities" routes
-* New URI: "/tools/create-media-extended" to generate a DICOMDIR
-  archive from several resources, including additional type-3 tags
-* Preservation of UID relationships while anonymizing
-
-Lua
----
-
-* New CMake option: "-DENABLE_LUA_MODULES=ON" to enable support for
-  loading external Lua modules if the Lua engine is statically linked
-
-Plugins
--------
-
-* New error code: DatabaseUnavailable
-
-Maintenance
------------
-
-* Orthanc now uses UTC (universal time) instead of local time in its database
-* Fix to allow creating DICOM instances with empty Specific Character Set (0008,0005)
-* Support of Linux Standard Base
-* Static linking against libuuid (from e2fsprogs)
-* Fix static build on CentOS 6
-* Possibility of using JsonCpp 0.10.6 if the compiler does not support C++11
-  with the "-DUSE_LEGACY_JSONCPP=ON" CMake option
-* Upgraded dependencies for static and Windows builds:
-  - boost 1.66.0
-  - curl 7.57.0
-  - jsoncpp 1.8.4
-  - zlib 1.2.11
-
-
-Version 1.3.1 (2017-11-29)
-==========================
-
-General
--------
-
-* Built-in decoding of palette images
-
-REST API
---------
-
-* New URI: "/instances/.../frames/.../raw.gz" to compress raw frames using gzip
-* New argument "ignore-length" to force the inclusion of too long tags in JSON
-* New argument "/.../media?extended" to include additional type-3 tags in DICOMDIR
-
-Plugins
--------
-
-* New pixel formats exposed in SDK: BGRA32, Float32, Grayscale32, RGB48
-
-Maintenance
------------
-
-* Creation of ./Resources/CMake/OrthancFramework*.cmake to reuse the Orthanc
-  C++ framework in other projects
-* New security-related options: "DicomAlwaysAllowEcho"
-* Use "GBK" (frequently used in China) as an alias for "GB18030"
-* Experimental support of actively maintained Civetweb to replace Mongoose 3.8
-* Fix issue 31 for good (create new modality types for Philips ADW, GE Xeleris, GE AWServer)
-* Fix issue 64 (OpenBSD support)
-* Fix static compilation of DCMTK 3.6.2 on Fedora
-* Upgrade to Boost 1.65.1 in static builds
-* Upgrade to SQLite amalgamation 3.21.0 in static builds
-
-
-Version 1.3.0 (2017-07-19)
-==========================
-
-General
--------
-
-* Orthanc now anonymizes according to Basic Profile of PS 3.15-2017c Table E.1-1
-* In the "DicomModalities" configuration:
-  - Manufacturer type MedInria is now obsolete
-  - Manufacturer types AgfaImpax and SyngoVia are obsolete too
-    (use GenericNoWildcardInDates instead)
-  - Obsolete manufacturers are still accepted but might disappear in the future
-  - Added new manufacturer: GenericNoUniversalWildcard to replace all '*' by '' in
-    outgoing C-Find requests
-* New security-related options: "DicomAlwaysAllowStore" and "DicomCheckModalityHost"
-
-REST API
---------
-
-* Argument "Since" in URI "/tools/find" (related to issue 53)
-* Argument "DicomVersion" in URIs "/{...}/{...}/anonymization"
-
-Plugins
--------
-
-* New function: "OrthancPluginRegisterIncomingHttpRequestFilter2()"
-
-Lua
----
-
-* Added HTTP headers support for Lua HttpPost/HttpGet/HttpPut/HttpDelete
-
-Orthanc Explorer
-----------------
-
-* Query/retrieve: Added button for "DR" modality
-
-Maintenance
------------
-
-* Ability to retrieve raw frames encoded as unsigned 32-bits integers
-* Fix issue 29 (more consistent handling of the "--upgrade" argument)
-* Fix issue 31 (create new modality types for Philips ADW, GE Xeleris, GE AWServer)
-* Fix issue 35 (AET name is not transferred to Orthanc using DCMTK 3.6.0)
-* Fix issue 44 (bad interpretation of photometric interpretation MONOCHROME1)
-* Fix issue 45 (crash when providing a folder to "--config" command-line option)
-* Fix issue 46 (PHI remaining after anonymization)
-* Fix issue 49 (worklists: accentuated characters are removed from C-Find responses)
-* Fix issue 52 (DICOM level security association problems)
-* Fix issue 55 (modification/anonymization of tags that might break the database
-  model now requires the "Force" parameter to be set to "true" in the query)
-* Fix issue 56 (case-insensitive matching over accents)
-* Fix Debian #865606 (orthanc FTBFS with libdcmtk-dev 3.6.1~20170228-2)
-* Fix XSS inside DICOM in Orthanc Explorer (as reported by Victor Pasnkel, Morphus Labs)
-* Upgrade to DCMTK 3.6.2 in static builds (released on 2017-07-17)
-* Upgrade to Boost 1.64.0 in static builds
-* New advanced "Locale" configuration option
-* Removed configuration option "USE_DCMTK_361_PRIVATE_DIC"
-
-
-Version 1.2.0 (2016/12/13)
-==========================
-
-General
--------
-
-* Handling of private tags/creators in the "Dictionary" configuration option
-* New configuration options: "LoadPrivateDictionary", "DicomScuTimeout" and "DicomScpTimeout"
-* New metadata automatically computed at the instance level: "TransferSyntax" and "SopClassUid"
-
-REST API
---------
-
-* "/tools/invalidate-tags" to invalidate the JSON summary of all the DICOM files
-  (useful if private tags are registered, or if changing the default encoding)
-* "Permissive" flag for URI "/modalities/{...}/store" to ignore C-STORE transfer errors
-* "Asynchronous" flag for URIs "/modalities/{...}/store" and "/peers/{...}/store"
-  to avoid waiting for the completion of image transfers
-* Possibility to DELETE "dicom-as-json" attachments to reconstruct the JSON summaries
-  (useful if "Dictionary" has changed)
-* "Keep" option for modifications to keep original DICOM identifiers (advanced feature)
-* "/tools/default-encoding" to get or temporarily change the default encoding
-* "/{resource}/{id}/reconstruct" to reconstruct the main DICOM tags, the JSON summary and
-  the metadata of a resource (useful to compute new metadata, or if using "Keep" above)
-
-Plugins
--------
-
-* New function: "OrthancPluginRegisterPrivateDictionaryTag()" to register private tags
-* More control over client cache in the ServeFolders plugin
-* New C++ help wrappers in "Plugins/Samples/Common/" to read DICOM datasets from REST API
-* New data structure: "OrthancPluginFindMatcher" to match DICOM against C-FIND queries
-
-Maintenance
------------
-
-* Fix handling of encodings in C-FIND requests (including for worklists)
-* Use of DCMTK 3.6.1 dictionary of private tags in standalone builds
-* Avoid hard crash if not enough memory (handling of std::bad_alloc)
-* Improved robustness of Orthanc Explorer wrt. query/retrieve (maybe fix issue 24)
-* Fix serious performance issue with C-FIND
-* Fix extraction of the symbolic name of the private tags
-* Performance warning if runtime debug assertions are turned on
-* Improved robustness against files with no PatientID
-* Upgrade to curl 7.50.3 for static and Windows builds
-* Content-Type for JSON documents is now "application/json; charset=utf-8"
-* Ignore "Group Length" tags in C-FIND queries
-* Fix handling of worklist SCP with ReferencedStudySequence and ReferencedPatientSequence
-* Fix handling of Move Originator AET and ID in C-MOVE SCP
-* Fix vulnerability ZSL-2016-5379 "Unquoted Service Path Privilege Escalation" in the
-  Windows service
-* Fix vulnerability ZSL-2016-5380 "Remote Memory Corruption Vulnerability" in DCMTK 3.6.0
-
-
-Version 1.1.0 (2016/06/27)
-==========================
-
-General
--------
-
-* HTTPS client certificates can be associated with Orthanc peers to enhance security over Internet
-* Possibility to use PKCS#11 authentication for hardware security modules with Orthanc peers
-* New command-line option "--logfile" to output the Orthanc log to the given file
-* Support of SIGHUP signal (restart Orthanc only if the configuration files have changed)
-
-REST API
---------
-
-* New URI: "/instances/.../frames/.../raw" to access the raw frames (bypass image decoding)
-* New URI "/modalities/.../move" to issue C-MOVE SCU requests
-* "MoveOriginatorID" can be specified for "/modalities/.../store"
-
-Dicom protocol
---------------
-
-* Support of optional tags for counting resources in C-FIND:
-  0008-0061, 0008-0062, 0020-1200, 0020-1202, 0020-1204, 0020-1206, 0020-1208, 0020-1209
-* Support of Move Originator Message ID (0000,1031) in C-STORE responses driven by C-MOVE
-
-Plugins
--------
-
-* Speedup in plugins by removing unnecessary locks
-* New callback to filter incoming HTTP requests: OrthancPluginRegisterIncomingHttpRequestFilter()
-* New callback to handle non-worklists C-FIND requests: OrthancPluginRegisterFindCallback()
-* New callback to handle C-MOVE requests: OrthancPluginRegisterMoveCallback()
-* New function: "OrthancPluginHttpClient()" to do HTTP requests with full control
-* New function: "OrthancPluginGenerateUuid()" to generate a UUID
-* More than one custom image decoder can be installed (e.g. to handle different transfer syntaxes)
-
-Lua
----
-
-* Possibility to dynamically fix outgoing C-FIND requests using "OutgoingFindRequestFilter()"
-* Access to the HTTP headers in the "IncomingHttpRequestFilter()" callback
-
-Image decoding
---------------
-
-* Huge speedup if decoding the family of JPEG transfer syntaxes
-* Refactoring leading to speedups with custom image decoders (including Web viewer plugin)
-* Support decoding of RLE Lossless transfer syntax
-* Support of signed 16bpp images in ParsedDicomFile
-
-Maintenance
------------
-
-* New logo of Orthanc
-* Fix issue 11 (is_regular_file() fails for FILE_ATTRIBUTE_REPARSE_POINT)
-* Fix issue 16 ("Limit" parameter error in REST API /tools/find method)
-* Fix of Debian bug #818512 ("FTBFS: Please install libdcmtk*-dev")
-* Fix of Debian bug #823139 ("orthanc: Please provide RecoverCompressedFile.cpp")
-* Replaced "localhost" by "127.0.0.1", as it might impact performance on Windows
-* Compatibility with CMake >= 3.5.0
-* Possibility to use forthcoming DCMTK 3.6.1 in static builds (instead of 3.6.0)
-* Upgrade to Boost 1.60.0 for static builds
-* Use of HTTP status 403 Forbidden (instead of 401) if access to a REST resource is disallowed
-* Option "HttpsVerifyPeers" can be used to connect against self-signed HTTPS certificates
-* New configuration option "AllowFindSopClassesInStudy"
-* Macro "__linux" (now obsolete) replaced by macro "__linux__" (maybe solves Debian bug #821011)
-* Modification of instances can now replace PixelData (resp. EncapsulatedDocument) with 
-  provided a PNG/JPEG image (resp. PDF file) if it is encoded using Data URI Scheme
-* Dropped support of Google Log
-
-
-Version 1.0.0 (2015/12/15)
-==========================
-
-* Lua: "IncomingFindRequestFilter()" to apply filters to incoming C-FIND requests
-* New function in plugin SDK: "OrthancPluginSendMultipartItem2()"
-* Fix of DICOMDIR generation with DCMTK 3.6.1, support of encodings
-* Fix range search if the lower or upper limit is absent
-* Fix modality worklists lookups if tags with UN (unknown) VR are present
-* Warn about badly formatted modality/peer definitions in configuration file at startup
-
-
-Version 0.9.6 (2015/12/08)
-==========================
-
-* Promiscuous mode (accept unknown SOP class UID) is now turned off by default
-* Fix serialization of DICOM buffers that might contain garbage trailing
-* Fix modality worklists server if some fields are null
-* More tolerant "/series/.../ordered-slices" with broken series
-* Improved logging information if upgrade fails
-* Fix formatting of multipart HTTP answers (bis)
-
-
-Version 0.9.5 (2015/12/02)
-==========================
-
-Major
------
-
-* Experimental support of DICOM C-FIND SCP for modality worklists through plugins
-* Support of DICOM C-FIND SCU for modality worklists ("/modalities/{dicom}/find-worklist")
-
-REST API
---------
-
-* New URIs:
-  - "/series/.../ordered-slices" to order the slices of a 2D+t or 3D series
-  - "/tools/shutdown" to stop Orthanc from the REST API
-  - ".../compress", ".../uncompress" and ".../is-compressed" for attachments
-  - "/tools/create-archive" to create ZIP from a set of resources
-  - "/tools/create-media" to create ZIP+DICOMDIR from a set of resources
-  - "/instances/.../header" to get the meta information (header) of the DICOM instance
-* "/tools/create-dicom":
-  - Support of binary tags encoded using data URI scheme
-  - Support of hierarchical structures (creation of sequences)
-  - Create tags with unknown VR
-* "/modify" can insert/modify sequences
-* ".../preview" and ".../image-uint8" can return JPEG images if the HTTP Accept Header asks so
-* "Origin" metadata for the instances
-
-Minor
------
-
-* New configuration options:
-  - "UnknownSopClassAccepted" to disable promiscuous mode (accept unknown SOP class UID)
-  - New configuration option: "Dictionary" to declare custom DICOM tags
-* Add ".dcm" suffix to files in ZIP archives (cf. URI ".../archive")
-* MIME content type can be associated to custom attachments (cf. "UserContentType")
-
-Plugins
--------
-
-* New functions:
-  - "OrthancPluginRegisterDecodeImageCallback()" to replace the built-in image decoder
-  - "OrthancPluginDicomInstanceToJson()" to convert DICOM to JSON
-  - "OrthancPluginDicomBufferToJson()" to convert DICOM to JSON
-  - "OrthancPluginRegisterErrorCode()" to declare custom error codes
-  - "OrthancPluginRegisterDictionaryTag()" to declare custom DICOM tags
-  - "OrthancPluginLookupDictionary()" to get information about some DICOM tag
-  - "OrthancPluginRestApiGet2()" to provide HTTP headers when calling Orthanc API
-  - "OrthancPluginGetInstanceOrigin()" to know through which mechanism an instance was received
-  - "OrthancPluginCreateImage()" and "OrthancPluginCreateImageAccessor()" to create images
-  - "OrthancPluginDecodeDicomImage()" to decode DICOM images
-  - "OrthancPluginComputeMd5()" and "OrthancPluginComputeSha1()" to compute MD5/SHA-1 hash
-* New events in change callbacks:
-  - "OrthancStarted"
-  - "OrthancStopped"
-  - "UpdatedAttachment" 
-  - "UpdatedMetadata"
-* "/system" URI gives information about the plugins used for storage area and DB back-end
-* Plugin callbacks must now return explicit "OrthancPluginErrorCode" (instead of integers)
-
-Lua
----
-
-* Optional argument "keepStrings" in "DumpJson()"
-
-Maintenance
------------
-
-* Full indexation of the patient/study tags to speed up searches and C-FIND
-* Many refactorings, notably of the searching features and of the image decoding
-* C-MOVE SCP for studies using AccessionNumber tag
-* Fix issue 4 (C-STORE Association not renegotiated on Specific-to-specific transfer syntax change)
-* Fix formatting of multipart HTTP answers
-* "--logdir" flag creates a single log file instead of 3 separate files for errors/warnings/infos
-* "--errors" flag lists the error codes that could be returned by Orthanc
-* Under Windows, the exit status of Orthanc corresponds to the encountered error code
-* New "AgfaImpax", "EFilm2" and "Vitrea" modality manufacturers
-* C-FIND SCP will return tags with sequence value representation
-* Upgrade to Boost 1.59.0 for static builds
-
-
-Version 0.9.4 (2015/09/16)
-==========================
-
-* Preview of PDF files encapsulated in DICOM from Orthanc Explorer
-* Creation of DICOM files with encapsulated PDF through "/tools/create-dicom"
-* "limit" and "since" arguments while retrieving DICOM resources in the REST API
-* Support of "deflate" and "gzip" content-types in HTTP requests
-* Options to validate peers against CA certificates in HTTPS requests
-* New configuration option: "HttpTimeout" to set the default timeout for HTTP requests
-
-Lua
----
-
-* More information about the origin request in the "OnStoredInstance()" and
-  "ReceivedInstanceFilter()" callbacks. WARNING: This can result in
-  incompatibilities wrt. previous versions of Orthanc.
-* New function "GetOrthancConfiguration()" to get the Orthanc configuration
-
-Plugins
--------
-
-* New functions to compress/uncompress images using PNG and JPEG
-* New functions to issue HTTP requests from plugins
-* New function "OrthancPluginBufferCompression()" to (un)compress memory buffers
-* New function "OrthancPluginReadFile()" to read files from the filesystem
-* New function "OrthancPluginWriteFile()" to write files to the filesystem
-* New function "OrthancPluginGetErrorDescription()" to convert error codes to strings
-* New function "OrthancPluginSendHttpStatus()" to send HTTP status with a body
-* New function "OrthancPluginRegisterRestCallbackNoLock()" for high-performance plugins
-* Plugins have access to explicit error codes 
-* Improvements to the sample "ServeFolders" plugin
-* Primitives to upgrade the database version in plugins
-
-Maintenance
------------
-
-* Many code refactorings
-* Improved error codes (no more custom descriptions in exceptions)
-* If error while calling the REST API, the answer body contains description of the error
-  (this feature can be disabled with the "HttpDescribeErrors" option)
-* Upgrade to curl 7.44.0 for static and Windows builds
-* Upgrade to libcurl 1.0.2d for static and Windows builds
-* Depends on libjpeg 9a
-* Bypass zlib uncompression if "StorageCompression" is enabled and HTTP client supports deflate
-
-
-Version 0.9.3 (2015/08/07)
-==========================
-
-* C-Echo testing can be triggered from Orthanc Explorer (in the query/retrieve page)
-* Removal of the dependency upon Google Log, Orthanc now uses its internal logger 
-  (use -DENABLE_GOOGLE_LOG=ON to re-enable Google Log)
-* Upgrade to JsonCpp 0.10.5 for static and Windows builds
-
-
-Version 0.9.2 (2015/08/02)
-==========================
-
-* Upgrade to Boost 1.58.0 for static and Windows builds
-* Source code repository moved from Google Code to BitBucket
-* Inject version information into Windows binaries
-* Fix access to binary data in HTTP/REST requests by Lua scripts
-* Fix potential deadlock in the callbacks of plugins
-
-
-Version 0.9.1 (2015/07/02)
-==========================
-
-General
--------
-
-* The configuration can be splitted into several files stored inside the same folder
-* Custom setting of the local AET during C-STORE SCU (both in Lua and in the REST API)
-* Many code refactorings
-
-Lua
----
-
-* Access to the REST API of Orthanc (RestApiGet, RestApiPost, RestApiPut, RestApiDelete)
-* Functions to convert between Lua values and JSON strings: "ParseJson" and "DumpJson"
-* New events: "OnStablePatient", "OnStableStudy", "OnStableSeries", "Initialize", "Finalize"
-
-Plugins
--------
-
-* Plugins can retrieve the configuration file directly as a JSON string
-* Plugins can send answers as multipart messages
-
-Fixes
------
-
-* Fix compatibility issues for C-FIND SCU to Siemens Syngo.Via modalities SCP
-* Fix issue 15 (Lua scripts making HTTP requests)
-* Fix issue 35 (Characters in PatientID string are not protected for C-FIND)
-* Fix issue 37 (Hyphens trigger range query even if datatype does not support ranges)
-
-
-Version 0.9.0 (2015/06/03)
-==========================
-
-Major
------
-
-* DICOM Query/Retrieve available from Orthanc Explorer
-* C-MOVE SCU and C-FIND SCU are accessible through the REST API
-* "?expand" flag for URIs "/patients", "/studies" and "/series"
-* "/tools/find" URI to search for DICOM resources from REST
-* Support of FreeBSD
-* The "Orthanc Client" SDK is now a separate project
-
-Minor
------
-
-* Speed-up in Orthanc Explorer for large amount of images
-* Speed-up of the C-FIND SCP server of Orthanc
-* Allow replacing PatientID/StudyInstanceUID/SeriesInstanceUID from Lua scripts
-* Option "CaseSensitivePN" to enable case-insensitive C-FIND SCP
-
-Fixes
------
-
-* Prevent freeze on C-FIND if no DICOM tag is to be returned
-* Fix slow C-STORE SCP on recent versions of GNU/Linux, if
-  USE_SYSTEM_DCMTK is set to OFF (http://forum.dcmtk.org/viewtopic.php?f=1&t=4009)
-* Fix issue 30 (QR response missing "Query/Retrieve Level" (008,0052))
-* Fix issue 32 (Cyrillic symbols): Introduction of the "Windows1251" encoding
-* Plugins now receive duplicated GET arguments in their REST callbacks
-
-
-Version 0.8.6 (2015/02/12)
-==========================
-
-Major
------
-
-* URIs to get all the parents of a given resource in a single REST call
-* Instances without PatientID are now allowed
-* Support of HTTP proxy to access Orthanc peers
-
-Minor
------
-
-* Support of Tudor DICOM in Query/Retrieve
-* More flexible "/modify" and "/anonymize" for single instance
-* Access to called AET and remote AET from Lua scripts ("OnStoredInstance")
-* Option "DicomAssociationCloseDelay" to set delay before closing DICOM association
-* ZIP archives now display the accession number of the studies
-
-Plugins
--------
-
-* Introspection of plugins (cf. the "/plugins" URI)
-* Plugins can access the command-line arguments used to launch Orthanc
-* Plugins can extend Orthanc Explorer with custom JavaScript
-* Plugins can get/set global properties to save their configuration
-* Plugins can do REST calls to other plugins (cf. "xxxAfterPlugins()")
-* Scan of folders for plugins
-
-Fixes
------
-
-* Code refactorings
-* Fix issue 25 (AET with underscore not allowed)
-* Fix replacement and insertion of private DICOM tags
-* Fix anonymization generating non-portable DICOM files
-
-
-Version 0.8.5 (2014/11/04)
-==========================
-
-General
--------
-
-* Major speed-up thanks to a new database schema
-* Plugins can monitor changes through callbacks
-* Download ZIP + DICOMDIR from Orthanc Explorer
-* Sample plugin framework to serve static resources (./Plugins/Samples/WebSkeleton/)
-
-Fixes
------
-
-* Fix issue 19 (YBR_FULL are decoded incorrectly)
-* Fix issue 21 (Microsoft Visual Studio precompiled headers)
-* Fix issue 22 (Error decoding multi-frame instances)
-* Fix issue 24 (Build fails on OSX when directory has .DS_Store files)
-* Fix crash when bad HTTP credentials are provided
-
-
-Version 0.8.4 (2014/09/19)
-==========================
-
-* "/instances-tags" to get the tags of all the child instances of a
-  patient/study/series with a single REST call (bulk tags retrieval)
-* Configuration/Lua to select the accepted C-STORE SCP transfer syntaxes
-* Fix reporting of errors in Orthanc Explorer when sending images to peers/modalities
-* Installation of plugin SDK in CMake
-
-
-Version 0.8.3 (2014/09/11)
-==========================
-
-Major
------
-
-* Creation of ZIP archives for media storage, with DICOMDIR
-* URIs to get all the children of a given resource in a single REST call
-* "/tools/lookup" URI to map DICOM UIDs to Orthanc identifiers
-* Support of index-only mode (using the "StoreDicom" option)
-* Plugins can implement a custom storage area
-
-Minor
------
-
-* Configuration option to enable HTTP Keep-Alive
-* Configuration option to disable the logging of exported resources in "/exports"
-* Plugins can retrieve the path to Orthanc and to its configuration file
-* "/tools/create-dicom" now accepts the "PatientID" DICOM tag (+ updated sample)
-* Possibility to set HTTP headers from plugins
-* "LastUpdate" metadata is now always returned for patients, studies and series
-
-Maintenance
------------
-
-* Refactoring of HttpOutput ("Content-Length" header is now always sent)
-* Upgrade to Mongoose 3.8
-* Fixes for Visual Studio 2013 and Windows 64bit
-* Fix issue 16: Handling of "AT" value representations in JSON
-* Fix issue 17
-
-
-Version 0.8.2 (2014/08/07)
-==========================
-
-* Support of the standard text encodings
-* Hot restart of Orthanc by posting to "/tools/reset"
-* More fault-tolerant commands in Lua scripts
-* Parameter to set the default encoding for DICOM files without SpecificCharacterSet
-* Fix of issue #14 (support of XCode 5.1)
-* Upgrade to Google Test 1.7.0
-
-
-Version 0.8.1 (2014/07/29)
-==========================
-
-General
--------
-
-* Access patient module at the study level to cope with PatientID collisions
-* On-the-fly conversion of JSON to XML according to the HTTP Accept header
-* C-Echo SCU in the REST API
-* DICOM conformance statement available at URI "/tools/dicom-conformance"
-
-Lua scripts
------------
-
-* Lua scripts can do HTTP requests, and thus can call Web services
-* Lua scripts can invoke system commands, with CallSystem()
-
-Plugins
--------
-
-* Lookup for DICOM UIDs in the plugin SDK
-* Plugins have access to the HTTP headers and can answer with HTTP status codes
-* Callback to react to the incoming of DICOM instances
-
-Fixes
------
-
-* Fix build of Google Log with Visual Studio >= 11.0
-* Fix automated generation of the list of resource children in the REST API
-
-
-Version 0.8.0 (2014/07/10)
-==========================
-
-Major changes
--------------
-
-* Routing images with Lua scripts
-* Introduction of the Orthanc Plugin SDK
-* Official support of OS X (Darwin) 10.8
-
-Minor changes
--------------
-
-* Extraction of tags for the patient/study/series/instance DICOM modules
-* Extraction of the tags shared by all the instances of a patient/study/series
-* Options to limit the number of results for an incoming C-FIND query
-* Support of kFreeBSD
-* Several code refactorings
-* Fix OrthancCppClient::GetVoxelSizeZ()
-
-
-Version 0.7.6 (2014/06/11)
-==========================
-
-* Support of JPEG and JPEG-LS decompression
-* Download DICOM images as Matlab/Octave arrays
-* Precompiled headers for Microsoft Visual Studio
-
-
-Version 0.7.5 (2014/05/08)
-==========================
-
-* Dynamic negotiation of SOP classes for C-STORE SCU
-* Creation of DICOM instances using the REST API
-* Embedding of images within DICOM instances
-* Adding/removal/modification of remote modalities/peers through REST
-* Reuse of the previous SCU connection to avoid unnecessary handshakes
-* Fix problems with anonymization and modification
-* Fix missing licensing terms about reuse of some code from DCMTK
-* Various code refactorings
-
-
-Version 0.7.4 (2014/04/16)
-==========================
-
-* Switch to openssl-1.0.1g in static builds (cf. Heartbleed exploit)
-* Switch to boost 1.55.0 in static builds (to solve compiling errors)
-* Better logging about nonexistent tags
-* Dcm4Chee manufacturer
-* Automatic discovering of the path to the DICOM dictionaries
-* In the "DicomModalities" config, the port number can be a string
-
-
-Version 0.7.3 (2014/02/14)
-==========================
-
-Major changes
--------------
-
-* Fixes in the implementation of the C-FIND handler for Query/Retrieve
-* Custom attachment of files to patients, studies, series or instances
-* Access to lowlevel info about the attached files through the REST API
-* Recover pixel data for more transfer syntaxes (notably JPEG)
-
-Minor changes
--------------
-
-* AET comparison is now case-insensitive by default
-* Possibility to disable the HTTP server or the DICOM server
-* Automatic computation of MD5 hashes for the stored DICOM files
-* Maintenance tool to recover DICOM files compressed by Orthanc
-* The newline characters in the configuration file are fixed for GNU/Linux
-* Capture of the SIGTERM signal in GNU/Linux
-
-
-Version 0.7.2 (2013/11/08)
-==========================
-
-* Support of Query/Retrieve from medInria
-* Accept more transfer syntaxes for C-STORE SCP and SCU (notably JPEG)
-* Create the meta-header when receiving files through C-STORE SCP
-* Fixes and improvements thanks to the static analyzer cppcheck
-
-
-Version 0.7.1 (2013/10/30)
-==========================
-
-* Use ZIP64 only when required to improve compatibility (cf. issue #7)
-* Refactoring of the CMake options
-* Fix for big-endian architectures (RedHat bug #985748)
-* Use filenames with 8 characters in ZIP files for maximum compatibility
-* Possibility to build Orthanc inplace (in the source directory)
-
-
-Version 0.7.0 (2013/10/25)
-==========================
-
-Major changes
--------------
-
-* DICOM Query/Retrieve is supported
-
-Minor changes
--------------
-
-* Possibility to keep the PatientID during an anonymization
-* Check whether "unzip", "tar" and/or "7-zip" are installed from CMake
-
-
-Version 0.6.2 (2013/10/04)
-==========================
-
-* Build of the C++ client as a shared library
-* Improvements and documentation of the C++ client API
-* Fix of Debian bug #724947 (licensing issue with the SHA-1 library)
-* Switch to Boost 1.54.0 (cf. issue #9)
-* "make uninstall" is now possible
-
-
-Version 0.6.1 (2013/09/16)
-==========================
-
-* Detection of stable patients/studies/series
-* C-FIND SCU at the instance level
-* Link from modified to original resource in Orthanc Explorer
-* Fix of issue #8
-* Anonymization of the medical alerts tag (0010,2000)
-
-
-Version 0.6.0 (2013/07/16)
-==========================
-
-Major changes
--------------
-
-* Introduction of the C++ client
-* Send DICOM resources to other Orthanc instances through HTTP
-* Access to signed images (instances/.../image-int16)
-  (Closes: Debian #716958)
-
-Minor changes
--------------
-
-* Export of DICOM files to the host filesystem (instances/.../export)
-* Statistics about patients, studies, series and instances
-* Link from anonymized to original resource in Orthanc Explorer
-* Fixes for Red Hat and Debian packaging
-* Fixes for history in Orthanc Explorer
-* Fixes for boost::thread, as reported by Cyril Paulus
-* Fix licensing (Closes: Debian #712038)
-
-Metadata
---------
-
-* Access to the metadata through the REST API (.../metadata)
-* Support of user-defined metadata
-* "LastUpdate" metadata for patients, studies and series
-* "/tools/now" to be used in combination with "LastUpdate"
-* Improved support of series with temporal positions
-
-
-Version 0.5.2 (2013/05/07)
-==========================
-
-* "Bulk" Store-SCU (send several DICOM instances with the same
-  DICOM connection)
-* Store-SCU for patients and studies in Orthanc Explorer
-* Filtering of incoming DICOM instances (through Lua scripting)
-* Filtering of incoming HTTP requests (through Lua scripting)
-* Clearing of "/exports" and "/changes"
-* Check MD5 of third party downloads
-* Faking of the HTTP methods PUT and DELETE
-
-
-Version 0.5.1 (2013/04/17)
-==========================
-
-* Support of RGB images
-* Fix of store SCU in release builds
-* Possibility to store the SQLite index at another place than the
-  DICOM instances (for performance)
-
-
-Version 0.5.0 (2013/01/31)
-==========================
-
-Major changes
--------------
-
-* Download of modified or anonymized DICOM instances
-* Inplace modification and anonymization of DICOM series, studies and patients
-
-Minor changes
--------------
-
-* Support of private tags
-* Implementation of the PMSCT_RLE1 image decoding for Philips modalities
-* Generation of random DICOM UID through the REST API (/tools/generate-uid)
-
-
-Version 0.4.0 (2012/12/14)
-==========================
-
-Major changes
--------------
-
-* Recycling of disk space
-* Raw access to the value of the DICOM tags in the REST API
-
-Minor changes
--------------
-
-* Protection of patients against recycling (also in Orthanc Explorer)
-* The DICOM dictionaries are embedded in Windows builds
-
-
-Version 0.3.1 (2012/12/05)
-==========================
-
-* Download archives of patients, studies and series as ZIP files
-* Orthanc now checks the version of its database schema before starting
-
-
-Version 0.3.0 (2012/11/30)
-==========================
-
-Major changes
--------------
-
-* Transparent compression of the DICOM instances on the disk
-* The patient/study/series/instances are now indexed by SHA-1 digests
-  of their DICOM Instance IDs (and not by UUIDs anymore): The same
-  DICOM objects are thus always identified by the same Orthanc IDs
-* Log of exported instances through DICOM C-STORE SCU ("/exported" URI)
-* Full refactoring of the DB schema and of the REST API
-* Introduction of generic classes for REST APIs (in Core/RestApi)
-
-Minor changes
--------------
-
-* "/statistics" URI
-* "last" flag to retrieve the last change from the "/changes" URI
-* Generate a sample configuration file from command line
-* "CompletedSeries" event in the changes API
-* Thread to continuously flush DB to disk (SQLite checkpoints for
-  improved robustness)
-
-
-Version 0.2.3 (2012/10/26)
-==========================
-
-* Use HTTP Content-Disposition to set a filename when downloading JSON/DCM
-* URI "/system" for general information about Orthanc
-* Versioning info and help on the command line
-* Improved logging
-* Possibility of dynamic linking against jsoncpp, sqlite, boost and dmctk
-  for Debian packaging
-* Fix some bugs
-* Switch to default 8042 port for HTTP
-
-
-Version 0.2.2 (2012/10/04)
-==========================
-
-* Switch to Google Log
-* Fixes to Debian packaging
-
-
-Version 0.2.1 (2012/09/28)
-==========================
-
-* Status of series
-* Continuous Integration Server is up and running
-* Ready for Debian packaging
-
-
-Version 0.2.0 (2012/09/16)
-==========================
-
-Major changes
--------------
-
-* Renaming to "Orthanc"
-* Focus on security: Support of SSL, HTTP Basic Authentication and
-  interdiction of remote access
-* Access to multi-frame images (for nuclear medicine)
-* Access to the raw PNG images (in 8bpp and 16bpp)
-
-Minor changes
--------------
-
-* Change of the licensing of the "Core/SQLite" folder to BSD (to
-  reflect the original licensing terms of Chromium, from which the
-  code derives)
-* Standalone build for cross-compilation
-
-
-Version 0.1.1 (2012/07/20)
-==========================
-
-* Fix Windows version
-* Native Windows build with Microsoft Visual Studio 2005
-* Add path to storage in Configuration.json
-
-
-Version 0.1.0 (2012/07/19)
-==========================
-
-* Initial release
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomDatasetReader.h"
-
-#include "OrthancPluginException.h"
-
-#include <boost/lexical_cast.hpp>
-
-namespace OrthancPlugins
-{
-  // This function is copied-pasted from "../../../Core/Toolbox.cpp",
-  // in order to avoid the dependency of plugins against the Orthanc core
-  static std::string StripSpaces(const std::string& source)
-  {
-    size_t first = 0;
-
-    while (first < source.length() &&
-           isspace(source[first]))
-    {
-      first++;
-    }
-
-    if (first == source.length())
-    {
-      // String containing only spaces
-      return "";
-    }
-
-    size_t last = source.length();
-    while (last > first &&
-           isspace(source[last - 1]))
-    {
-      last--;
-    }          
-    
-    assert(first <= last);
-    return source.substr(first, last - first);
-  }
-
-
-  DicomDatasetReader::DicomDatasetReader(const IDicomDataset& dataset) :
-    dataset_(dataset)
-  {
-  }
-  
-
-  std::string DicomDatasetReader::GetStringValue(const DicomPath& path,
-                                                 const std::string& defaultValue) const
-  {
-    std::string s;
-    if (dataset_.GetStringValue(s, path))
-    {
-      return s;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  std::string DicomDatasetReader::GetMandatoryStringValue(const DicomPath& path) const
-  {
-    std::string s;
-    if (dataset_.GetStringValue(s, path))
-    {
-      return s;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentTag);
-    }
-  }
-
-
-  template <typename T>
-  static bool GetValueInternal(T& target,
-                               const IDicomDataset& dataset,
-                               const DicomPath& path)
-  {
-    try
-    {
-      std::string s;
-
-      if (dataset.GetStringValue(s, path))
-      {
-        target = boost::lexical_cast<T>(StripSpaces(s));
-        return true;
-      }
-      else
-      {
-        return false;
-      }
-    }
-    catch (boost::bad_lexical_cast&)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);        
-    }
-  }
-
-
-  bool DicomDatasetReader::GetIntegerValue(int& target,
-                                           const DicomPath& path) const
-  {
-    return GetValueInternal<int>(target, dataset_, path);
-  }
-
-
-  bool DicomDatasetReader::GetUnsignedIntegerValue(unsigned int& target,
-                                                   const DicomPath& path) const
-  {
-    int value;
-
-    if (!GetIntegerValue(value, path))
-    {
-      return false;
-    }
-    else if (value >= 0)
-    {
-      target = static_cast<unsigned int>(value);
-      return true;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  bool DicomDatasetReader::GetFloatValue(float& target,
-                                         const DicomPath& path) const
-  {
-    return GetValueInternal<float>(target, dataset_, path);
-  }
-
-
-  bool DicomDatasetReader::GetDoubleValue(double& target,
-                                          const DicomPath& path) const
-  {
-    return GetValueInternal<double>(target, dataset_, path);
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "IDicomDataset.h"
-
-#include <memory>
-#include <vector>
-
-namespace OrthancPlugins
-{
-  class DicomDatasetReader : public boost::noncopyable
-  {
-  private:
-    const IDicomDataset&  dataset_;
-
-  public:
-    DicomDatasetReader(const IDicomDataset& dataset);
-
-    const IDicomDataset& GetDataset() const
-    {
-      return dataset_;
-    }
-
-    std::string GetStringValue(const DicomPath& path,
-                               const std::string& defaultValue) const;
-
-    std::string GetMandatoryStringValue(const DicomPath& path) const;
-
-    bool GetIntegerValue(int& target,
-                         const DicomPath& path) const;
-
-    bool GetUnsignedIntegerValue(unsigned int& target,
-                                 const DicomPath& path) const;
-
-    bool GetFloatValue(float& target,
-                       const DicomPath& path) const;
-
-    bool GetDoubleValue(double& target,
-                        const DicomPath& path) const;
-  };
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomPath.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomPath.h"
-
-#include "OrthancPluginException.h"
-
-namespace OrthancPlugins
-{
-  const DicomPath::Prefix& DicomPath::GetPrefixItem(size_t depth) const
-  {
-    if (depth >= prefix_.size())
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-    else
-    {
-      return prefix_[depth];
-    }
-  }
-
-
-  DicomPath::DicomPath(const DicomTag& sequence,
-                       size_t index,
-                       const DicomTag& tag) :
-    finalTag_(tag)
-  {
-    AddToPrefix(sequence, index);
-  }
-
-
-  DicomPath::DicomPath(const DicomTag& sequence1,
-                       size_t index1,
-                       const DicomTag& sequence2,
-                       size_t index2,
-                       const DicomTag& tag) :
-    finalTag_(tag)
-  {
-    AddToPrefix(sequence1, index1);
-    AddToPrefix(sequence2, index2);
-  }
-
-
-  DicomPath::DicomPath(const DicomTag& sequence1,
-                       size_t index1,
-                       const DicomTag& sequence2,
-                       size_t index2,
-                       const DicomTag& sequence3,
-                       size_t index3,
-                       const DicomTag& tag) :
-    finalTag_(tag)
-  {
-    AddToPrefix(sequence1, index1);
-    AddToPrefix(sequence2, index2);
-    AddToPrefix(sequence3, index3);
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomPath.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomTag.h"
-
-#include <vector>
-#include <stddef.h>
-
-namespace OrthancPlugins
-{
-  class DicomPath
-  {
-  private:
-    typedef std::pair<DicomTag, size_t>  Prefix;
-
-    std::vector<Prefix>  prefix_;
-    DicomTag             finalTag_;
-
-    const Prefix& GetPrefixItem(size_t depth) const;
-
-  public:
-    DicomPath(const DicomTag& finalTag) :
-    finalTag_(finalTag)
-    {
-    }
-
-    DicomPath(const DicomTag& sequence,
-              size_t index,
-              const DicomTag& tag);
-
-    DicomPath(const DicomTag& sequence1,
-              size_t index1,
-              const DicomTag& sequence2,
-              size_t index2,
-              const DicomTag& tag);
-
-    DicomPath(const DicomTag& sequence1,
-              size_t index1,
-              const DicomTag& sequence2,
-              size_t index2,
-              const DicomTag& sequence3,
-              size_t index3,
-              const DicomTag& tag);
-
-    void AddToPrefix(const DicomTag& tag,
-                     size_t position)
-    {
-      prefix_.push_back(std::make_pair(tag, position));
-    }
-
-    size_t GetPrefixLength() const
-    {
-      return prefix_.size();
-    }
-    
-    DicomTag GetPrefixTag(size_t depth) const
-    {
-      return GetPrefixItem(depth).first;
-    }
-
-    size_t GetPrefixIndex(size_t depth) const
-    {
-      return GetPrefixItem(depth).second;
-    }
-    
-    const DicomTag& GetFinalTag() const
-    {
-      return finalTag_;
-    }
-
-    void SetFinalTag(const DicomTag& tag)
-    {
-      finalTag_ = tag;
-    }
-  };
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomTag.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomTag.h"
-
-#include "OrthancPluginException.h"
-
-namespace OrthancPlugins
-{
-  const char* DicomTag::GetName() const
-  {
-    if (*this == DICOM_TAG_BITS_STORED)
-    {
-      return "BitsStored";
-    }
-    else if (*this == DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX)
-    {
-      return "ColumnPositionInTotalImagePixelMatrix";
-    }
-    else if (*this == DICOM_TAG_COLUMNS)
-    {
-      return "Columns";
-    }
-    else if (*this == DICOM_TAG_MODALITY)
-    {
-      return "Modality";
-    }
-    else if (*this == DICOM_TAG_NUMBER_OF_FRAMES)
-    {
-      return "NumberOfFrames";
-    }
-    else if (*this == DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE)
-    {
-      return "PerFrameFunctionalGroupsSequence";
-    }
-    else if (*this == DICOM_TAG_PHOTOMETRIC_INTERPRETATION)
-    {
-      return "PhotometricInterpretation";
-    }
-    else if (*this == DICOM_TAG_PIXEL_REPRESENTATION)
-    {
-      return "PixelRepresentation";
-    }
-    else if (*this == DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE)
-    {
-      return "PlanePositionSlideSequence";
-    }
-    else if (*this == DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX)
-    {
-      return "RowPositionInTotalImagePixelMatrix";
-    }
-    else if (*this == DICOM_TAG_ROWS)
-    {
-      return "Rows";
-    }
-    else if (*this == DICOM_TAG_SOP_CLASS_UID)
-    {
-      return "SOPClassUID";
-    }
-    else if (*this == DICOM_TAG_SAMPLES_PER_PIXEL)
-    {
-      return "SamplesPerPixel";
-    }
-    else if (*this == DICOM_TAG_TOTAL_PIXEL_MATRIX_COLUMNS)
-    {
-      return "TotalPixelMatrixColumns";
-    }
-    else if (*this == DICOM_TAG_TOTAL_PIXEL_MATRIX_ROWS)
-    {
-      return "TotalPixelMatrixRows";
-    }
-    else if (*this == DICOM_TAG_TRANSFER_SYNTAX_UID)
-    {
-      return "TransferSyntaxUID";
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NotImplemented);
-    }
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/DicomTag.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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>
-
-namespace OrthancPlugins
-{
-  class DicomTag
-  {
-  private:
-    uint16_t  group_;
-    uint16_t  element_;
-
-    DicomTag();  // Forbidden
-
-  public:
-    DicomTag(uint16_t group,
-             uint16_t element) :
-      group_(group),
-      element_(element)
-    {
-    }
-
-    uint16_t GetGroup() const
-    {
-      return group_;
-    }
-
-    uint16_t GetElement() const
-    {
-      return element_;
-    }
-
-    const char* GetName() const;
-
-    bool operator== (const DicomTag& other) const
-    {
-      return group_ == other.group_ && element_ == other.element_;
-    }
-
-    bool operator!= (const DicomTag& other) const
-    {
-      return !(*this == other);
-    }
-  };
-
-
-  static const DicomTag DICOM_TAG_BITS_STORED(0x0028, 0x0101);
-  static const DicomTag DICOM_TAG_COLUMNS(0x0028, 0x0011);
-  static const DicomTag DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021e);
-  static const DicomTag DICOM_TAG_IMAGE_ORIENTATION_PATIENT(0x0020, 0x0037);
-  static const DicomTag DICOM_TAG_IMAGE_POSITION_PATIENT(0x0020, 0x0032);
-  static const DicomTag DICOM_TAG_MODALITY(0x0008, 0x0060);
-  static const DicomTag DICOM_TAG_NUMBER_OF_FRAMES(0x0028, 0x0008);
-  static const DicomTag DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE(0x5200, 0x9230);
-  static const DicomTag DICOM_TAG_PHOTOMETRIC_INTERPRETATION(0x0028, 0x0004);
-  static const DicomTag DICOM_TAG_PIXEL_REPRESENTATION(0x0028, 0x0103);
-  static const DicomTag DICOM_TAG_PIXEL_SPACING(0x0028, 0x0030);
-  static const DicomTag DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE(0x0048, 0x021a);
-  static const DicomTag DICOM_TAG_RESCALE_INTERCEPT(0x0028, 0x1052);
-  static const DicomTag DICOM_TAG_RESCALE_SLOPE(0x0028, 0x1053);
-  static const DicomTag DICOM_TAG_ROWS(0x0028, 0x0010);
-  static const DicomTag DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021f);
-  static const DicomTag DICOM_TAG_SAMPLES_PER_PIXEL(0x0028, 0x0002);
-  static const DicomTag DICOM_TAG_SERIES_INSTANCE_UID(0x0020, 0x000e);
-  static const DicomTag DICOM_TAG_SLICE_THICKNESS(0x0018, 0x0050);
-  static const DicomTag DICOM_TAG_SOP_CLASS_UID(0x0008, 0x0016);
-  static const DicomTag DICOM_TAG_SOP_INSTANCE_UID(0x0008, 0x0018);
-  static const DicomTag DICOM_TAG_TOTAL_PIXEL_MATRIX_COLUMNS(0x0048, 0x0006);
-  static const DicomTag DICOM_TAG_TOTAL_PIXEL_MATRIX_ROWS(0x0048, 0x0007);
-  static const DicomTag DICOM_TAG_TRANSFER_SYNTAX_UID(0x0002, 0x0010);
-  static const DicomTag DICOM_TAG_WINDOW_CENTER(0x0028, 0x1050);
-  static const DicomTag DICOM_TAG_WINDOW_WIDTH(0x0028, 0x1051);
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/ExportedSymbols.list	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-# This is the list of the symbols that must be exported by Orthanc
-# plugins, if targeting OS X
-
-_OrthancPluginInitialize
-_OrthancPluginFinalize
-_OrthancPluginGetName
-_OrthancPluginGetVersion
--- a/Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "FullOrthancDataset.h"
-
-#include "OrthancPluginException.h"
-
-#include <stdio.h>
-#include <cassert>
-
-namespace OrthancPlugins
-{
-  static const Json::Value* AccessTag(const Json::Value& dataset,
-                                      const DicomTag& tag) 
-  {
-    if (dataset.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    char name[16];
-    sprintf(name, "%04x,%04x", tag.GetGroup(), tag.GetElement());
-
-    if (!dataset.isMember(name))
-    {
-      return NULL;
-    }
-
-    const Json::Value& value = dataset[name];
-    if (value.type() != Json::objectValue ||
-        !value.isMember("Name") ||
-        !value.isMember("Type") ||
-        !value.isMember("Value") ||
-        value["Name"].type() != Json::stringValue ||
-        value["Type"].type() != Json::stringValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    return &value;
-  }
-
-
-  static const Json::Value& GetSequenceContent(const Json::Value& sequence)
-  {
-    assert(sequence.type() == Json::objectValue);
-    assert(sequence.isMember("Type"));
-    assert(sequence.isMember("Value"));
-
-    const Json::Value& value = sequence["Value"];
-      
-    if (sequence["Type"].asString() != "Sequence" ||
-        value.type() != Json::arrayValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-    else
-    {
-      return value;
-    }
-  }
-
-
-  static bool GetStringInternal(std::string& result,
-                                const Json::Value& tag)
-  {
-    assert(tag.type() == Json::objectValue);
-    assert(tag.isMember("Type"));
-    assert(tag.isMember("Value"));
-
-    const Json::Value& value = tag["Value"];
-      
-    if (tag["Type"].asString() != "String" ||
-        value.type() != Json::stringValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-    else
-    {
-      result = value.asString();
-      return true;
-    }
-  }
-
-
-  const Json::Value* FullOrthancDataset::LookupPath(const DicomPath& path) const
-  {
-    const Json::Value* content = &root_;
-                                  
-    for (unsigned int depth = 0; depth < path.GetPrefixLength(); depth++)
-    {
-      const Json::Value* sequence = AccessTag(*content, path.GetPrefixTag(depth));
-      if (sequence == NULL)
-      {
-        return NULL;
-      }
-
-      const Json::Value& nextContent = GetSequenceContent(*sequence);
-
-      size_t index = path.GetPrefixIndex(depth);
-      if (index >= nextContent.size())
-      {
-        return NULL;
-      }
-      else
-      {
-        content = &nextContent[static_cast<Json::Value::ArrayIndex>(index)];
-      }
-    }
-
-    return AccessTag(*content, path.GetFinalTag());
-  }
-
-
-  void FullOrthancDataset::CheckRoot() const
-  {
-    if (root_.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  FullOrthancDataset::FullOrthancDataset(IOrthancConnection& orthanc,
-                                         const std::string& uri)
-  {
-    IOrthancConnection::RestApiGet(root_, orthanc, uri);
-    CheckRoot();
-  }
-
-
-  FullOrthancDataset::FullOrthancDataset(const std::string& content)
-  {
-    IOrthancConnection::ParseJson(root_, content);
-    CheckRoot();
-  }
-
-
-  FullOrthancDataset::FullOrthancDataset(const void* content,
-                                         size_t size)
-  {
-    IOrthancConnection::ParseJson(root_, content, size);
-    CheckRoot();
-  }
-
-
-  FullOrthancDataset::FullOrthancDataset(const Json::Value& root) :
-    root_(root)
-  {
-    CheckRoot();
-  }
-
-
-  bool FullOrthancDataset::GetStringValue(std::string& result,
-                                          const DicomPath& path) const
-  {
-    const Json::Value* value = LookupPath(path);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      return GetStringInternal(result, *value);
-    }
-  }
-
-
-  bool FullOrthancDataset::GetSequenceSize(size_t& size,
-                                           const DicomPath& path) const
-  {
-    const Json::Value* sequence = LookupPath(path);
-
-    if (sequence == NULL)
-    {
-      return false;
-    }
-    else
-    {
-      size = GetSequenceContent(*sequence).size();
-      return true;
-    }
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "IOrthancConnection.h"
-#include "IDicomDataset.h"
-
-#include <json/value.h>
-
-namespace OrthancPlugins
-{
-  class FullOrthancDataset : public IDicomDataset
-  {
-  private:
-    Json::Value   root_;
-
-    const Json::Value* LookupPath(const DicomPath& path) const;
-
-    void CheckRoot() const;
-
-  public:
-    FullOrthancDataset(IOrthancConnection& orthanc,
-                       const std::string& uri);
-
-    FullOrthancDataset(const std::string& content);
-
-    FullOrthancDataset(const void* content,
-                       size_t size);
-
-    FullOrthancDataset(const Json::Value& root);
-
-    virtual bool GetStringValue(std::string& result,
-                                const DicomPath& path) const;
-
-    virtual bool GetSequenceSize(size_t& size,
-                                 const DicomPath& path) const;
-  };
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/IDicomDataset.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomPath.h"
-
-#include <boost/noncopyable.hpp>
-#include <string>
-
-namespace OrthancPlugins
-{
-  class IDicomDataset : public boost::noncopyable
-  {
-  public:
-    virtual ~IDicomDataset()
-    {
-    }
-
-    virtual bool GetStringValue(std::string& result,
-                                const DicomPath& path) const = 0;
-
-    virtual bool GetSequenceSize(size_t& size,
-                                 const DicomPath& path) const = 0;
-  };
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "IOrthancConnection.h"
-
-#include "OrthancPluginException.h"
-
-#include <json/reader.h>
-
-namespace OrthancPlugins
-{
-  void IOrthancConnection::ParseJson(Json::Value& result,
-                                     const std::string& content)
-  {
-    Json::Reader reader;
-    
-    if (!reader.parse(content, result))
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  void IOrthancConnection::ParseJson(Json::Value& result,
-                                     const void* content,
-                                     size_t size)
-  {
-    Json::Reader reader;
-    
-    if (!reader.parse(reinterpret_cast<const char*>(content),
-                      reinterpret_cast<const char*>(content) + size, result))
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  void IOrthancConnection::RestApiGet(Json::Value& result,
-                                      IOrthancConnection& orthanc,
-                                      const std::string& uri)
-  {
-    std::string content;
-    orthanc.RestApiGet(content, uri);
-    ParseJson(result, content);
-  }
-
-
-  void IOrthancConnection::RestApiPost(Json::Value& result,
-                                       IOrthancConnection& orthanc,
-                                       const std::string& uri,
-                                       const std::string& body)
-  {
-    std::string content;
-    orthanc.RestApiPost(content, uri, body);
-    ParseJson(result, content);
-  }
-
-
-  void IOrthancConnection::RestApiPut(Json::Value& result,
-                                      IOrthancConnection& orthanc,
-                                      const std::string& uri,
-                                      const std::string& body)
-  {
-    std::string content;
-    orthanc.RestApiPut(content, uri, body);
-    ParseJson(result, content);
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "DicomPath.h"
-
-#include <boost/noncopyable.hpp>
-#include <string>
-#include <json/value.h>
-
-namespace OrthancPlugins
-{
-  class IOrthancConnection : public boost::noncopyable
-  {
-  public:
-    virtual ~IOrthancConnection()
-    {
-    }
-
-    virtual void RestApiGet(std::string& result,
-                            const std::string& uri) = 0;
-
-    virtual void RestApiPost(std::string& result,
-                             const std::string& uri,
-                             const std::string& body) = 0;
-
-    virtual void RestApiPut(std::string& result,
-                            const std::string& uri,
-                            const std::string& body) = 0;
-
-    virtual void RestApiDelete(const std::string& uri) = 0;
-
-    static void ParseJson(Json::Value& result,
-                          const std::string& content);
-
-    static void ParseJson(Json::Value& result,
-                          const void* content,
-                          size_t size);
-
-    static void RestApiGet(Json::Value& result,
-                           IOrthancConnection& orthanc,
-                           const std::string& uri);
-
-    static void RestApiPost(Json::Value& result,
-                            IOrthancConnection& orthanc,
-                            const std::string& uri,
-                            const std::string& body);
-
-    static void RestApiPut(Json::Value& result,
-                           IOrthancConnection& orthanc,
-                           const std::string& uri,
-                           const std::string& body);
-  };
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "OrthancHttpConnection.h"
-
-namespace OrthancPlugins
-{
-  void OrthancHttpConnection::Setup()
-  {
-    url_ = client_.GetUrl();
-
-    // Don't follow 3xx HTTP (avoid redirections to "unsupported.png" in Orthanc)
-    client_.SetRedirectionFollowed(false);  
-  }
-
-
-  OrthancHttpConnection::OrthancHttpConnection() :
-    client_(Orthanc::WebServiceParameters(), "")
-  {
-    Setup();
-  }
-
-
-  OrthancHttpConnection::OrthancHttpConnection(const Orthanc::WebServiceParameters& parameters) :
-    client_(parameters, "")
-  {
-    Setup();
-  }
-
-
-  void OrthancHttpConnection::RestApiGet(std::string& result,
-                                         const std::string& uri)
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    client_.SetMethod(Orthanc::HttpMethod_Get);
-    client_.SetUrl(url_ + uri);
-    client_.ApplyAndThrowException(result);
-  }
-
-
-  void OrthancHttpConnection::RestApiPost(std::string& result,
-                                          const std::string& uri,
-                                          const std::string& body)
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    client_.SetMethod(Orthanc::HttpMethod_Post);
-    client_.SetUrl(url_ + uri);
-    client_.SetBody(body);
-    client_.ApplyAndThrowException(result);
-  }
-
-
-  void OrthancHttpConnection::RestApiPut(std::string& result,
-                                         const std::string& uri,
-                                         const std::string& body)
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    client_.SetMethod(Orthanc::HttpMethod_Put);
-    client_.SetUrl(url_ + uri);
-    client_.SetBody(body);
-    client_.ApplyAndThrowException(result);
-  }
-
-
-  void OrthancHttpConnection::RestApiDelete(const std::string& uri)
-  {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    std::string result;
-
-    client_.SetMethod(Orthanc::HttpMethod_Delete);
-    client_.SetUrl(url_ + uri);
-    client_.ApplyAndThrowException(result);
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancHttpConnection.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "IOrthancConnection.h"
-
-#if HAS_ORTHANC_EXCEPTION != 1
-#  error The macro HAS_ORTHANC_EXCEPTION must be set to 1 if using this header
-#endif
-
-#include "../../../Core/HttpClient.h"
-
-#include <boost/thread/mutex.hpp>
-
-namespace OrthancPlugins
-{
-  // This class is thread-safe
-  class OrthancHttpConnection : public IOrthancConnection
-  {
-  private:
-    boost::mutex         mutex_;
-    Orthanc::HttpClient  client_;
-    std::string          url_;
-
-    void Setup();
-
-  public:
-    OrthancHttpConnection();
-
-    OrthancHttpConnection(const Orthanc::WebServiceParameters& parameters);
-
-    virtual void RestApiGet(std::string& result,
-                            const std::string& uri);
-
-    virtual void RestApiPost(std::string& result,
-                             const std::string& uri,
-                             const std::string& body);
-
-    virtual void RestApiPut(std::string& result,
-                            const std::string& uri,
-                            const std::string& body);
-
-    virtual void RestApiDelete(const std::string& uri);
-  };
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginConnection.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "OrthancPluginConnection.h"
-
-#include "OrthancPluginCppWrapper.h"
-
-namespace OrthancPlugins
-{
-  void OrthancPluginConnection::RestApiGet(std::string& result,
-                                           const std::string& uri) 
-  {
-    OrthancPlugins::MemoryBuffer buffer(context_);
-
-    if (buffer.RestApiGet(uri, false))
-    {
-      buffer.ToString(result);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
-    }
-  }
-
-
-  void OrthancPluginConnection::RestApiPost(std::string& result,
-                                            const std::string& uri,
-                                            const std::string& body)
-  {
-    OrthancPlugins::MemoryBuffer buffer(context_);
-
-    if (buffer.RestApiPost(uri, body.c_str(), body.size(), false))
-    {
-      buffer.ToString(result);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
-    }
-  }
-
-
-  void OrthancPluginConnection::RestApiPut(std::string& result,
-                                           const std::string& uri,
-                                           const std::string& body)
-  {
-    OrthancPlugins::MemoryBuffer buffer(context_);
-
-    if (buffer.RestApiPut(uri, body.c_str(), body.size(), false))
-    {
-      buffer.ToString(result);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
-    }
-  }
-
-
-  void OrthancPluginConnection::RestApiDelete(const std::string& uri)
-  {
-    OrthancPlugins::MemoryBuffer buffer(context_);
-
-    if (!::OrthancPlugins::RestApiDelete(context_, uri, false))
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
-    }
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginConnection.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "IOrthancConnection.h"
-
-#include <orthanc/OrthancCPlugin.h>
-
-namespace OrthancPlugins
-{
-  // This class is thread-safe
-  class OrthancPluginConnection : public IOrthancConnection
-  {
-  private:
-    OrthancPluginContext*   context_;
-
-  public:
-    OrthancPluginConnection(OrthancPluginContext* context) :
-    context_(context)
-    {
-    }
-
-    virtual void RestApiGet(std::string& result,
-                            const std::string& uri);
-
-    virtual void RestApiPost(std::string& result,
-                             const std::string& uri,
-                             const std::string& body);
-
-    virtual void RestApiPut(std::string& result,
-                            const std::string& uri,
-                            const std::string& body);
-
-    virtual void RestApiDelete(const std::string& uri);
-  };
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1222 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "OrthancPluginCppWrapper.h"
-
-#include <json/reader.h>
-#include <json/writer.h>
-
-
-namespace OrthancPlugins
-{
-  void MemoryBuffer::Check(OrthancPluginErrorCode code)
-  {
-    if (code != OrthancPluginErrorCode_Success)
-    {
-      // Prevent using garbage information
-      buffer_.data = NULL;
-      buffer_.size = 0;
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-
-
-  bool MemoryBuffer::CheckHttp(OrthancPluginErrorCode code)
-  {
-    if (code != OrthancPluginErrorCode_Success)
-    {
-      // Prevent using garbage information
-      buffer_.data = NULL;
-      buffer_.size = 0;
-    }
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (code == OrthancPluginErrorCode_UnknownResource ||
-             code == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-
-
-  MemoryBuffer::MemoryBuffer(OrthancPluginContext* context) : 
-    context_(context)
-  {
-    buffer_.data = NULL;
-    buffer_.size = 0;
-  }
-
-
-  void MemoryBuffer::Clear()
-  {
-    if (buffer_.data != NULL)
-    {
-      OrthancPluginFreeMemoryBuffer(context_, &buffer_);
-      buffer_.data = NULL;
-      buffer_.size = 0;
-    }
-  }
-
-
-  void MemoryBuffer::Assign(OrthancPluginMemoryBuffer& other)
-  {
-    Clear();
-
-    buffer_.data = other.data;
-    buffer_.size = other.size;
-
-    other.data = NULL;
-    other.size = 0;
-  }
-
-
-  void MemoryBuffer::ToString(std::string& target) const
-  {
-    if (buffer_.size == 0)
-    {
-      target.clear();
-    }
-    else
-    {
-      target.assign(reinterpret_cast<const char*>(buffer_.data), buffer_.size);
-    }
-  }
-
-
-  void MemoryBuffer::ToJson(Json::Value& target) const
-  {
-    if (buffer_.data == NULL ||
-        buffer_.size == 0)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    const char* tmp = reinterpret_cast<const char*>(buffer_.data);
-
-    Json::Reader reader;
-    if (!reader.parse(tmp, tmp + buffer_.size, target))
-    {
-      OrthancPluginLogError(context_, "Cannot convert some memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiGet(const std::string& uri,
-                                bool applyPlugins)
-  {
-    Clear();
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiGetAfterPlugins(context_, &buffer_, uri.c_str()));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiGet(context_, &buffer_, uri.c_str()));
-    }
-  }
-
-  
-  bool MemoryBuffer::RestApiPost(const std::string& uri,
-                                 const char* body,
-                                 size_t bodySize,
-                                 bool applyPlugins)
-  {
-    Clear();
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiPostAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiPost(context_, &buffer_, uri.c_str(), body, bodySize));
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiPut(const std::string& uri,
-                                const char* body,
-                                size_t bodySize,
-                                bool applyPlugins)
-  {
-    Clear();
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiPutAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiPut(context_, &buffer_, uri.c_str(), body, bodySize));
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiPost(const std::string& uri,
-                                 const Json::Value& body,
-                                 bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPost(uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool MemoryBuffer::RestApiPut(const std::string& uri,
-                                const Json::Value& body,
-                                bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPut(uri, writer.write(body), applyPlugins);
-  }
-
-
-  void MemoryBuffer::CreateDicom(const Json::Value& tags,
-                                 OrthancPluginCreateDicomFlags flags)
-  {
-    Clear();
-
-    Json::FastWriter writer;
-    std::string s = writer.write(tags);
-    
-    Check(OrthancPluginCreateDicom(context_, &buffer_, s.c_str(), NULL, flags));
-  }
-
-
-  void MemoryBuffer::ReadFile(const std::string& path)
-  {
-    Clear();
-    Check(OrthancPluginReadFile(context_, &buffer_, path.c_str()));
-  }
-
-
-  void MemoryBuffer::GetDicomQuery(const OrthancPluginWorklistQuery* query)
-  {
-    Clear();
-    Check(OrthancPluginWorklistGetDicomQuery(context_, &buffer_, query));
-  }
-
-
-  void OrthancString::Assign(char* str)
-  {
-    if (str == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-    else
-    {
-      Clear();
-      str_ = str;
-    }
-  }
-
-
-  void OrthancString::Clear()
-  {
-    if (str_ != NULL)
-    {
-      OrthancPluginFreeString(context_, str_);
-      str_ = NULL;
-    }
-  }
-
-
-  void OrthancString::ToString(std::string& target) const
-  {
-    if (str_ == NULL)
-    {
-      target.clear();
-    }
-    else
-    {
-      target.assign(str_);
-    }
-  }
-
-
-  void OrthancString::ToJson(Json::Value& target) const
-  {
-    if (str_ == NULL)
-    {
-      OrthancPluginLogError(context_, "Cannot convert an empty memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    Json::Reader reader;
-    if (!reader.parse(str_, target))
-    {
-      OrthancPluginLogError(context_, "Cannot convert some memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-  
-  void MemoryBuffer::DicomToJson(Json::Value& target,
-                                 OrthancPluginDicomToJsonFormat format,
-                                 OrthancPluginDicomToJsonFlags flags,
-                                 uint32_t maxStringLength)
-  {
-    OrthancString str(context_);
-    str.Assign(OrthancPluginDicomBufferToJson(context_, GetData(), GetSize(), format, flags, maxStringLength));
-    str.ToJson(target);
-  }
-
-
-  bool MemoryBuffer::HttpGet(const std::string& url,
-                             const std::string& username,
-                             const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpGet(context_, &buffer_, url.c_str(),
-                                          username.empty() ? NULL : username.c_str(),
-                                          password.empty() ? NULL : password.c_str()));
-  }
-
-  
-  bool MemoryBuffer::HttpPost(const std::string& url,
-                              const std::string& body,
-                              const std::string& username,
-                              const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpPost(context_, &buffer_, url.c_str(),
-                                           body.c_str(), body.size(),
-                                           username.empty() ? NULL : username.c_str(),
-                                           password.empty() ? NULL : password.c_str()));
-  }
-  
- 
-  bool MemoryBuffer::HttpPut(const std::string& url,
-                             const std::string& body,
-                             const std::string& username,
-                             const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpPut(context_, &buffer_, url.c_str(),
-                                          body.empty() ? NULL : body.c_str(),
-                                          body.size(),
-                                          username.empty() ? NULL : username.c_str(),
-                                          password.empty() ? NULL : password.c_str()));
-  }
-  
- 
-  bool HttpDelete(OrthancPluginContext* context_,
-                  const std::string& url,
-                  const std::string& username,
-                  const std::string& password)
-  {
-    OrthancPluginErrorCode error = OrthancPluginHttpDelete
-      (context_, url.c_str(),
-       username.empty() ? NULL : username.c_str(),
-       password.empty() ? NULL : password.c_str());
-  
-    if (error == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (error == OrthancPluginErrorCode_UnknownResource ||
-             error == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-  }
-  
-
-  OrthancConfiguration::OrthancConfiguration(OrthancPluginContext* context) : 
-    context_(context)
-  {
-    OrthancString str(context);
-    str.Assign(OrthancPluginGetConfiguration(context));
-
-    if (str.GetContent() == NULL)
-    {
-      OrthancPluginLogError(context, "Cannot access the Orthanc configuration");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    str.ToJson(configuration_);
-
-    if (configuration_.type() != Json::objectValue)
-    {
-      OrthancPluginLogError(context, "Unable to read the Orthanc configuration");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-
-  OrthancPluginContext* OrthancConfiguration::GetContext() const
-  {
-    if (context_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      return context_;
-    }
-  }
-
-
-  std::string OrthancConfiguration::GetPath(const std::string& key) const
-  {
-    if (path_.empty())
-    {
-      return key;
-    }
-    else
-    {
-      return path_ + "." + key;
-    }
-  }
-
-
-  bool OrthancConfiguration::IsSection(const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    return (configuration_.isMember(key) &&
-            configuration_[key].type() == Json::objectValue);
-  }
-
-
-  void OrthancConfiguration::GetSection(OrthancConfiguration& target,
-                                        const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    target.context_ = context_;
-    target.path_ = GetPath(key);
-
-    if (!configuration_.isMember(key))
-    {
-      target.configuration_ = Json::objectValue;
-    }
-    else
-    {
-      if (configuration_[key].type() != Json::objectValue)
-      {
-        if (context_ != NULL)
-        {
-          std::string s = "The configuration section \"" + target.path_ + "\" is not an associative array as expected";
-          OrthancPluginLogError(context_, s.c_str());
-        }
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-      }
-
-      target.configuration_ = configuration_[key];
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupStringValue(std::string& target,
-                                               const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    if (configuration_[key].type() != Json::stringValue)
-    {
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not a string as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    target = configuration_[key].asString();
-    return true;
-  }
-
-
-  bool OrthancConfiguration::LookupIntegerValue(int& target,
-                                                const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::intValue:
-        target = configuration_[key].asInt();
-        return true;
-        
-      case Json::uintValue:
-        target = configuration_[key].asUInt();
-        return true;
-        
-      default:
-        if (context_ != NULL)
-        {
-          std::string s = "The configuration option \"" + GetPath(key) + "\" is not an integer as expected";
-          OrthancPluginLogError(context_, s.c_str());
-        }
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupUnsignedIntegerValue(unsigned int& target,
-                                                        const std::string& key) const
-  {
-    int tmp;
-    if (!LookupIntegerValue(tmp, key))
-    {
-      return false;
-    }
-
-    if (tmp < 0)
-    {
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not a positive integer as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-    else
-    {
-      target = static_cast<unsigned int>(tmp);
-      return true;
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupBooleanValue(bool& target,
-                                                const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    if (configuration_[key].type() != Json::booleanValue)
-    {
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not a Boolean as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    target = configuration_[key].asBool();
-    return true;
-  }
-
-
-  bool OrthancConfiguration::LookupFloatValue(float& target,
-                                              const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::realValue:
-        target = configuration_[key].asFloat();
-        return true;
-        
-      case Json::intValue:
-        target = static_cast<float>(configuration_[key].asInt());
-        return true;
-        
-      case Json::uintValue:
-        target = static_cast<float>(configuration_[key].asUInt());
-        return true;
-        
-      default:
-        if (context_ != NULL)
-        {
-          std::string s = "The configuration option \"" + GetPath(key) + "\" is not an integer as expected";
-          OrthancPluginLogError(context_, s.c_str());
-        }
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupListOfStrings(std::list<std::string>& target,
-                                                 const std::string& key,
-                                                 bool allowSingleString) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    target.clear();
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::arrayValue:
-      {
-        bool ok = true;
-    
-        for (Json::Value::ArrayIndex i = 0; ok && i < configuration_[key].size(); i++)
-        {
-          if (configuration_[key][i].type() == Json::stringValue)
-          {
-            target.push_back(configuration_[key][i].asString());
-          }
-          else
-          {
-            ok = false;
-          }
-        }
-
-        if (ok)
-        {
-          return true;
-        }
-
-        break;
-      }
-
-      case Json::stringValue:
-        if (allowSingleString)
-        {
-          target.push_back(configuration_[key].asString());
-          return true;
-        }
-
-        break;
-
-      default:
-        break;
-    }
-
-    if (context_ != NULL)
-    {
-      std::string s = ("The configuration option \"" + GetPath(key) +
-                       "\" is not a list of strings as expected");
-      OrthancPluginLogError(context_, s.c_str());
-    }
-
-    ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-  }
-
-
-  bool OrthancConfiguration::LookupSetOfStrings(std::set<std::string>& target,
-                                                const std::string& key,
-                                                bool allowSingleString) const
-  {
-    std::list<std::string> lst;
-
-    if (LookupListOfStrings(lst, key, allowSingleString))
-    {
-      target.clear();
-
-      for (std::list<std::string>::const_iterator
-             it = lst.begin(); it != lst.end(); ++it)
-      {
-        target.insert(*it);
-      }
-
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-  
-  std::string OrthancConfiguration::GetStringValue(const std::string& key,
-                                                   const std::string& defaultValue) const
-  {
-    std::string tmp;
-    if (LookupStringValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  int OrthancConfiguration::GetIntegerValue(const std::string& key,
-                                            int defaultValue) const
-  {
-    int tmp;
-    if (LookupIntegerValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  unsigned int OrthancConfiguration::GetUnsignedIntegerValue(const std::string& key,
-                                                             unsigned int defaultValue) const
-  {
-    unsigned int tmp;
-    if (LookupUnsignedIntegerValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  bool OrthancConfiguration::GetBooleanValue(const std::string& key,
-                                             bool defaultValue) const
-  {
-    bool tmp;
-    if (LookupBooleanValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  float OrthancConfiguration::GetFloatValue(const std::string& key,
-                                            float defaultValue) const
-  {
-    float tmp;
-    if (LookupFloatValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  void OrthancImage::Clear()
-  {
-    if (image_ != NULL)
-    {
-      OrthancPluginFreeImage(context_, image_);
-      image_ = NULL;
-    }
-  }
-
-
-  void OrthancImage::CheckImageAvailable()
-  {
-    if (image_ == NULL)
-    {
-      OrthancPluginLogError(context_, "Trying to access a NULL image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginContext*  context) :
-    context_(context),
-    image_(NULL)
-  {
-    if (context == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginContext*  context,
-                             OrthancPluginImage*    image) :
-    context_(context),
-    image_(image)
-  {
-    if (context == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-  
-
-  OrthancImage::OrthancImage(OrthancPluginContext*     context,
-                             OrthancPluginPixelFormat  format,
-                             uint32_t                  width,
-                             uint32_t                  height) :
-    context_(context)
-  {
-    if (context == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-    else
-    {
-      image_ = OrthancPluginCreateImage(context, format, width, height);
-    }
-  }
-
-
-  void OrthancImage::UncompressPngImage(const void* data,
-                                        size_t size)
-  {
-    Clear();
-    image_ = OrthancPluginUncompressImage(context_, data, size, OrthancPluginImageFormat_Png);
-    if (image_ == NULL)
-    {
-      OrthancPluginLogError(context_, "Cannot uncompress a PNG image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void OrthancImage::UncompressJpegImage(const void* data,
-                                         size_t size)
-  {
-    Clear();
-    image_ = OrthancPluginUncompressImage(context_, data, size, OrthancPluginImageFormat_Jpeg);
-    if (image_ == NULL)
-    {
-      OrthancPluginLogError(context_, "Cannot uncompress a JPEG image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void OrthancImage::DecodeDicomImage(const void* data,
-                                      size_t size,
-                                      unsigned int frame)
-  {
-    Clear();
-    image_ = OrthancPluginDecodeDicomImage(context_, data, size, frame);
-    if (image_ == NULL)
-    {
-      OrthancPluginLogError(context_, "Cannot uncompress a DICOM image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  OrthancPluginPixelFormat OrthancImage::GetPixelFormat()
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImagePixelFormat(context_, image_);
-  }
-
-
-  unsigned int OrthancImage::GetWidth()
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageWidth(context_, image_);
-  }
-
-
-  unsigned int OrthancImage::GetHeight()
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageHeight(context_, image_);
-  }
-
-
-  unsigned int OrthancImage::GetPitch()
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImagePitch(context_, image_);
-  }
-
-    
-  const void* OrthancImage::GetBuffer()
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageBuffer(context_, image_);
-  }
-
-
-  void OrthancImage::CompressPngImage(MemoryBuffer& target)
-  {
-    CheckImageAvailable();
-    
-    OrthancPluginMemoryBuffer tmp;
-    OrthancPluginCompressPngImage(context_, &tmp, GetPixelFormat(), 
-                                  GetWidth(), GetHeight(), GetPitch(), GetBuffer());
-
-    target.Assign(tmp);
-  }
-
-
-  void OrthancImage::CompressJpegImage(MemoryBuffer& target,
-                                       uint8_t quality)
-  {
-    CheckImageAvailable();
-    
-    OrthancPluginMemoryBuffer tmp;
-    OrthancPluginCompressJpegImage(context_, &tmp, GetPixelFormat(), 
-                                   GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
-    
-    target.Assign(tmp);
-  }
-
-
-  void OrthancImage::AnswerPngImage(OrthancPluginRestOutput* output)
-  {
-    CheckImageAvailable();
-    OrthancPluginCompressAndAnswerPngImage(context_, output, GetPixelFormat(),
-                                           GetWidth(), GetHeight(), GetPitch(), GetBuffer());
-  }
-
-
-  void OrthancImage::AnswerJpegImage(OrthancPluginRestOutput* output,
-                                     uint8_t quality)
-  {
-    CheckImageAvailable();
-    OrthancPluginCompressAndAnswerJpegImage(context_, output, GetPixelFormat(),
-                                            GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
-  }
-
-
-
-#if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
-  FindMatcher::FindMatcher(OrthancPluginContext*              context,
-                           const OrthancPluginWorklistQuery*  worklist) :
-    context_(context),
-    matcher_(NULL),
-    worklist_(worklist)
-  {
-    if (worklist_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void FindMatcher::SetupDicom(OrthancPluginContext*  context,
-                               const void*            query,
-                               uint32_t               size)
-  {
-    context_ = context;
-    worklist_ = NULL;
-
-    matcher_ = OrthancPluginCreateFindMatcher(context_, query, size);
-    if (matcher_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-
-  FindMatcher::~FindMatcher()
-  {
-    // The "worklist_" field 
-
-    if (matcher_ != NULL)
-    {
-      OrthancPluginFreeFindMatcher(context_, matcher_);
-    }
-  }
-
-
-
-  bool FindMatcher::IsMatch(const void*  dicom,
-                            uint32_t     size) const
-  {
-    int32_t result;
-
-    if (matcher_ != NULL)
-    {
-      result = OrthancPluginFindMatcherIsMatch(context_, matcher_, dicom, size);
-    }
-    else if (worklist_ != NULL)
-    {
-      result = OrthancPluginWorklistIsMatch(context_, worklist_, dicom, size);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    if (result == 0)
-    {
-      return false;
-    }
-    else if (result == 1)
-    {
-      return true;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-#endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */
-
-
-  bool RestApiGet(Json::Value& result,
-                  OrthancPluginContext* context,
-                  const std::string& uri,
-                  bool applyPlugins)
-  {
-    MemoryBuffer answer(context);
-    if (!answer.RestApiGet(uri, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      answer.ToJson(result);
-      return true;
-    }
-  }
-
-
-  bool RestApiPost(Json::Value& result,
-                   OrthancPluginContext* context,
-                   const std::string& uri,
-                   const char* body,
-                   size_t bodySize,
-                   bool applyPlugins)
-  {
-    MemoryBuffer answer(context);
-    if (!answer.RestApiPost(uri, body, bodySize, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      answer.ToJson(result);
-      return true;
-    }
-  }
-
-
-  bool RestApiPost(Json::Value& result,
-                   OrthancPluginContext* context,
-                   const std::string& uri,
-                   const Json::Value& body,
-                   bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPost(result, context, uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool RestApiPut(Json::Value& result,
-                  OrthancPluginContext* context,
-                  const std::string& uri,
-                  const char* body,
-                  size_t bodySize,
-                  bool applyPlugins)
-  {
-    MemoryBuffer answer(context);
-    if (!answer.RestApiPut(uri, body, bodySize, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      answer.ToJson(result);
-      return true;
-    }
-  }
-
-
-  bool RestApiPut(Json::Value& result,
-                   OrthancPluginContext* context,
-                   const std::string& uri,
-                   const Json::Value& body,
-                   bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPut(result, context, uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool RestApiDelete(OrthancPluginContext* context,
-                     const std::string& uri,
-                     bool applyPlugins)
-  {
-    OrthancPluginErrorCode error;
-
-    if (applyPlugins)
-    {
-      error = OrthancPluginRestApiDeleteAfterPlugins(context, uri.c_str());
-    }
-    else
-    {
-      error = OrthancPluginRestApiDelete(context, uri.c_str());
-    }
-
-    if (error == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (error == OrthancPluginErrorCode_UnknownResource ||
-             error == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-  }
-
-
-  void ReportMinimalOrthancVersion(OrthancPluginContext* context,
-                                   unsigned int major,
-                                   unsigned int minor,
-                                   unsigned int revision)
-  {
-    std::string s = ("Your version of the Orthanc core (" +
-                     std::string(context->orthancVersion) +
-                     ") is too old to run this plugin (version " +
-                     boost::lexical_cast<std::string>(major) + "." +
-                     boost::lexical_cast<std::string>(minor) + "." +
-                     boost::lexical_cast<std::string>(revision) + 
-                     " is required)");
-    
-    OrthancPluginLogError(context, s.c_str());
-  }
-
-
-  bool CheckMinimalOrthancVersion(OrthancPluginContext* context,
-                                  unsigned int major,
-                                  unsigned int minor,
-                                  unsigned int revision)
-  {
-    if (context == NULL)
-    {
-      OrthancPluginLogError(context, "Bad Orthanc context in the plugin");      
-      return false;
-    }
-
-    if (!strcmp(context->orthancVersion, "mainline"))
-    {
-      // Assume compatibility with the mainline
-      return true;
-    }
-
-    // Parse the version of the Orthanc core
-    int aa, bb, cc;
-    if ( 
-#ifdef _MSC_VER
-      sscanf_s
-#else
-      sscanf
-#endif
-      (context->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
-      aa < 0 ||
-      bb < 0 ||
-      cc < 0)
-    {
-      throw false;
-    }
-
-    unsigned int a = static_cast<unsigned int>(aa);
-    unsigned int b = static_cast<unsigned int>(bb);
-    unsigned int c = static_cast<unsigned int>(cc);
-
-    // Check the major version number
-
-    if (a > major)
-    {
-      return true;
-    }
-
-    if (a < major)
-    {
-      return false;
-    }
-
-
-    // Check the minor version number
-    assert(a == major);
-
-    if (b > minor)
-    {
-      return true;
-    }
-
-    if (b < minor)
-    {
-      return false;
-    }
-
-    // Check the patch level version number
-    assert(a == major && b == minor);
-
-    if (c >= revision)
-    {
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-}
-
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,526 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "OrthancPluginException.h"
-
-#include <orthanc/OrthancCPlugin.h>
-#include <boost/noncopyable.hpp>
-#include <boost/lexical_cast.hpp>
-#include <json/value.h>
-#include <list>
-#include <set>
-
-
-
-#if !defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)
-#define ORTHANC_PLUGINS_VERSION_IS_ABOVE(major, minor, revision) \
-  (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER > major ||               \
-   (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER == major &&             \
-    (ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER > minor ||             \
-     (ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER == minor &&           \
-      ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER >= revision))))
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0)
-// The "OrthancPluginFindMatcher()" primitive was introduced in Orthanc 1.2.0
-#  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  1
-#else
-#  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  0
-#endif
-
-
-
-namespace OrthancPlugins
-{
-  typedef void (*RestCallback) (OrthancPluginRestOutput* output,
-                                const char* url,
-                                const OrthancPluginHttpRequest* request);
-
-  class MemoryBuffer : public boost::noncopyable
-  {
-  private:
-    OrthancPluginContext*      context_;
-    OrthancPluginMemoryBuffer  buffer_;
-
-    void Check(OrthancPluginErrorCode code);
-
-    bool CheckHttp(OrthancPluginErrorCode code);
-
-  public:
-    MemoryBuffer(OrthancPluginContext* context);
-
-    ~MemoryBuffer()
-    {
-      Clear();
-    }
-
-    OrthancPluginMemoryBuffer* operator*()
-    {
-      return &buffer_;
-    }
-
-    // This transfers ownership
-    void Assign(OrthancPluginMemoryBuffer& other);
-
-    const char* GetData() const
-    {
-      if (buffer_.size > 0)
-      {
-        return reinterpret_cast<const char*>(buffer_.data);
-      }
-      else
-      {
-        return NULL;
-      }
-    }
-
-    size_t GetSize() const
-    {
-      return buffer_.size;
-    }
-
-    void Clear();
-
-    void ToString(std::string& target) const;
-
-    void ToJson(Json::Value& target) const;
-
-    bool RestApiGet(const std::string& uri,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const char* body,
-                     size_t bodySize,
-                     bool applyPlugins);
-
-    bool RestApiPut(const std::string& uri,
-                    const char* body,
-                    size_t bodySize,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const Json::Value& body,
-                     bool applyPlugins);
-
-    bool RestApiPut(const std::string& uri,
-                    const Json::Value& body,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const std::string& body,
-                     bool applyPlugins)
-    {
-      return RestApiPost(uri, body.empty() ? NULL : body.c_str(), body.size(), applyPlugins);
-    }
-
-    bool RestApiPut(const std::string& uri,
-                    const std::string& body,
-                    bool applyPlugins)
-    {
-      return RestApiPut(uri, body.empty() ? NULL : body.c_str(), body.size(), applyPlugins);
-    }
-
-    void CreateDicom(const Json::Value& tags,
-                     OrthancPluginCreateDicomFlags flags);
-
-    void ReadFile(const std::string& path);
-
-    void GetDicomQuery(const OrthancPluginWorklistQuery* query);
-
-    void DicomToJson(Json::Value& target,
-                     OrthancPluginDicomToJsonFormat format,
-                     OrthancPluginDicomToJsonFlags flags,
-                     uint32_t maxStringLength);
-
-    bool HttpGet(const std::string& url,
-                 const std::string& username,
-                 const std::string& password);
- 
-    bool HttpPost(const std::string& url,
-                  const std::string& body,
-                  const std::string& username,
-                  const std::string& password);
- 
-    bool HttpPut(const std::string& url,
-                 const std::string& body,
-                 const std::string& username,
-                 const std::string& password);
-  };
-
-
-  class OrthancString : public boost::noncopyable
-  {
-  private:
-    OrthancPluginContext*  context_;
-    char*                  str_;
-
-    void Clear();
-
-  public:
-    OrthancString(OrthancPluginContext* context) :
-      context_(context),
-      str_(NULL)
-    {
-    }
-
-    ~OrthancString()
-    {
-      Clear();
-    }
-
-    // This transfers ownership, warning: The string must have been
-    // allocated by the Orthanc core
-    void Assign(char* str);
-
-    const char* GetContent() const
-    {
-      return str_;
-    }
-
-    void ToString(std::string& target) const;
-
-    void ToJson(Json::Value& target) const;
-  };
-
-
-  class OrthancConfiguration : public boost::noncopyable
-  {
-  private:
-    OrthancPluginContext*  context_;
-    Json::Value            configuration_;  // Necessarily a Json::objectValue
-    std::string            path_;
-
-    std::string GetPath(const std::string& key) const;
-
-  public:
-    OrthancConfiguration() : context_(NULL)
-    {
-    }
-
-    OrthancConfiguration(OrthancPluginContext* context);
-
-    OrthancPluginContext* GetContext() const;
-
-    const Json::Value& GetJson() const
-    {
-      return configuration_;
-    }
-
-    bool IsSection(const std::string& key) const;
-
-    void GetSection(OrthancConfiguration& target,
-                    const std::string& key) const;
-
-    bool LookupStringValue(std::string& target,
-                           const std::string& key) const;
-    
-    bool LookupIntegerValue(int& target,
-                            const std::string& key) const;
-
-    bool LookupUnsignedIntegerValue(unsigned int& target,
-                                    const std::string& key) const;
-
-    bool LookupBooleanValue(bool& target,
-                            const std::string& key) const;
-
-    bool LookupFloatValue(float& target,
-                          const std::string& key) const;
-
-    bool LookupListOfStrings(std::list<std::string>& target,
-                             const std::string& key,
-                             bool allowSingleString) const;
-
-    bool LookupSetOfStrings(std::set<std::string>& target,
-                            const std::string& key,
-                            bool allowSingleString) const;
-
-    std::string GetStringValue(const std::string& key,
-                               const std::string& defaultValue) const;
-
-    int GetIntegerValue(const std::string& key,
-                        int defaultValue) const;
-
-    unsigned int GetUnsignedIntegerValue(const std::string& key,
-                                         unsigned int defaultValue) const;
-
-    bool GetBooleanValue(const std::string& key,
-                         bool defaultValue) const;
-
-    float GetFloatValue(const std::string& key,
-                        float defaultValue) const;
-  };
-
-  class OrthancImage : public boost::noncopyable
-  {
-  private:
-    OrthancPluginContext*  context_;
-    OrthancPluginImage*    image_;
-
-    void Clear();
-
-    void CheckImageAvailable();
-
-  public:
-    OrthancImage(OrthancPluginContext*  context);
-
-    OrthancImage(OrthancPluginContext*  context,
-                 OrthancPluginImage*    image);
-
-    OrthancImage(OrthancPluginContext*     context,
-                 OrthancPluginPixelFormat  format,
-                 uint32_t                  width,
-                 uint32_t                  height);
-
-    ~OrthancImage()
-    {
-      Clear();
-    }
-
-    void UncompressPngImage(const void* data,
-                            size_t size);
-
-    void UncompressJpegImage(const void* data,
-                             size_t size);
-
-    void DecodeDicomImage(const void* data,
-                          size_t size,
-                          unsigned int frame);
-
-    OrthancPluginPixelFormat GetPixelFormat();
-
-    unsigned int GetWidth();
-
-    unsigned int GetHeight();
-
-    unsigned int GetPitch();
-    
-    const void* GetBuffer();
-
-    void CompressPngImage(MemoryBuffer& target);
-
-    void CompressJpegImage(MemoryBuffer& target,
-                           uint8_t quality);
-
-    void AnswerPngImage(OrthancPluginRestOutput* output);
-
-    void AnswerJpegImage(OrthancPluginRestOutput* output,
-                         uint8_t quality);
-  };
-
-
-#if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
-  class FindMatcher : public boost::noncopyable
-  {
-  private:
-    OrthancPluginContext*              context_;
-    OrthancPluginFindMatcher*          matcher_;
-    const OrthancPluginWorklistQuery*  worklist_;
-
-    void SetupDicom(OrthancPluginContext*  context,
-                    const void*            query,
-                    uint32_t               size);
-
-  public:
-    FindMatcher(OrthancPluginContext*              context,
-                const OrthancPluginWorklistQuery*  worklist);
-
-    FindMatcher(OrthancPluginContext*  context,
-                const void*            query,
-                uint32_t               size)
-    {
-      SetupDicom(context, query, size);
-    }
-
-    FindMatcher(OrthancPluginContext*  context,
-                const MemoryBuffer&    dicom)
-    {
-      SetupDicom(context, dicom.GetData(), dicom.GetSize());
-    }
-
-    ~FindMatcher();
-
-    bool IsMatch(const void*  dicom,
-                 uint32_t     size) const;
-
-    bool IsMatch(const MemoryBuffer& dicom) const
-    {
-      return IsMatch(dicom.GetData(), dicom.GetSize());
-    }
-  };
-#endif
-
-
-  bool RestApiGet(Json::Value& result,
-                  OrthancPluginContext* context,
-                  const std::string& uri,
-                  bool applyPlugins);
-
-  bool RestApiPost(Json::Value& result,
-                   OrthancPluginContext* context,
-                   const std::string& uri,
-                   const char* body,
-                   size_t bodySize,
-                   bool applyPlugins);
-
-  bool RestApiPost(Json::Value& result,
-                   OrthancPluginContext* context,
-                   const std::string& uri,
-                   const Json::Value& body,
-                   bool applyPlugins);
-
-  inline bool RestApiPost(Json::Value& result,
-                          OrthancPluginContext* context,
-                          const std::string& uri,
-                          const std::string& body,
-                          bool applyPlugins)
-  {
-    return RestApiPost(result, context, uri, body.empty() ? NULL : body.c_str(), 
-                       body.size(), applyPlugins);
-  }
-
-  bool RestApiPut(Json::Value& result,
-                  OrthancPluginContext* context,
-                  const std::string& uri,
-                  const char* body,
-                  size_t bodySize,
-                  bool applyPlugins);
-
-  bool RestApiPut(Json::Value& result,
-                  OrthancPluginContext* context,
-                  const std::string& uri,
-                  const Json::Value& body,
-                  bool applyPlugins);
-
-  inline bool RestApiPut(Json::Value& result,
-                         OrthancPluginContext* context,
-                         const std::string& uri,
-                         const std::string& body,
-                         bool applyPlugins)
-  {
-    return RestApiPut(result, context, uri, body.empty() ? NULL : body.c_str(), 
-                      body.size(), applyPlugins);
-  }
-
-  bool RestApiDelete(OrthancPluginContext* context,
-                     const std::string& uri,
-                     bool applyPlugins);
-
-  bool HttpDelete(OrthancPluginContext* context,
-                  const std::string& url,
-                  const std::string& username,
-                  const std::string& password);
-
-  inline void LogError(OrthancPluginContext* context,
-                       const std::string& message)
-  {
-    if (context != NULL)
-    {
-      OrthancPluginLogError(context, message.c_str());
-    }
-  }
-
-  inline void LogWarning(OrthancPluginContext* context,
-                         const std::string& message)
-  {
-    if (context != NULL)
-    {
-      OrthancPluginLogWarning(context, message.c_str());
-    }
-  }
-
-  inline void LogInfo(OrthancPluginContext* context,
-                      const std::string& message)
-  {
-    if (context != NULL)
-    {
-      OrthancPluginLogInfo(context, message.c_str());
-    }
-  }
-
-  void ReportMinimalOrthancVersion(OrthancPluginContext* context,
-                                   unsigned int major,
-                                   unsigned int minor,
-                                   unsigned int revision);
-  
-  bool CheckMinimalOrthancVersion(OrthancPluginContext* context,
-                                  unsigned int major,
-                                  unsigned int minor,
-                                  unsigned int revision);
-
-
-  namespace Internals
-  {
-    template <RestCallback Callback>
-    OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output,
-                                   const char* url,
-                                   const OrthancPluginHttpRequest* request)
-    {
-      try
-      {
-        Callback(output, url, request);
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-  }
-
-  
-  template <RestCallback Callback>
-  void RegisterRestCallback(OrthancPluginContext* context,
-                            const std::string& uri,
-                            bool isThreadSafe)
-  {
-    if (isThreadSafe)
-    {
-      OrthancPluginRegisterRestCallbackNoLock(context, uri.c_str(), Internals::Protect<Callback>);
-    }
-    else
-    {
-      OrthancPluginRegisterRestCallback(context, uri.c_str(), Internals::Protect<Callback>);
-    }
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginException.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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(HAS_ORTHANC_EXCEPTION)
-#  error The macro HAS_ORTHANC_EXCEPTION must be defined
-#endif
-
-
-#if HAS_ORTHANC_EXCEPTION == 1
-#  include "../../../Core/OrthancException.h"
-#  define ORTHANC_PLUGINS_ERROR_ENUMERATION     ::Orthanc::ErrorCode
-#  define ORTHANC_PLUGINS_EXCEPTION_CLASS       ::Orthanc::OrthancException
-#  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)  ::Orthanc::ErrorCode_ ## code
-#else
-#  include <orthanc/OrthancCPlugin.h>
-#  define ORTHANC_PLUGINS_ERROR_ENUMERATION     ::OrthancPluginErrorCode
-#  define ORTHANC_PLUGINS_EXCEPTION_CLASS       ::OrthancPlugins::PluginException
-#  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)  ::OrthancPluginErrorCode_ ## code
-#endif
-
-
-#define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code)                   \
-  throw ORTHANC_PLUGINS_EXCEPTION_CLASS(static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code));
-
-
-#define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                           \
-  throw ORTHANC_PLUGINS_EXCEPTION_CLASS(ORTHANC_PLUGINS_GET_ERROR_CODE(code));
-                                                  
-
-#define ORTHANC_PLUGINS_CHECK_ERROR(code)                           \
-  if (code != ORTHANC_PLUGINS_GET_ERROR_CODE(Success))              \
-  {                                                                 \
-    ORTHANC_PLUGINS_THROW_EXCEPTION(code);                          \
-  }
-
-
-namespace OrthancPlugins
-{
-#if HAS_ORTHANC_EXCEPTION == 0
-  class PluginException
-  {
-  private:
-    OrthancPluginErrorCode  code_;
-
-  public:
-    explicit PluginException(OrthancPluginErrorCode code) : code_(code)
-    {
-    }
-
-    OrthancPluginErrorCode GetErrorCode() const
-    {
-      return code_;
-    }
-
-    const char* What(OrthancPluginContext* context) const
-    {
-      const char* description = OrthancPluginGetErrorDescription(context, code_);
-      if (description)
-      {
-        return description;
-      }
-      else
-      {
-        return "No description available";
-      }
-    }
-  };
-#endif
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/SimplifiedOrthancDataset.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "SimplifiedOrthancDataset.h"
-
-#include "OrthancPluginException.h"
-
-namespace OrthancPlugins
-{
-  const Json::Value* SimplifiedOrthancDataset::LookupPath(const DicomPath& path) const
-  {
-    const Json::Value* content = &root_;
-                                  
-    for (unsigned int depth = 0; depth < path.GetPrefixLength(); depth++)
-    {
-      const char* name = path.GetPrefixTag(depth).GetName();
-      if (content->type() != Json::objectValue)
-      {
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-      }
-
-      if (!content->isMember(name))
-      {
-        return NULL;
-      }
-
-      const Json::Value& sequence = (*content) [name];
-      if (sequence.type() != Json::arrayValue)
-      {
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-      }
-
-      size_t index = path.GetPrefixIndex(depth);
-      if (index >= sequence.size())
-      {
-        return NULL;
-      }
-      else
-      {
-        content = &sequence[static_cast<Json::Value::ArrayIndex>(index)];
-      }
-    }
-
-    const char* name = path.GetFinalTag().GetName();
-
-    if (content->type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-    if (!content->isMember(name))
-    {
-      return NULL;
-    }
-    else
-    {
-      return &((*content) [name]);
-    }
-  }
-
-
-  void SimplifiedOrthancDataset::CheckRoot() const
-  {
-    if (root_.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  SimplifiedOrthancDataset::SimplifiedOrthancDataset(IOrthancConnection& orthanc,
-                                                     const std::string& uri)
-  {
-    IOrthancConnection::RestApiGet(root_, orthanc, uri);
-    CheckRoot();
-  }
-
-
-  SimplifiedOrthancDataset::SimplifiedOrthancDataset(const std::string& content)
-  {
-    IOrthancConnection::ParseJson(root_, content);
-    CheckRoot();
-  }
-
-
-  bool SimplifiedOrthancDataset::GetStringValue(std::string& result,
-                                                const DicomPath& path) const
-  {
-    const Json::Value* value = LookupPath(path);
-
-    if (value == NULL)
-    {
-      return false;
-    }
-    else if (value->type() != Json::stringValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-    else
-    {
-      result = value->asString();
-      return true;
-    }
-  }
-
-
-  bool SimplifiedOrthancDataset::GetSequenceSize(size_t& size,
-                                                 const DicomPath& path) const
-  {
-    const Json::Value* sequence = LookupPath(path);
-
-    if (sequence == NULL)
-    {
-      // Inexistent path
-      return false;
-    }
-    else if (sequence->type() != Json::arrayValue)
-    {
-      // Not a sequence
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-    else
-    {
-      size = sequence->size();
-      return true;
-    }
-  }
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/SimplifiedOrthancDataset.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, 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 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 "IOrthancConnection.h"
-#include "IDicomDataset.h"
-
-namespace OrthancPlugins
-{
-  class SimplifiedOrthancDataset : public IDicomDataset
-  {
-  private:
-    Json::Value   root_;
-
-    const Json::Value* LookupPath(const DicomPath& path) const;
-
-    void CheckRoot() const;
-
-  public:
-    SimplifiedOrthancDataset(IOrthancConnection& orthanc,
-                             const std::string& uri);
-
-    SimplifiedOrthancDataset(const std::string& content);
-
-    virtual bool GetStringValue(std::string& result,
-                                const DicomPath& path) const;
-
-    virtual bool GetSequenceSize(size_t& size,
-                                 const DicomPath& path) const;
-  };
-}
--- a/Resources/Orthanc/Plugins/Samples/Common/VersionScript.map	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-# This is a version-script for Orthanc plugins
-
-{
-global:
-  OrthancPluginInitialize;
-  OrthancPluginFinalize;
-  OrthancPluginGetName;
-  OrthancPluginGetVersion;
-
-local:
-  *;
-};
--- a/Resources/Orthanc/Resources/CMake/AutoGeneratedCode.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-set(AUTOGENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/AUTOGENERATED")
-set(AUTOGENERATED_SOURCES)
-
-file(MAKE_DIRECTORY ${AUTOGENERATED_DIR})
-include_directories(${AUTOGENERATED_DIR})
-
-macro(EmbedResources)
-  # Convert a semicolon separated list to a whitespace separated string
-  set(SCRIPT_OPTIONS)
-  set(SCRIPT_ARGUMENTS)
-  set(DEPENDENCIES)
-  set(IS_PATH_NAME false)
-
-  # Loop over the arguments of the function
-  foreach(arg ${ARGN})
-    # Extract the first character of the argument
-    string(SUBSTRING "${arg}" 0 1 FIRST_CHAR)
-    if (${FIRST_CHAR} STREQUAL "-")
-      # If the argument starts with a dash "-", this is an option to
-      # EmbedResources.py
-      list(APPEND SCRIPT_OPTIONS ${arg})
-    else()
-      if (${IS_PATH_NAME})
-        list(APPEND SCRIPT_ARGUMENTS "${arg}")
-        list(APPEND DEPENDENCIES "${arg}")
-        set(IS_PATH_NAME false)
-      else()
-        list(APPEND SCRIPT_ARGUMENTS "${arg}")
-        set(IS_PATH_NAME true)
-      endif()
-    endif()
-  endforeach()
-
-  set(TARGET_BASE "${AUTOGENERATED_DIR}/EmbeddedResources")
-  add_custom_command(
-    OUTPUT
-    "${TARGET_BASE}.h"
-    "${TARGET_BASE}.cpp"
-    COMMAND 
-    ${PYTHON_EXECUTABLE}
-    "${ORTHANC_ROOT}/Resources/EmbedResources.py"
-    ${SCRIPT_OPTIONS}
-    "${AUTOGENERATED_DIR}/EmbeddedResources"
-    ${SCRIPT_ARGUMENTS}
-    DEPENDS
-    "${ORTHANC_ROOT}/Resources/EmbedResources.py"
-    ${DEPENDENCIES}
-    )
-
-  list(APPEND AUTOGENERATED_SOURCES
-    "${AUTOGENERATED_DIR}/EmbeddedResources.cpp"
-    ) 
-endmacro()
--- a/Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,310 +0,0 @@
-if (STATIC_BUILD OR NOT USE_SYSTEM_BOOST)
-  set(BOOST_STATIC 1)
-else()
-  include(FindBoost)
-
-  set(BOOST_STATIC 0)
-  #set(Boost_DEBUG 1)
-  #set(Boost_USE_STATIC_LIBS ON)
-
-  if (ENABLE_LOCALE)
-    list(APPEND ORTHANC_BOOST_COMPONENTS locale)
-  endif()
-
-  list(APPEND ORTHANC_BOOST_COMPONENTS filesystem thread system date_time regex)
-  find_package(Boost COMPONENTS "${ORTHANC_BOOST_COMPONENTS}")
-
-  if (NOT Boost_FOUND)
-    foreach (item ${ORTHANC_BOOST_COMPONENTS})
-      string(TOUPPER ${item} tmp)
-
-      if (Boost_${tmp}_FOUND)
-        set(tmp2 "found")
-      else()
-        set(tmp2 "missing")
-      endif()
-      
-      message("Boost component ${item} - ${tmp2}")
-    endforeach()
-    
-    message(FATAL_ERROR "Unable to locate Boost on this system")
-  endif()
-
-  # Boost releases 1.44 through 1.47 supply both V2 and V3 filesystem
-  # http://www.boost.org/doc/libs/1_46_1/libs/filesystem/v3/doc/index.htm
-  if (${Boost_VERSION} LESS 104400)
-    add_definitions(
-      -DBOOST_HAS_FILESYSTEM_V3=0
-      )
-  else()
-    add_definitions(
-      -DBOOST_HAS_FILESYSTEM_V3=1
-      -DBOOST_FILESYSTEM_VERSION=3
-      )
-  endif()
-
-  include_directories(${Boost_INCLUDE_DIRS})
-  link_libraries(${Boost_LIBRARIES})
-endif()
-
-
-if (BOOST_STATIC)
-  ##
-  ## Parameters for static compilation of Boost 
-  ##
-  
-  set(BOOST_NAME boost_1_66_0)
-  set(BOOST_BCP_SUFFIX bcpdigest-1.3.2)
-  set(BOOST_MD5 "e509e66140e8f2fd4d326b0052825f52")
-  set(BOOST_URL "http://www.orthanc-server.com/downloads/third-party/${BOOST_NAME}_${BOOST_BCP_SUFFIX}.tar.gz")
-  set(BOOST_SOURCES_DIR ${CMAKE_BINARY_DIR}/${BOOST_NAME})
-
-  if (IS_DIRECTORY "${BOOST_SOURCES_DIR}")
-    set(FirstRun OFF)
-  else()
-    set(FirstRun ON)
-  endif()
-
-  DownloadPackage(${BOOST_MD5} ${BOOST_URL} "${BOOST_SOURCES_DIR}")
-
-
-  ##
-  ## Generic configuration of Boost
-  ## 
-
-  if (CMAKE_COMPILER_IS_GNUCXX)
-    add_definitions(-isystem ${BOOST_SOURCES_DIR})
-  endif()
-
-  include_directories(
-    ${BOOST_SOURCES_DIR}
-    )
-
-  add_definitions(
-    # Static build of Boost
-    -DBOOST_ALL_NO_LIB 
-    -DBOOST_ALL_NOLIB 
-    -DBOOST_DATE_TIME_NO_LIB 
-    -DBOOST_THREAD_BUILD_LIB
-    -DBOOST_PROGRAM_OPTIONS_NO_LIB
-    -DBOOST_REGEX_NO_LIB
-    -DBOOST_SYSTEM_NO_LIB
-    -DBOOST_LOCALE_NO_LIB
-    )
-
-  set(BOOST_SOURCES
-    ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp
-    )
-
-  if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase")
-    add_definitions(
-      -DBOOST_SYSTEM_USE_STRERROR=1
-      )
-    
-    execute_process(
-      COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
-      ${ORTHANC_ROOT}/Resources/Patches/boost-1.66.0-linux-standard-base.patch
-      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-      RESULT_VARIABLE Failure
-      )
-
-    if (FirstRun AND Failure)
-      message(FATAL_ERROR "Error while patching a file")
-    endif()
-  endif()
-
-  
-  ##
-  ## Configuration of boost::thread
-  ##
-  
-  if (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
-      CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
-      CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
-      CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD" OR
-      CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR
-      CMAKE_SYSTEM_NAME STREQUAL "PNaCl" OR
-      CMAKE_SYSTEM_NAME STREQUAL "NaCl32" OR
-      CMAKE_SYSTEM_NAME STREQUAL "NaCl64")
-    list(APPEND BOOST_SOURCES
-      ${BOOST_SOURCES_DIR}/libs/atomic/src/lockpool.cpp
-      ${BOOST_SOURCES_DIR}/libs/thread/src/pthread/once.cpp
-      ${BOOST_SOURCES_DIR}/libs/thread/src/pthread/thread.cpp
-      )
-
-    if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase" OR
-        CMAKE_SYSTEM_NAME STREQUAL "PNaCl" OR
-        CMAKE_SYSTEM_NAME STREQUAL "NaCl32" OR
-        CMAKE_SYSTEM_NAME STREQUAL "NaCl64")
-      add_definitions(-DBOOST_HAS_SCHED_YIELD=1)
-    endif()
-
-  elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
-    list(APPEND BOOST_SOURCES
-      ${BOOST_SOURCES_DIR}/libs/thread/src/win32/tss_dll.cpp
-      ${BOOST_SOURCES_DIR}/libs/thread/src/win32/thread.cpp
-      ${BOOST_SOURCES_DIR}/libs/thread/src/win32/tss_pe.cpp
-      )
-
-  elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
-    # No support for threads in WebAssembly
-
-  else()
-    message(FATAL_ERROR "Support your platform here")
-  endif()
-
-
-  ##
-  ## Configuration of boost::regex
-  ##
-  
-  aux_source_directory(${BOOST_SOURCES_DIR}/libs/regex/src BOOST_REGEX_SOURCES)
-
-  list(APPEND BOOST_SOURCES
-    ${BOOST_REGEX_SOURCES}
-    )
-
-
-  ##
-  ## Configuration of boost::datetime
-  ##
-  
-  list(APPEND BOOST_SOURCES
-    ${BOOST_SOURCES_DIR}/libs/date_time/src/gregorian/greg_month.cpp
-    )
-
-
-  ##
-  ## Configuration of boost::filesystem
-  ## 
-
-  if (CMAKE_SYSTEM_NAME STREQUAL "PNaCl" OR
-      CMAKE_SYSTEM_NAME STREQUAL "NaCl32" OR
-      CMAKE_SYSTEM_NAME STREQUAL "NaCl64")
-    # boost::filesystem is not available on PNaCl
-    add_definitions(
-      -DBOOST_HAS_FILESYSTEM_V3=0
-      -D__INTEGRITY=1
-      )
-  else()
-    add_definitions(
-      -DBOOST_HAS_FILESYSTEM_V3=1
-      )
-    list(APPEND BOOST_SOURCES
-      ${BOOST_NAME}/libs/filesystem/src/codecvt_error_category.cpp
-      ${BOOST_NAME}/libs/filesystem/src/operations.cpp
-      ${BOOST_NAME}/libs/filesystem/src/path.cpp
-      ${BOOST_NAME}/libs/filesystem/src/path_traits.cpp
-      )
-
-    if (CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
-        CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR
-        CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
-     list(APPEND BOOST_SOURCES
-        ${BOOST_SOURCES_DIR}/libs/filesystem/src/utf8_codecvt_facet.cpp
-        )
-
-    elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
-      list(APPEND BOOST_SOURCES
-        ${BOOST_NAME}/libs/filesystem/src/windows_file_codecvt.cpp
-        )
-    endif()
-  endif()
-
-
-  ##
-  ## Configuration of boost::locale
-  ## 
-
-  if (NOT ENABLE_LOCALE)
-    message("boost::locale is disabled")
-  else()
-    list(APPEND BOOST_SOURCES
-      ${BOOST_SOURCES_DIR}/libs/locale/src/encoding/codepage.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/shared/generator.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/shared/date_time.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/shared/formatting.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/shared/ids.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/shared/localization_backend.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/shared/message.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/shared/mo_lambda.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/util/codecvt_converter.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/util/default_locale.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/util/gregorian.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/util/info.cpp
-      ${BOOST_SOURCES_DIR}/libs/locale/src/util/locale_data.cpp
-      )        
-
-    if (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR
-        CMAKE_SYSTEM_VERSION STREQUAL "LinuxStandardBase")
-      list(APPEND BOOST_SOURCES
-        ${BOOST_SOURCES_DIR}/libs/locale/src/std/codecvt.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/std/collate.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/std/converter.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/std/numeric.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/std/std_backend.cpp
-        )
-
-      add_definitions(
-        -DBOOST_LOCALE_WITH_ICONV=1
-        -DBOOST_LOCALE_NO_WINAPI_BACKEND=1
-        -DBOOST_LOCALE_NO_POSIX_BACKEND=1
-        )
-      
-    elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
-            CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
-            CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
-            CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD" OR
-            CMAKE_SYSTEM_NAME STREQUAL "PNaCl" OR
-            CMAKE_SYSTEM_NAME STREQUAL "NaCl32" OR
-            CMAKE_SYSTEM_NAME STREQUAL "NaCl64" OR
-            CMAKE_SYSTEM_NAME STREQUAL "Emscripten") # For WebAssembly or asm.js
-      list(APPEND BOOST_SOURCES
-        ${BOOST_SOURCES_DIR}/libs/locale/src/posix/codecvt.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/posix/collate.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/posix/converter.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/posix/numeric.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/posix/posix_backend.cpp
-        )
-
-      add_definitions(
-        -DBOOST_LOCALE_WITH_ICONV=1
-        -DBOOST_LOCALE_NO_WINAPI_BACKEND=1
-        -DBOOST_LOCALE_NO_STD_BACKEND=1
-        )
-      
-    elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
-      list(APPEND BOOST_SOURCES
-        ${BOOST_SOURCES_DIR}/libs/locale/src/win32/collate.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/win32/converter.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/win32/lcid.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/win32/numeric.cpp
-        ${BOOST_SOURCES_DIR}/libs/locale/src/win32/win_backend.cpp
-        )
-
-      add_definitions(
-        -DBOOST_LOCALE_NO_POSIX_BACKEND=1
-        -DBOOST_LOCALE_NO_STD_BACKEND=1
-        )
-
-      # Starting with release 0.8.2, Orthanc statically links against
-      # libiconv, even on Windows. Indeed, the "WCONV" library of
-      # Windows XP seems not to support properly several codepages
-      # (notably "Latin3", "Hebrew", and "Arabic"). Set
-      # "USE_BOOST_ICONV" to "OFF" to use WCONV anyway.
-
-      if (USE_BOOST_ICONV)
-        add_definitions(-DBOOST_LOCALE_WITH_ICONV=1)
-      else()
-        add_definitions(-DBOOST_LOCALE_WITH_WCONV=1)
-      endif()
-
-    else()
-      message(FATAL_ERROR "Support your platform here")
-    endif()
-  endif()
-
-  
-  source_group(ThirdParty\\boost REGULAR_EXPRESSION ${BOOST_SOURCES_DIR}/.*)
-
-endif()
--- a/Resources/Orthanc/Resources/CMake/Compiler.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-# This file sets all the compiler-related flags
-
-if (CMAKE_CROSSCOMPILING OR
-    "${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase")
-  # Cross-compilation necessarily implies standalone and static build
-  SET(STATIC_BUILD ON)
-  SET(STANDALONE_BUILD ON)
-endif()
-
-if (CMAKE_COMPILER_IS_GNUCXX)
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-long-long")
-
-  # --std=c99 makes libcurl not to compile
-  # -pedantic gives a lot of warnings on OpenSSL 
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -Wno-variadic-macros")
-
-  if (CMAKE_CROSSCOMPILING)
-    # http://stackoverflow.com/a/3543845/881731
-    set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -O coff -I<CMAKE_CURRENT_SOURCE_DIR> <SOURCE> <OBJECT>")
-  endif()
-
-elseif (MSVC)
-  # Use static runtime under Visual Studio
-  # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace
-  # http://stackoverflow.com/a/6510446
-  foreach(flag_var
-    CMAKE_C_FLAGS_DEBUG
-    CMAKE_CXX_FLAGS_DEBUG
-    CMAKE_C_FLAGS_RELEASE 
-    CMAKE_CXX_FLAGS_RELEASE
-    CMAKE_C_FLAGS_MINSIZEREL 
-    CMAKE_CXX_FLAGS_MINSIZEREL 
-    CMAKE_C_FLAGS_RELWITHDEBINFO 
-    CMAKE_CXX_FLAGS_RELWITHDEBINFO) 
-    string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
-    string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
-  endforeach(flag_var)
-
-  # Add /Zm256 compiler option to Visual Studio to fix PCH errors
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm256")
-
-  add_definitions(
-    -D_CRT_SECURE_NO_WARNINGS=1
-    -D_CRT_SECURE_NO_DEPRECATE=1
-    )
-
-  if (MSVC_VERSION LESS 1600)
-    # Starting with Visual Studio >= 2010 (i.e. macro _MSC_VER >=
-    # 1600), Microsoft ships a standard-compliant <stdint.h>
-    # header. For earlier versions of Visual Studio, give access to a
-    # compatibility header.
-    # http://stackoverflow.com/a/70630/881731
-    # https://en.wikibooks.org/wiki/C_Programming/C_Reference/stdint.h#External_links
-    include_directories(${ORTHANC_ROOT}/Resources/ThirdParty/VisualStudio)
-  endif()
-
-  link_libraries(netapi32)
-endif()
-
-
-if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-  # In FreeBSD/OpenBSD, the "/usr/local/" folder contains the ports and need to be imported
-  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/include")
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/local/include")
-  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L/usr/local/lib")
-endif()
-
-
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-
-  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-    # The "--no-undefined" linker flag makes the shared libraries
-    # (plugins ModalityWorklists and ServeFolders) fail to compile on OpenBSD
-    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined")
-    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
-  endif()
-
-  if (NOT DEFINED ENABLE_PLUGINS_VERSION_SCRIPT OR 
-      ENABLE_PLUGINS_VERSION_SCRIPT)
-    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script=${ORTHANC_ROOT}/Plugins/Samples/Common/VersionScript.map")
-  endif()
-
-  # Remove the "-rdynamic" option
-  # http://www.mail-archive.com/cmake@cmake.org/msg08837.html
-  set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
-  link_libraries(pthread)
-
-  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-    link_libraries(rt)
-  endif()
-
-  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND
-      NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-    link_libraries(dl)
-  endif()
-
-  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND
-      NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-    # The "--as-needed" linker flag is not available on FreeBSD and OpenBSD
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
-    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--as-needed")
-    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed")
-  endif()
-
-  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND
-      NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-    # FreeBSD/OpenBSD have just one single interface for file
-    # handling, which is 64bit clean, so there is no need to define macro
-    # for LFS (Large File Support).
-    # https://ohse.de/uwe/articles/lfs.html
-    add_definitions(
-      -D_LARGEFILE64_SOURCE=1 
-      -D_FILE_OFFSET_BITS=64
-      )
-  endif()
-
-elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
-  if (MSVC)
-    message("MSVC compiler version = " ${MSVC_VERSION} "\n")
-    # Starting Visual Studio 2013 (version 1800), it is not possible
-    # to target Windows XP anymore
-    if (MSVC_VERSION LESS 1800)
-      add_definitions(
-        -DWINVER=0x0501
-        -D_WIN32_WINNT=0x0501
-        )
-    endif()
-  else()
-    add_definitions(
-      -DWINVER=0x0501
-      -D_WIN32_WINNT=0x0501
-      )
-  endif()
-
-  add_definitions(
-    -D_CRT_SECURE_NO_WARNINGS=1
-    )
-  link_libraries(rpcrt4 ws2_32)
-
-  if (CMAKE_COMPILER_IS_GNUCXX)
-    # Some additional C/C++ compiler flags for MinGW
-    SET(MINGW_NO_WARNINGS "-Wno-unused-function -Wno-unused-variable")
-    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MINGW_NO_WARNINGS} -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast")
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MINGW_NO_WARNINGS}")
-
-    # This is a patch for MinGW64
-    SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++")
-    SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++")
-
-    CHECK_LIBRARY_EXISTS(winpthread pthread_create "" HAVE_WIN_PTHREAD)
-    if (HAVE_WIN_PTHREAD)
-      # This line is necessary to compile with recent versions of MinGW,
-      # otherwise "libwinpthread-1.dll" is not statically linked.
-      SET(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic")
-      add_definitions(-DHAVE_WIN_PTHREAD=1)
-    else()
-      add_definitions(-DHAVE_WIN_PTHREAD=0)
-    endif()
-  endif()
-
-elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${ORTHANC_ROOT}/Plugins/Samples/Common/ExportedSymbols.list")
-
-  add_definitions(
-    -D_XOPEN_SOURCE=1
-    )
-  link_libraries(iconv)
-
-elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
-  message("Building using Emscripten (for WebAssembly or asm.js targets)")
-
-  # The BINARYEN_TRAP_MODE specifies what to do when divisions per
-  # zero (and similar conditions like integer overflows) are
-  # encountered: The "clamp" mode avoids throwing errors, as they
-  # cannot be properly catched by "try {} catch (...)" constructions.
-  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]' -s BINARYEN_TRAP_MODE='\"clamp\"'")
-
-else()
-  message(FATAL_ERROR "Support your platform here")
-endif()
-
-
-if (DEFINED ENABLE_PROFILING AND ENABLE_PROFILING)
-  if (CMAKE_COMPILER_IS_GNUCXX)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
-    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -pg")
-    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg")
-  else()
-    message(FATAL_ERROR "Don't know how to enable profiling on your configuration")
-  endif()
-endif()
-
-
-if (CMAKE_COMPILER_IS_GNUCXX)
-  # "When creating a static library using binutils (ar) and there
-  # exist a duplicate object name (e.g. a/Foo.cpp.o, b/Foo.cpp.o), the
-  # resulting static library can end up having only one of the
-  # duplicate objects. [...] This bug only happens if there are many
-  # objects." The trick consists in replacing the "r" argument
-  # ("replace") provided to "ar" (as used in CMake < 3.1) by the "q"
-  # argument ("quick append"). This is because of the fact that CMake
-  # will invoke "ar" several times with several batches of ".o"
-  # objects, and using "r" would overwrite symbols defined in
-  # preceding batches. https://cmake.org/Bug/view.php?id=14874
-  set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> <LINK_FLAGS> q <TARGET> <OBJECTS>")
-endif()
-
-
-if (STATIC_BUILD)
-  add_definitions(-DORTHANC_STATIC=1)
-else()
-  add_definitions(-DORTHANC_STATIC=0)
-endif()
--- a/Resources/Orthanc/Resources/CMake/DcmtkConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,434 +0,0 @@
-if (NOT DEFINED ENABLE_DCMTK_NETWORKING)
-    set(ENABLE_DCMTK_NETWORKING ON)
-endif()
-
-if (STATIC_BUILD OR NOT USE_SYSTEM_DCMTK)
-  if (USE_DCMTK_360)
-    SET(DCMTK_VERSION_NUMBER 360)
-    SET(DCMTK_PACKAGE_VERSION "3.6.0")
-    SET(DCMTK_SOURCES_DIR ${CMAKE_BINARY_DIR}/dcmtk-3.6.0)
-    SET(DCMTK_URL "http://www.orthanc-server.com/downloads/third-party/dcmtk-3.6.0.zip")
-    SET(DCMTK_MD5 "219ad631b82031806147e4abbfba4fa4")
-  else()
-    SET(DCMTK_VERSION_NUMBER 362)
-    SET(DCMTK_PACKAGE_VERSION "3.6.2")
-    SET(DCMTK_SOURCES_DIR ${CMAKE_BINARY_DIR}/dcmtk-3.6.2)
-    SET(DCMTK_URL "http://www.orthanc-server.com/downloads/third-party/dcmtk-3.6.2.tar.gz")
-    SET(DCMTK_MD5 "d219a4152772985191c9b89d75302d12")
-
-    macro(DCMTK_UNSET)
-    endmacro()
-
-    macro(DCMTK_UNSET_CACHE)
-    endmacro()
-
-    set(DCMTK_BINARY_DIR ${DCMTK_SOURCES_DIR}/)
-    set(DCMTK_CMAKE_INCLUDE ${DCMTK_SOURCES_DIR}/)
-    set(DCMTK_WITH_THREADS ON)
-    
-    add_definitions(-DDCMTK_INSIDE_LOG4CPLUS=1)
-  endif()
-  
-  if (IS_DIRECTORY "${DCMTK_SOURCES_DIR}")
-    set(FirstRun OFF)
-  else()
-    set(FirstRun ON)
-  endif()
-
-  DownloadPackage(${DCMTK_MD5} ${DCMTK_URL} "${DCMTK_SOURCES_DIR}")
-
-  
-  if (FirstRun)
-    if (USE_DCMTK_360)
-      # If using DCMTK 3.6.0, backport the "private.dic" file from DCMTK
-      # 3.6.2. This adds support for more private tags, and fixes some
-      # import problems with Philips MRI Achieva.
-      if (USE_DCMTK_362_PRIVATE_DIC)
-        message("Using the dictionary of private tags from DCMTK 3.6.2")
-        configure_file(
-          ${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.2-private.dic
-          ${DCMTK_SOURCES_DIR}/dcmdata/data/private.dic
-          COPYONLY)
-      else()
-        message("Using the dictionary of private tags from DCMTK 3.6.0")
-      endif()
-      
-      # Patches specific to DCMTK 3.6.0
-      message("Applying patch to solve vulnerability in DCMTK 3.6.0")
-      execute_process(
-        COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
-        ${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.0-dulparse-vulnerability.patch
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        RESULT_VARIABLE Failure
-        )
-
-      if (Failure)
-        message(FATAL_ERROR "Error while patching a file")
-      endif()
-
-      # This patch is not needed anymore thanks to the following commit
-      # (information sent by Jorg Riesmeier on Twitter on 2017-07-19):
-      # http://git.dcmtk.org/?p=dcmtk.git;a=commit;h=8df1f5e517b8629ae09088d0935c2a8dd333c76f
-      message("Applying patch for speed in DCMTK 3.6.0")
-      execute_process(
-        COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
-        ${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.0-speed.patch
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        RESULT_VARIABLE Failure
-        )
-
-      if (Failure)
-        message(FATAL_ERROR "Error while patching a file")
-      endif()
-
-    else()
-      # "3.6.2 CXX11 fails on Linux; patch suggestions included"
-      # https://forum.dcmtk.org/viewtopic.php?f=3&t=4637
-      message("Applying patch to detect mathematic primitives in DCMTK 3.6.2 with C++11")
-      execute_process(
-        COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
-        ${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.2-cmath.patch
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        RESULT_VARIABLE Failure
-        )
-
-      if (Failure)
-        message(FATAL_ERROR "Error while patching a file")
-      endif()
-    endif()
-  else()
-    message("The patches for DCMTK have already been applied")
-  endif()
-
-
-  # C_CHAR_UNSIGNED *must* be set before calling "GenerateDCMTKConfigure.cmake"
-  IF (CMAKE_CROSSCOMPILING)
-    if (CMAKE_COMPILER_IS_GNUCXX AND
-        CMAKE_SYSTEM_NAME STREQUAL "Windows")  # MinGW
-      SET(C_CHAR_UNSIGNED 1 CACHE INTERNAL "Whether char is unsigned.")
-
-    elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")  # WebAssembly or asm.js
-
-      # Check out "../WebAssembly/ArithmeticTests/" to regenerate the
-      # "arith.h" file
-      configure_file(
-        ${ORTHANC_ROOT}/Resources/WebAssembly/arith.h
-        ${DCMTK_SOURCES_DIR}/config/include/dcmtk/config/arith.h
-        COPYONLY)
-
-      UNSET(C_CHAR_UNSIGNED CACHE)
-      SET(C_CHAR_UNSIGNED 0 CACHE INTERNAL "")
-
-    else()
-      message(FATAL_ERROR "Support your platform here")
-    endif()
-  ENDIF()
-
-  
-  if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase")
-    SET(DCMTK_ENABLE_CHARSET_CONVERSION "iconv" CACHE STRING "")
-    SET(HAVE_SYS_GETTID 0 CACHE INTERNAL "")
-
-    execute_process(
-      COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
-      ${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.2-linux-standard-base.patch
-      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-      RESULT_VARIABLE Failure
-      )
-
-    if (FirstRun AND Failure)
-      message(FATAL_ERROR "Error while patching a file")
-    endif()
-  endif()
-
-  SET(DCMTK_SOURCE_DIR ${DCMTK_SOURCES_DIR})
-  include(${DCMTK_SOURCES_DIR}/CMake/CheckFunctionWithHeaderExists.cmake)
-  include(${DCMTK_SOURCES_DIR}/CMake/GenerateDCMTKConfigure.cmake)
-
-
-  if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")  # WebAssembly or
-    # asm.js The macros below are not properly discovered by DCMTK
-    # when using WebAssembly. Check out "../WebAssembly/arith.h" for
-    # how we produced these values. This step MUST be after
-    # "GenerateDCMTKConfigure" and before the generation of
-    # "osconfig.h".
-    UNSET(SIZEOF_VOID_P   CACHE)
-    UNSET(SIZEOF_CHAR     CACHE)
-    UNSET(SIZEOF_DOUBLE   CACHE)
-    UNSET(SIZEOF_FLOAT    CACHE)
-    UNSET(SIZEOF_INT      CACHE)
-    UNSET(SIZEOF_LONG     CACHE)
-    UNSET(SIZEOF_SHORT    CACHE)
-    UNSET(SIZEOF_VOID_P   CACHE)
-
-    SET(SIZEOF_VOID_P 4   CACHE INTERNAL "")
-    SET(SIZEOF_CHAR 1     CACHE INTERNAL "")
-    SET(SIZEOF_DOUBLE 8   CACHE INTERNAL "")
-    SET(SIZEOF_FLOAT 4    CACHE INTERNAL "")
-    SET(SIZEOF_INT 4      CACHE INTERNAL "")
-    SET(SIZEOF_LONG 4     CACHE INTERNAL "")
-    SET(SIZEOF_SHORT 2    CACHE INTERNAL "")
-    SET(SIZEOF_VOID_P 4   CACHE INTERNAL "")
-  endif()
-
-
-  set(DCMTK_PACKAGE_VERSION_SUFFIX "")
-  set(DCMTK_PACKAGE_VERSION_NUMBER ${DCMTK_VERSION_NUMBER})
-
-  CONFIGURE_FILE(
-    ${DCMTK_SOURCES_DIR}/CMake/osconfig.h.in
-    ${DCMTK_SOURCES_DIR}/config/include/dcmtk/config/osconfig.h)
-
-  if (NOT USE_DCMTK_360)
-    if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
-      link_libraries(netapi32)  # For NetWkstaUserGetInfo@12
-      link_libraries(iphlpapi)  # For GetAdaptersInfo@8
-
-      # Configure Wine if cross-compiling for Windows
-      if (CMAKE_COMPILER_IS_GNUCXX)
-        include(${DCMTK_SOURCES_DIR}/CMake/dcmtkUseWine.cmake)
-        FIND_PROGRAM(WINE_WINE_PROGRAM wine)
-        FIND_PROGRAM(WINE_WINEPATH_PROGRAM winepath)
-        list(APPEND DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS=-static")
-      endif()
-    endif()
-
-    # This step must be after the generation of "osconfig.h"
-    if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
-      INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES()
-    endif()
-  endif()
-
-  AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmdata/libsrc DCMTK_SOURCES)
-  AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/ofstd/libsrc DCMTK_SOURCES)
-
-  if (ENABLE_DCMTK_NETWORKING)
-    AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmnet/libsrc DCMTK_SOURCES)
-    include_directories(
-      ${DCMTK_SOURCES_DIR}/dcmnet/include
-      )
-  endif()
-
-  if (ENABLE_DCMTK_JPEG)
-    AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc DCMTK_SOURCES)
-    AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmjpeg/libijg8 DCMTK_SOURCES)
-    AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmjpeg/libijg12 DCMTK_SOURCES)
-    AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmjpeg/libijg16 DCMTK_SOURCES)
-    include_directories(
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/include
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libijg8
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libijg12
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libijg16
-      ${DCMTK_SOURCES_DIR}/dcmimgle/include
-      )
-    list(REMOVE_ITEM DCMTK_SOURCES 
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/ddpiimpl.cc
-
-      # Disable support for encoding JPEG (modification in Orthanc 1.0.1)
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djcodece.cc
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djencsv1.cc
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djencbas.cc
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djencpro.cc
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djenclol.cc
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djencode.cc
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djencext.cc
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djencsps.cc
-      )
-  endif()
-
-
-  if (ENABLE_DCMTK_JPEG_LOSSLESS)
-    AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmjpls/libsrc DCMTK_SOURCES)
-    AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmjpls/libcharls DCMTK_SOURCES)
-    include_directories(
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/include
-      ${DCMTK_SOURCES_DIR}/dcmjpls/include
-      ${DCMTK_SOURCES_DIR}/dcmjpls/libcharls
-      )
-    list(REMOVE_ITEM DCMTK_SOURCES 
-      ${DCMTK_SOURCES_DIR}/dcmjpls/libsrc/djcodece.cc
-
-      # Disable support for encoding JPEG-LS (modification in Orthanc 1.0.1)
-      ${DCMTK_SOURCES_DIR}/dcmjpls/libsrc/djencode.cc
-      )
-    list(APPEND DCMTK_SOURCES 
-      ${DCMTK_SOURCES_DIR}/dcmjpeg/libsrc/djrplol.cc
-      )
-  endif()
-
-
-  # Source for the logging facility of DCMTK
-  AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/oflog/libsrc DCMTK_SOURCES)
-  if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
-    list(REMOVE_ITEM DCMTK_SOURCES 
-      ${DCMTK_SOURCES_DIR}/oflog/libsrc/clfsap.cc
-      ${DCMTK_SOURCES_DIR}/oflog/libsrc/windebap.cc
-      ${DCMTK_SOURCES_DIR}/oflog/libsrc/winsock.cc
-      )
-
-  elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
-    list(REMOVE_ITEM DCMTK_SOURCES 
-      ${DCMTK_SOURCES_DIR}/oflog/libsrc/unixsock.cc
-      ${DCMTK_SOURCES_DIR}/oflog/libsrc/clfsap.cc
-      )
-
-    if (CMAKE_COMPILER_IS_GNUCXX AND
-        DCMTK_PATCH_MINGW64 AND
-        USE_DCMTK_360)
-      # This is a patch for MinGW64
-      execute_process(
-        COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
-        ${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.0-mingw64.patch
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        RESULT_VARIABLE Failure
-        )
-
-      if (Failure AND FirstRun)
-        message(FATAL_ERROR "Error while patching a file")
-      endif()
-    endif()
-  endif()
-
-
-  if (NOT USE_DCMTK_360 AND
-      ORTHANC_SANDBOXED)
-    configure_file(
-      ${ORTHANC_ROOT}/Resources/WebAssembly/dcdict.h
-      ${DCMTK_SOURCES_DIR}/dcmdata/include/dcmtk/dcmdata/dcdict.h
-      COPYONLY)
-    
-    configure_file(
-      ${ORTHANC_ROOT}/Resources/WebAssembly/dcdict.cc
-      ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/dcdict.cc
-      COPYONLY)
-  endif()
-
-  
-  list(REMOVE_ITEM DCMTK_SOURCES 
-    ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/mkdictbi.cc
-    ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/mkdeftag.cc
-    )
-
-  #set_source_files_properties(${DCMTK_SOURCES}
-  #  PROPERTIES COMPILE_DEFINITIONS
-  #  "PACKAGE_VERSION=\"${DCMTK_PACKAGE_VERSION}\";PACKAGE_VERSION_NUMBER=\"${DCMTK_VERSION_NUMBER}\"")
-
-  # This fixes crashes related to the destruction of the DCMTK OFLogger
-  # http://support.dcmtk.org/docs-snapshot/file_macros.html
-  add_definitions(
-    -DLOG4CPLUS_DISABLE_FATAL=1
-    -DDCMTK_VERSION_NUMBER=${DCMTK_VERSION_NUMBER}
-    )
-
-  include_directories(
-    #${DCMTK_SOURCES_DIR}
-    ${DCMTK_SOURCES_DIR}/config/include
-    ${DCMTK_SOURCES_DIR}/ofstd/include
-    ${DCMTK_SOURCES_DIR}/oflog/include
-    ${DCMTK_SOURCES_DIR}/dcmdata/include
-    )
-
-  source_group(ThirdParty\\Dcmtk REGULAR_EXPRESSION ${DCMTK_SOURCES_DIR}/.*)
-
-  set(DCMTK_BUNDLES_LOG4CPLUS 1)
-
-  if (STANDALONE_BUILD)
-    set(DCMTK_USE_EMBEDDED_DICTIONARIES 1)
-    set(DCMTK_DICTIONARIES
-      DICTIONARY_DICOM ${DCMTK_SOURCES_DIR}/dcmdata/data/dicom.dic
-      DICTIONARY_PRIVATE ${DCMTK_SOURCES_DIR}/dcmdata/data/private.dic
-      DICTIONARY_DICONDE ${DCMTK_SOURCES_DIR}/dcmdata/data/diconde.dic
-      )
-  else()
-    set(DCMTK_USE_EMBEDDED_DICTIONARIES 0)
-  endif()
-
-else()
-  # The following line allows to manually add libraries at the
-  # command-line, which is necessary for Ubuntu/Debian packages
-  set(tmp "${DCMTK_LIBRARIES}")
-  include(FindDCMTK)
-  list(APPEND DCMTK_LIBRARIES "${tmp}")
-
-  include_directories(${DCMTK_INCLUDE_DIRS})
-
-  add_definitions(
-    -DHAVE_CONFIG_H=1
-    )
-
-  if (EXISTS "${DCMTK_config_INCLUDE_DIR}/cfunix.h")
-    set(DCMTK_CONFIGURATION_FILE "${DCMTK_config_INCLUDE_DIR}/cfunix.h")
-  elseif (EXISTS "${DCMTK_config_INCLUDE_DIR}/osconfig.h")  # This is for Arch Linux
-    set(DCMTK_CONFIGURATION_FILE "${DCMTK_config_INCLUDE_DIR}/osconfig.h")
-  elseif (EXISTS "${DCMTK_INCLUDE_DIRS}/dcmtk/config/osconfig.h")  # This is for Debian Buster
-    set(DCMTK_CONFIGURATION_FILE "${DCMTK_INCLUDE_DIRS}/dcmtk/config/osconfig.h")
-  else()
-    message(FATAL_ERROR "Please install libdcmtk*-dev")
-  endif()
-
-  message("DCMTK configuration file: ${DCMTK_CONFIGURATION_FILE}")
-  
-  # Autodetection of the version of DCMTK
-  file(STRINGS
-    "${DCMTK_CONFIGURATION_FILE}" 
-    DCMTK_VERSION_NUMBER1 REGEX
-    ".*PACKAGE_VERSION .*")    
-
-  string(REGEX REPLACE
-    ".*PACKAGE_VERSION.*\"([0-9]*)\\.([0-9]*)\\.([0-9]*)\"$"
-    "\\1\\2\\3" 
-    DCMTK_VERSION_NUMBER 
-    ${DCMTK_VERSION_NUMBER1})
-
-  set(DCMTK_USE_EMBEDDED_DICTIONARIES 0)
-endif()
-
-
-add_definitions(-DDCMTK_VERSION_NUMBER=${DCMTK_VERSION_NUMBER})
-message("DCMTK version: ${DCMTK_VERSION_NUMBER}")
-
-
-add_definitions(-DDCMTK_USE_EMBEDDED_DICTIONARIES=${DCMTK_USE_EMBEDDED_DICTIONARIES})
-if (NOT DCMTK_USE_EMBEDDED_DICTIONARIES)
-  # Lookup for DICOM dictionaries, if none is specified by the user
-  if (DCMTK_DICTIONARY_DIR STREQUAL "")
-    find_path(DCMTK_DICTIONARY_DIR_AUTO dicom.dic
-      /usr/share/dcmtk
-      /usr/share/libdcmtk1
-      /usr/share/libdcmtk2
-      /usr/share/libdcmtk3
-      /usr/share/libdcmtk4
-      /usr/share/libdcmtk5
-      /usr/share/libdcmtk6
-      /usr/share/libdcmtk7
-      /usr/share/libdcmtk8
-      /usr/share/libdcmtk9
-      /usr/share/libdcmtk10
-      /usr/share/libdcmtk11
-      /usr/share/libdcmtk12
-      /usr/share/libdcmtk13
-      /usr/share/libdcmtk14
-      /usr/share/libdcmtk15
-      /usr/share/libdcmtk16
-      /usr/share/libdcmtk17
-      /usr/share/libdcmtk18
-      /usr/share/libdcmtk19
-      /usr/share/libdcmtk20
-      /usr/local/share/dcmtk
-      )
-
-    if (${DCMTK_DICTIONARY_DIR_AUTO} MATCHES "DCMTK_DICTIONARY_DIR_AUTO-NOTFOUND")
-      message(FATAL_ERROR "Cannot locate the DICOM dictionary on this system")
-    endif()
-
-    message("Autodetected path to the DICOM dictionaries: ${DCMTK_DICTIONARY_DIR_AUTO}")
-    add_definitions(-DDCMTK_DICTIONARY_DIR="${DCMTK_DICTIONARY_DIR_AUTO}")
-  else()
-    add_definitions(-DDCMTK_DICTIONARY_DIR="${DCMTK_DICTIONARY_DIR}")
-  endif()
-endif()
--- a/Resources/Orthanc/Resources/CMake/DownloadPackage.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-macro(GetUrlFilename TargetVariable Url)
-  string(REGEX REPLACE "^.*/" "" ${TargetVariable} "${Url}")
-endmacro()
-
-
-macro(GetUrlExtension TargetVariable Url)
-  #string(REGEX REPLACE "^.*/[^.]*\\." "" TMP "${Url}")
-  string(REGEX REPLACE "^.*\\." "" TMP "${Url}")
-  string(TOLOWER "${TMP}" "${TargetVariable}")
-endmacro()
-
-
-
-##
-## Setup the patch command-line tool
-##
-
-if (NOT ORTHANC_DISABLE_PATCH)
-  if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
-    set(PATCH_EXECUTABLE ${CMAKE_CURRENT_LIST_DIR}/../ThirdParty/patch/patch.exe)
-    if (NOT EXISTS ${PATCH_EXECUTABLE})
-      message(FATAL_ERROR "Unable to find the patch.exe tool that is shipped with Orthanc")
-    endif()
-
-  else ()
-    find_program(PATCH_EXECUTABLE patch)
-    if (${PATCH_EXECUTABLE} MATCHES "PATCH_EXECUTABLE-NOTFOUND")
-      message(FATAL_ERROR "Please install the 'patch' standard command-line tool")
-    endif()
-  endif()
-endif()
-
-
-
-##
-## Check the existence of the required decompression tools
-##
-
-if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
-  find_program(ZIP_EXECUTABLE 7z 
-    PATHS 
-    "$ENV{ProgramFiles}/7-Zip"
-    "$ENV{ProgramW6432}/7-Zip"
-    )
-
-  if (${ZIP_EXECUTABLE} MATCHES "ZIP_EXECUTABLE-NOTFOUND")
-    message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)")
-  endif()
-
-else()
-  find_program(UNZIP_EXECUTABLE unzip)
-  if (${UNZIP_EXECUTABLE} MATCHES "UNZIP_EXECUTABLE-NOTFOUND")
-    message(FATAL_ERROR "Please install the 'unzip' package")
-  endif()
-
-  find_program(TAR_EXECUTABLE tar)
-  if (${TAR_EXECUTABLE} MATCHES "TAR_EXECUTABLE-NOTFOUND")
-    message(FATAL_ERROR "Please install the 'tar' package")
-  endif()
-endif()
-
-
-macro(DownloadPackage MD5 Url TargetDirectory)
-  if (NOT IS_DIRECTORY "${TargetDirectory}")
-    GetUrlFilename(TMP_FILENAME "${Url}")
-
-    set(TMP_PATH "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${TMP_FILENAME}")
-    if (NOT EXISTS "${TMP_PATH}")
-      message("Downloading ${Url}")
-
-      # This fixes issue 6: "I think cmake shouldn't download the
-      # packages which are not in the system, it should stop and let
-      # user know."
-      # https://code.google.com/p/orthanc/issues/detail?id=6
-      if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
-	message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
-      endif()
-
-      file(DOWNLOAD "${Url}" "${TMP_PATH}" 
-        SHOW_PROGRESS EXPECTED_MD5 "${MD5}"
-        TIMEOUT 60 INACTIVITY_TIMEOUT 60)
-    else()
-      message("Using local copy of ${Url}")
-    endif()
-
-    GetUrlExtension(TMP_EXTENSION "${Url}")
-    #message(${TMP_EXTENSION})
-    message("Uncompressing ${TMP_FILENAME}")
-
-    if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
-      # How to silently extract files using 7-zip
-      # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly
-
-      if (("${TMP_EXTENSION}" STREQUAL "gz") OR 
-          ("${TMP_EXTENSION}" STREQUAL "tgz") OR
-          ("${TMP_EXTENSION}" STREQUAL "xz"))
-        execute_process(
-          COMMAND ${ZIP_EXECUTABLE} e -y ${TMP_PATH}
-          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-          RESULT_VARIABLE Failure
-          OUTPUT_QUIET
-          )
-
-        if (Failure)
-          message(FATAL_ERROR "Error while running the uncompression tool")
-        endif()
-
-        if ("${TMP_EXTENSION}" STREQUAL "tgz")
-          string(REGEX REPLACE ".tgz$" ".tar" TMP_FILENAME2 "${TMP_FILENAME}")
-        elseif ("${TMP_EXTENSION}" STREQUAL "gz")
-          string(REGEX REPLACE ".gz$" "" TMP_FILENAME2 "${TMP_FILENAME}")
-        elseif ("${TMP_EXTENSION}" STREQUAL "xz")
-          string(REGEX REPLACE ".xz" "" TMP_FILENAME2 "${TMP_FILENAME}")
-        endif()
-
-        execute_process(
-          COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_FILENAME2}
-          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-          RESULT_VARIABLE Failure
-          OUTPUT_QUIET
-          )
-      elseif ("${TMP_EXTENSION}" STREQUAL "zip")
-        execute_process(
-          COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_PATH}
-          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-          RESULT_VARIABLE Failure
-          OUTPUT_QUIET
-          )
-      else()
-        message(FATAL_ERROR "Support your platform here")
-      endif()
-
-    else()
-      if ("${TMP_EXTENSION}" STREQUAL "zip")
-        execute_process(
-          COMMAND sh -c "${UNZIP_EXECUTABLE} -q ${TMP_PATH}"
-          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-          RESULT_VARIABLE Failure
-        )
-      elseif (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz"))
-        #message("tar xvfz ${TMP_PATH}")
-        execute_process(
-          COMMAND sh -c "${TAR_EXECUTABLE} xfz ${TMP_PATH}"
-          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-          RESULT_VARIABLE Failure
-          )
-      elseif ("${TMP_EXTENSION}" STREQUAL "bz2")
-        execute_process(
-          COMMAND sh -c "${TAR_EXECUTABLE} xfj ${TMP_PATH}"
-          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-          RESULT_VARIABLE Failure
-          )
-      elseif ("${TMP_EXTENSION}" STREQUAL "xz")
-        execute_process(
-          COMMAND sh -c "${TAR_EXECUTABLE} xf ${TMP_PATH}"
-          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-          RESULT_VARIABLE Failure
-          )
-      else()
-        message(FATAL_ERROR "Unknown package format.")
-      endif()
-    endif()
-   
-    if (Failure)
-      message(FATAL_ERROR "Error while running the uncompression tool")
-    endif()
-
-    if (NOT IS_DIRECTORY "${TargetDirectory}")
-      message(FATAL_ERROR "The package was not uncompressed at the proper location. Check the CMake instructions.")
-    endif()
-  endif()
-endmacro()
--- a/Resources/Orthanc/Resources/CMake/JsonCppConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-set(JSONCPP_CXX11 OFF)
-
-if (STATIC_BUILD OR NOT USE_SYSTEM_JSONCPP)
-  if (USE_LEGACY_JSONCPP)
-    set(JSONCPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/jsoncpp-0.10.6)
-    set(JSONCPP_URL "http://www.orthanc-server.com/downloads/third-party/jsoncpp-0.10.6.tar.gz")
-    set(JSONCPP_MD5 "13d1991d79697df8cadbc25c93e37c83")
-    add_definitions(-DORTHANC_LEGACY_JSONCPP=1)
-  else()
-    set(JSONCPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/jsoncpp-1.8.4)
-    set(JSONCPP_URL "http://www.orthanc-server.com/downloads/third-party/jsoncpp-1.8.4.tar.gz")
-    set(JSONCPP_MD5 "fa47a3ab6b381869b6a5f20811198662")
-    add_definitions(-DORTHANC_LEGACY_JSONCPP=0)
-    set(JSONCPP_CXX11 ON)
-  endif()
-
-  DownloadPackage(${JSONCPP_MD5} ${JSONCPP_URL} "${JSONCPP_SOURCES_DIR}")
-
-  set(JSONCPP_SOURCES
-    ${JSONCPP_SOURCES_DIR}/src/lib_json/json_reader.cpp
-    ${JSONCPP_SOURCES_DIR}/src/lib_json/json_value.cpp
-    ${JSONCPP_SOURCES_DIR}/src/lib_json/json_writer.cpp
-    )
-
-  include_directories(
-    ${JSONCPP_SOURCES_DIR}/include
-    )
-
-  source_group(ThirdParty\\JsonCpp REGULAR_EXPRESSION ${JSONCPP_SOURCES_DIR}/.*)
-
-else()
-  find_path(JSONCPP_INCLUDE_DIR json/reader.h
-    /usr/include/jsoncpp
-    /usr/local/include/jsoncpp
-    )
-
-  message("JsonCpp include dir: ${JSONCPP_INCLUDE_DIR}")
-  include_directories(${JSONCPP_INCLUDE_DIR})
-  link_libraries(jsoncpp)
-
-  CHECK_INCLUDE_FILE_CXX(${JSONCPP_INCLUDE_DIR}/json/reader.h HAVE_JSONCPP_H)
-  if (NOT HAVE_JSONCPP_H)
-    message(FATAL_ERROR "Please install the libjsoncpp-dev package")
-  endif()
-
-  # Switch to the C++11 standard if the version of JsonCpp is 1.y.z
-  if (EXISTS ${JSONCPP_INCLUDE_DIR}/json/version.h)
-    file(STRINGS
-      "${JSONCPP_INCLUDE_DIR}/json/version.h" 
-      JSONCPP_VERSION_MAJOR1 REGEX
-      ".*define JSONCPP_VERSION_MAJOR.*")
-
-    if (NOT JSONCPP_VERSION_MAJOR1)
-      message(FATAL_ERROR "Unable to extract the major version of JsonCpp")
-    endif()
-    
-    string(REGEX REPLACE
-      ".*JSONCPP_VERSION_MAJOR.*([0-9]+)$" "\\1" 
-      JSONCPP_VERSION_MAJOR ${JSONCPP_VERSION_MAJOR1})
-    message("JsonCpp major version: ${JSONCPP_VERSION_MAJOR}")
-
-    if (JSONCPP_VERSION_MAJOR GREATER 0)
-      set(JSONCPP_CXX11 ON)
-    endif()
-  else()
-    message("Unable to detect the major version of JsonCpp, assuming < 1.0.0")
-  endif()
-endif()
-
-
-if (JSONCPP_CXX11)
-  # Osimis has encountered problems when this macro is left at its
-  # default value (1000), so we increase this limit
-  # https://gitlab.kitware.com/third-party/jsoncpp/commit/56df2068470241f9043b676bfae415ed62a0c172
-  add_definitions(-DJSONCPP_DEPRECATED_STACK_LIMIT=5000)
-
-  if (CMAKE_COMPILER_IS_GNUCXX OR
-      "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
-    message("Switching to C++11 standard in gcc/clang, as version of JsonCpp is >= 1.0.0")
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-deprecated-declarations")
-  endif()
-endif()
--- a/Resources/Orthanc/Resources/CMake/LibCurlConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,323 +0,0 @@
-if (STATIC_BUILD OR NOT USE_SYSTEM_CURL)
-  SET(CURL_SOURCES_DIR ${CMAKE_BINARY_DIR}/curl-7.57.0)
-  SET(CURL_URL "http://www.orthanc-server.com/downloads/third-party/curl-7.57.0.tar.gz")
-  SET(CURL_MD5 "c7aab73aaf5e883ca1d7518f93649dc2")
-
-  if (IS_DIRECTORY "${CURL_SOURCES_DIR}")
-    set(FirstRun OFF)
-  else()
-    set(FirstRun ON)
-  endif()
-  
-  DownloadPackage(${CURL_MD5} ${CURL_URL} "${CURL_SOURCES_DIR}")
-
-  if (FirstRun)
-    execute_process(
-      COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
-      ${ORTHANC_ROOT}/Resources/Patches/curl-7.57.0-cmake.patch
-      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-      RESULT_VARIABLE Failure
-      )
-    
-    if (Failure)
-      message(FATAL_ERROR "Error while patching a file")
-    endif()
-  endif()
-  
-  include_directories(
-    ${CURL_SOURCES_DIR}/include
-    )
-
-  AUX_SOURCE_DIRECTORY(${CURL_SOURCES_DIR}/lib CURL_SOURCES)
-  AUX_SOURCE_DIRECTORY(${CURL_SOURCES_DIR}/lib/vauth CURL_SOURCES)
-  AUX_SOURCE_DIRECTORY(${CURL_SOURCES_DIR}/lib/vtls CURL_SOURCES)
-  source_group(ThirdParty\\LibCurl REGULAR_EXPRESSION ${CURL_SOURCES_DIR}/.*)
-
-  add_definitions(
-    -DBUILDING_LIBCURL=1
-    -DCURL_STATICLIB=1
-    -DCURL_DISABLE_LDAPS=1
-    -DCURL_DISABLE_LDAP=1
-    -DCURL_DISABLE_DICT=1
-    -DCURL_DISABLE_FILE=1
-    -DCURL_DISABLE_FTP=1
-    -DCURL_DISABLE_GOPHER=1
-    -DCURL_DISABLE_LDAP=1
-    -DCURL_DISABLE_LDAPS=1
-    -DCURL_DISABLE_POP3=1
-    #-DCURL_DISABLE_PROXY=1
-    -DCURL_DISABLE_RTSP=1
-    -DCURL_DISABLE_TELNET=1
-    -DCURL_DISABLE_TFTP=1
-    )
-
-  if (ENABLE_SSL)
-    add_definitions(
-      #-DHAVE_LIBSSL=1
-      -DUSE_OPENSSL=1
-      -DHAVE_OPENSSL_ENGINE_H=1
-      -DUSE_SSLEAY=1
-      )
-  endif()
-
-  if (NOT EXISTS "${CURL_SOURCES_DIR}/lib/curl_config.h")
-    #file(WRITE ${CURL_SOURCES_DIR}/lib/curl_config.h "")
-
-    file(WRITE ${CURL_SOURCES_DIR}/lib/vauth/vauth/vauth.h "#include \"../vauth.h\"\n")
-    file(WRITE ${CURL_SOURCES_DIR}/lib/vauth/vauth/digest.h "#include \"../digest.h\"\n")
-    file(WRITE ${CURL_SOURCES_DIR}/lib/vauth/vauth/ntlm.h "#include \"../ntlm.h\"\n")
-    file(WRITE ${CURL_SOURCES_DIR}/lib/vauth/vtls/vtls.h "#include \"../../vtls/vtls.h\"\n")
-
-    file(GLOB CURL_LIBS_HEADERS ${CURL_SOURCES_DIR}/lib/*.h)
-    foreach (header IN LISTS CURL_LIBS_HEADERS)
-      get_filename_component(filename ${header} NAME)
-      file(WRITE ${CURL_SOURCES_DIR}/lib/vauth/${filename} "#include \"../${filename}\"\n")
-      file(WRITE ${CURL_SOURCES_DIR}/lib/vtls/${filename} "#include \"../${filename}\"\n")
-    endforeach()
-  endif()
-
-  if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-    if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
-      SET(TMP_OS "x86_64")
-    else()
-      SET(TMP_OS "x86")
-    endif()
-
-    set_property(
-      SOURCE ${CURL_SOURCES}
-      PROPERTY COMPILE_DEFINITIONS "HAVE_CONFIG_H=1;OS=\"${TMP_OS}\""
-      )
-   
-    include(${CURL_SOURCES_DIR}/CMake/Macros.cmake)
-
-    # WARNING: Do *not* reorder the "check_include_file_concat()" below!
-    check_include_file_concat("stdio.h"          HAVE_STDIO_H)
-    check_include_file_concat("inttypes.h"       HAVE_INTTYPES_H)
-    check_include_file_concat("sys/filio.h"      HAVE_SYS_FILIO_H)
-    check_include_file_concat("sys/ioctl.h"      HAVE_SYS_IOCTL_H)
-    check_include_file_concat("sys/param.h"      HAVE_SYS_PARAM_H)
-    check_include_file_concat("sys/poll.h"       HAVE_SYS_POLL_H)
-    check_include_file_concat("sys/resource.h"   HAVE_SYS_RESOURCE_H)
-    check_include_file_concat("sys/select.h"     HAVE_SYS_SELECT_H)
-    check_include_file_concat("sys/socket.h"     HAVE_SYS_SOCKET_H)
-    check_include_file_concat("sys/sockio.h"     HAVE_SYS_SOCKIO_H)
-    check_include_file_concat("sys/stat.h"       HAVE_SYS_STAT_H)
-    check_include_file_concat("sys/time.h"       HAVE_SYS_TIME_H)
-    check_include_file_concat("sys/types.h"      HAVE_SYS_TYPES_H)
-    check_include_file_concat("sys/uio.h"        HAVE_SYS_UIO_H)
-    check_include_file_concat("sys/un.h"         HAVE_SYS_UN_H)
-    check_include_file_concat("sys/utime.h"      HAVE_SYS_UTIME_H)
-    check_include_file_concat("sys/xattr.h"      HAVE_SYS_XATTR_H)
-    check_include_file_concat("alloca.h"         HAVE_ALLOCA_H)
-    check_include_file_concat("arpa/inet.h"      HAVE_ARPA_INET_H)
-    check_include_file_concat("arpa/tftp.h"      HAVE_ARPA_TFTP_H)
-    check_include_file_concat("assert.h"         HAVE_ASSERT_H)
-    check_include_file_concat("crypto.h"         HAVE_CRYPTO_H)
-    check_include_file_concat("des.h"            HAVE_DES_H)
-    check_include_file_concat("err.h"            HAVE_ERR_H)
-    check_include_file_concat("errno.h"          HAVE_ERRNO_H)
-    check_include_file_concat("fcntl.h"          HAVE_FCNTL_H)
-    check_include_file_concat("idn2.h"           HAVE_IDN2_H)
-    check_include_file_concat("ifaddrs.h"        HAVE_IFADDRS_H)
-    check_include_file_concat("io.h"             HAVE_IO_H)
-    check_include_file_concat("krb.h"            HAVE_KRB_H)
-    check_include_file_concat("libgen.h"         HAVE_LIBGEN_H)
-    check_include_file_concat("limits.h"         HAVE_LIMITS_H)
-    check_include_file_concat("locale.h"         HAVE_LOCALE_H)
-    check_include_file_concat("net/if.h"         HAVE_NET_IF_H)
-    check_include_file_concat("netdb.h"          HAVE_NETDB_H)
-    check_include_file_concat("netinet/in.h"     HAVE_NETINET_IN_H)
-    check_include_file_concat("netinet/tcp.h"    HAVE_NETINET_TCP_H)
-
-    check_include_file_concat("pem.h"            HAVE_PEM_H)
-    check_include_file_concat("poll.h"           HAVE_POLL_H)
-    check_include_file_concat("pwd.h"            HAVE_PWD_H)
-    check_include_file_concat("rsa.h"            HAVE_RSA_H)
-    check_include_file_concat("setjmp.h"         HAVE_SETJMP_H)
-    check_include_file_concat("sgtty.h"          HAVE_SGTTY_H)
-    check_include_file_concat("signal.h"         HAVE_SIGNAL_H)
-    check_include_file_concat("ssl.h"            HAVE_SSL_H)
-    check_include_file_concat("stdbool.h"        HAVE_STDBOOL_H)
-    check_include_file_concat("stdint.h"         HAVE_STDINT_H)
-    check_include_file_concat("stdio.h"          HAVE_STDIO_H)
-    check_include_file_concat("stdlib.h"         HAVE_STDLIB_H)
-    check_include_file_concat("string.h"         HAVE_STRING_H)
-    check_include_file_concat("strings.h"        HAVE_STRINGS_H)
-    check_include_file_concat("stropts.h"        HAVE_STROPTS_H)
-    check_include_file_concat("termio.h"         HAVE_TERMIO_H)
-    check_include_file_concat("termios.h"        HAVE_TERMIOS_H)
-    check_include_file_concat("time.h"           HAVE_TIME_H)
-    check_include_file_concat("unistd.h"         HAVE_UNISTD_H)
-    check_include_file_concat("utime.h"          HAVE_UTIME_H)
-    check_include_file_concat("x509.h"           HAVE_X509_H)
-
-    check_include_file_concat("process.h"        HAVE_PROCESS_H)
-    check_include_file_concat("stddef.h"         HAVE_STDDEF_H)
-    check_include_file_concat("dlfcn.h"          HAVE_DLFCN_H)
-    check_include_file_concat("malloc.h"         HAVE_MALLOC_H)
-    check_include_file_concat("memory.h"         HAVE_MEMORY_H)
-    check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
-    check_include_file_concat("stdint.h"        HAVE_STDINT_H)
-    check_include_file_concat("sockio.h"        HAVE_SOCKIO_H)
-    check_include_file_concat("sys/utsname.h"   HAVE_SYS_UTSNAME_H)
-
-    check_type_size("size_t"  SIZEOF_SIZE_T)
-    check_type_size("ssize_t"  SIZEOF_SSIZE_T)
-    check_type_size("long long"  SIZEOF_LONG_LONG)
-    check_type_size("long"  SIZEOF_LONG)
-    check_type_size("short"  SIZEOF_SHORT)
-    check_type_size("int"  SIZEOF_INT)
-    check_type_size("__int64"  SIZEOF___INT64)
-    check_type_size("long double"  SIZEOF_LONG_DOUBLE)
-    check_type_size("time_t"  SIZEOF_TIME_T)
-    check_type_size("off_t"  SIZEOF_OFF_T)
-    check_type_size("socklen_t" CURL_SIZEOF_CURL_SOCKLEN_T)
-
-    check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
-    check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
-    # poll on macOS is unreliable, it first did not exist, then was broken until
-    # fixed in 10.9 only to break again in 10.12.
-    if(NOT APPLE)
-      check_symbol_exists(poll        "${CURL_INCLUDES}" HAVE_POLL)
-    endif()
-    check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
-    check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
-    check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
-    check_symbol_exists(strtok_r      "${CURL_INCLUDES}" HAVE_STRTOK_R)
-    check_symbol_exists(strftime      "${CURL_INCLUDES}" HAVE_STRFTIME)
-    check_symbol_exists(uname         "${CURL_INCLUDES}" HAVE_UNAME)
-    check_symbol_exists(strcasecmp    "${CURL_INCLUDES}" HAVE_STRCASECMP)
-    check_symbol_exists(stricmp       "${CURL_INCLUDES}" HAVE_STRICMP)
-    check_symbol_exists(strcmpi       "${CURL_INCLUDES}" HAVE_STRCMPI)
-    check_symbol_exists(strncmpi      "${CURL_INCLUDES}" HAVE_STRNCMPI)
-    check_symbol_exists(alarm         "${CURL_INCLUDES}" HAVE_ALARM)
-    if(NOT HAVE_STRNCMPI)
-      set(HAVE_STRCMPI)
-    endif(NOT HAVE_STRNCMPI)
-
-    check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
-    check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
-    check_symbol_exists(gettimeofday  "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
-    check_symbol_exists(inet_addr     "${CURL_INCLUDES}" HAVE_INET_ADDR)
-    check_symbol_exists(inet_ntoa     "${CURL_INCLUDES}" HAVE_INET_NTOA)
-    check_symbol_exists(inet_ntoa_r   "${CURL_INCLUDES}" HAVE_INET_NTOA_R)
-    check_symbol_exists(tcsetattr     "${CURL_INCLUDES}" HAVE_TCSETATTR)
-    check_symbol_exists(tcgetattr     "${CURL_INCLUDES}" HAVE_TCGETATTR)
-    check_symbol_exists(perror        "${CURL_INCLUDES}" HAVE_PERROR)
-    check_symbol_exists(closesocket   "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
-    check_symbol_exists(setvbuf       "${CURL_INCLUDES}" HAVE_SETVBUF)
-    check_symbol_exists(sigsetjmp     "${CURL_INCLUDES}" HAVE_SIGSETJMP)
-    check_symbol_exists(getpass_r     "${CURL_INCLUDES}" HAVE_GETPASS_R)
-    check_symbol_exists(strlcat       "${CURL_INCLUDES}" HAVE_STRLCAT)
-    check_symbol_exists(getpwuid      "${CURL_INCLUDES}" HAVE_GETPWUID)
-    check_symbol_exists(geteuid       "${CURL_INCLUDES}" HAVE_GETEUID)
-    check_symbol_exists(utime         "${CURL_INCLUDES}" HAVE_UTIME)
-    check_symbol_exists(gmtime_r      "${CURL_INCLUDES}" HAVE_GMTIME_R)
-    check_symbol_exists(localtime_r   "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
-
-    check_symbol_exists(gethostbyname   "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME)
-    check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
-
-    check_symbol_exists(signal        "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC)
-    check_symbol_exists(SIGALRM       "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
-    if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
-      set(HAVE_SIGNAL 1)
-    endif(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
-    check_symbol_exists(uname          "${CURL_INCLUDES}" HAVE_UNAME)
-    check_symbol_exists(strtoll        "${CURL_INCLUDES}" HAVE_STRTOLL)
-    check_symbol_exists(_strtoi64      "${CURL_INCLUDES}" HAVE__STRTOI64)
-    check_symbol_exists(strerror_r     "${CURL_INCLUDES}" HAVE_STRERROR_R)
-    check_symbol_exists(siginterrupt   "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
-    check_symbol_exists(perror         "${CURL_INCLUDES}" HAVE_PERROR)
-    check_symbol_exists(fork           "${CURL_INCLUDES}" HAVE_FORK)
-    check_symbol_exists(getaddrinfo    "${CURL_INCLUDES}" HAVE_GETADDRINFO)
-    check_symbol_exists(freeaddrinfo   "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
-    check_symbol_exists(freeifaddrs    "${CURL_INCLUDES}" HAVE_FREEIFADDRS)
-    check_symbol_exists(pipe           "${CURL_INCLUDES}" HAVE_PIPE)
-    check_symbol_exists(ftruncate      "${CURL_INCLUDES}" HAVE_FTRUNCATE)
-    check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
-    check_symbol_exists(getrlimit      "${CURL_INCLUDES}" HAVE_GETRLIMIT)
-    check_symbol_exists(setlocale      "${CURL_INCLUDES}" HAVE_SETLOCALE)
-    check_symbol_exists(setmode        "${CURL_INCLUDES}" HAVE_SETMODE)
-    check_symbol_exists(setrlimit      "${CURL_INCLUDES}" HAVE_SETRLIMIT)
-    check_symbol_exists(fcntl          "${CURL_INCLUDES}" HAVE_FCNTL)
-    check_symbol_exists(ioctl          "${CURL_INCLUDES}" HAVE_IOCTL)
-    check_symbol_exists(setsockopt     "${CURL_INCLUDES}" HAVE_SETSOCKOPT)
-
-    if(HAVE_SIZEOF_LONG_LONG)
-      set(HAVE_LONGLONG 1)
-      set(HAVE_LL 1)
-    endif(HAVE_SIZEOF_LONG_LONG)
-
-    check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
-    check_function_exists(gethostname HAVE_GETHOSTNAME)
-
-    check_include_file_concat("pthread.h" HAVE_PTHREAD_H)
-    check_symbol_exists(recv "sys/socket.h" HAVE_RECV)
-    check_symbol_exists(send "sys/socket.h" HAVE_SEND)
-
-    check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS)
-
-    set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCES_DIR}/include")
-    set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h")
-    check_type_size("curl_off_t"  SIZEOF_CURL_OFF_T)
-
-    add_definitions(-DHAVE_GLIBC_STRERROR_R=1)
-
-    include(${CURL_SOURCES_DIR}/CMake/OtherTests.cmake)
-
-    foreach(CURL_TEST
-        HAVE_FCNTL_O_NONBLOCK
-        HAVE_IOCTLSOCKET
-        HAVE_IOCTLSOCKET_CAMEL
-        HAVE_IOCTLSOCKET_CAMEL_FIONBIO
-        HAVE_IOCTLSOCKET_FIONBIO
-        HAVE_IOCTL_FIONBIO
-        HAVE_IOCTL_SIOCGIFADDR
-        HAVE_SETSOCKOPT_SO_NONBLOCK
-        HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
-        TIME_WITH_SYS_TIME
-        HAVE_O_NONBLOCK
-        HAVE_GETHOSTBYADDR_R_5
-        HAVE_GETHOSTBYADDR_R_7
-        HAVE_GETHOSTBYADDR_R_8
-        HAVE_GETHOSTBYADDR_R_5_REENTRANT
-        HAVE_GETHOSTBYADDR_R_7_REENTRANT
-        HAVE_GETHOSTBYADDR_R_8_REENTRANT
-        HAVE_GETHOSTBYNAME_R_3
-        HAVE_GETHOSTBYNAME_R_5
-        HAVE_GETHOSTBYNAME_R_6
-        HAVE_GETHOSTBYNAME_R_3_REENTRANT
-        HAVE_GETHOSTBYNAME_R_5_REENTRANT
-        HAVE_GETHOSTBYNAME_R_6_REENTRANT
-        HAVE_SOCKLEN_T
-        HAVE_IN_ADDR_T
-        HAVE_BOOL_T
-        STDC_HEADERS
-        RETSIGTYPE_TEST
-        HAVE_INET_NTOA_R_DECL
-        HAVE_INET_NTOA_R_DECL_REENTRANT
-        HAVE_GETADDRINFO
-        HAVE_FILE_OFFSET_BITS
-        )
-      curl_internal_test(${CURL_TEST})
-    endforeach(CURL_TEST)
-
-    configure_file(
-      ${CURL_SOURCES_DIR}/lib/curl_config.h.cmake
-      ${CURL_SOURCES_DIR}/lib/curl_config.h
-      )
-  endif()
-else()
-  include(FindCURL)
-  include_directories(${CURL_INCLUDE_DIRS})
-  link_libraries(${CURL_LIBRARIES})
-
-  if (NOT ${CURL_FOUND})
-    message(FATAL_ERROR "Unable to find LibCurl")
-  endif()
-endif()
--- a/Resources/Orthanc/Resources/CMake/LibIconvConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-if (NOT ENABLE_LOCALE)
-  message("Support for locales is disabled")
-
-elseif (NOT USE_BOOST_ICONV)
-  message("Not using libiconv")
-
-else()
-  message("Using libiconv")
-
-  if (STATIC_BUILD OR NOT USE_SYSTEM_LIBICONV)
-    set(LIBICONV_SOURCES_DIR ${CMAKE_BINARY_DIR}/libiconv-1.15)
-    set(LIBICONV_URL "http://www.orthanc-server.com/downloads/third-party/libiconv-1.15.tar.gz")
-    set(LIBICONV_MD5 "ace8b5f2db42f7b3b3057585e80d9808")
-
-    DownloadPackage(${LIBICONV_MD5} ${LIBICONV_URL} "${LIBICONV_SOURCES_DIR}")
-
-    # Disable the support of libiconv that is shipped by default with
-    # the C standard library on Linux. Setting this macro redirects
-    # calls from "iconv*()" to "libiconv*()" by defining macros in the
-    # C headers of "libiconv-1.15".
-    add_definitions(-DLIBICONV_PLUG=1)
-
-    # https://groups.google.com/d/msg/android-ndk/AS1nkxnk6m4/EQm09hD1tigJ
-    add_definitions(
-      -DBUILDING_LIBICONV=1
-      -DIN_LIBRARY=1
-      -DLIBDIR=""
-      -DICONV_CONST=
-      )
-
-    configure_file(
-      ${LIBICONV_SOURCES_DIR}/srclib/localcharset.h
-      ${LIBICONV_SOURCES_DIR}/include
-      COPYONLY)
-
-    set(HAVE_VISIBILITY 0)
-    set(ICONV_CONST ${ICONV_CONST})
-    set(USE_MBSTATE_T 1)
-    set(BROKEN_WCHAR_H 0)
-    set(EILSEQ)
-    set(HAVE_WCHAR_T 1)
-    configure_file(
-      ${LIBICONV_SOURCES_DIR}/include/iconv.h.build.in
-      ${LIBICONV_SOURCES_DIR}/include/iconv.h
-      )
-    unset(HAVE_VISIBILITY)
-    unset(ICONV_CONST)
-    unset(USE_MBSTATE_T)
-    unset(BROKEN_WCHAR_H)
-    unset(EILSEQ)
-    unset(HAVE_WCHAR_T)
-
-    if (NOT EXISTS ${LIBICONV_SOURCES_DIR}/include/config.h)
-      # Create an empty "config.h" for libiconv
-      file(WRITE ${LIBICONV_SOURCES_DIR}/include/config.h "")
-    endif()
-
-    include_directories(
-      ${LIBICONV_SOURCES_DIR}/include
-      )
-
-    set(LIBICONV_SOURCES
-      ${LIBICONV_SOURCES_DIR}/lib/iconv.c  
-      ${LIBICONV_SOURCES_DIR}/lib/relocatable.c
-      ${LIBICONV_SOURCES_DIR}/libcharset/lib/localcharset.c  
-      ${LIBICONV_SOURCES_DIR}/libcharset/lib/relocatable.c
-      )
-
-    source_group(ThirdParty\\libiconv REGULAR_EXPRESSION ${LIBICONV_SOURCES_DIR}/.*)
-
-    if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
-      add_definitions(-DHAVE_WORKING_O_NOFOLLOW=0)
-    else()
-      add_definitions(-DHAVE_WORKING_O_NOFOLLOW=1)
-    endif()
-
-  else() 
-    CHECK_INCLUDE_FILE_CXX(iconv.h HAVE_ICONV_H)
-    if (NOT HAVE_ICONV_H)
-      message(FATAL_ERROR "Please install the libiconv-dev package")
-    endif()
-
-    # Check whether the support for libiconv is bundled within the
-    # standard C library
-    CHECK_FUNCTION_EXISTS(iconv_open HAVE_ICONV_LIB)
-    if (NOT HAVE_ICONV_LIB)
-      # No builtin support for libiconv, try and find an external library.
-      # Open question: Does this make sense on any platform?
-      CHECK_LIBRARY_EXISTS(iconv iconv_open "" HAVE_ICONV_LIB_2)
-      if (NOT HAVE_ICONV_LIB_2)
-        message(FATAL_ERROR "Please install the libiconv-dev package")
-      else()
-        link_libraries(iconv)
-      endif()
-    endif()
-
-  endif()
-endif()
--- a/Resources/Orthanc/Resources/CMake/LibJpegConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-if (STATIC_BUILD OR NOT USE_SYSTEM_LIBJPEG)
-  set(LIBJPEG_SOURCES_DIR ${CMAKE_BINARY_DIR}/jpeg-9a)
-  DownloadPackage(
-    "3353992aecaee1805ef4109aadd433e7"
-    "http://www.orthanc-server.com/downloads/third-party/jpegsrc.v9a.tar.gz"
-    "${LIBJPEG_SOURCES_DIR}")
-
-  include_directories(
-    ${LIBJPEG_SOURCES_DIR}
-    )
-
-  list(APPEND LIBJPEG_SOURCES 
-    ${LIBJPEG_SOURCES_DIR}/jaricom.c
-    ${LIBJPEG_SOURCES_DIR}/jcapimin.c
-    ${LIBJPEG_SOURCES_DIR}/jcapistd.c
-    ${LIBJPEG_SOURCES_DIR}/jcarith.c
-    ${LIBJPEG_SOURCES_DIR}/jccoefct.c
-    ${LIBJPEG_SOURCES_DIR}/jccolor.c
-    ${LIBJPEG_SOURCES_DIR}/jcdctmgr.c
-    ${LIBJPEG_SOURCES_DIR}/jchuff.c
-    ${LIBJPEG_SOURCES_DIR}/jcinit.c
-    ${LIBJPEG_SOURCES_DIR}/jcmarker.c
-    ${LIBJPEG_SOURCES_DIR}/jcmaster.c
-    ${LIBJPEG_SOURCES_DIR}/jcomapi.c
-    ${LIBJPEG_SOURCES_DIR}/jcparam.c
-    ${LIBJPEG_SOURCES_DIR}/jcprepct.c
-    ${LIBJPEG_SOURCES_DIR}/jcsample.c
-    ${LIBJPEG_SOURCES_DIR}/jctrans.c
-    ${LIBJPEG_SOURCES_DIR}/jdapimin.c
-    ${LIBJPEG_SOURCES_DIR}/jdapistd.c
-    ${LIBJPEG_SOURCES_DIR}/jdarith.c
-    ${LIBJPEG_SOURCES_DIR}/jdatadst.c
-    ${LIBJPEG_SOURCES_DIR}/jdatasrc.c
-    ${LIBJPEG_SOURCES_DIR}/jdcoefct.c
-    ${LIBJPEG_SOURCES_DIR}/jdcolor.c
-    ${LIBJPEG_SOURCES_DIR}/jddctmgr.c
-    ${LIBJPEG_SOURCES_DIR}/jdhuff.c
-    ${LIBJPEG_SOURCES_DIR}/jdinput.c
-    ${LIBJPEG_SOURCES_DIR}/jcmainct.c
-    ${LIBJPEG_SOURCES_DIR}/jdmainct.c
-    ${LIBJPEG_SOURCES_DIR}/jdmarker.c
-    ${LIBJPEG_SOURCES_DIR}/jdmaster.c
-    ${LIBJPEG_SOURCES_DIR}/jdmerge.c
-    ${LIBJPEG_SOURCES_DIR}/jdpostct.c
-    ${LIBJPEG_SOURCES_DIR}/jdsample.c
-    ${LIBJPEG_SOURCES_DIR}/jdtrans.c
-    ${LIBJPEG_SOURCES_DIR}/jerror.c
-    ${LIBJPEG_SOURCES_DIR}/jfdctflt.c
-    ${LIBJPEG_SOURCES_DIR}/jfdctfst.c
-    ${LIBJPEG_SOURCES_DIR}/jfdctint.c
-    ${LIBJPEG_SOURCES_DIR}/jidctflt.c
-    ${LIBJPEG_SOURCES_DIR}/jidctfst.c
-    ${LIBJPEG_SOURCES_DIR}/jidctint.c
-    #${LIBJPEG_SOURCES_DIR}/jmemansi.c
-    #${LIBJPEG_SOURCES_DIR}/jmemdos.c
-    #${LIBJPEG_SOURCES_DIR}/jmemmac.c
-    ${LIBJPEG_SOURCES_DIR}/jmemmgr.c
-    #${LIBJPEG_SOURCES_DIR}/jmemname.c
-    ${LIBJPEG_SOURCES_DIR}/jmemnobs.c
-    ${LIBJPEG_SOURCES_DIR}/jquant1.c
-    ${LIBJPEG_SOURCES_DIR}/jquant2.c
-    ${LIBJPEG_SOURCES_DIR}/jutils.c
-
-    # ${LIBJPEG_SOURCES_DIR}/rdbmp.c
-    # ${LIBJPEG_SOURCES_DIR}/rdcolmap.c
-    # ${LIBJPEG_SOURCES_DIR}/rdgif.c
-    # ${LIBJPEG_SOURCES_DIR}/rdppm.c
-    # ${LIBJPEG_SOURCES_DIR}/rdrle.c
-    # ${LIBJPEG_SOURCES_DIR}/rdswitch.c
-    # ${LIBJPEG_SOURCES_DIR}/rdtarga.c
-    # ${LIBJPEG_SOURCES_DIR}/transupp.c
-    # ${LIBJPEG_SOURCES_DIR}/wrbmp.c
-    # ${LIBJPEG_SOURCES_DIR}/wrgif.c
-    # ${LIBJPEG_SOURCES_DIR}/wrppm.c
-    # ${LIBJPEG_SOURCES_DIR}/wrrle.c
-    # ${LIBJPEG_SOURCES_DIR}/wrtarga.c
-    )
-
-  configure_file(
-    ${LIBJPEG_SOURCES_DIR}/jconfig.txt
-    ${LIBJPEG_SOURCES_DIR}/jconfig.h COPYONLY
-    )
-
-  source_group(ThirdParty\\libjpeg REGULAR_EXPRESSION ${LIBJPEG_SOURCES_DIR}/.*)
-
-else()
-  include(FindJPEG)
-
-  if (NOT ${JPEG_FOUND})
-    message(FATAL_ERROR "Unable to find libjpeg")
-  endif()
-
-  include_directories(${JPEG_INCLUDE_DIR})
-  link_libraries(${JPEG_LIBRARIES})
-endif()
--- a/Resources/Orthanc/Resources/CMake/LibPngConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-if (STATIC_BUILD OR NOT USE_SYSTEM_LIBPNG)
-  SET(LIBPNG_SOURCES_DIR ${CMAKE_BINARY_DIR}/libpng-1.5.12)
-  SET(LIBPNG_URL "http://www.orthanc-server.com/downloads/third-party/libpng-1.5.12.tar.gz")
-  SET(LIBPNG_MD5 "8ea7f60347a306c5faf70b977fa80e28")
-
-  DownloadPackage(${LIBPNG_MD5} ${LIBPNG_URL} "${LIBPNG_SOURCES_DIR}")
-
-  include_directories(
-    ${LIBPNG_SOURCES_DIR}
-    )
-
-  configure_file(
-    ${LIBPNG_SOURCES_DIR}/scripts/pnglibconf.h.prebuilt
-    ${LIBPNG_SOURCES_DIR}/pnglibconf.h
-    )
-
-  set(LIBPNG_SOURCES
-    #${LIBPNG_SOURCES_DIR}/example.c
-    ${LIBPNG_SOURCES_DIR}/png.c
-    ${LIBPNG_SOURCES_DIR}/pngerror.c
-    ${LIBPNG_SOURCES_DIR}/pngget.c
-    ${LIBPNG_SOURCES_DIR}/pngmem.c
-    ${LIBPNG_SOURCES_DIR}/pngpread.c
-    ${LIBPNG_SOURCES_DIR}/pngread.c
-    ${LIBPNG_SOURCES_DIR}/pngrio.c
-    ${LIBPNG_SOURCES_DIR}/pngrtran.c
-    ${LIBPNG_SOURCES_DIR}/pngrutil.c
-    ${LIBPNG_SOURCES_DIR}/pngset.c
-    #${LIBPNG_SOURCES_DIR}/pngtest.c
-    ${LIBPNG_SOURCES_DIR}/pngtrans.c
-    ${LIBPNG_SOURCES_DIR}/pngwio.c
-    ${LIBPNG_SOURCES_DIR}/pngwrite.c
-    ${LIBPNG_SOURCES_DIR}/pngwtran.c
-    ${LIBPNG_SOURCES_DIR}/pngwutil.c
-    )
-
-  #set_property(
-  #  SOURCE ${LIBPNG_SOURCES}
-  #  PROPERTY COMPILE_FLAGS -UHAVE_CONFIG_H)
-
-  add_definitions(
-    -DPNG_NO_CONSOLE_IO=1
-    -DPNG_NO_STDIO=1
-    # The following declaration avoids "__declspec(dllexport)" in
-    # libpng to prevent publicly exposing its symbols by the DLLs
-    -DPNG_IMPEXP=
-    )
-
-  source_group(ThirdParty\\libpng REGULAR_EXPRESSION ${LIBPNG_SOURCES_DIR}/.*)
-
-else()
-  include(FindPNG)
-
-  if (NOT ${PNG_FOUND})
-    message(FATAL_ERROR "Unable to find libpng")
-  endif()
-
-  include_directories(${PNG_INCLUDE_DIRS})
-  link_libraries(${PNG_LIBRARIES})
-  add_definitions(${PNG_DEFINITIONS})
-endif()
--- a/Resources/Orthanc/Resources/CMake/OpenSslConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-if (STATIC_BUILD OR NOT USE_SYSTEM_OPENSSL)
-  # WARNING - We had to repack the upstream ".tar.gz" file to a ZIP
-  # file, as the upstream distribution ships symbolic links that are
-  # not always properly handled when uncompressing on Windows.
-
-  SET(OPENSSL_SOURCES_DIR ${CMAKE_BINARY_DIR}/openssl-1.0.2d)
-  SET(OPENSSL_URL "http://www.orthanc-server.com/downloads/third-party/openssl-1.0.2d.zip")
-  SET(OPENSSL_MD5 "4b2ac15fc6db17f3dadc54482d3eee85")
-
-  if (IS_DIRECTORY "${OPENSSL_SOURCES_DIR}")
-    set(FirstRun OFF)
-  else()
-    set(FirstRun ON)
-  endif()
-
-  DownloadPackage(${OPENSSL_MD5} ${OPENSSL_URL} "${OPENSSL_SOURCES_DIR}")
-
-  add_definitions(
-    -DOPENSSL_THREADS
-    -DOPENSSL_IA32_SSE2
-    -DOPENSSL_NO_ASM
-    -DOPENSSL_NO_DYNAMIC_ENGINE
-    -DNO_WINDOWS_BRAINDEATH
-
-    -DOPENSSL_NO_BF 
-    -DOPENSSL_NO_CAMELLIA
-    -DOPENSSL_NO_CAST 
-    -DOPENSSL_NO_EC_NISTP_64_GCC_128
-    -DOPENSSL_NO_GMP
-    -DOPENSSL_NO_GOST
-    -DOPENSSL_NO_HW
-    -DOPENSSL_NO_JPAKE
-    -DOPENSSL_NO_IDEA
-    -DOPENSSL_NO_KRB5 
-    -DOPENSSL_NO_MD2 
-    -DOPENSSL_NO_MDC2 
-    -DOPENSSL_NO_MD4
-    -DOPENSSL_NO_RC2 
-    -DOPENSSL_NO_RC4 
-    -DOPENSSL_NO_RC5 
-    -DOPENSSL_NO_RFC3779
-    -DOPENSSL_NO_SCTP
-    -DOPENSSL_NO_STORE
-    -DOPENSSL_NO_SEED
-    -DOPENSSL_NO_WHIRLPOOL
-    -DOPENSSL_NO_RIPEMD
-    )
-
-  include_directories(
-    ${OPENSSL_SOURCES_DIR}
-    ${OPENSSL_SOURCES_DIR}/crypto
-    ${OPENSSL_SOURCES_DIR}/crypto/asn1
-    ${OPENSSL_SOURCES_DIR}/crypto/modes
-    ${OPENSSL_SOURCES_DIR}/crypto/evp
-    ${OPENSSL_SOURCES_DIR}/include
-    )
-
-  set(OPENSSL_SOURCES_SUBDIRS
-    ${OPENSSL_SOURCES_DIR}/crypto
-    ${OPENSSL_SOURCES_DIR}/crypto/aes
-    ${OPENSSL_SOURCES_DIR}/crypto/asn1
-    ${OPENSSL_SOURCES_DIR}/crypto/bio
-    ${OPENSSL_SOURCES_DIR}/crypto/bn
-    ${OPENSSL_SOURCES_DIR}/crypto/buffer
-    ${OPENSSL_SOURCES_DIR}/crypto/cmac
-    ${OPENSSL_SOURCES_DIR}/crypto/cms
-    ${OPENSSL_SOURCES_DIR}/crypto/comp
-    ${OPENSSL_SOURCES_DIR}/crypto/conf
-    ${OPENSSL_SOURCES_DIR}/crypto/des
-    ${OPENSSL_SOURCES_DIR}/crypto/dh
-    ${OPENSSL_SOURCES_DIR}/crypto/dsa
-    ${OPENSSL_SOURCES_DIR}/crypto/dso
-    ${OPENSSL_SOURCES_DIR}/crypto/engine
-    ${OPENSSL_SOURCES_DIR}/crypto/err
-    ${OPENSSL_SOURCES_DIR}/crypto/evp
-    ${OPENSSL_SOURCES_DIR}/crypto/hmac
-    ${OPENSSL_SOURCES_DIR}/crypto/lhash
-    ${OPENSSL_SOURCES_DIR}/crypto/md5
-    ${OPENSSL_SOURCES_DIR}/crypto/modes
-    ${OPENSSL_SOURCES_DIR}/crypto/objects
-    ${OPENSSL_SOURCES_DIR}/crypto/ocsp
-    ${OPENSSL_SOURCES_DIR}/crypto/pem
-    ${OPENSSL_SOURCES_DIR}/crypto/pkcs12
-    ${OPENSSL_SOURCES_DIR}/crypto/pkcs7
-    ${OPENSSL_SOURCES_DIR}/crypto/pqueue
-    ${OPENSSL_SOURCES_DIR}/crypto/rand
-    ${OPENSSL_SOURCES_DIR}/crypto/rsa
-    ${OPENSSL_SOURCES_DIR}/crypto/sha
-    ${OPENSSL_SOURCES_DIR}/crypto/srp
-    ${OPENSSL_SOURCES_DIR}/crypto/stack
-    ${OPENSSL_SOURCES_DIR}/crypto/ts
-    ${OPENSSL_SOURCES_DIR}/crypto/txt_db
-    ${OPENSSL_SOURCES_DIR}/crypto/ui
-    ${OPENSSL_SOURCES_DIR}/crypto/x509
-    ${OPENSSL_SOURCES_DIR}/crypto/x509v3
-    ${OPENSSL_SOURCES_DIR}/ssl
-    )
-
-  if (ENABLE_PKCS11)
-    list(APPEND OPENSSL_SOURCES_SUBDIRS
-      # EC, ECDH and ECDSA are necessary for PKCS11
-      ${OPENSSL_SOURCES_DIR}/crypto/ec
-      ${OPENSSL_SOURCES_DIR}/crypto/ecdh
-      ${OPENSSL_SOURCES_DIR}/crypto/ecdsa
-      )
-  else()
-    add_definitions(
-      -DOPENSSL_NO_EC
-      -DOPENSSL_NO_ECDH
-      -DOPENSSL_NO_ECDSA
-      )
-  endif()
-
-  foreach(d ${OPENSSL_SOURCES_SUBDIRS})
-    AUX_SOURCE_DIRECTORY(${d} OPENSSL_SOURCES)
-  endforeach()
-
-  list(REMOVE_ITEM OPENSSL_SOURCES
-    ${OPENSSL_SOURCES_DIR}/crypto/LPdir_unix.c
-    ${OPENSSL_SOURCES_DIR}/crypto/LPdir_vms.c
-    ${OPENSSL_SOURCES_DIR}/crypto/LPdir_win.c
-    ${OPENSSL_SOURCES_DIR}/crypto/LPdir_win32.c
-    ${OPENSSL_SOURCES_DIR}/crypto/LPdir_wince.c
-    ${OPENSSL_SOURCES_DIR}/crypto/armcap.c
-    ${OPENSSL_SOURCES_DIR}/crypto/bf/bfs.cpp
-    ${OPENSSL_SOURCES_DIR}/crypto/bio/bss_rtcp.c
-    ${OPENSSL_SOURCES_DIR}/crypto/bn/exp.c
-    ${OPENSSL_SOURCES_DIR}/crypto/conf/cnf_save.c
-    ${OPENSSL_SOURCES_DIR}/crypto/conf/test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/des/des.c
-    ${OPENSSL_SOURCES_DIR}/crypto/des/des3s.cpp
-    ${OPENSSL_SOURCES_DIR}/crypto/des/des_opts.c
-    ${OPENSSL_SOURCES_DIR}/crypto/des/dess.cpp
-    ${OPENSSL_SOURCES_DIR}/crypto/des/read_pwd.c
-    ${OPENSSL_SOURCES_DIR}/crypto/des/speed.c
-    ${OPENSSL_SOURCES_DIR}/crypto/evp/e_dsa.c
-    ${OPENSSL_SOURCES_DIR}/crypto/evp/m_ripemd.c
-    ${OPENSSL_SOURCES_DIR}/crypto/lhash/lh_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/md5/md5s.cpp
-    ${OPENSSL_SOURCES_DIR}/crypto/pkcs7/bio_ber.c
-    ${OPENSSL_SOURCES_DIR}/crypto/pkcs7/pk7_enc.c
-    ${OPENSSL_SOURCES_DIR}/crypto/ppccap.c
-    ${OPENSSL_SOURCES_DIR}/crypto/rand/randtest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/s390xcap.c
-    ${OPENSSL_SOURCES_DIR}/crypto/sparcv9cap.c
-    ${OPENSSL_SOURCES_DIR}/crypto/x509v3/tabtest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/x509v3/v3conf.c
-    ${OPENSSL_SOURCES_DIR}/ssl/ssl_task.c
-    ${OPENSSL_SOURCES_DIR}/crypto/LPdir_nyi.c
-    ${OPENSSL_SOURCES_DIR}/crypto/aes/aes_x86core.c
-    ${OPENSSL_SOURCES_DIR}/crypto/bio/bss_dgram.c
-    ${OPENSSL_SOURCES_DIR}/crypto/bn/bntest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/bn/expspeed.c
-    ${OPENSSL_SOURCES_DIR}/crypto/bn/exptest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/engine/enginetest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/evp/evp_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/hmac/hmactest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/md5/md5.c
-    ${OPENSSL_SOURCES_DIR}/crypto/md5/md5test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/o_dir_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/pkcs7/dec.c
-    ${OPENSSL_SOURCES_DIR}/crypto/pkcs7/enc.c
-    ${OPENSSL_SOURCES_DIR}/crypto/pkcs7/sign.c
-    ${OPENSSL_SOURCES_DIR}/crypto/pkcs7/verify.c
-    ${OPENSSL_SOURCES_DIR}/crypto/rsa/rsa_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/sha/sha.c
-    ${OPENSSL_SOURCES_DIR}/crypto/sha/sha1.c
-    ${OPENSSL_SOURCES_DIR}/crypto/sha/sha1t.c
-    ${OPENSSL_SOURCES_DIR}/crypto/sha/sha1test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/sha/sha256t.c
-    ${OPENSSL_SOURCES_DIR}/crypto/sha/sha512t.c
-    ${OPENSSL_SOURCES_DIR}/crypto/sha/shatest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/srp/srptest.c
-
-    ${OPENSSL_SOURCES_DIR}/crypto/bn/divtest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/bn/bnspeed.c
-    ${OPENSSL_SOURCES_DIR}/crypto/des/destest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/dh/p192.c
-    ${OPENSSL_SOURCES_DIR}/crypto/dh/p512.c
-    ${OPENSSL_SOURCES_DIR}/crypto/dh/p1024.c
-    ${OPENSSL_SOURCES_DIR}/crypto/des/rpw.c
-    ${OPENSSL_SOURCES_DIR}/ssl/ssltest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/dsa/dsagen.c
-    ${OPENSSL_SOURCES_DIR}/crypto/dsa/dsatest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/dh/dhtest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/pqueue/pq_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/des/ncbc_enc.c
-
-    ${OPENSSL_SOURCES_DIR}/crypto/evp/evp_extra_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/evp/verify_extra_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/x509/verify_extra_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/x509v3/v3prin.c
-    ${OPENSSL_SOURCES_DIR}/crypto/x509v3/v3nametest.c
-    ${OPENSSL_SOURCES_DIR}/crypto/constant_time_test.c
-    ${OPENSSL_SOURCES_DIR}/crypto/ec/ecp_nistz256_table.c
-
-    ${OPENSSL_SOURCES_DIR}/ssl/heartbeat_test.c
-    )
-
-
-  if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
-    set_source_files_properties(
-      ${OPENSSL_SOURCES}
-      PROPERTIES COMPILE_DEFINITIONS
-      "OPENSSL_SYSNAME_WIN32;SO_WIN32;WIN32_LEAN_AND_MEAN;L_ENDIAN")
-  endif()
-
-  source_group(ThirdParty\\OpenSSL REGULAR_EXPRESSION ${OPENSSL_SOURCES_DIR}/.*)
-
-else()
-  include(FindOpenSSL)
-
-  if (NOT ${OPENSSL_FOUND})
-    message(FATAL_ERROR "Unable to find OpenSSL")
-  endif()
-
-  include_directories(${OPENSSL_INCLUDE_DIR})
-  link_libraries(${OPENSSL_LIBRARIES})
-endif()
--- a/Resources/Orthanc/Resources/CMake/UuidConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
-
-  if (STATIC_BUILD OR NOT USE_SYSTEM_UUID)
-    SET(E2FSPROGS_SOURCES_DIR ${CMAKE_BINARY_DIR}/e2fsprogs-1.43.8)
-    SET(E2FSPROGS_URL "http://www.orthanc-server.com/downloads/third-party/e2fsprogs-1.43.8.tar.gz")
-    SET(E2FSPROGS_MD5 "670b7a74a8ead5333acf21b9afc92b3c")
-
-    DownloadPackage(${E2FSPROGS_MD5} ${E2FSPROGS_URL} "${E2FSPROGS_SOURCES_DIR}")
-
-    include_directories(
-      ${E2FSPROGS_SOURCES_DIR}/lib
-      )
-
-    set(UUID_SOURCES
-      #${E2FSPROGS_SOURCES_DIR}/lib/uuid/tst_uuid.c
-      #${E2FSPROGS_SOURCES_DIR}/lib/uuid/uuid_time.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/clear.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/compare.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/copy.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/gen_uuid.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/isnull.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/pack.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/parse.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/unpack.c
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/unparse.c
-      )
-
-    check_include_file("net/if.h"       HAVE_NET_IF_H)
-    check_include_file("net/if_dl.h"    HAVE_NET_IF_DL_H)
-    check_include_file("netinet/in.h"   HAVE_NETINET_IN_H)
-    check_include_file("stdlib.h"       HAVE_STDLIB_H)
-    check_include_file("sys/file.h"     HAVE_SYS_FILE_H)
-    check_include_file("sys/ioctl.h"    HAVE_SYS_IOCTL_H)
-    check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H)
-    check_include_file("sys/socket.h"   HAVE_SYS_SOCKET_H)
-    check_include_file("sys/sockio.h"   HAVE_SYS_SOCKIO_H)
-    check_include_file("sys/syscall.h"  HAVE_SYS_SYSCALL_H)
-    check_include_file("sys/time.h"     HAVE_SYS_TIME_H)
-    check_include_file("sys/un.h"       HAVE_SYS_UN_H)
-    check_include_file("unistd.h"       HAVE_UNISTD_H)
-
-    if (NOT HAVE_NET_IF_H)  # This is the case of OpenBSD
-      unset(HAVE_NET_IF_H CACHE)
-      check_include_files("sys/socket.h;net/if.h" HAVE_NET_IF_H)
-    endif()
-
-    if (NOT HAVE_NETINET_TCP_H)  # This is the case of OpenBSD
-      unset(HAVE_NETINET_TCP_H CACHE)
-      check_include_files("sys/socket.h;netinet/tcp.h" HAVE_NETINET_TCP_H)
-    endif()
-
-    if (NOT EXISTS ${E2FSPROGS_SOURCES_DIR}/lib/uuid/config.h)
-      file(WRITE ${E2FSPROGS_SOURCES_DIR}/lib/uuid/config.h.cmake "
-#cmakedefine HAVE_NET_IF_H \@HAVE_NET_IF_H\@
-#cmakedefine HAVE_NET_IF_DL_H \@HAVE_NET_IF_DL_H\@
-#cmakedefine HAVE_NETINET_IN_H \@HAVE_NETINET_IN_H\@
-#cmakedefine HAVE_STDLIB_H \@HAVE_STDLIB_H \@
-#cmakedefine HAVE_SYS_FILE_H \@HAVE_SYS_FILE_H\@
-#cmakedefine HAVE_SYS_IOCTL_H \@HAVE_SYS_IOCTL_H\@
-#cmakedefine HAVE_SYS_RESOURCE_H \@HAVE_SYS_RESOURCE_H\@
-#cmakedefine HAVE_SYS_SOCKET_H \@HAVE_SYS_SOCKET_H\@
-#cmakedefine HAVE_SYS_SOCKIO_H \@HAVE_SYS_SOCKIO_H\@
-#cmakedefine HAVE_SYS_SYSCALL_H \@HAVE_SYS_SYSCALL_H\@
-#cmakedefine HAVE_SYS_TIME_H \@HAVE_SYS_TIME_H\@
-#cmakedefine HAVE_SYS_UN_H \@HAVE_SYS_UN_H\@
-#cmakedefine HAVE_UNISTD_H \@HAVE_UNISTD_H\@
-")
-    endif()
-      
-    configure_file(
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/config.h.cmake
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/config.h
-      )
-      
-    configure_file(
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/uuid.h.in
-      ${E2FSPROGS_SOURCES_DIR}/lib/uuid/uuid.h
-      )
-
-    if (NOT EXISTS ${E2FSPROGS_SOURCES_DIR}/lib/uuid/uuid_types.h)
-      file(WRITE
-        ${E2FSPROGS_SOURCES_DIR}/lib/uuid/uuid_types.h
-        "#include <stdint.h>\n")
-    endif()
-    
-    source_group(ThirdParty\\uuid REGULAR_EXPRESSION ${E2FSPROGS_SOURCES_DIR}/.*)
-
-  else()
-    CHECK_INCLUDE_FILE(uuid/uuid.h HAVE_UUID_H)
-    if (NOT HAVE_UUID_H)
-      message(FATAL_ERROR "Please install uuid-dev, e2fsprogs (OpenBSD) or e2fsprogs-libuuid (FreeBSD)")
-    endif()
-
-    check_library_exists(uuid uuid_generate_random "" HAVE_UUID_LIB)
-    if (NOT HAVE_UUID_LIB)
-      message(FATAL_ERROR "Unable to find the uuid library")
-    endif()
-    
-    link_libraries(uuid)
-  endif()
-
-endif()
--- a/Resources/Orthanc/Resources/CMake/VisualStudioPrecompiledHeaders.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-macro(ADD_VISUAL_STUDIO_PRECOMPILED_HEADERS PrecompiledHeaders PrecompiledSource Sources Target)
-  get_filename_component(PrecompiledBasename ${PrecompiledHeaders} NAME_WE)
-  set(PrecompiledBinary "${PrecompiledBasename}_$(ConfigurationName).pch")
-
-  set_source_files_properties(${PrecompiledSource}
-    PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeaders}\" /Fp\"${PrecompiledBinary}\""
-    OBJECT_OUTPUTS "${PrecompiledBinary}")
-
-  set_source_files_properties(${${Sources}}
-    PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeaders}\" /FI\"${PrecompiledHeaders}\" /Fp\"${PrecompiledBinary}\""
-    OBJECT_DEPENDS "${PrecompiledBinary}")
-
-  set(${Target} ${PrecompiledSource})
-endmacro()
--- a/Resources/Orthanc/Resources/CMake/ZlibConfiguration.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-if (STATIC_BUILD OR NOT USE_SYSTEM_ZLIB)
-  SET(ZLIB_SOURCES_DIR ${CMAKE_BINARY_DIR}/zlib-1.2.11)
-  SET(ZLIB_URL "http://www.orthanc-server.com/downloads/third-party/zlib-1.2.11.tar.gz")
-  SET(ZLIB_MD5 "1c9f62f0778697a09d36121ead88e08e")
-
-  DownloadPackage(${ZLIB_MD5} ${ZLIB_URL} "${ZLIB_SOURCES_DIR}")
-
-  include_directories(
-    ${ZLIB_SOURCES_DIR}
-    )
-
-  list(APPEND ZLIB_SOURCES 
-    ${ZLIB_SOURCES_DIR}/adler32.c
-    ${ZLIB_SOURCES_DIR}/compress.c
-    ${ZLIB_SOURCES_DIR}/crc32.c 
-    ${ZLIB_SOURCES_DIR}/deflate.c 
-    ${ZLIB_SOURCES_DIR}/gzclose.c 
-    ${ZLIB_SOURCES_DIR}/gzlib.c 
-    ${ZLIB_SOURCES_DIR}/gzread.c 
-    ${ZLIB_SOURCES_DIR}/gzwrite.c 
-    ${ZLIB_SOURCES_DIR}/infback.c 
-    ${ZLIB_SOURCES_DIR}/inffast.c 
-    ${ZLIB_SOURCES_DIR}/inflate.c 
-    ${ZLIB_SOURCES_DIR}/inftrees.c 
-    ${ZLIB_SOURCES_DIR}/trees.c 
-    ${ZLIB_SOURCES_DIR}/uncompr.c 
-    ${ZLIB_SOURCES_DIR}/zutil.c
-    )
-
-  source_group(ThirdParty\\zlib REGULAR_EXPRESSION ${ZLIB_SOURCES_DIR}/.*)
-
-  if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-    # "ioapi.c" from zlib (minizip) expects the "IOAPI_NO_64" macro to be set to "true"
-    # https://ohse.de/uwe/articles/lfs.html
-    add_definitions(
-      -DIOAPI_NO_64=1
-      )
-  endif()
-
-else()
-  include(FindZLIB)
-  include_directories(${ZLIB_INCLUDE_DIRS})
-  link_libraries(${ZLIB_LIBRARIES})
-endif()
--- a/Resources/Orthanc/Resources/EmbedResources.py	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,431 +0,0 @@
-#!/usr/bin/python
-
-# Orthanc - A Lightweight, RESTful DICOM Store
-# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
-# Department, University Hospital of Liege, 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 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/>.
-
-
-import sys
-import os
-import os.path
-import pprint
-import re
-
-UPCASE_CHECK = True
-USE_SYSTEM_EXCEPTION = False
-EXCEPTION_CLASS = 'OrthancException'
-OUT_OF_RANGE_EXCEPTION = 'OrthancException(ErrorCode_ParameterOutOfRange)'
-INEXISTENT_PATH_EXCEPTION = 'OrthancException(ErrorCode_InexistentItem)'
-NAMESPACE = 'Orthanc'
-
-ARGS = []
-for i in range(len(sys.argv)):
-    if not sys.argv[i].startswith('--'):
-        ARGS.append(sys.argv[i])
-    elif sys.argv[i].lower() == '--no-upcase-check':
-        UPCASE_CHECK = False
-    elif sys.argv[i].lower() == '--system-exception':
-        USE_SYSTEM_EXCEPTION = True
-        EXCEPTION_CLASS = '::std::runtime_error'
-        OUT_OF_RANGE_EXCEPTION = '%s("Parameter out of range")' % EXCEPTION_CLASS
-        INEXISTENT_PATH_EXCEPTION = '%s("Unknown path in a directory resource")' % EXCEPTION_CLASS
-    elif sys.argv[i].startswith('--namespace='):
-        NAMESPACE = sys.argv[i][sys.argv[i].find('=') + 1 : ]
-
-if len(ARGS) < 2 or len(ARGS) % 2 != 0:
-    print ('Usage:')
-    print ('python %s [--no-upcase-check] [--system-exception] [--namespace=<Namespace>] <TargetBaseFilename> [ <Name> <Source> ]*' % sys.argv[0])
-    exit(-1)
-
-TARGET_BASE_FILENAME = ARGS[1]
-SOURCES = ARGS[2:]
-
-try:
-    # Make sure the destination directory exists
-    os.makedirs(os.path.normpath(os.path.join(TARGET_BASE_FILENAME, '..')))
-except:
-    pass
-
-
-#####################################################################
-## Read each resource file
-#####################################################################
-
-def CheckNoUpcase(s):
-    global UPCASE_CHECK
-    if (UPCASE_CHECK and
-        re.search('[A-Z]', s) != None):
-        raise Exception("Path in a directory with an upcase letter: %s" % s)
-
-resources = {}
-
-counter = 0
-i = 0
-while i < len(SOURCES):
-    resourceName = SOURCES[i].upper()
-    pathName = SOURCES[i + 1]
-
-    if not os.path.exists(pathName):
-        raise Exception("Non existing path: %s" % pathName)
-
-    if resourceName in resources:
-        raise Exception("Twice the same resource: " + resourceName)
-    
-    if os.path.isdir(pathName):
-        # The resource is a directory: Recursively explore its files
-        content = {}
-        for root, dirs, files in os.walk(pathName):
-            base = os.path.relpath(root, pathName)
-
-            # Fix issue #24 (Build fails on OSX when directory has .DS_Store files):
-            # Ignore folders whose name starts with a dot (".")
-            if base.find('/.') != -1:
-                print('Ignoring folder: %s' % root)
-                continue
-
-            for f in files:
-                if f.find('~') == -1:  # Ignore Emacs backup files
-                    if base == '.':
-                        r = f
-                    else:
-                        r = os.path.join(base, f)
-
-                    CheckNoUpcase(r)
-                    r = '/' + r.replace('\\', '/')
-                    if r in content:
-                        raise Exception("Twice the same filename (check case): " + r)
-
-                    content[r] = {
-                        'Filename' : os.path.join(root, f),
-                        'Index' : counter
-                        }
-                    counter += 1
-
-        resources[resourceName] = {
-            'Type' : 'Directory',
-            'Files' : content
-            }
-
-    elif os.path.isfile(pathName):
-        resources[resourceName] = {
-            'Type' : 'File',
-            'Index' : counter,
-            'Filename' : pathName
-            }
-        counter += 1
-
-    else:
-        raise Exception("Not a regular file, nor a directory: " + pathName)
-
-    i += 2
-
-#pprint.pprint(resources)
-
-
-#####################################################################
-## Write .h header
-#####################################################################
-
-header = open(TARGET_BASE_FILENAME + '.h', 'w')
-
-header.write("""
-#pragma once
-
-#include <string>
-#include <list>
-
-#if defined(_MSC_VER)
-#  pragma warning(disable: 4065)  // "Switch statement contains 'default' but no 'case' labels"
-#endif
-
-namespace %s
-{
-  namespace EmbeddedResources
-  {
-    enum FileResourceId
-    {
-""" % NAMESPACE)
-
-isFirst = True
-for name in resources:
-    if resources[name]['Type'] == 'File':
-        if isFirst:
-            isFirst = False
-        else:    
-            header.write(',\n')
-        header.write('      %s' % name)
-
-header.write("""
-    };
-
-    enum DirectoryResourceId
-    {
-""")
-
-isFirst = True
-for name in resources:
-    if resources[name]['Type'] == 'Directory':
-        if isFirst:
-            isFirst = False
-        else:    
-            header.write(',\n')
-        header.write('      %s' % name)
-
-header.write("""
-    };
-
-    const void* GetFileResourceBuffer(FileResourceId id);
-    size_t GetFileResourceSize(FileResourceId id);
-    void GetFileResource(std::string& result, FileResourceId id);
-
-    const void* GetDirectoryResourceBuffer(DirectoryResourceId id, const char* path);
-    size_t GetDirectoryResourceSize(DirectoryResourceId id, const char* path);
-    void GetDirectoryResource(std::string& result, DirectoryResourceId id, const char* path);
-
-    void ListResources(std::list<std::string>& result, DirectoryResourceId id);
-  }
-}
-""")
-header.close()
-
-
-
-#####################################################################
-## Write the resource content in the .cpp source
-#####################################################################
-
-PYTHON_MAJOR_VERSION = sys.version_info[0]
-
-def WriteResource(cpp, item):
-    cpp.write('    static const uint8_t resource%dBuffer[] = {' % item['Index'])
-
-    f = open(item['Filename'], "rb")
-    content = f.read()
-    f.close()
-
-    # http://stackoverflow.com/a/1035360
-    pos = 0
-    for b in content:
-        if PYTHON_MAJOR_VERSION == 2:
-            c = ord(b[0])
-        else:
-            c = b
-
-        if pos > 0:
-            cpp.write(', ')
-
-        if (pos % 16) == 0:
-            cpp.write('\n    ')
-
-        if c < 0:
-            raise Exception("Internal error")
-
-        cpp.write("0x%02x" % c)
-        pos += 1
-
-    # Zero-size array are disallowed, so we put one single void character in it.
-    if pos == 0:
-        cpp.write('  0')
-
-    cpp.write('  };\n')
-    cpp.write('    static const size_t resource%dSize = %d;\n' % (item['Index'], pos))
-
-
-cpp = open(TARGET_BASE_FILENAME + '.cpp', 'w')
-
-cpp.write('#include "%s.h"\n' % os.path.basename(TARGET_BASE_FILENAME))
-
-if USE_SYSTEM_EXCEPTION:
-    cpp.write('#include <stdexcept>')
-else:
-    cpp.write('#include "%s/Core/OrthancException.h"' % os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
-
-cpp.write("""
-#include <stdint.h>
-#include <string.h>
-
-namespace %s
-{
-  namespace EmbeddedResources
-  {
-""" % NAMESPACE)
-
-
-for name in resources:
-    if resources[name]['Type'] == 'File':
-        WriteResource(cpp, resources[name])
-    else:
-        for f in resources[name]['Files']:
-            WriteResource(cpp, resources[name]['Files'][f])
-
-
-
-#####################################################################
-## Write the accessors to the file resources in .cpp
-#####################################################################
-
-cpp.write("""
-    const void* GetFileResourceBuffer(FileResourceId id)
-    {
-      switch (id)
-      {
-""")
-for name in resources:
-    if resources[name]['Type'] == 'File':
-        cpp.write('      case %s:\n' % name)
-        cpp.write('        return resource%dBuffer;\n' % resources[name]['Index'])
-
-cpp.write("""
-      default:
-        throw %s;
-      }
-    }
-
-    size_t GetFileResourceSize(FileResourceId id)
-    {
-      switch (id)
-      {
-""" % OUT_OF_RANGE_EXCEPTION)
-
-for name in resources:
-    if resources[name]['Type'] == 'File':
-        cpp.write('      case %s:\n' % name)
-        cpp.write('        return resource%dSize;\n' % resources[name]['Index'])
-
-cpp.write("""
-      default:
-        throw %s;
-      }
-    }
-""" % OUT_OF_RANGE_EXCEPTION)
-
-
-
-#####################################################################
-## Write the accessors to the directory resources in .cpp
-#####################################################################
-
-cpp.write("""
-    const void* GetDirectoryResourceBuffer(DirectoryResourceId id, const char* path)
-    {
-      switch (id)
-      {
-""")
-
-for name in resources:
-    if resources[name]['Type'] == 'Directory':
-        cpp.write('      case %s:\n' % name)
-        isFirst = True
-        for path in resources[name]['Files']:
-            cpp.write('        if (!strcmp(path, "%s"))\n' % path)
-            cpp.write('          return resource%dBuffer;\n' % resources[name]['Files'][path]['Index'])
-        cpp.write('        throw %s;\n\n' % INEXISTENT_PATH_EXCEPTION)
-
-cpp.write("""      default:
-        throw %s;
-      }
-    }
-
-    size_t GetDirectoryResourceSize(DirectoryResourceId id, const char* path)
-    {
-      switch (id)
-      {
-""" % OUT_OF_RANGE_EXCEPTION)
-
-for name in resources:
-    if resources[name]['Type'] == 'Directory':
-        cpp.write('      case %s:\n' % name)
-        isFirst = True
-        for path in resources[name]['Files']:
-            cpp.write('        if (!strcmp(path, "%s"))\n' % path)
-            cpp.write('          return resource%dSize;\n' % resources[name]['Files'][path]['Index'])
-        cpp.write('        throw %s;\n\n' % INEXISTENT_PATH_EXCEPTION)
-
-cpp.write("""      default:
-        throw %s;
-      }
-    }
-""" % OUT_OF_RANGE_EXCEPTION)
-
-
-
-
-#####################################################################
-## List the resources in a directory
-#####################################################################
-
-cpp.write("""
-    void ListResources(std::list<std::string>& result, DirectoryResourceId id)
-    {
-      result.clear();
-
-      switch (id)
-      {
-""")
-
-for name in resources:
-    if resources[name]['Type'] == 'Directory':
-        cpp.write('      case %s:\n' % name)
-        for path in sorted(resources[name]['Files']):
-            cpp.write('        result.push_back("%s");\n' % path)
-        cpp.write('        break;\n\n')
-
-cpp.write("""      default:
-        throw %s;
-      }
-    }
-""" % OUT_OF_RANGE_EXCEPTION)
-
-
-
-
-#####################################################################
-## Write the convenience wrappers in .cpp
-#####################################################################
-
-cpp.write("""
-    void GetFileResource(std::string& result, FileResourceId id)
-    {
-      size_t size = GetFileResourceSize(id);
-      result.resize(size);
-      if (size > 0)
-        memcpy(&result[0], GetFileResourceBuffer(id), size);
-    }
-
-    void GetDirectoryResource(std::string& result, DirectoryResourceId id, const char* path)
-    {
-      size_t size = GetDirectoryResourceSize(id, path);
-      result.resize(size);
-      if (size > 0)
-        memcpy(&result[0], GetDirectoryResourceBuffer(id, path), size);
-    }
-  }
-}
-""")
-cpp.close()
--- a/Resources/Orthanc/Resources/LinuxStandardBaseToolchain.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-# LSB_CC=gcc-4.8 LSB_CXX=g++-4.8 cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../Resources/LinuxStandardBaseToolchain.cmake -DUSE_LEGACY_JSONCPP=ON
-
-INCLUDE(CMakeForceCompiler)
-
-SET(LSB_PATH $ENV{LSB_PATH})
-SET(LSB_CC $ENV{LSB_CC})
-SET(LSB_CXX $ENV{LSB_CXX})
-SET(LSB_TARGET_VERSION "4.0")
-
-IF ("${LSB_PATH}" STREQUAL "")
-  SET(LSB_PATH "/opt/lsb")
-ENDIF()
-
-IF (EXISTS ${LSB_PATH}/lib64)
-  SET(LSB_TARGET_PROCESSOR "x86_64")
-  SET(LSB_LIBPATH ${LSB_PATH}/lib64-${LSB_TARGET_VERSION})
-ELSEIF (EXISTS ${LSB_PATH}/lib)
-  SET(LSB_TARGET_PROCESSOR "x86")
-  SET(LSB_LIBPATH ${LSB_PATH}/lib-${LSB_TARGET_VERSION})
-ELSE()
-  MESSAGE(FATAL_ERROR "Unable to detect the target processor architecture. Check the LSB_PATH environment variable.")
-ENDIF()
-
-SET(LSB_CPPPATH ${LSB_PATH}/include)
-SET(PKG_CONFIG_PATH ${LSB_LIBPATH}/pkgconfig/)
-
-# the name of the target operating system
-SET(CMAKE_SYSTEM_NAME Linux)
-SET(CMAKE_SYSTEM_VERSION LinuxStandardBase)
-SET(CMAKE_SYSTEM_PROCESSOR ${LSB_TARGET_PROCESSOR})
-
-# which compilers to use for C and C++
-SET(CMAKE_C_COMPILER ${LSB_PATH}/bin/lsbcc)
-CMAKE_FORCE_CXX_COMPILER(${LSB_PATH}/bin/lsbc++ GNU)
-
-# here is the target environment located
-SET(CMAKE_FIND_ROOT_PATH ${LSB_PATH})
-
-# adjust the default behaviour of the FIND_XXX() commands:
-# search headers and libraries in the target environment, search 
-# programs in the host environment
-SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
-SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
-
-SET(CMAKE_CROSSCOMPILING OFF)
-
-
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -I${LSB_PATH}/include" CACHE INTERNAL "" FORCE)
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -nostdinc++ -I${LSB_PATH}/include -I${LSB_PATH}/include/c++ -I${LSB_PATH}/include/c++/backward" CACHE INTERNAL "" FORCE)
-SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH} --lsb-besteffort" CACHE INTERNAL "" FORCE)
-SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH} --lsb-besteffort" CACHE INTERNAL "" FORCE)
-
-if (NOT "${LSB_CXX}" STREQUAL "")
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-cxx=${LSB_CXX}")
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-cxx=${LSB_CXX}")
-  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-cxx=${LSB_CXX}")
-endif()
-
-if (NOT "${LSB_CC}" STREQUAL "")
-  SET(CMAKE_C_FLAGS "${CMAKE_CC_FLAGS} --lsb-cc=${LSB_CC}")
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-cc=${LSB_CC}")
-  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-cc=${LSB_CC}")
-  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-cc=${LSB_CC}")
-endif()
-
--- a/Resources/Orthanc/Resources/MinGW-W64-Toolchain32.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# the name of the target operating system
-set(CMAKE_SYSTEM_NAME Windows)
-
-# which compilers to use for C and C++
-set(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
-set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
-set(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
-
-# here is the target environment located
-set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
-
-# adjust the default behaviour of the FIND_XXX() commands:
-# search headers and libraries in the target environment, search 
-# programs in the host environment
-set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--- a/Resources/Orthanc/Resources/MinGW-W64-Toolchain64.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# the name of the target operating system
-set(CMAKE_SYSTEM_NAME Windows)
-
-# which compilers to use for C and C++
-set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
-set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
-set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
-
-# here is the target environment located
-set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
-
-# adjust the default behaviour of the FIND_XXX() commands:
-# search headers and libraries in the target environment, search 
-# programs in the host environment
-set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--- a/Resources/Orthanc/Resources/MinGWToolchain.cmake	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# the name of the target operating system
-set(CMAKE_SYSTEM_NAME Windows)
-
-# which compilers to use for C and C++
-set(CMAKE_C_COMPILER i586-mingw32msvc-gcc)
-set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++)
-set(CMAKE_RC_COMPILER i586-mingw32msvc-windres)
-
-# here is the target environment located
-set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc)
-
-# adjust the default behaviour of the FIND_XXX() commands:
-# search headers and libraries in the target environment, search 
-# programs in the host environment
-set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--- a/Resources/Orthanc/Resources/Patches/boost-1.66.0-linux-standard-base.patch	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-diff -urEb boost_1_66_0.orig/boost/move/adl_move_swap.hpp boost_1_66_0/boost/move/adl_move_swap.hpp
---- boost_1_66_0.orig/boost/move/adl_move_swap.hpp	2018-04-11 11:56:16.761768726 +0200
-+++ boost_1_66_0/boost/move/adl_move_swap.hpp	2018-04-11 11:57:01.073881330 +0200
-@@ -28,6 +28,8 @@
- //Try to avoid including <algorithm>, as it's quite big
- #if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
-    #include <utility>   //Dinkum libraries define std::swap in utility which is lighter than algorithm
-+#elif defined(__LSB_VERSION__)
-+#  include <utility>
- #elif defined(BOOST_GNU_STDLIB)
-    //For non-GCC compilers, where GNUC version is not very reliable, or old GCC versions
-    //use the good old stl_algobase header, which is quite lightweight
-Only in boost_1_66_0/boost/move: adl_move_swap.hpp~
--- a/Resources/Orthanc/Resources/Patches/curl-7.57.0-cmake.patch	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-diff -urEb curl-7.57.0.orig/CMake/Macros.cmake curl-7.57.0/CMake/Macros.cmake
---- curl-7.57.0.orig/CMake/Macros.cmake	2017-11-09 23:40:36.000000000 +0100
-+++ curl-7.57.0/CMake/Macros.cmake	2018-01-03 10:39:15.589520034 +0100
-@@ -38,7 +38,7 @@
-     message(STATUS "Performing Curl Test ${CURL_TEST}")
-     try_compile(${CURL_TEST}
-       ${CMAKE_BINARY_DIR}
--      ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
-+      ${CURL_SOURCES_DIR}/CMake/CurlTests.c
-       CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
-       "${CURL_TEST_ADD_LIBRARIES}"
-       OUTPUT_VARIABLE OUTPUT)
--- a/Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-dulparse-vulnerability.patch	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-diff -urEb dcmtk-3.6.0.orig/dcmnet/libsrc/dulparse.cc dcmtk-3.6.0/dcmnet/libsrc/dulparse.cc
---- dcmtk-3.6.0.orig/dcmnet/libsrc/dulparse.cc	2010-12-01 09:26:36.000000000 +0100
-+++ dcmtk-3.6.0/dcmnet/libsrc/dulparse.cc	2016-12-02 15:58:49.930540033 +0100
-@@ -393,6 +393,8 @@
-                     return cond;
- 
-                 buf += length;
-+                if (presentationLength < length)
-+                  return EC_MemoryExhausted;
-                 presentationLength -= length;
-                 DCMNET_TRACE("Successfully parsed Abstract Syntax");
-                 break;
-@@ -404,12 +406,16 @@
-                 cond = LST_Enqueue(&context->transferSyntaxList, (LST_NODE*)subItem);
-                 if (cond.bad()) return cond;
-                 buf += length;
-+                if (presentationLength < length)
-+                  return EC_MemoryExhausted;
-                 presentationLength -= length;
-                 DCMNET_TRACE("Successfully parsed Transfer Syntax");
-                 break;
-             default:
-                 cond = parseDummy(buf, &length, presentationLength);
-                 buf += length;
-+                if (presentationLength < length)
-+                  return EC_MemoryExhausted;
-                 presentationLength -= length;
-                 break;
-             }
--- a/Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-mingw64.patch	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-diff -urEb dcmtk-3.6.0.orig/ofstd/include/dcmtk/ofstd/offile.h dcmtk-3.6.0/ofstd/include/dcmtk/ofstd/offile.h
---- dcmtk-3.6.0.orig/ofstd/include/dcmtk/ofstd/offile.h	2010-12-17 11:50:30.000000000 +0100
-+++ dcmtk-3.6.0/ofstd/include/dcmtk/ofstd/offile.h	2013-07-19 15:56:25.688996134 +0200
-@@ -196,7 +196,7 @@
-   OFBool popen(const char *command, const char *modes)
-   {
-     if (file_) fclose();
--#ifdef _WIN32
-+#if 0
-     file_ = _popen(command, modes);
- #else
-     file_ = :: popen(command, modes);
-@@ -258,7 +258,7 @@
-     {
-       if (popened_)
-       {
--#ifdef _WIN32
-+#if 0
-         result = _pclose(file_);
- #else
-         result = :: pclose(file_);
-Only in dcmtk-3.6.0/ofstd/include/dcmtk/ofstd: offile.h~
--- a/Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-speed.patch	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-diff -urEb dcmtk-3.6.0.orig/dcmnet/libsrc/dul.cc dcmtk-3.6.0/dcmnet/libsrc/dul.cc
---- dcmtk-3.6.0.orig/dcmnet/libsrc/dul.cc	2017-03-17 15:49:23.043061969 +0100
-+++ dcmtk-3.6.0/dcmnet/libsrc/dul.cc	2017-03-17 15:50:44.075359547 +0100
-@@ -630,7 +630,10 @@
-     if (cond.bad())
-         return cond;
- 
--    cond = PRV_NextPDUType(association, block, timeout, &pduType);
-+    /* This is the first time we read from this new connection, so in case it
-+     * doesn't speak DICOM, we shouldn't wait forever (= DUL_NOBLOCK).
-+     */
-+    cond = PRV_NextPDUType(association, DUL_NOBLOCK, PRV_DEFAULTTIMEOUT, &pduType);
- 
-     if (cond == DUL_NETWORKCLOSED)
-         event = TRANS_CONN_CLOSED;
-@@ -1770,7 +1773,7 @@
-                 // send number of socket handle in child process over anonymous pipe
-                 DWORD bytesWritten;
-                 char buf[20];
--                sprintf(buf, "%i", OFreinterpret_cast(int, childSocketHandle));
-+                sprintf(buf, "%i", OFstatic_cast(int, OFreinterpret_cast(size_t, childSocketHandle)));
-                 if (!WriteFile(hChildStdInWriteDup, buf, strlen(buf) + 1, &bytesWritten, NULL))
-                 {
-                     CloseHandle(hChildStdInWriteDup);
-@@ -1780,7 +1783,7 @@
-                 // return OF_ok status code DULC_FORKEDCHILD with descriptive text
-                 OFOStringStream stream;
-                 stream << "New child process started with pid " << OFstatic_cast(int, pi.dwProcessId)
--                       << ", socketHandle " << OFreinterpret_cast(int, childSocketHandle) << OFStringStream_ends;
-+                       << ", socketHandle " << OFstatic_cast(int, OFreinterpret_cast(size_t, childSocketHandle)) << OFStringStream_ends;
-                 OFSTRINGSTREAM_GETOFSTRING(stream, msg)
-                 return makeDcmnetCondition(DULC_FORKEDCHILD, OF_ok, msg.c_str());
-             }
-@@ -1840,7 +1843,7 @@
-     }
- #endif
- #endif
--    setTCPBufferLength(sock);
-+    //setTCPBufferLength(sock);
- 
- #ifndef DONT_DISABLE_NAGLE_ALGORITHM
-     /*
-diff -urEb dcmtk-3.6.0.orig/dcmnet/libsrc/dulfsm.cc dcmtk-3.6.0/dcmnet/libsrc/dulfsm.cc
---- dcmtk-3.6.0.orig/dcmnet/libsrc/dulfsm.cc	2017-03-17 15:49:23.043061969 +0100
-+++ dcmtk-3.6.0/dcmnet/libsrc/dulfsm.cc	2017-03-17 15:49:48.467144792 +0100
-@@ -2417,7 +2417,7 @@
-           return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
-         }
- #endif
--        setTCPBufferLength(s);
-+        //setTCPBufferLength(s);
- 
- #ifndef DONT_DISABLE_NAGLE_ALGORITHM
-         /*
--- a/Resources/Orthanc/Resources/Patches/dcmtk-3.6.2-cmath.patch	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-diff -urEb dcmtk-3.6.2.orig/CMake/GenerateDCMTKConfigure.cmake dcmtk-3.6.2/CMake/GenerateDCMTKConfigure.cmake
---- dcmtk-3.6.2.orig/CMake/GenerateDCMTKConfigure.cmake	2018-03-24 11:19:13.705396611 +0100
-+++ dcmtk-3.6.2/CMake/GenerateDCMTKConfigure.cmake	2018-03-24 11:19:33.429286501 +0100
-@@ -571,9 +571,9 @@
-   CHECK_FUNCTIONWITHHEADER_EXISTS(isinf "${HEADERS}" HAVE_PROTOTYPE_ISINF)
-   CHECK_FUNCTIONWITHHEADER_EXISTS(isnan "${HEADERS}" HAVE_PROTOTYPE_ISNAN)
-   CHECK_FUNCTIONWITHHEADER_EXISTS(finite "${HEADERS}" HAVE_PROTOTYPE_FINITE)
--  CHECK_FUNCTIONWITHHEADER_EXISTS(std::isinf "${HEADERS}" HAVE_PROTOTYPE_STD__ISINF)
--  CHECK_FUNCTIONWITHHEADER_EXISTS(std::isnan "${HEADERS}" HAVE_PROTOTYPE_STD__ISNAN)
--  CHECK_FUNCTIONWITHHEADER_EXISTS(std::finite "${HEADERS}" HAVE_PROTOTYPE_STD__FINITE)
-+  CHECK_FUNCTIONWITHHEADER_EXISTS(std::isinf<double> "${HEADERS}" HAVE_PROTOTYPE_STD__ISINF)
-+  CHECK_FUNCTIONWITHHEADER_EXISTS(std::isnan<double> "${HEADERS}" HAVE_PROTOTYPE_STD__ISNAN)
-+  CHECK_FUNCTIONWITHHEADER_EXISTS(std::finite<double> "${HEADERS}" HAVE_PROTOTYPE_STD__FINITE)
-   CHECK_FUNCTIONWITHHEADER_EXISTS(flock "${HEADERS}" HAVE_PROTOTYPE_FLOCK)
-   CHECK_FUNCTIONWITHHEADER_EXISTS(gethostbyname "${HEADERS}" HAVE_PROTOTYPE_GETHOSTBYNAME)
-   CHECK_FUNCTIONWITHHEADER_EXISTS(gethostbyname_r "${HEADERS}" HAVE_PROTOTYPE_GETHOSTBYNAME_R)
-Only in dcmtk-3.6.2/CMake: GenerateDCMTKConfigure.cmake~
--- a/Resources/Orthanc/Resources/Patches/dcmtk-3.6.2-linux-standard-base.patch	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-diff -urEb dcmtk-3.6.2.orig/ofstd/include/dcmtk/ofstd/offile.h dcmtk-3.6.2/ofstd/include/dcmtk/ofstd/offile.h
---- dcmtk-3.6.2.orig/ofstd/include/dcmtk/ofstd/offile.h	2017-07-14 17:41:11.000000000 +0200
-+++ dcmtk-3.6.2/ofstd/include/dcmtk/ofstd/offile.h	2018-01-02 13:56:04.075293459 +0100
-@@ -551,7 +551,7 @@
-    */
-   void setlinebuf()
-   {
--#if defined(_WIN32) || defined(__hpux)
-+#if defined(_WIN32) || defined(__hpux) || defined(__LSB_VERSION__)
-     this->setvbuf(NULL, _IOLBF, 0);
- #else
-     :: setlinebuf(file_);
--- a/Resources/Orthanc/Resources/ThirdParty/VisualStudio/stdint.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,259 +0,0 @@
-// ISO C9x  compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
-// 
-//  Copyright (c) 2006-2013 Alexander Chemeris
-// 
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// 
-//   1. Redistributions of source code must retain the above copyright notice,
-//      this list of conditions and the following disclaimer.
-// 
-//   2. Redistributions in binary form must reproduce the above copyright
-//      notice, this list of conditions and the following disclaimer in the
-//      documentation and/or other materials provided with the distribution.
-// 
-//   3. Neither the name of the product nor the names of its contributors may
-//      be used to endorse or promote products derived from this software
-//      without specific prior written permission.
-// 
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// 
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_STDINT_H_ // [
-#define _MSC_STDINT_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#if _MSC_VER >= 1600 // [
-#include <stdint.h>
-#else // ] _MSC_VER >= 1600 [
-
-#include <limits.h>
-
-// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
-// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
-// or compiler give many errors like this:
-//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
-#ifdef __cplusplus
-extern "C" {
-#endif
-#  include <wchar.h>
-#ifdef __cplusplus
-}
-#endif
-
-// Define _W64 macros to mark types changing their size, like intptr_t.
-#ifndef _W64
-#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
-#     define _W64 __w64
-#  else
-#     define _W64
-#  endif
-#endif
-
-
-// 7.18.1 Integer types
-
-// 7.18.1.1 Exact-width integer types
-
-// Visual Studio 6 and Embedded Visual C++ 4 doesn't
-// realize that, e.g. char has the same size as __int8
-// so we give up on __intX for them.
-#if (_MSC_VER < 1300)
-   typedef signed char       int8_t;
-   typedef signed short      int16_t;
-   typedef signed int        int32_t;
-   typedef unsigned char     uint8_t;
-   typedef unsigned short    uint16_t;
-   typedef unsigned int      uint32_t;
-#else
-   typedef signed __int8     int8_t;
-   typedef signed __int16    int16_t;
-   typedef signed __int32    int32_t;
-   typedef unsigned __int8   uint8_t;
-   typedef unsigned __int16  uint16_t;
-   typedef unsigned __int32  uint32_t;
-#endif
-typedef signed __int64       int64_t;
-typedef unsigned __int64     uint64_t;
-
-
-// 7.18.1.2 Minimum-width integer types
-typedef int8_t    int_least8_t;
-typedef int16_t   int_least16_t;
-typedef int32_t   int_least32_t;
-typedef int64_t   int_least64_t;
-typedef uint8_t   uint_least8_t;
-typedef uint16_t  uint_least16_t;
-typedef uint32_t  uint_least32_t;
-typedef uint64_t  uint_least64_t;
-
-// 7.18.1.3 Fastest minimum-width integer types
-typedef int8_t    int_fast8_t;
-typedef int16_t   int_fast16_t;
-typedef int32_t   int_fast32_t;
-typedef int64_t   int_fast64_t;
-typedef uint8_t   uint_fast8_t;
-typedef uint16_t  uint_fast16_t;
-typedef uint32_t  uint_fast32_t;
-typedef uint64_t  uint_fast64_t;
-
-// 7.18.1.4 Integer types capable of holding object pointers
-#ifdef _WIN64 // [
-   typedef signed __int64    intptr_t;
-   typedef unsigned __int64  uintptr_t;
-#else // _WIN64 ][
-   typedef _W64 signed int   intptr_t;
-   typedef _W64 unsigned int uintptr_t;
-#endif // _WIN64 ]
-
-// 7.18.1.5 Greatest-width integer types
-typedef int64_t   intmax_t;
-typedef uint64_t  uintmax_t;
-
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN     ((int8_t)_I8_MIN)
-#define INT8_MAX     _I8_MAX
-#define INT16_MIN    ((int16_t)_I16_MIN)
-#define INT16_MAX    _I16_MAX
-#define INT32_MIN    ((int32_t)_I32_MIN)
-#define INT32_MAX    _I32_MAX
-#define INT64_MIN    ((int64_t)_I64_MIN)
-#define INT64_MAX    _I64_MAX
-#define UINT8_MAX    _UI8_MAX
-#define UINT16_MAX   _UI16_MAX
-#define UINT32_MAX   _UI32_MAX
-#define UINT64_MAX   _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN    INT8_MIN
-#define INT_LEAST8_MAX    INT8_MAX
-#define INT_LEAST16_MIN   INT16_MIN
-#define INT_LEAST16_MAX   INT16_MAX
-#define INT_LEAST32_MIN   INT32_MIN
-#define INT_LEAST32_MAX   INT32_MAX
-#define INT_LEAST64_MIN   INT64_MIN
-#define INT_LEAST64_MAX   INT64_MAX
-#define UINT_LEAST8_MAX   UINT8_MAX
-#define UINT_LEAST16_MAX  UINT16_MAX
-#define UINT_LEAST32_MAX  UINT32_MAX
-#define UINT_LEAST64_MAX  UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN    INT8_MIN
-#define INT_FAST8_MAX    INT8_MAX
-#define INT_FAST16_MIN   INT16_MIN
-#define INT_FAST16_MAX   INT16_MAX
-#define INT_FAST32_MIN   INT32_MIN
-#define INT_FAST32_MAX   INT32_MAX
-#define INT_FAST64_MIN   INT64_MIN
-#define INT_FAST64_MAX   INT64_MAX
-#define UINT_FAST8_MAX   UINT8_MAX
-#define UINT_FAST16_MAX  UINT16_MAX
-#define UINT_FAST32_MAX  UINT32_MAX
-#define UINT_FAST64_MAX  UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-#  define INTPTR_MIN   INT64_MIN
-#  define INTPTR_MAX   INT64_MAX
-#  define UINTPTR_MAX  UINT64_MAX
-#else // _WIN64 ][
-#  define INTPTR_MIN   INT32_MIN
-#  define INTPTR_MAX   INT32_MAX
-#  define UINTPTR_MAX  UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN   INT64_MIN
-#define INTMAX_MAX   INT64_MAX
-#define UINTMAX_MAX  UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-#  define PTRDIFF_MIN  _I64_MIN
-#  define PTRDIFF_MAX  _I64_MAX
-#else  // _WIN64 ][
-#  define PTRDIFF_MIN  _I32_MIN
-#  define PTRDIFF_MAX  _I32_MAX
-#endif  // _WIN64 ]
-
-#define SIG_ATOMIC_MIN  INT_MIN
-#define SIG_ATOMIC_MAX  INT_MAX
-
-#ifndef SIZE_MAX // [
-#  ifdef _WIN64 // [
-#     define SIZE_MAX  _UI64_MAX
-#  else // _WIN64 ][
-#     define SIZE_MAX  _UI32_MAX
-#  endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
-#ifndef WCHAR_MIN // [
-#  define WCHAR_MIN  0
-#endif  // WCHAR_MIN ]
-#ifndef WCHAR_MAX // [
-#  define WCHAR_MAX  _UI16_MAX
-#endif  // WCHAR_MAX ]
-
-#define WINT_MIN  0
-#define WINT_MAX  _UI16_MAX
-
-#endif // __STDC_LIMIT_MACROS ]
-
-
-// 7.18.4 Limits of other integer types
-
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
-
-// 7.18.4.1 Macros for minimum-width integer constants
-
-#define INT8_C(val)  val##i8
-#define INT16_C(val) val##i16
-#define INT32_C(val) val##i32
-#define INT64_C(val) val##i64
-
-#define UINT8_C(val)  val##ui8
-#define UINT16_C(val) val##ui16
-#define UINT32_C(val) val##ui32
-#define UINT64_C(val) val##ui64
-
-// 7.18.4.2 Macros for greatest-width integer constants
-// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
-// Check out Issue 9 for the details.
-#ifndef INTMAX_C //   [
-#  define INTMAX_C   INT64_C
-#endif // INTMAX_C    ]
-#ifndef UINTMAX_C //  [
-#  define UINTMAX_C  UINT64_C
-#endif // UINTMAX_C   ]
-
-#endif // __STDC_CONSTANT_MACROS ]
-
-#endif // _MSC_VER >= 1600 ]
-
-#endif // _MSC_STDINT_H_ ]
--- a/Resources/Orthanc/Resources/ThirdParty/base64/base64.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/* 
-   base64.cpp and base64.h
-
-   Copyright (C) 2004-2008 René Nyffenegger
-
-   This source code is provided 'as-is', without any express or implied
-   warranty. In no event will the author be held liable for any damages
-   arising from the use of this software.
-
-   Permission is granted to anyone to use this software for any purpose,
-   including commercial applications, and to alter it and redistribute it
-   freely, subject to the following restrictions:
-
-   1. The origin of this source code must not be misrepresented; you must not
-      claim that you wrote the original source code. If you use this source code
-      in a product, an acknowledgment in the product documentation would be
-      appreciated but is not required.
-
-   2. Altered source versions must be plainly marked as such, and must not be
-      misrepresented as being the original source code.
-
-   3. This notice may not be removed or altered from any source distribution.
-
-   René Nyffenegger rene.nyffenegger@adp-gmbh.ch
-
-*/
-
-#include "base64.h"
-#include <string.h>
-
-static const std::string base64_chars = 
-             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-             "abcdefghijklmnopqrstuvwxyz"
-             "0123456789+/";
-
-
-static inline bool is_base64(unsigned char c) {
-  return (isalnum(c) || (c == '+') || (c == '/'));
-}
-
-std::string base64_encode(const std::string& stringToEncode) 
-{
-  const unsigned char* bytes_to_encode = reinterpret_cast<const unsigned char*>
-    (stringToEncode.size() > 0 ? &stringToEncode[0] : NULL);
-  unsigned int in_len = stringToEncode.size();
-  
-  std::string ret;
-  int i = 0;
-  int j = 0;
-  unsigned char char_array_3[3];
-  unsigned char char_array_4[4];
-
-  while (in_len--) {
-    char_array_3[i++] = *(bytes_to_encode++);
-    if (i == 3) {
-      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
-      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
-      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
-      char_array_4[3] = char_array_3[2] & 0x3f;
-
-      for(i = 0; (i <4) ; i++)
-        ret += base64_chars[char_array_4[i]];
-      i = 0;
-    }
-  }
-
-  if (i)
-  {
-    for(j = i; j < 3; j++)
-      char_array_3[j] = '\0';
-
-    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
-    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
-    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
-    char_array_4[3] = char_array_3[2] & 0x3f;
-
-    for (j = 0; (j < i + 1); j++)
-      ret += base64_chars[char_array_4[j]];
-
-    while((i++ < 3))
-      ret += '=';
-
-  }
-
-  return ret;
-}
-
-
-std::string base64_decode(const std::string& encoded_string) {
-  int in_len = encoded_string.size();
-  int i = 0;
-  int j = 0;
-  int in_ = 0;
-  unsigned char char_array_4[4], char_array_3[3];
-  std::string ret;
-
-  while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
-    char_array_4[i++] = encoded_string[in_]; in_++;
-    if (i ==4) {
-      for (i = 0; i <4; i++)
-        char_array_4[i] = base64_chars.find(char_array_4[i]);
-
-      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
-      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
-      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
-
-      for (i = 0; (i < 3); i++)
-        ret += char_array_3[i];
-      i = 0;
-    }
-  }
-
-  if (i) {
-    for (j = i; j <4; j++)
-      char_array_4[j] = 0;
-
-    for (j = 0; j <4; j++)
-      char_array_4[j] = base64_chars.find(char_array_4[j]);
-
-    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
-    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
-    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
-
-    for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
-  }
-
-  return ret;
-}
--- a/Resources/Orthanc/Resources/ThirdParty/base64/base64.h	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-#include <string>
-
-std::string base64_encode(const std::string& stringToEncode);
-std::string base64_decode(const std::string& s);
--- a/Resources/Orthanc/Resources/ThirdParty/patch/NOTES.txt	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-===========
-INFORMATION
-===========
-
-This is a precompiled version of the "patch" standard tool for
-Windows. It was compiled using the MSYS framework.
-
-The binaries originate from the "Git for Windows 1.9.5" package
-(https://msysgit.github.io/). The build instructions have been
-provided on the discussion group of Git for Windows [1]. They are
-copied/pasted below for reference.
-
-
-
-================
-UPSTREAM PROJECT
-================
-
-URL to the upstream project:
-http://savannah.gnu.org/projects/patch/
-
-License of patch: GPLv2 (GNU General Public License v2)
-
-Copyright (C) 1988 Larry Wall "with lots o' patches by Paul Eggert"
-Copyright (C) 1997 Free Software Foundation, Inc.
-
-
-
-======================
-BUILD INSTRUCTIONS [1]
-======================
-
-The easiest way to find out about this is to install the Git SDK, then 
-run 
-
-     pacman -Qu $(which patch.exe) 
-
-to find out which package contains the `patch.exe` binary. It so happens 
-to be patch.2.7.5-1 at the moment. Since this is an MSys2 package (not a 
-MinGW one, otherwise the patch utility would be in /mingw64/bin/, not 
-/usr/bin/), this package is built from the recipes in 
-
-     https://github.com/msys2/MSYS2-packages 
-
-The `patch` package is obviously built from the subdirectory 
-
-     https://github.com/Alexpux/MSYS2-packages/tree/master/patch 
-
-and the PKGBUILD file specifies that the source is fetched from 
-ftp://ftp.gnu.org/gnu/patch/patch-2.7.5.tar.xz: 
-
-https://github.com/Alexpux/MSYS2-packages/blob/900744becd072f687029b0f830ab6fe95cf533d6/patch/PKGBUILD#L14 
-
-and then these two patches are applied before building: 
-     
-https://github.com/Alexpux/MSYS2-packages/blob/900744becd072f687029b0f830ab6fe95cf533d6/patch/msys2-patch-2.7.1.patch 
-
-and 
-      
-https://github.com/Alexpux/MSYS2-packages/blob/900744becd072f687029b0f830ab6fe95cf533d6/patch/msys2-patch-manifest.patch 
-
-As you can see, some light changes are applied, i.e. `patch.exe` will 
-always write in binary mode with MSys2, and the executable will have a 
-manifest embedded that allows it to run as non-administrator. 
-
-Ciao, 
-Johannes Schindelin
-
-
-[1] https://groups.google.com/d/msg/git-for-windows/xWyVr4z6Ri0/6RKeV028EAAJ
Binary file Resources/Orthanc/Resources/ThirdParty/patch/msys-1.0.dll has changed
Binary file Resources/Orthanc/Resources/ThirdParty/patch/patch.exe has changed
--- a/Resources/Orthanc/Resources/ThirdParty/patch/patch.exe.manifest	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
-  <assemblyIdentity version="7.95.0.0"
-     processorArchitecture="X86"
-     name="patch.exe"
-     type="win32"/>
-
-  <!-- Identify the application security requirements. -->
-  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
-    <security>
-      <requestedPrivileges>
-        <requestedExecutionLevel
-          level="asInvoker"
-          uiAccess="false"/>
-        </requestedPrivileges>
-       </security>
-  </trustInfo>
-</assembly>
-
--- a/Resources/Orthanc/Resources/WindowsResources.py	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-#!/usr/bin/python
-
-# Orthanc - A Lightweight, RESTful DICOM Store
-# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
-# Department, University Hospital of Liege, 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 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/>.
-
-
-import os
-import sys
-import datetime
-
-if len(sys.argv) != 5:
-    sys.stderr.write('Usage: %s <Version> <ProductName> <Filename> <Description>\n\n' % sys.argv[0])
-    sys.stderr.write('Example: %s 0.9.1 Orthanc Orthanc.exe "Lightweight, RESTful DICOM server for medical imaging"\n' % sys.argv[0])
-    sys.exit(-1)
-
-SOURCE = os.path.join(os.path.dirname(__file__), 'WindowsResources.rc')
-
-VERSION = sys.argv[1]
-PRODUCT = sys.argv[2]
-FILENAME = sys.argv[3]
-DESCRIPTION = sys.argv[4]
-
-if VERSION == 'mainline':
-    VERSION = '999.999.999'
-    RELEASE = 'This is a mainline build, not an official release'
-else:
-    RELEASE = 'Release %s' % VERSION
-
-v = VERSION.split('.')
-if len(v) != 2 and len(v) != 3:
-    sys.stderr.write('Bad version number: %s\n' % VERSION)
-    sys.exit(-1)
-
-if len(v) == 2:
-    v.append('0')
-
-extension = os.path.splitext(FILENAME)[1]
-if extension.lower() == '.dll':
-    BLOCK = '040904E4'
-    TYPE = 'VFT_DLL'
-elif extension.lower() == '.exe':
-    #BLOCK = '040904B0'   # LANG_ENGLISH/SUBLANG_ENGLISH_US,
-    BLOCK = '040904E4'   # Lang=US English, CharSet=Windows Multilingual
-    TYPE = 'VFT_APP'
-else:
-    sys.stderr.write('Unsupported extension (.EXE or .DLL only): %s\n' % extension)
-    sys.exit(-1)
-
-
-with open(SOURCE, 'r') as source:
-    content = source.read()
-    content = content.replace('${VERSION_MAJOR}', v[0])
-    content = content.replace('${VERSION_MINOR}', v[1])
-    content = content.replace('${VERSION_PATCH}', v[2])
-    content = content.replace('${RELEASE}', RELEASE)
-    content = content.replace('${DESCRIPTION}', DESCRIPTION)
-    content = content.replace('${PRODUCT}', PRODUCT)   
-    content = content.replace('${FILENAME}', FILENAME)   
-    content = content.replace('${YEAR}', str(datetime.datetime.now().year))
-    content = content.replace('${BLOCK}', BLOCK)
-    content = content.replace('${TYPE}', TYPE)
-
-    sys.stdout.write(content)
--- a/Resources/Orthanc/Resources/WindowsResources.rc	Wed Apr 11 16:24:26 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#include <winver.h>
-
-VS_VERSION_INFO VERSIONINFO
-   FILEVERSION ${VERSION_MAJOR},${VERSION_MINOR},0,${VERSION_PATCH}
-   PRODUCTVERSION ${VERSION_MAJOR},${VERSION_MINOR},0,0
-   FILEOS VOS_NT_WINDOWS32
-   FILETYPE ${TYPE}
-   BEGIN
-      BLOCK "StringFileInfo"
-      BEGIN
-         BLOCK "${BLOCK}"
-         BEGIN
-            VALUE "Comments", "${RELEASE}"
-            VALUE "CompanyName", "University Hospital of Liege, Belgium"
-            VALUE "FileDescription", "${DESCRIPTION}"
-            VALUE "FileVersion", "${VERSION_MAJOR}.${VERSION_MINOR}.0.${VERSION_PATCH}"
-            VALUE "InternalName", "${PRODUCT}"
-            VALUE "LegalCopyright", "(c) 2012-${YEAR}, Sebastien Jodogne, University Hospital of Liege, Belgium"
-            VALUE "LegalTrademarks", "Licensing information is available at http://www.orthanc-server.com/"
-            VALUE "OriginalFilename", "${FILENAME}"
-            VALUE "ProductName", "${PRODUCT}"
-            VALUE "ProductVersion", "${VERSION_MAJOR}.${VERSION_MINOR}"
-         END
-      END
-
-      BLOCK "VarFileInfo"
-      BEGIN
-        VALUE "Translation", 0x409, 1252  // U.S. English
-      END
-   END
--- a/Resources/SyncOrthancFolder.py	Wed Apr 11 16:24:26 2018 +0200
+++ b/Resources/SyncOrthancFolder.py	Tue Apr 17 15:47:47 2018 +0200
@@ -10,146 +10,20 @@
 import stat
 import urllib2
 
-TARGET = os.path.join(os.path.dirname(__file__), '..', 'Resources', 'Orthanc')
+TARGET = os.path.join(os.path.dirname(__file__), 'Orthanc')
 PLUGIN_SDK_VERSION = '1.0.0'
-REPOSITORY = 'http://bitbucket.org/sjodogne/orthanc/raw'
+REPOSITORY = 'https://bitbucket.org/sjodogne/orthanc/raw'
 
 FILES = [
-    'NEWS',
-    'Core/Cache/LeastRecentlyUsedIndex.h',
-    'Core/ChunkedBuffer.cpp',
-    'Core/ChunkedBuffer.h',
-    'Core/DicomFormat/DicomArray.cpp',
-    'Core/DicomFormat/DicomArray.h',
-    'Core/DicomFormat/DicomElement.h',
-    'Core/DicomFormat/DicomMap.cpp',
-    'Core/DicomFormat/DicomMap.h',
-    'Core/DicomFormat/DicomTag.cpp',
-    'Core/DicomFormat/DicomTag.h',
-    'Core/DicomFormat/DicomValue.cpp',
-    'Core/DicomFormat/DicomValue.h',
-    'Core/DicomParsing/ITagVisitor.h',
-    'Core/DicomParsing/FromDcmtkBridge.cpp',
-    'Core/DicomParsing/FromDcmtkBridge.h',
-    'Core/DicomParsing/ToDcmtkBridge.cpp',
-    'Core/DicomParsing/ToDcmtkBridge.h',
-    'Core/Endianness.h',
-    'Core/EnumerationDictionary.h',
-    'Core/Enumerations.cpp',
-    'Core/Enumerations.h',
-    'Core/HttpClient.cpp',
-    'Core/HttpClient.h',
-    'Core/ICommand.h',
-    'Core/IDynamicObject.h',
-    'Core/Images/IImageWriter.cpp',
-    'Core/Images/IImageWriter.h',
-    'Core/Images/Image.cpp',
-    'Core/Images/Image.h',
-    'Core/Images/ImageAccessor.cpp',
-    'Core/Images/ImageAccessor.h',
-    'Core/Images/ImageBuffer.cpp',
-    'Core/Images/ImageBuffer.h',
-    'Core/Images/ImageProcessing.cpp',
-    'Core/Images/ImageProcessing.h',
-    'Core/Images/JpegErrorManager.cpp',
-    'Core/Images/JpegErrorManager.h',
-    'Core/Images/JpegReader.cpp',
-    'Core/Images/JpegReader.h',
-    'Core/Images/JpegWriter.cpp',
-    'Core/Images/JpegWriter.h',
-    'Core/Images/PixelTraits.h',
-    'Core/Images/PngReader.cpp',
-    'Core/Images/PngReader.h',
-    'Core/Images/PngWriter.cpp',
-    'Core/Images/PngWriter.h',
-    'Core/Logging.cpp',
-    'Core/Logging.h',
-    'Core/MultiThreading/BagOfTasks.h',
-    'Core/MultiThreading/BagOfTasksProcessor.cpp',
-    'Core/MultiThreading/BagOfTasksProcessor.h',
-    'Core/MultiThreading/Semaphore.cpp',
-    'Core/MultiThreading/Semaphore.h',
-    'Core/MultiThreading/SharedMessageQueue.cpp',
-    'Core/MultiThreading/SharedMessageQueue.h',
-    'Core/OrthancException.h',
-    'Core/PrecompiledHeaders.cpp',
-    'Core/PrecompiledHeaders.h',
-    'Core/SharedLibrary.cpp',
-    'Core/SharedLibrary.h',
-    'Core/SystemToolbox.cpp',
-    'Core/SystemToolbox.h',
-    'Core/TemporaryFile.cpp',
-    'Core/TemporaryFile.h',
-    'Core/Toolbox.cpp',
-    'Core/Toolbox.h',
-    'Core/WebServiceParameters.cpp',
-    'Core/WebServiceParameters.h',
-    'Plugins/Samples/Common/DicomDatasetReader.cpp',
-    'Plugins/Samples/Common/DicomDatasetReader.h',
-    'Plugins/Samples/Common/DicomPath.cpp',
-    'Plugins/Samples/Common/DicomPath.h',
-    'Plugins/Samples/Common/DicomTag.cpp',
-    'Plugins/Samples/Common/DicomTag.h',
-    'Plugins/Samples/Common/ExportedSymbols.list',
-    'Plugins/Samples/Common/FullOrthancDataset.cpp',
-    'Plugins/Samples/Common/FullOrthancDataset.h',
-    'Plugins/Samples/Common/IDicomDataset.h',
-    'Plugins/Samples/Common/IOrthancConnection.cpp',
-    'Plugins/Samples/Common/IOrthancConnection.h',
-    'Plugins/Samples/Common/OrthancHttpConnection.cpp',
-    'Plugins/Samples/Common/OrthancHttpConnection.h',
-    'Plugins/Samples/Common/OrthancPluginConnection.cpp',
-    'Plugins/Samples/Common/OrthancPluginConnection.h',
-    'Plugins/Samples/Common/OrthancPluginCppWrapper.cpp',
-    'Plugins/Samples/Common/OrthancPluginCppWrapper.h',
-    'Plugins/Samples/Common/OrthancPluginException.h',
-    'Plugins/Samples/Common/SimplifiedOrthancDataset.cpp',
-    'Plugins/Samples/Common/SimplifiedOrthancDataset.h',
-    'Plugins/Samples/Common/VersionScript.map',
-    'Resources/CMake/AutoGeneratedCode.cmake',
-    'Resources/CMake/BoostConfiguration.cmake',
-    'Resources/CMake/Compiler.cmake',
-    'Resources/CMake/DcmtkConfiguration.cmake',
-    'Resources/CMake/DownloadPackage.cmake',
-    'Resources/CMake/JsonCppConfiguration.cmake',
-    'Resources/CMake/LibCurlConfiguration.cmake',
-    'Resources/CMake/LibIconvConfiguration.cmake',
-    'Resources/CMake/LibJpegConfiguration.cmake',
-    'Resources/CMake/LibPngConfiguration.cmake',
-    'Resources/CMake/OpenSslConfiguration.cmake',
-    'Resources/CMake/UuidConfiguration.cmake',
-    'Resources/CMake/VisualStudioPrecompiledHeaders.cmake',
-    'Resources/CMake/ZlibConfiguration.cmake',
-    'Resources/EmbedResources.py',
-    'Resources/LinuxStandardBaseToolchain.cmake',
-    'Resources/MinGW-W64-Toolchain32.cmake',
-    'Resources/MinGW-W64-Toolchain64.cmake',
-    'Resources/MinGWToolchain.cmake',
-    'Resources/Patches/boost-1.66.0-linux-standard-base.patch',
-    'Resources/Patches/curl-7.57.0-cmake.patch',
-    'Resources/Patches/dcmtk-3.6.0-dulparse-vulnerability.patch',
-    'Resources/Patches/dcmtk-3.6.0-mingw64.patch',
-    'Resources/Patches/dcmtk-3.6.0-speed.patch',
-    'Resources/Patches/dcmtk-3.6.2-linux-standard-base.patch',
-    'Resources/Patches/dcmtk-3.6.2-cmath.patch',
-    'Resources/ThirdParty/VisualStudio/stdint.h',
-    'Resources/ThirdParty/base64/base64.cpp',
-    'Resources/ThirdParty/base64/base64.h',
-    'Resources/ThirdParty/patch/NOTES.txt',
-    'Resources/ThirdParty/patch/msys-1.0.dll',
-    'Resources/ThirdParty/patch/patch.exe',
-    'Resources/ThirdParty/patch/patch.exe.manifest',
-    'Resources/WindowsResources.py',
-    'Resources/WindowsResources.rc',
+    'DownloadOrthancFramework.cmake',
+    'LinuxStandardBaseToolchain.cmake',
+    'MinGW-W64-Toolchain32.cmake',
+    'MinGW-W64-Toolchain64.cmake',
+    'MinGWToolchain.cmake',
 ]
 
 SDK = [
     'orthanc/OrthancCPlugin.h',
-]   
-
-EXE = [
-    'Resources/EmbedResources.py',
-    'Resources/WindowsResources.py',
 ]
 
 
@@ -166,21 +40,19 @@
 
     url = '%s/%s/%s' % (REPOSITORY, branch, source)
 
-    try:
-        with open(target, 'w') as f:
-            f.write(urllib2.urlopen(url).read())
-    except:
-        print('Cannot download file %s' % url)
-        raise
+    with open(target, 'w') as f:
+        f.write(urllib2.urlopen(url).read())
 
 
 commands = []
 
 for f in FILES:
-    commands.append([ 'default', f, f ])
+    commands.append([ 'default',
+                      os.path.join('Resources', f),
+                      f ])
 
 for f in SDK:
-    commands.append([ 
+    commands.append([
         'Orthanc-%s' % PLUGIN_SDK_VERSION, 
         'Plugins/Include/%s' % f,
         'Sdk-%s/%s' % (PLUGIN_SDK_VERSION, f) 
@@ -189,10 +61,3 @@
 
 pool = multiprocessing.Pool(10)  # simultaneous downloads
 pool.map(Download, commands)
-
-
-for exe in EXE:
-    path = os.path.join(TARGET, exe)
-    st = os.stat(path)
-    os.chmod(path, st.st_mode | stat.S_IEXEC)
-
--- a/ViewerPlugin/CMakeLists.txt	Wed Apr 11 16:24:26 2018 +0200
+++ b/ViewerPlugin/CMakeLists.txt	Tue Apr 17 15:47:47 2018 +0200
@@ -1,6 +1,8 @@
 cmake_minimum_required(VERSION 2.8)
 project(OrthancWSIPlugin)
 
+include(${CMAKE_SOURCE_DIR}/../Resources/CMake/Version.cmake)
+
 
 #####################################################################
 ## Parameters of the build
@@ -11,14 +13,8 @@
 SET(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages")
 
 # 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_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp")
-SET(USE_SYSTEM_LIBJPEG ON CACHE BOOL "Use the system version of libjpeg")
-SET(USE_SYSTEM_LIBPNG ON CACHE BOOL "Use the system version of libpng")
 SET(USE_SYSTEM_OPENJPEG ON CACHE BOOL "Use the system version of OpenJpeg")
 SET(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK")
-SET(USE_SYSTEM_ZLIB ON CACHE BOOL "Use the system version of ZLib")
-set(USE_SYSTEM_UUID ON CACHE BOOL "Use the system version of the uuid library from e2fsprogs")
 
 # Parameters related to OpenLayers
 SET(USE_SYSTEM_OPENLAYERS OFF CACHE BOOL "Use the system version of OpenLayers")
@@ -31,60 +27,32 @@
 #####################################################################
 
 SET(ORTHANC_WSI_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
-SET(ORTHANC_ROOT ${ORTHANC_WSI_DIR}/Resources/Orthanc)
-
 SET(USE_OPENJPEG_JP2 ON)
-SET(ENABLE_LOCALE OFF)         # Disable support for locales (notably in Boost)
 
-include(CheckIncludeFile)
-include(CheckIncludeFileCXX)
-include(CheckIncludeFiles)
-include(CheckLibraryExists)
-include(CheckSymbolExists)
-include(FindPkgConfig)
-include(FindPythonInterp)
+include(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/DownloadOrthancFramework.cmake)
+
+set(ORTHANC_FRAMEWORK_PLUGIN ON)
+include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
 
-include(${ORTHANC_ROOT}/Resources/CMake/Compiler.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/AutoGeneratedCode.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/VisualStudioPrecompiledHeaders.cmake)
+set(ENABLE_LOCALE OFF)         # Disable support for locales (notably in Boost)
+set(ENABLE_ZLIB ON)
+set(ENABLE_PNG ON)
+set(ENABLE_JPEG ON)
 
-# Third-party components shipped with Orthanc
-include(${ORTHANC_ROOT}/Resources/CMake/BoostConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/JsonCppConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/LibJpegConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/LibPngConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/UuidConfiguration.cmake)
-include(${ORTHANC_ROOT}/Resources/CMake/ZlibConfiguration.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkConfiguration.cmake)
+include_directories(${ORTHANC_ROOT})
 
 # Include components specific to WSI
 include(${ORTHANC_WSI_DIR}/Resources/CMake/Version.cmake)
 include(${ORTHANC_WSI_DIR}/Resources/CMake/OpenJpegConfiguration.cmake)
 
-add_definitions(
-  -DHAS_ORTHANC_EXCEPTION=1
-  -DORTHANC_DEFAULT_DICOM_ENCODING=Encoding_Latin1
-  -DORTHANC_ENABLE_BASE64=0
-  -DORTHANC_ENABLE_CURL=0
-  -DORTHANC_ENABLE_DCMTK=0
-  -DORTHANC_ENABLE_JPEG=1
-  -DORTHANC_ENABLE_LOCALE=0
-  -DORTHANC_ENABLE_LOGGING=1
-  -DORTHANC_ENABLE_LOGGING_PLUGIN=1
-  -DORTHANC_ENABLE_LOGGING_STDIO=0
-  -DORTHANC_ENABLE_MD5=0
-  -DORTHANC_ENABLE_PNG=1
-  -DORTHANC_ENABLE_PUGIXML=0
-  -DORTHANC_SANDBOXED=0
-  )
-
 
 #####################################################################
 ## Find the Orthanc SDK
 #####################################################################
 
 if (STATIC_BUILD OR NOT USE_SYSTEM_ORTHANC_SDK)
-  include_directories(${ORTHANC_ROOT}/Sdk-1.0.0)
+  include_directories(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/Sdk-1.0.0)
 else ()
   CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCPlugin.h HAVE_ORTHANC_H)
   if (NOT HAVE_ORTHANC_H)
@@ -170,6 +138,7 @@
 set(ORTHANC_WSI_SOURCES
   DicomPyramidCache.cpp
   Plugin.cpp
+
   ${ORTHANC_WSI_DIR}/Framework/DicomToolbox.cpp
   ${ORTHANC_WSI_DIR}/Framework/Enumerations.cpp
   ${ORTHANC_WSI_DIR}/Framework/ImageToolbox.cpp
@@ -179,25 +148,7 @@
   ${ORTHANC_WSI_DIR}/Framework/Inputs/PyramidWithRawTiles.cpp
   ${ORTHANC_WSI_DIR}/Framework/Jpeg2000Reader.cpp
   ${ORTHANC_WSI_DIR}/Framework/Jpeg2000Writer.cpp
-  )
 
-set(ORTHANC_CORE_SOURCES
-  ${ORTHANC_ROOT}/Core/ChunkedBuffer.cpp
-  ${ORTHANC_ROOT}/Core/Enumerations.cpp
-  ${ORTHANC_ROOT}/Core/Images/IImageWriter.cpp
-  ${ORTHANC_ROOT}/Core/Images/Image.cpp
-  ${ORTHANC_ROOT}/Core/Images/ImageAccessor.cpp
-  ${ORTHANC_ROOT}/Core/Images/ImageBuffer.cpp
-  ${ORTHANC_ROOT}/Core/Images/ImageProcessing.cpp
-  ${ORTHANC_ROOT}/Core/Images/JpegErrorManager.cpp
-  ${ORTHANC_ROOT}/Core/Images/JpegReader.cpp
-  ${ORTHANC_ROOT}/Core/Images/JpegWriter.cpp
-  ${ORTHANC_ROOT}/Core/Images/PngReader.cpp
-  ${ORTHANC_ROOT}/Core/Images/PngWriter.cpp
-  ${ORTHANC_ROOT}/Core/Logging.cpp
-  ${ORTHANC_ROOT}/Core/MultiThreading/Semaphore.cpp
-  ${ORTHANC_ROOT}/Core/SystemToolbox.cpp
-  ${ORTHANC_ROOT}/Core/Toolbox.cpp
   ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomDatasetReader.cpp
   ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomPath.cpp
   ${ORTHANC_ROOT}/Plugins/Samples/Common/FullOrthancDataset.cpp
@@ -216,7 +167,7 @@
 
   ADD_VISUAL_STUDIO_PRECOMPILED_HEADERS(
     "PrecompiledHeaders.h" "${ORTHANC_WSI_DIR}/Resources/Orthanc/Core/PrecompiledHeaders.cpp"
-    ORTHANC_CORE_SOURCES ORTHANC_CORE_PCH)
+    ORTHANC_CORE_SOURCES_INTERNAL ORTHANC_CORE_PCH)
 
   ADD_VISUAL_STUDIO_PRECOMPILED_HEADERS(
     "PrecompiledHeadersWSI.h" "${ORTHANC_WSI_DIR}/Framework/PrecompiledHeadersWSI.cpp"
@@ -232,19 +183,12 @@
 
 add_library(OrthancWSI SHARED
   ${ORTHANC_CORE_PCH}
-  ${ORTHANC_CORE_SOURCES}
+  ${ORTHANC_CORE_SOURCES_INTERNAL}
+  ${ORTHANC_CORE_SOURCES_DEPENDENCIES}
   ${ORTHANC_WSI_PCH}
   ${ORTHANC_WSI_SOURCES}
   ${AUTOGENERATED_SOURCES}
-  
-  # Mandatory components
-  ${BOOST_SOURCES}
-  ${JSONCPP_SOURCES}
-  ${LIBJPEG_SOURCES}
-  ${LIBPNG_SOURCES}
   ${OPENJPEG_SOURCES}
-  ${UUID_SOURCES}
-  ${ZLIB_SOURCES}
   )
 
 message("Setting the version of the library to ${ORTHANC_WSI_VERSION}")
--- a/ViewerPlugin/DicomPyramidCache.h	Wed Apr 11 16:24:26 2018 +0200
+++ b/ViewerPlugin/DicomPyramidCache.h	Tue Apr 17 15:47:47 2018 +0200
@@ -22,7 +22,8 @@
 #pragma once
 
 #include "../Framework/Inputs/DicomPyramid.h"
-#include "../Resources/Orthanc/Core/Cache/LeastRecentlyUsedIndex.h"
+
+#include <Core/Cache/LeastRecentlyUsedIndex.h>
 
 #include <boost/thread/mutex.hpp>
 
--- a/ViewerPlugin/Plugin.cpp	Wed Apr 11 16:24:26 2018 +0200
+++ b/ViewerPlugin/Plugin.cpp	Tue Apr 17 15:47:47 2018 +0200
@@ -24,12 +24,12 @@
 #include "DicomPyramidCache.h"
 #include "../Framework/Jpeg2000Reader.h"
 
-#include "../Resources/Orthanc/Core/Images/ImageProcessing.h"
-#include "../Resources/Orthanc/Core/Images/PngWriter.h"
-#include "../Resources/Orthanc/Core/MultiThreading/Semaphore.h"
-#include "../Resources/Orthanc/Core/OrthancException.h"
-#include "../Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h"
-#include "../Resources/Orthanc/Plugins/Samples/Common/OrthancPluginConnection.h"
+#include <Core/Images/ImageProcessing.h>
+#include <Core/Images/PngWriter.h>
+#include <Core/MultiThreading/Semaphore.h>
+#include <Core/OrthancException.h>
+#include <Plugins/Samples/Common/OrthancPluginCppWrapper.h>
+#include <Plugins/Samples/Common/OrthancPluginConnection.h>
 
 #include <EmbeddedResources.h>