changeset 107:a3e8ac8b7256

support for OpenBSD
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 23 Aug 2017 11:10:48 +0200
parents 42dcf1438943
children c0ac0d350193
files Applications/CMakeLists.txt NEWS Resources/Orthanc/Core/Enumerations.cpp Resources/Orthanc/Core/Enumerations.h Resources/Orthanc/Core/HttpClient.cpp Resources/Orthanc/Core/Images/ImageProcessing.cpp Resources/Orthanc/Core/Images/ImageProcessing.h Resources/Orthanc/Core/Logging.cpp Resources/Orthanc/Core/SystemToolbox.cpp Resources/Orthanc/Core/SystemToolbox.h Resources/Orthanc/Core/Toolbox.cpp Resources/Orthanc/Core/Toolbox.h Resources/Orthanc/OrthancServer/FromDcmtkBridge.cpp Resources/Orthanc/OrthancServer/ServerEnumerations.cpp Resources/Orthanc/OrthancServer/ServerEnumerations.h Resources/Orthanc/Plugins/Engine/SharedLibrary.cpp Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.cpp Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.cpp Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake Resources/Orthanc/Resources/CMake/Compiler.cmake Resources/Orthanc/Resources/CMake/DcmtkConfiguration.cmake Resources/Orthanc/Resources/CMake/LibCurlConfiguration.cmake Resources/Orthanc/Resources/CMake/LibIconvConfiguration.cmake Resources/Orthanc/Resources/CMake/OpenSslConfiguration.cmake Resources/Orthanc/Resources/CMake/ZlibConfiguration.cmake Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-speed.patch Resources/Orthanc/Resources/Patches/dcmtk-3.6.1-speed.patch Resources/SyncOrthancFolder.py ViewerPlugin/CMakeLists.txt
diffstat 33 files changed, 1349 insertions(+), 620 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/CMakeLists.txt	Wed Mar 22 15:53:48 2017 +0100
+++ b/Applications/CMakeLists.txt	Wed Aug 23 11:10:48 2017 +0200
@@ -27,6 +27,7 @@
 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")
@@ -37,6 +38,9 @@
 
 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)
+
 
 #####################################################################
 ## Configure mandatory third-party components
@@ -48,9 +52,11 @@
 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)
 SET(STANDALONE_BUILD ON)       # Embed DCMTK's dictionaries for static builds
 SET(USE_DCMTK_361_PRIVATE_DIC OFF)  # No need for private tags
 
+include(CheckFunctionExists)
 include(CheckIncludeFiles)
 include(CheckIncludeFileCXX)
 include(CheckLibraryExists)
@@ -67,6 +73,7 @@
 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/ZlibConfiguration.cmake)
@@ -83,6 +90,7 @@
   -DORTHANC_ENABLE_CURL=1
   -DORTHANC_ENABLE_DCMTK=1
   -DORTHANC_ENABLE_JPEG=0       # Disable DCMTK's support for JPEG
+  -DORTHANC_ENABLE_LOCALE=1
   -DORTHANC_ENABLE_LOGGING=1
   -DORTHANC_ENABLE_LOGGING_PLUGIN=0
   -DORTHANC_ENABLE_LUA=0        # For FromDcmtkBridge
@@ -240,6 +248,7 @@
   ${CURL_SOURCES}
   ${DCMTK_SOURCES}
   ${JSONCPP_SOURCES}
+  ${LIBICONV_SOURCES}
   ${LIBJPEG_SOURCES}
   ${LIBPNG_SOURCES}
   ${LIBTIFF_SOURCES}
--- a/NEWS	Wed Mar 22 15:53:48 2017 +0100
+++ b/NEWS	Wed Aug 23 11:10:48 2017 +0200
@@ -1,6 +1,8 @@
 Pending changes in the mainline
 ===============================
 
+* Support for OpenBSD
+
 
 Version 0.4 (2017-03-01)
 ========================
--- a/Resources/Orthanc/Core/Enumerations.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/Enumerations.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -636,10 +636,10 @@
         return "RGB";
 
       case PhotometricInterpretation_Monochrome1:
-        return "Monochrome1";
+        return "MONOCHROME1";
 
       case PhotometricInterpretation_Monochrome2:
-        return "Monochrome2";
+        return "MONOCHROME2";
 
       case PhotometricInterpretation_ARGB:
         return "ARGB";
@@ -651,25 +651,25 @@
         return "HSV";
 
       case PhotometricInterpretation_Palette:
-        return "Palette color";
+        return "PALETTE COLOR";
 
       case PhotometricInterpretation_YBRFull:
-        return "YBR full";
+        return "YBR_FULL";
 
       case PhotometricInterpretation_YBRFull422:
-        return "YBR full 422";
+        return "YBR_FULL_422";
 
       case PhotometricInterpretation_YBRPartial420:
-        return "YBR partial 420"; 
+        return "YBR_PARTIAL_420"; 
 
       case PhotometricInterpretation_YBRPartial422:
-        return "YBR partial 422"; 
+        return "YBR_PARTIAL_422"; 
 
       case PhotometricInterpretation_YBR_ICT:
-        return "YBR ICT"; 
+        return "YBR_ICT"; 
 
       case PhotometricInterpretation_YBR_RCT:
-        return "YBR RCT"; 
+        return "YBR_RCT"; 
 
       case PhotometricInterpretation_Unknown:
         return "Unknown";
@@ -1053,6 +1053,80 @@
   }
 
 
+  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);
+  }
+  
+
   unsigned int GetBytesPerPixel(PixelFormat format)
   {
     switch (format)
--- a/Resources/Orthanc/Core/Enumerations.h	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/Enumerations.h	Wed Aug 23 11:10:48 2017 +0200
@@ -524,6 +524,8 @@
   ValueRepresentation StringToValueRepresentation(const std::string& vr,
                                                   bool throwIfUnsupported);
 
+  PhotometricInterpretation StringToPhotometricInterpretation(const char* value);
+  
   unsigned int GetBytesPerPixel(PixelFormat format);
 
   bool GetDicomEncoding(Encoding& encoding,
--- a/Resources/Orthanc/Core/HttpClient.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/HttpClient.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -823,10 +823,12 @@
 
   void HttpClient::FinalizeOpenSsl()
   {
- #if ORTHANC_ENABLE_SSL == 1
+#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();
--- a/Resources/Orthanc/Core/Images/ImageProcessing.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/Images/ImageProcessing.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -772,4 +772,29 @@
         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);
+    }   
+  }
 }
--- a/Resources/Orthanc/Core/Images/ImageProcessing.h	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/Images/ImageProcessing.h	Wed Aug 23 11:10:48 2017 +0200
@@ -73,5 +73,7 @@
     static void ShiftScale(ImageAccessor& image,
                            float offset,
                            float scaling);
+
+    static void Invert(ImageAccessor& image);
   };
 }
--- a/Resources/Orthanc/Core/Logging.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/Logging.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -91,7 +91,7 @@
 
     void Initialize(OrthancPluginContext* context)
     {
-      context_ = context_;
+      context_ = context;
     }
 
     InternalLogger::InternalLogger(const char* level,
@@ -117,6 +117,11 @@
         {
           OrthancPluginLogInfo(context_, message_.c_str());
         }
+        else
+        {
+          std::string s = "Unknown log level (" + level_ + ") for message: " + message_;
+          OrthancPluginLogError(context_, s.c_str());
+        }
       }
     }
 
@@ -156,12 +161,7 @@
 #include <fstream>
 #include <boost/filesystem.hpp>
 #include <boost/thread.hpp>
-
-#if BOOST_HAS_DATE_TIME == 1
-#  include <boost/date_time/posix_time/posix_time.hpp>
-#else
-#  error Boost::date_time is required
-#endif
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 
 namespace
--- a/Resources/Orthanc/Core/SystemToolbox.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/SystemToolbox.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -35,11 +35,6 @@
 #include "SystemToolbox.h"
 
 
-#if BOOST_HAS_DATE_TIME == 1
-#  include <boost/date_time/posix_time/posix_time.hpp>
-#endif
-
-
 #if defined(_WIN32)
 #  include <windows.h>
 #  include <process.h>   // For "_spawnvp()" and "_getpid()"
@@ -62,12 +57,17 @@
 #endif
 
 
+#if defined(__OpenBSD__)
+#  include <sys/sysctl.h>  // For "sysctl", "CTL_KERN" and "KERN_PROC_ARGS"
+#endif
+
+
 // Inclusions for UUID
 // http://stackoverflow.com/a/1626302
 
 extern "C"
 {
-#ifdef WIN32
+#if defined(_WIN32)
 #  include <rpc.h>
 #else
 #  include <uuid/uuid.h>
@@ -81,6 +81,7 @@
 
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 
 namespace Orthanc
@@ -157,7 +158,7 @@
   {
 #if defined(_WIN32)
     ::Sleep(static_cast<DWORD>(microSeconds / static_cast<uint64_t>(1000)));
-#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__native_client__)
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__native_client__)
     usleep(microSeconds);
 #else
 #error Support your platform here
@@ -193,7 +194,7 @@
     }
 
     std::streamsize size = GetStreamSize(f);
-    content.resize(size);
+    content.resize(static_cast<size_t>(size));
     if (size != 0)
     {
       f.read(reinterpret_cast<char*>(&content[0]), size);
@@ -231,7 +232,7 @@
       }
       else if (static_cast<size_t>(size) < headerSize)
       {
-        headerSize = size;  // Truncate to the size of the file
+        headerSize = static_cast<size_t>(size);  // Truncate to the size of the file
         full = false;
       }
     }
@@ -349,6 +350,8 @@
 #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)
@@ -370,6 +373,37 @@
     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
@@ -527,13 +561,13 @@
   }
 
 
-#if BOOST_HAS_DATE_TIME == 1
   std::string SystemToolbox::GetNowIsoString()
   {
     boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
     return boost::posix_time::to_iso_string(now);
   }
 
+  
   void SystemToolbox::GetNowDicom(std::string& date,
                                   std::string& time)
   {
@@ -548,5 +582,4 @@
     sprintf(s, "%02d%02d%02d.%06d", tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
     time.assign(s);
   }
-#endif
 }
--- a/Resources/Orthanc/Core/SystemToolbox.h	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/SystemToolbox.h	Wed Aug 23 11:10:48 2017 +0200
@@ -95,11 +95,9 @@
 
     std::string GenerateUuid();
 
-#if BOOST_HAS_DATE_TIME == 1
     std::string GetNowIsoString();
 
     void GetNowDicom(std::string& date,
                      std::string& time);
-#endif
   }
 }
--- a/Resources/Orthanc/Core/Toolbox.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/Toolbox.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -37,24 +37,18 @@
 #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/locale.hpp>
+#include <boost/regex.hpp> 
 #include <boost/uuid/sha1.hpp>
-
+ 
 #include <string>
 #include <stdint.h>
 #include <string.h>
 #include <algorithm>
 #include <ctype.h>
 
-#if BOOST_HAS_REGEX == 1
-#  include <boost/regex.hpp> 
-#endif
-
-#if BOOST_HAS_LOCALE != 1
-#  error Since version 0.7.6, Orthanc entirely relies on boost::locale
-#endif
 
 #if ORTHANC_ENABLE_MD5 == 1
 #  include "../Resources/ThirdParty/md5/md5.h"
@@ -64,6 +58,10 @@
 #  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
@@ -368,7 +366,6 @@
   }
 
 
-#  if BOOST_HAS_REGEX == 1
   bool Toolbox::DecodeDataUriScheme(std::string& mime,
                                     std::string& content,
                                     const std::string& source)
@@ -388,7 +385,6 @@
       return false;
     }
   }
-#  endif
 
 
   void Toolbox::EncodeDataUriScheme(std::string& result,
@@ -469,6 +465,7 @@
   }
 
 
+#if ORTHANC_ENABLE_LOCALE == 1
   std::string Toolbox::ConvertToUtf8(const std::string& source,
                                      Encoding sourceEncoding)
   {
@@ -495,8 +492,10 @@
       return ConvertToAscii(source);
     }
   }
+#endif
+  
 
-
+#if ORTHANC_ENABLE_LOCALE == 1
   std::string Toolbox::ConvertFromUtf8(const std::string& source,
                                        Encoding targetEncoding)
   {
@@ -523,6 +522,7 @@
       return ConvertToAscii(source);
     }
   }
+#endif
 
 
   bool Toolbox::IsAsciiString(const void* data,
@@ -778,7 +778,6 @@
   }
 
 
-#if BOOST_HAS_REGEX == 1
   std::string Toolbox::WildcardToRegularExpression(const std::string& source)
   {
     // TODO - Speed up this with a regular expression
@@ -806,8 +805,6 @@
 
     return result;
   }
-#endif
-
 
 
   void Toolbox::TokenizeString(std::vector<std::string>& result,
@@ -1251,4 +1248,124 @@
 
     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
 }
--- a/Resources/Orthanc/Core/Toolbox.h	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Core/Toolbox.h	Wed Aug 23 11:10:48 2017 +0200
@@ -45,6 +45,10 @@
 #  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
@@ -53,10 +57,6 @@
 #  error The macro ORTHANC_ENABLE_PUGIXML must be defined
 #endif
 
-#if !defined(BOOST_HAS_REGEX)
-#  error The macro BOOST_HAS_REGEX must be defined
-#endif
-
 
 /**
  * NOTE: GUID vs. UUID
@@ -132,22 +132,22 @@
     void EncodeBase64(std::string& result, 
                       const std::string& data);
 
-#  if BOOST_HAS_REGEX == 1
     bool DecodeDataUriScheme(std::string& mime,
                              std::string& content,
                              const std::string& source);
-#  endif
 
     void EncodeDataUriScheme(std::string& result,
                              const std::string& mime,
                              const std::string& content);
 #endif
 
+#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);
@@ -161,9 +161,7 @@
 
     Endianness DetectEndianness();
 
-#if BOOST_HAS_REGEX == 1
     std::string WildcardToRegularExpression(const std::string& s);
-#endif
 
     void TokenizeString(std::vector<std::string>& result,
                         const std::string& source,
@@ -206,5 +204,13 @@
     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
   }
 }
--- a/Resources/Orthanc/OrthancServer/FromDcmtkBridge.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/OrthancServer/FromDcmtkBridge.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -181,6 +181,8 @@
 
   void FromDcmtkBridge::InitializeDictionary(bool loadPrivateDictionary)
   {
+    LOG(INFO) << "Using DCTMK version: " << DCMTK_VERSION_NUMBER;
+    
     {
       DictionaryLocker locker;
 
@@ -207,7 +209,7 @@
         LOG(INFO) << "The dictionary of private tags has not been loaded";
       }
 
-#elif defined(__linux__) || defined(__FreeBSD_kernel__)
+#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);
@@ -1681,7 +1683,7 @@
           throw OrthancException(ErrorCode_BadParameterType);
         }
 
-        DcmSequenceOfItems* sequence = new DcmSequenceOfItems(key, value.size());
+        DcmSequenceOfItems* sequence = new DcmSequenceOfItems(key);
         element.reset(sequence);
         
         for (Json::Value::ArrayIndex i = 0; i < value.size(); i++)
--- a/Resources/Orthanc/OrthancServer/ServerEnumerations.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/OrthancServer/ServerEnumerations.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -325,27 +325,21 @@
       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_MedInria:
-        return "MedInria";
-
       case ModalityManufacturer_Dcm4Chee:
         return "Dcm4Chee";
       
-      case ModalityManufacturer_SyngoVia:
-        return "SyngoVia";
-      
-      case ModalityManufacturer_AgfaImpax:
-        return "AgfaImpax";
-      
-      case ModalityManufacturer_EFilm2:
-        return "EFilm2";
-      
       case ModalityManufacturer_Vitrea:
         return "Vitrea";
       
@@ -388,10 +382,21 @@
 
   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;
@@ -400,34 +405,41 @@
     {
       return ModalityManufacturer_StoreScp;
     }
-    else if (manufacturer == "MedInria")
-    {
-      return ModalityManufacturer_MedInria;
-    }
     else if (manufacturer == "Dcm4Chee")
     {
       return ModalityManufacturer_Dcm4Chee;
     }
-    else if (manufacturer == "SyngoVia")
-    {
-      return ModalityManufacturer_SyngoVia;
-    }
-    else if (manufacturer == "AgfaImpax")
-    {
-      return ModalityManufacturer_AgfaImpax;
-    }
     else if (manufacturer == "Vitrea")
     {
       return ModalityManufacturer_Vitrea;
     }
-    else if (manufacturer == "EFilm2")
+    else if (manufacturer == "AgfaImpax" ||
+             manufacturer == "SyngoVia")
     {
-      return ModalityManufacturer_EFilm2;
+      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;
   }
 
 
@@ -462,6 +474,41 @@
   }
 
 
+  const char* EnumerationToString(DicomVersion version)
+  {
+    switch (version)
+    {
+      case DicomVersion_2008:
+        return "2008";
+        break;
+
+      case DicomVersion_2017c:
+        return "2017c";
+        break;
+
+      default: 
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+
+  DicomVersion StringToDicomVersion(const std::string& version)
+  {
+    if (version == "2008")
+    {
+      return DicomVersion_2008;
+    }
+    else if (version == "2017c")
+    {
+      return DicomVersion_2017c;
+    }
+    else
+    {
+      throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+  
   bool IsUserMetadata(MetadataType metadata)
   {
     return (metadata >= MetadataType_StartUser &&
--- a/Resources/Orthanc/OrthancServer/ServerEnumerations.h	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/OrthancServer/ServerEnumerations.h	Wed Aug 23 11:10:48 2017 +0200
@@ -59,13 +59,11 @@
   enum ModalityManufacturer
   {
     ModalityManufacturer_Generic,
+    ModalityManufacturer_GenericNoWildcardInDates,
+    ModalityManufacturer_GenericNoUniversalWildcard,
     ModalityManufacturer_StoreScp,
     ModalityManufacturer_ClearCanvas,
-    ModalityManufacturer_MedInria,
     ModalityManufacturer_Dcm4Chee,
-    ModalityManufacturer_SyngoVia,
-    ModalityManufacturer_AgfaImpax,
-    ModalityManufacturer_EFilm2,
     ModalityManufacturer_Vitrea
   };
 
@@ -135,6 +133,12 @@
     IdentifierConstraintType_Wildcard        /* Case sensitive, "*" or "?" are the only allowed wildcards */
   };
 
+  enum DicomVersion
+  {
+    DicomVersion_2008,
+    DicomVersion_2017c
+  };
+
 
   /**
    * WARNING: Do not change the explicit values in the enumerations
@@ -146,7 +150,8 @@
   {
     GlobalProperty_DatabaseSchemaVersion = 1,   // Unused in the Orthanc core as of Orthanc 0.9.5
     GlobalProperty_FlushSleep = 2,
-    GlobalProperty_AnonymizationSequence = 3
+    GlobalProperty_AnonymizationSequence = 3,
+    GlobalProperty_DatabasePatchLevel = 4       // Reserved for internal use of the database plugins
   };
 
   enum MetadataType
@@ -229,7 +234,11 @@
 
   const char* EnumerationToString(TransferSyntax syntax);
 
+  const char* EnumerationToString(DicomVersion version);
+
   ModalityManufacturer StringToModalityManufacturer(const std::string& manufacturer);
 
+  DicomVersion StringToDicomVersion(const std::string& version);
+
   bool IsUserMetadata(MetadataType type);
 }
--- a/Resources/Orthanc/Plugins/Engine/SharedLibrary.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Plugins/Engine/SharedLibrary.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -46,7 +46,7 @@
 
 #if defined(_WIN32)
 #include <windows.h>
-#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
+#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__)
 #include <dlfcn.h>
 #else
 #error Support your platform here
@@ -66,7 +66,7 @@
       throw OrthancException(ErrorCode_SharedLibrary);
     }
 
-#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
+#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__)
     handle_ = ::dlopen(path_.c_str(), RTLD_NOW);
     if (handle_ == NULL) 
     {
@@ -92,7 +92,7 @@
     {
 #if defined(_WIN32)
       ::FreeLibrary((HMODULE)handle_);
-#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
+#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__OpenBSD__)
       ::dlclose(handle_);
 #else
 #error Support your platform here
@@ -110,7 +110,7 @@
 
 #if defined(_WIN32)
     return ::GetProcAddress((HMODULE)handle_, name.c_str());
-#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
+#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
--- a/Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -166,6 +166,21 @@
   }
 
 
+  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
   {
--- a/Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h	Wed Aug 23 11:10:48 2017 +0200
@@ -55,6 +55,11 @@
 
     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;
 
--- a/Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -51,6 +51,20 @@
   }
 
 
+  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)
--- a/Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/IOrthancConnection.h	Wed Aug 23 11:10:48 2017 +0200
@@ -64,6 +64,10 @@
     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);
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Wed Aug 23 11:10:48 2017 +0200
@@ -51,6 +51,31 @@
   }
 
 
+  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)
   {
@@ -119,29 +144,13 @@
   {
     Clear();
 
-    OrthancPluginErrorCode error;
-
     if (applyPlugins)
     {
-      error = OrthancPluginRestApiGetAfterPlugins(context_, &buffer_, uri.c_str());
+      return CheckHttp(OrthancPluginRestApiGetAfterPlugins(context_, &buffer_, uri.c_str()));
     }
     else
     {
-      error = OrthancPluginRestApiGet(context_, &buffer_, 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);
+      return CheckHttp(OrthancPluginRestApiGet(context_, &buffer_, uri.c_str()));
     }
   }
 
@@ -153,29 +162,13 @@
   {
     Clear();
 
-    OrthancPluginErrorCode error;
-
     if (applyPlugins)
     {
-      error = OrthancPluginRestApiPostAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize);
+      return CheckHttp(OrthancPluginRestApiPostAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize));
     }
     else
     {
-      error = OrthancPluginRestApiPost(context_, &buffer_, uri.c_str(), body, bodySize);
-    }
-
-    if (error == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (error == OrthancPluginErrorCode_UnknownResource ||
-             error == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
+      return CheckHttp(OrthancPluginRestApiPost(context_, &buffer_, uri.c_str(), body, bodySize));
     }
   }
 
@@ -187,29 +180,13 @@
   {
     Clear();
 
-    OrthancPluginErrorCode error;
-
     if (applyPlugins)
     {
-      error = OrthancPluginRestApiPutAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize);
+      return CheckHttp(OrthancPluginRestApiPutAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize));
     }
     else
     {
-      error = OrthancPluginRestApiPut(context_, &buffer_, uri.c_str(), body, bodySize);
-    }
-
-    if (error == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (error == OrthancPluginErrorCode_UnknownResource ||
-             error == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
+      return CheckHttp(OrthancPluginRestApiPut(context_, &buffer_, uri.c_str(), body, bodySize));
     }
   }
 
@@ -322,6 +299,69 @@
     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) : 
@@ -557,6 +597,94 @@
     }
   }
 
+
+  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
@@ -998,15 +1126,20 @@
   }
 
 
-  static void ReportIncompatibleVersion(OrthancPluginContext* context,
-                                        unsigned int major,
-                                        unsigned int minor,
-                                        unsigned int revision)
+  void ReportMinimalOrthancVersion(OrthancPluginContext* context,
+                                   unsigned int major,
+                                   unsigned int minor,
+                                   unsigned int revision)
   {
-    char buf[128];
-    sprintf(buf, "Your version of the Orthanc core (%s) is too old to run this plugin (%d.%d.%d is required)",
-            context->orthancVersion, major, minor, revision);
-    OrthancPluginLogError(context, buf);
+    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());
   }
 
 
@@ -1056,7 +1189,6 @@
 
     if (a < major)
     {
-      ReportIncompatibleVersion(context, major, minor, revision);
       return false;
     }
 
@@ -1071,7 +1203,6 @@
 
     if (b < minor)
     {
-      ReportIncompatibleVersion(context, major, minor, revision);
       return false;
     }
 
@@ -1084,7 +1215,6 @@
     }
     else
     {
-      ReportIncompatibleVersion(context, major, minor, revision);
       return false;
     }
   }
--- a/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Wed Aug 23 11:10:48 2017 +0200
@@ -39,11 +39,20 @@
 #include <boost/noncopyable.hpp>
 #include <boost/lexical_cast.hpp>
 #include <json/value.h>
+#include <list>
+#include <set>
+
 
 
-#if (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER >= 2 ||   \
-     (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER == 1 &&  \
-      ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER >= 2))
+#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))))
+  
+
+#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
@@ -66,6 +75,8 @@
 
     void Check(OrthancPluginErrorCode code);
 
+    bool CheckHttp(OrthancPluginErrorCode code);
+
   public:
     MemoryBuffer(OrthancPluginContext* context);
 
@@ -151,6 +162,20 @@
                      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);
   };
 
 
@@ -232,6 +257,14 @@
     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;
 
@@ -403,6 +436,11 @@
                      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)
   {
@@ -430,6 +468,11 @@
     }
   }
 
+  void ReportMinimalOrthancVersion(OrthancPluginContext* context,
+                                   unsigned int major,
+                                   unsigned int minor,
+                                   unsigned int revision);
+  
   bool CheckMinimalOrthancVersion(OrthancPluginContext* context,
                                   unsigned int major,
                                   unsigned int minor,
--- a/Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake	Wed Aug 23 11:10:48 2017 +0200
@@ -7,8 +7,12 @@
   #set(Boost_DEBUG 1)
   #set(Boost_USE_STATIC_LIBS ON)
 
+  if (ENABLE_LOCALE)
+    list(APPEND ORTHANC_BOOST_COMPONENTS locale)
+  endif()
+
   find_package(Boost
-    COMPONENTS filesystem thread system date_time regex locale ${ORTHANC_BOOST_COMPONENTS})
+    COMPONENTS filesystem thread system date_time regex ${ORTHANC_BOOST_COMPONENTS})
 
   if (NOT Boost_FOUND)
     message(FATAL_ERROR "Unable to locate Boost on this system")
@@ -27,112 +31,120 @@
       )
   endif()
 
-  #if (${Boost_VERSION} LESS 104800)
-  # boost::locale is only available from 1.48.00
-  #message("Too old version of Boost (${Boost_LIB_VERSION}): Building the static version")
-  #  set(BOOST_STATIC 1)
-  #endif()
-
   include_directories(${Boost_INCLUDE_DIRS})
   link_libraries(${Boost_LIBRARIES})
 endif()
 
 
 if (BOOST_STATIC)
-  # Parameters for Boost 1.60.0
-  set(BOOST_NAME boost_1_60_0)
-  set(BOOST_BCP_SUFFIX bcpdigest-1.0.1)
-  set(BOOST_MD5 "a789f8ec2056ad1c2d5f0cb64687cc7b")
+  ##
+  ## Parameters for static compilation of Boost 
+  ##
+  
+  set(BOOST_NAME boost_1_64_0)
+  set(BOOST_BCP_SUFFIX bcpdigest-1.3.0)
+  set(BOOST_MD5 "ecb266cf46adcc7f695ad12685871174")
   set(BOOST_URL "http://www.orthanc-server.com/downloads/third-party/${BOOST_NAME}_${BOOST_BCP_SUFFIX}.tar.gz")
-  set(BOOST_FILESYSTEM_SOURCES_DIR "${BOOST_NAME}/libs/filesystem/src") 
   set(BOOST_SOURCES_DIR ${CMAKE_BINARY_DIR}/${BOOST_NAME})
 
   DownloadPackage(${BOOST_MD5} ${BOOST_URL} "${BOOST_SOURCES_DIR}")
 
-  set(BOOST_SOURCES)
+
+  ##
+  ## Generic configuration of Boost
+  ## 
+
+  if (CMAKE_COMPILER_IS_GNUCXX)
+    add_definitions(-isystem ${BOOST_SOURCES_DIR})
+  endif()
+
+  include_directories(
+    ${BOOST_SOURCES_DIR}
+    )
 
-  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 "PNaCl" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64")
+  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
+    )
+
+
+  ##
+  ## 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
       )
-    add_definitions(
-      -DBOOST_LOCALE_WITH_ICONV=1
-      -DBOOST_LOCALE_NO_WINAPI_BACKEND=1
-      -DBOOST_LOCALE_NO_STD_BACKEND=1
-      )
 
     if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase" OR
-        ${CMAKE_SYSTEM_NAME} STREQUAL "PNaCl" OR
-        ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR
-        ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64")
+        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")
+  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
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/windows_file_codecvt.cpp
       )
 
-    # 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").
-
-    if (USE_BOOST_ICONV)
-      include(${ORTHANC_ROOT}/Resources/CMake/LibIconvConfiguration.cmake)
-    else()
-      add_definitions(-DBOOST_LOCALE_WITH_WCONV=1)
-    endif()
-
-    add_definitions(
-      -DBOOST_LOCALE_NO_POSIX_BACKEND=1
-      -DBOOST_LOCALE_NO_STD_BACKEND=1
-      )
-
-  elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
-    add_definitions(
-      -DBOOST_LOCALE_NO_POSIX_BACKEND=1
-      -DBOOST_LOCALE_NO_STD_BACKEND=1
-      )
+  elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
 
   else()
     message(FATAL_ERROR "Support your platform here")
   endif()
 
-  if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
-    list(APPEND BOOST_SOURCES
-      ${BOOST_SOURCES_DIR}/libs/filesystem/src/utf8_codecvt_facet.cpp
-      )
-  endif()
 
+  ##
+  ## Configuration of boost::regex
+  ##
+  
   aux_source_directory(${BOOST_SOURCES_DIR}/libs/regex/src BOOST_REGEX_SOURCES)
 
   list(APPEND BOOST_SOURCES
     ${BOOST_REGEX_SOURCES}
-    ${BOOST_SOURCES_DIR}/libs/date_time/src/gregorian/greg_month.cpp
-    ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp
     )
 
-  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
-    list(APPEND BOOST_SOURCES
-      ${BOOST_SOURCES_DIR}/libs/locale/src/encoding/codepage.cpp
-      )
-  endif()
+
+  ##
+  ## Configuration of boost::datetime
+  ##
+  
+  list(APPEND BOOST_SOURCES
+    ${BOOST_SOURCES_DIR}/libs/date_time/src/gregorian/greg_month.cpp
+    )
 
-  if (${CMAKE_SYSTEM_NAME} STREQUAL "PNaCl" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64")
+
+  ##
+  ## 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
@@ -143,50 +155,35 @@
       -DBOOST_HAS_FILESYSTEM_V3=1
       )
     list(APPEND BOOST_SOURCES
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/codecvt_error_category.cpp
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/operations.cpp
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/path.cpp
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/path_traits.cpp
+      ${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")
+     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()
 
-  if (USE_BOOST_LOCALE_BACKENDS)
-    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 "PNaCl" OR
-        ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR
-        ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64")
-      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
-        )
-    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
-        )
-    else()
-      message(FATAL_ERROR "Support your platform here")
-    endif()
+
+  ##
+  ## Configuration of boost::locale
+  ## 
 
+  if (NOT ENABLE_LOCALE)
+    message("boost::locale is disabled")
+  else()
     list(APPEND BOOST_SOURCES
-      ${BOOST_REGEX_SOURCES}
-      ${BOOST_SOURCES_DIR}/libs/date_time/src/gregorian/greg_month.cpp
-      ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp
-
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/codecvt_error_category.cpp
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/operations.cpp
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/path.cpp
-      ${BOOST_FILESYSTEM_SOURCES_DIR}/path_traits.cpp
-
+      ${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
@@ -200,39 +197,75 @@
       ${BOOST_SOURCES_DIR}/libs/locale/src/util/info.cpp
       ${BOOST_SOURCES_DIR}/libs/locale/src/util/locale_data.cpp
       )        
+
+    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 "PNaCl" OR
+        CMAKE_SYSTEM_NAME STREQUAL "NaCl32" OR
+        CMAKE_SYSTEM_NAME STREQUAL "NaCl64")
+      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 "OpenBSD")
+      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 "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()
 
-  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
-    -DBOOST_HAS_LOCALE=1
-    )
-
-  if (CMAKE_COMPILER_IS_GNUCXX)
-    add_definitions(-isystem ${BOOST_SOURCES_DIR})
-  endif()
-
-  include_directories(
-    ${BOOST_SOURCES_DIR}
-    )
-
+  
   source_group(ThirdParty\\boost REGULAR_EXPRESSION ${BOOST_SOURCES_DIR}/.*)
 
-else()
-  add_definitions(
-    -DBOOST_HAS_LOCALE=1
-    )
 endif()
-
-
-add_definitions(
-  -DBOOST_HAS_DATE_TIME=1
-  -DBOOST_HAS_REGEX=1
-  )
--- a/Resources/Orthanc/Resources/CMake/Compiler.cmake	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Resources/CMake/Compiler.cmake	Wed Aug 23 11:10:48 2017 +0200
@@ -7,7 +7,8 @@
 endif()
 
 if (CMAKE_COMPILER_IS_GNUCXX)
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-long-long -Wno-implicit-function-declaration")  
+  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")
@@ -56,11 +57,27 @@
 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")
-  set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined")
-  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
+    ${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)
@@ -70,22 +87,39 @@
   # Remove the "-rdynamic" option
   # http://www.mail-archive.com/cmake@cmake.org/msg08837.html
   set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
-  link_libraries(uuid pthread rt)
+  link_libraries(uuid 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")
+    # The "--as-needed" linker flag is not available on FreeBSD
     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
       )
-    link_libraries(dl)
   endif()
 
   CHECK_INCLUDE_FILES(uuid/uuid.h HAVE_UUID_H)
   if (NOT HAVE_UUID_H)
-    message(FATAL_ERROR "Please install the uuid-dev package")
+    message(FATAL_ERROR "Please install the uuid-dev package (or e2fsprogs if OpenBSD)")
   endif()
 
 elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
@@ -145,6 +179,8 @@
     message(FATAL_ERROR "Please install the uuid-dev package")
   endif()
 
+else()
+  message(FATAL_ERROR "Support your platform here")
 endif()
 
 
@@ -155,15 +191,6 @@
 endif()
 
 
-if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
-  # In FreeBSD, 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_C_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 (DEFINED ENABLE_PROFILING AND ENABLE_PROFILING)
   if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
     message(WARNING "Enabling profiling on a non-debug build will not produce full information")
--- a/Resources/Orthanc/Resources/CMake/DcmtkConfiguration.cmake	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Resources/CMake/DcmtkConfiguration.cmake	Wed Aug 23 11:10:48 2017 +0200
@@ -3,21 +3,7 @@
 endif()
 
 if (STATIC_BUILD OR NOT USE_SYSTEM_DCMTK)
-  if (USE_DCMTK_361)
-    SET(DCMTK_VERSION_NUMBER 361)
-    SET(DCMTK_PACKAGE_VERSION "3.6.1")
-    SET(DCMTK_SOURCES_DIR ${CMAKE_BINARY_DIR}/dcmtk-3.6.1_20160216)
-    SET(DCMTK_URL "http://www.orthanc-server.com/downloads/third-party/dcmtk-3.6.1_20160216.tar.gz")
-    SET(DCMTK_MD5 "273c8a544b9fe09b8a4fb4eb51df8e52")
-    SET(DCMTK_PATCH_SPEED "${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.1-speed.patch")
-
-    macro(DCMTK_UNSET)
-    endmacro()
-
-    set(DCMTK_BINARY_DIR ${DCMTK_SOURCES_DIR}/)
-    set(DCMTK_CMAKE_INCLUDE ${DCMTK_SOURCES_DIR}/)
-    add_definitions(-DDCMTK_INSIDE_LOG4CPLUS=1)
-  else()
+  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)
@@ -25,8 +11,24 @@
     SET(DCMTK_MD5 "219ad631b82031806147e4abbfba4fa4")
     SET(DCMTK_PATCH_SPEED "${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.0-speed.patch")
     SET(DCMTK_PATCH_MINGW64 "${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.0-mingw64.patch")
+  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}/)
+    add_definitions(-DDCMTK_INSIDE_LOG4CPLUS=1)
   endif()
-
+  
   if (IS_DIRECTORY "${DCMTK_SOURCES_DIR}")
     set(FirstRun OFF)
   else()
@@ -36,37 +38,65 @@
   DownloadPackage(${DCMTK_MD5} ${DCMTK_URL} "${DCMTK_SOURCES_DIR}")
 
   
-  if (FirstRun AND
-      NOT USE_DCMTK_361)
-    if (USE_DCMTK_361_PRIVATE_DIC)
+  if (FirstRun)
+    if (USE_DCMTK_360)
       # If using DCMTK 3.6.0, backport the "private.dic" file from DCMTK
-      # 3.6.1 snapshot. This adds support for more private tags, and
-      # fixes some import problems with Philips MRI Achieva.
-      message("Using the dictionary of private tags from DCMTK 3.6.1")
-      configure_file(
-        ${ORTHANC_ROOT}/Resources/Patches/dcmtk-3.6.1-private.dic
-        ${DCMTK_SOURCES_DIR}/dcmdata/data/private.dic
-        COPYONLY)
-    else()
-      message("Using the dictionary of private tags from DCMTK 3.6.0")
-    endif()
+      # 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
+        )
 
-    # Patches specific to 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()
 
-    if (Failure)
-      message(FATAL_ERROR "Error while patching a file")
+      # 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 (FirstRun())
+      message("No need to apply a patch for speed in DCMTK")
     endif()
+  else()
+    message("The patches for DCMTK have already been applied")
   endif()
 
-
   IF (CMAKE_CROSSCOMPILING)
-    SET(C_CHAR_UNSIGNED 1 CACHE INTERNAL "Whether char is unsigned.")
+    if (CMAKE_COMPILER_IS_GNUCXX AND
+        ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")  # MinGW
+      SET(C_CHAR_UNSIGNED 1 CACHE INTERNAL "Whether char is unsigned.")
+    else()
+      message(FATAL_ERROR "Support your platform here")
+    endif()
   ENDIF()
+  
   SET(DCMTK_SOURCE_DIR ${DCMTK_SOURCES_DIR})
   include(${DCMTK_SOURCES_DIR}/CMake/CheckFunctionWithHeaderExists.cmake)
   include(${DCMTK_SOURCES_DIR}/CMake/GenerateDCMTKConfigure.cmake)
@@ -91,7 +121,20 @@
     ${DCMTK_SOURCES_DIR}/CMake/osconfig.h.in
     ${DCMTK_SOURCES_DIR}/config/include/dcmtk/config/osconfig.h)
 
-  if (USE_DCMTK_361)
+  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"
     INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES()
   endif()
@@ -159,29 +202,23 @@
   if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
       ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR
       ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD")
+      ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
+      ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
     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
       )
-    
-    execute_process(
-      COMMAND ${PATCH_EXECUTABLE} -p0 -N -i ${DCMTK_PATCH_SPEED}
-      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-      RESULT_VARIABLE Failure
-      )
-
-    if (Failure AND FirstRun)
-      message(FATAL_ERROR "Error while patching a file")
-    endif()
 
   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)
+    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 ${DCMTK_PATCH_MINGW64}
@@ -193,18 +230,6 @@
         message(FATAL_ERROR "Error while patching a file")
       endif()
     endif()
-
-    # This patch improves speed, even for Windows
-    execute_process(
-      COMMAND ${PATCH_EXECUTABLE} -p0 -N 
-      INPUT_FILE ${DCMTK_PATCH_SPEED}
-      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-      RESULT_VARIABLE Failure
-      )
-
-    if (Failure AND FirstRun)
-      message(FATAL_ERROR "Error while patching a file")
-    endif()
   endif()
 
   list(REMOVE_ITEM DCMTK_SOURCES 
@@ -212,7 +237,7 @@
     ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/mkdeftag.cc
     )
 
-  if (NOT USE_DCMTK_361)
+  if (USE_DCMTK_360)
     # Removing this file is required with DCMTK 3.6.0
     list(REMOVE_ITEM DCMTK_SOURCES 
       ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/dcdictbi.cc
@@ -270,10 +295,14 @@
     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}" 
@@ -309,6 +338,13 @@
       /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/local/share/dcmtk
       )
 
--- a/Resources/Orthanc/Resources/CMake/LibCurlConfiguration.cmake	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Resources/CMake/LibCurlConfiguration.cmake	Wed Aug 23 11:10:48 2017 +0200
@@ -60,7 +60,8 @@
   if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
       ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR
       ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-      ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD")
+      ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
+      ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
     if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
       SET(TMP_OS "x86_64")
     else()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Resources/CMake/LibIconvConfiguration.cmake	Wed Aug 23 11:10:48 2017 +0200
@@ -0,0 +1,96 @@
+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)
+
+    # Create an empty "config.h" for libiconv
+    file(WRITE ${LIBICONV_SOURCES_DIR}/include/config.h "")
+
+    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/OpenSslConfiguration.cmake	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Resources/CMake/OpenSslConfiguration.cmake	Wed Aug 23 11:10:48 2017 +0200
@@ -1,230 +1,232 @@
-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 (ENABLE_SSL)
+  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.
 
-  if (IS_DIRECTORY "${OPENSSL_SOURCES_DIR}")
-    set(FirstRun OFF)
-  else()
-    set(FirstRun ON)
-  endif()
+    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")
 
-  DownloadPackage(${OPENSSL_MD5} ${OPENSSL_URL} "${OPENSSL_SOURCES_DIR}")
+    if (IS_DIRECTORY "${OPENSSL_SOURCES_DIR}")
+      set(FirstRun OFF)
+    else()
+      set(FirstRun ON)
+    endif()
 
-  add_definitions(
-    -DOPENSSL_THREADS
-    -DOPENSSL_IA32_SSE2
-    -DOPENSSL_NO_ASM
-    -DOPENSSL_NO_DYNAMIC_ENGINE
-    -DNO_WINDOWS_BRAINDEATH
+    DownloadPackage(${OPENSSL_MD5} ${OPENSSL_URL} "${OPENSSL_SOURCES_DIR}")
 
-    -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
-    )
+    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
-    )
+    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
-    )
+    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()
+    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()
+    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
+    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/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}/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
-    )
+      ${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")
+    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")
 
-  elseif ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase")
-    execute_process(
-      COMMAND ${PATCH_EXECUTABLE} -N ui_openssl.c -i ${ORTHANC_ROOT}/Resources/Patches/openssl-lsb.diff
-      WORKING_DIRECTORY ${OPENSSL_SOURCES_DIR}/crypto/ui
-      RESULT_VARIABLE Failure
-      )
+    elseif ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase")
+      execute_process(
+        COMMAND ${PATCH_EXECUTABLE} -N ui_openssl.c -i ${ORTHANC_ROOT}/Resources/Patches/openssl-lsb.diff
+        WORKING_DIRECTORY ${OPENSSL_SOURCES_DIR}/crypto/ui
+        RESULT_VARIABLE Failure
+        )
 
-    if (Failure AND FirstRun)
-      message(FATAL_ERROR "Error while patching a file")
+      if (Failure AND FirstRun)
+        message(FATAL_ERROR "Error while patching a file")
+      endif()
     endif()
-  endif()
 
-  source_group(ThirdParty\\OpenSSL REGULAR_EXPRESSION ${OPENSSL_SOURCES_DIR}/.*)
+    source_group(ThirdParty\\OpenSSL REGULAR_EXPRESSION ${OPENSSL_SOURCES_DIR}/.*)
 
-else()
-  include(FindOpenSSL)
+  else()
+    include(FindOpenSSL)
 
-  if (NOT ${OPENSSL_FOUND})
-    message(FATAL_ERROR "Unable to find OpenSSL")
-  endif()
+    if (NOT ${OPENSSL_FOUND})
+      message(FATAL_ERROR "Unable to find OpenSSL")
+    endif()
 
-  include_directories(${OPENSSL_INCLUDE_DIR})
-  link_libraries(${OPENSSL_LIBRARIES})
+    include_directories(${OPENSSL_INCLUDE_DIR})
+    link_libraries(${OPENSSL_LIBRARIES})
+  endif()
 endif()
--- a/Resources/Orthanc/Resources/CMake/ZlibConfiguration.cmake	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Resources/CMake/ZlibConfiguration.cmake	Wed Aug 23 11:10:48 2017 +0200
@@ -29,6 +29,15 @@
 
   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})
--- a/Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-speed.patch	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/Orthanc/Resources/Patches/dcmtk-3.6.0-speed.patch	Wed Aug 23 11:10:48 2017 +0200
@@ -1,7 +1,19 @@
 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	2016-04-05 14:30:18.254459281 +0200
-+++ dcmtk-3.6.0/dcmnet/libsrc/dul.cc	2016-04-05 14:32:07.246463713 +0200
-@@ -1770,7 +1770,7 @@
+--- 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];
@@ -10,7 +22,7 @@
                  if (!WriteFile(hChildStdInWriteDup, buf, strlen(buf) + 1, &bytesWritten, NULL))
                  {
                      CloseHandle(hChildStdInWriteDup);
-@@ -1780,7 +1780,7 @@
+@@ -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)
@@ -19,7 +31,7 @@
                  OFSTRINGSTREAM_GETOFSTRING(stream, msg)
                  return makeDcmnetCondition(DULC_FORKEDCHILD, OF_ok, msg.c_str());
              }
-@@ -1840,7 +1840,7 @@
+@@ -1840,7 +1843,7 @@
      }
  #endif
  #endif
@@ -28,10 +40,9 @@
  
  #ifndef DONT_DISABLE_NAGLE_ALGORITHM
      /*
-Only in dcmtk-3.6.0/dcmnet/libsrc: dul.cc~
 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	2016-04-05 14:30:18.250459281 +0200
-+++ dcmtk-3.6.0/dcmnet/libsrc/dulfsm.cc	2016-04-05 14:32:20.566464254 +0200
+--- 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());
          }
@@ -41,4 +52,3 @@
  
  #ifndef DONT_DISABLE_NAGLE_ALGORITHM
          /*
-Only in dcmtk-3.6.0/dcmnet/libsrc: dulfsm.cc~
--- a/Resources/Orthanc/Resources/Patches/dcmtk-3.6.1-speed.patch	Wed Mar 22 15:53:48 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-diff -urEb dcmtk-3.6.1_20160216.orig/dcmnet/libsrc/dul.cc dcmtk-3.6.1_20160216/dcmnet/libsrc/dul.cc
---- dcmtk-3.6.1_20160216.orig/dcmnet/libsrc/dul.cc	2016-04-05 12:56:28.962230391 +0200
-+++ dcmtk-3.6.1_20160216/dcmnet/libsrc/dul.cc	2016-04-05 12:57:15.814232296 +0200
-@@ -1841,7 +1841,7 @@
-         return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
-     }
- #endif
--    setTCPBufferLength(sock);
-+    //setTCPBufferLength(sock);
- 
- #ifndef DONT_DISABLE_NAGLE_ALGORITHM
-     /*
-Only in dcmtk-3.6.1_20160216/dcmnet/libsrc: dul.cc~
-diff -urEb dcmtk-3.6.1_20160216.orig/dcmnet/libsrc/dulfsm.cc dcmtk-3.6.1_20160216/dcmnet/libsrc/dulfsm.cc
---- dcmtk-3.6.1_20160216.orig/dcmnet/libsrc/dulfsm.cc	2016-04-05 12:56:28.962230391 +0200
-+++ dcmtk-3.6.1_20160216/dcmnet/libsrc/dulfsm.cc	2016-04-05 12:57:31.946232952 +0200
-@@ -2431,7 +2431,7 @@
-           return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
-         }
- #endif
--        setTCPBufferLength(s);
-+        //setTCPBufferLength(s);
- 
- #ifndef DONT_DISABLE_NAGLE_ALGORITHM
-         /*
-Only in dcmtk-3.6.1_20160216/dcmnet/libsrc: dulfsm.cc~
--- a/Resources/SyncOrthancFolder.py	Wed Mar 22 15:53:48 2017 +0100
+++ b/Resources/SyncOrthancFolder.py	Wed Aug 23 11:10:48 2017 +0200
@@ -113,6 +113,7 @@
     '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',
@@ -125,7 +126,6 @@
     '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.1-speed.patch',
     'Resources/ThirdParty/VisualStudio/stdint.h',
     'Resources/ThirdParty/base64/base64.cpp',
     'Resources/ThirdParty/base64/base64.h',
--- a/ViewerPlugin/CMakeLists.txt	Wed Mar 22 15:53:48 2017 +0100
+++ b/ViewerPlugin/CMakeLists.txt	Wed Aug 23 11:10:48 2017 +0200
@@ -33,6 +33,7 @@
 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(CheckIncludeFiles)
 include(CheckIncludeFileCXX)
@@ -61,6 +62,7 @@
   -DORTHANC_ENABLE_BASE64=0
   -DORTHANC_ENABLE_CURL=0
   -DORTHANC_ENABLE_DCMTK=0
+  -DORTHANC_ENABLE_LOCALE=0
   -DORTHANC_ENABLE_LOGGING=1
   -DORTHANC_ENABLE_LOGGING_PLUGIN=1
   -DORTHANC_ENABLE_MD5=0