changeset 4023:cbdf62468d77 more-changes

merge
author Alain Mazy <alain@mazy.be>
date Tue, 09 Jun 2020 11:54:58 +0200
parents a2e4edc7b9aa (current diff) ceba3213cb9e (diff)
children 1d2b31fc782f
files
diffstat 25 files changed, 334 insertions(+), 328 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Jun 09 08:46:52 2020 +0200
+++ b/CMakeLists.txt	Tue Jun 09 11:54:58 2020 +0200
@@ -252,7 +252,6 @@
 
 add_definitions(
   -DORTHANC_BUILD_UNIT_TESTS=1
-  -DORTHANC_ENABLE_LOGGING_PLUGIN=0
   
   # Macros for the plugins
   -DHAS_ORTHANC_EXCEPTION=0
--- a/Core/DicomParsing/FromDcmtkBridge.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/Core/DicomParsing/FromDcmtkBridge.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -1718,7 +1718,8 @@
       case Json::arrayValue:
       {
         const char* p = NULL;
-        if (!privateCreator.empty())
+        if (tag.IsPrivate() &&
+            !privateCreator.empty())
         {
           p = privateCreator.c_str();
         }
--- a/Core/Logging.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/Core/Logging.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -96,6 +96,10 @@
 {
   namespace Logging
   {
+    void InitializePluginContext(void* pluginContext)
+    {
+    }
+
     void Initialize()
     {
     }
@@ -150,7 +154,6 @@
  *********************************************************/
 
 #include <stdio.h>
-#include <boost/lexical_cast.hpp>
 
 #ifdef __EMSCRIPTEN__
 #  include <emscripten/html5.h>
@@ -160,8 +163,8 @@
 {
   namespace Logging
   {
-    static bool globalVerbose_ = false;
-    static bool globalTrace_ = false;
+    static bool infoEnabled_ = false;
+    static bool traceEnabled_ = false;
     
 #ifdef __EMSCRIPTEN__
     static void ErrorLogFunc(const char* msg)
@@ -183,8 +186,7 @@
     {
       emscripten_console_log(msg);
     }
-#else
-// __EMSCRIPTEN__ not #defined
+#else  /* __EMSCRIPTEN__ not #defined */
     static void ErrorLogFunc(const char* msg)
     {
       fprintf(stderr, "E: %s\n", msg);
@@ -204,15 +206,8 @@
     {
       fprintf(stdout, "T: %s\n", msg);
     }
-#endif 
-// __EMSCRIPTEN__
+#endif  /* __EMSCRIPTEN__ */
 
-    InternalLogger::InternalLogger(LogLevel level,
-                                   const char* file  /* ignored */,
-                                   int line  /* ignored */) :
-      level_(level)
-    {
-    }
 
     InternalLogger::~InternalLogger()
     {
@@ -221,25 +216,25 @@
       switch (level_)
       {
         case LogLevel_ERROR:
-          globalErrorLogFunc(message.c_str());
+          ErrorLogFunc(message.c_str());
           break;
 
         case LogLevel_WARNING:
-          globalWarningLogFunc(message.c_str());
+          WarningLogFunc(message.c_str());
           break;
 
         case LogLevel_INFO:
-          if (globalVerbose_)
+          if (infoEnabled_)
           {
-            globalInfoLogFunc(message.c_str());
+            InfoLogFunc(message.c_str());
             // TODO: stone_console_info(message_.c_str());
           }
           break;
 
         case LogLevel_TRACE:
-          if (globalTrace_)
+          if (traceEnabled_)
           {
-            globalTraceLogFunc(message.c_str());
+            TraceLogFunc(message.c_str());
           }
           break;
 
@@ -248,11 +243,15 @@
           std::stringstream ss;
           ss << "Unknown log level (" << level_ << ") for message: " << message;
           std::string s = ss.str();
-          globalErrorLogFunc(s.c_str());
+          ErrorLogFunc(s.c_str());
         }
       }
     }
 
+    void InitializePluginContext(void* pluginContext)
+    {
+    }
+
     void Initialize()
     {
     }
@@ -271,22 +270,28 @@
 
     void EnableInfoLevel(bool enabled)
     {
-      globalVerbose_ = enabled;
+      infoEnabled_ = enabled;
+
+      if (!enabled)
+      {
+        // Also disable the "TRACE" level when info-level debugging is disabled
+        traceEnabled_ = false;
+      }
     }
 
     bool IsInfoLevelEnabled()
     {
-      return globalVerbose_;
+      return infoEnabled_;
     }
 
     void EnableTraceLevel(bool enabled)
     {
-      globalTrace_ = enabled;
+      traceEnabled_ = enabled;
     }
 
     bool IsTraceLevelEnabled()
     {
-      return globalTrace_;
+      return traceEnabled_;
     }
 
     void SetTargetFile(const std::string& path)
@@ -300,10 +305,11 @@
 }
 
 
-#elif ORTHANC_ENABLE_LOGGING_PLUGIN == 1
+#else
 
 /*********************************************************
- * Logger compatible with the Orthanc plugin SDK
+ * Logger compatible with the Orthanc plugin SDK, or that
+ * mimics behavior from Google Log.
  *********************************************************/
 
 #include <cassert>
@@ -335,83 +341,8 @@
 }
   
 
-#include <boost/lexical_cast.hpp>
-#include <sstream>
-
-namespace Orthanc
-{
-  namespace Logging
-  {
-    static OrthancPluginContext* context_ = NULL;
-
-    void Initialize(void* context)
-    {
-      assert(sizeof(_OrthancPluginService) == sizeof(int32_t));
-      context_ = reinterpret_cast<OrthancPluginContext*>(context);
-    }
-
-    InternalLogger::InternalLogger(LogLevel level,
-                                   const char* file  /* ignored */,
-                                   int line  /* ignored */) :
-      level_(level)
-    {
-    }
-
-    InternalLogger::~InternalLogger()
-    {
-      std::string message = messageStream_.str();
-      if (context_ != NULL)
-      {
-        switch (level_)
-        {
-          case LogLevel_ERROR:
-            context_->InvokeService(context_, _OrthancPluginService_LogError, message.c_str());
-            break;
-
-          case LogLevel_WARNING:
-            context_->InvokeService(context_, _OrthancPluginService_LogWarning, message.c_str());
-            break;
-
-          case LogLevel_INFO:
-            context_->InvokeService(context_, _OrthancPluginService_LogInfo, message.c_str());
-            break;
-
-          case LogLevel_TRACE:
-            // Not used by plugins
-            break;
-
-          default:
-          {
-            std::string s = ("Unknown log level (" + boost::lexical_cast<std::string>(level_) +
-                             ") for message: " + message);
-            context_->InvokeService(context_, _OrthancPluginService_LogInfo, s.c_str());
-            break;
-          }
-        }
-      }
-    }
-  }
-}
-
-
-#else  /* ORTHANC_ENABLE_LOGGING_PLUGIN == 0 && 
-          ORTHANC_ENABLE_LOGGING_STDIO == 0 && 
-          ORTHANC_ENABLE_LOGGING == 1 */
-
-/*********************************************************
- * Internal logger of Orthanc, that mimics some
- * behavior from Google Log.
- *********************************************************/
-
-#include "Compatibility.h"
 #include "Enumerations.h"
-#include "Toolbox.h"
-
-#if ORTHANC_SANDBOXED == 1
-#  include <stdio.h>
-#else
-#  include "SystemToolbox.h"
-#endif
+#include "SystemToolbox.h"
 
 #include <fstream>
 #include <boost/filesystem.hpp>
@@ -421,10 +352,8 @@
 
 namespace
 {
-  struct LoggingContext
+  struct LoggingStreamsContext
   {
-    bool infoEnabled_;
-    bool traceEnabled_;
     std::string  targetFile_;
     std::string  targetFolder_;
 
@@ -434,9 +363,7 @@
 
     std::unique_ptr<std::ofstream> file_;
 
-    LoggingContext() : 
-      infoEnabled_(false),
-      traceEnabled_(false),
+    LoggingStreamsContext() : 
       error_(&std::cerr),
       warning_(&std::cerr),
       info_(&std::cerr)
@@ -447,9 +374,12 @@
 
 
 
-static std::unique_ptr<LoggingContext> loggingContext_;
-static boost::mutex  loggingMutex_;
-
+static std::unique_ptr<LoggingStreamsContext> loggingStreamsContext_;
+static boost::mutex                           loggingStreamsMutex_;
+static Orthanc::Logging::NullStream           nullStream_;
+static OrthancPluginContext*                  pluginContext_ = NULL;
+static bool                                   infoEnabled_ = false;
+static bool                                   traceEnabled_ = false;
 
 
 namespace Orthanc
@@ -515,10 +445,11 @@
     }
 
 
+    // "loggingStreamsMutex_" must be locked
     static void CheckFile(std::unique_ptr<std::ofstream>& f)
     {
-      if (loggingContext_->file_.get() == NULL ||
-          !loggingContext_->file_->is_open())
+      if (loggingStreamsContext_->file_.get() == NULL ||
+          !loggingStreamsContext_->file_->is_open())
       {
         throw OrthancException(ErrorCode_CannotWriteFile);
       }
@@ -593,45 +524,52 @@
     }
     
 
+    void InitializePluginContext(void* pluginContext)
+    {
+      assert(sizeof(_OrthancPluginService) == sizeof(int32_t));
+
+      boost::mutex::scoped_lock lock(loggingStreamsMutex_);
+      loggingStreamsContext_.reset(NULL);
+      pluginContext_ = reinterpret_cast<OrthancPluginContext*>(pluginContext);
+    }
+
+
     void Initialize()
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      loggingContext_.reset(new LoggingContext);
+      boost::mutex::scoped_lock lock(loggingStreamsMutex_);
+      loggingStreamsContext_.reset(new LoggingStreamsContext);
     }
 
     void Finalize()
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      loggingContext_.reset(NULL);
+      boost::mutex::scoped_lock lock(loggingStreamsMutex_);
+      loggingStreamsContext_.reset(NULL);
     }
 
     void Reset()
     {
       // Recover the old logging context
-      std::unique_ptr<LoggingContext> old;
+      std::unique_ptr<LoggingStreamsContext> old;
 
       {
-        boost::mutex::scoped_lock lock(loggingMutex_);
-        if (loggingContext_.get() == NULL)
+        boost::mutex::scoped_lock lock(loggingStreamsMutex_);
+        if (loggingStreamsContext_.get() == NULL)
         {
           return;
         }
         else
         {
 #if __cplusplus < 201103L
-          old.reset(loggingContext_.release());
+          old.reset(loggingStreamsContext_.release());
 #else
-          old = std::move(loggingContext_);
+          old = std::move(loggingStreamsContext_);
 #endif
 
           // Create a new logging context, 
-          loggingContext_.reset(new LoggingContext);
+          loggingStreamsContext_.reset(new LoggingStreamsContext);
         }
       }
       
-      EnableInfoLevel(old->infoEnabled_);
-      EnableTraceLevel(old->traceEnabled_);
-
       if (!old->targetFolder_.empty())
       {
         SetTargetFolder(old->targetFolder_);
@@ -645,177 +583,196 @@
 
     void EnableInfoLevel(bool enabled)
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      loggingContext_->infoEnabled_ = enabled;
+      infoEnabled_ = enabled;
       
       if (!enabled)
       {
         // Also disable the "TRACE" level when info-level debugging is disabled
-        loggingContext_->traceEnabled_ = false;
+        traceEnabled_ = false;
       }
     }
 
     bool IsInfoLevelEnabled()
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      return loggingContext_->infoEnabled_;
+      return infoEnabled_;
     }
 
     void EnableTraceLevel(bool enabled)
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      loggingContext_->traceEnabled_ = enabled;
+      traceEnabled_ = enabled;
       
       if (enabled)
       {
         // Also enable the "INFO" level when trace-level debugging is enabled
-        loggingContext_->infoEnabled_ = true;
+        infoEnabled_ = true;
       }
     }
 
     bool IsTraceLevelEnabled()
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      return loggingContext_->traceEnabled_;
+      return traceEnabled_;
     }
 
 
     void SetTargetFolder(const std::string& path)
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
-
-      PrepareLogFolder(loggingContext_->file_, "" /* no suffix */, path);
-      CheckFile(loggingContext_->file_);
+      boost::mutex::scoped_lock lock(loggingStreamsMutex_);
+      if (loggingStreamsContext_.get() != NULL)
+      {
+        PrepareLogFolder(loggingStreamsContext_->file_, "" /* no suffix */, path);
+        CheckFile(loggingStreamsContext_->file_);
 
-      loggingContext_->targetFile_.clear();
-      loggingContext_->targetFolder_ = path;
-      loggingContext_->warning_ = loggingContext_->file_.get();
-      loggingContext_->error_ = loggingContext_->file_.get();
-      loggingContext_->info_ = loggingContext_->file_.get();
+        loggingStreamsContext_->targetFile_.clear();
+        loggingStreamsContext_->targetFolder_ = path;
+        loggingStreamsContext_->warning_ = loggingStreamsContext_->file_.get();
+        loggingStreamsContext_->error_ = loggingStreamsContext_->file_.get();
+        loggingStreamsContext_->info_ = loggingStreamsContext_->file_.get();
+      }
     }
 
 
     void SetTargetFile(const std::string& path)
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
-      assert(loggingContext_.get() != NULL);
+      boost::mutex::scoped_lock lock(loggingStreamsMutex_);
 
-      loggingContext_->file_.reset(new std::ofstream(path.c_str(), std::fstream::app));
-      CheckFile(loggingContext_->file_);
+      if (loggingStreamsContext_.get() != NULL)
+      {
+        loggingStreamsContext_->file_.reset(new std::ofstream(path.c_str(), std::fstream::app));
+        CheckFile(loggingStreamsContext_->file_);
 
-      loggingContext_->targetFile_ = path;
-      loggingContext_->targetFolder_.clear();
-      loggingContext_->warning_ = loggingContext_->file_.get();
-      loggingContext_->error_ = loggingContext_->file_.get();
-      loggingContext_->info_ = loggingContext_->file_.get();
+        loggingStreamsContext_->targetFile_ = path;
+        loggingStreamsContext_->targetFolder_.clear();
+        loggingStreamsContext_->warning_ = loggingStreamsContext_->file_.get();
+        loggingStreamsContext_->error_ = loggingStreamsContext_->file_.get();
+        loggingStreamsContext_->info_ = loggingStreamsContext_->file_.get();
+      }
     }
 
 
     InternalLogger::InternalLogger(LogLevel level,
                                    const char* file,
                                    int line) : 
-      lock_(loggingMutex_, boost::defer_lock_t()), 
-      stream_(&null_)  // By default, logging to "/dev/null" is simulated
+      lock_(loggingStreamsMutex_, boost::defer_lock_t()),
+      level_(level),
+      stream_(&nullStream_)  // By default, logging to "/dev/null" is simulated
     {
-      lock_.lock();
-      
-      if (loggingContext_.get() == NULL)
+      if (pluginContext_ != NULL)
       {
-        fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n");
-        return;
-      }
+        // We are logging using the Orthanc plugin SDK
 
-      try
-      {
-        if ((level == LogLevel_INFO  && !loggingContext_->infoEnabled_) ||
-            (level == LogLevel_TRACE && !loggingContext_->traceEnabled_))
+        if (level == LogLevel_TRACE)
         {
-          // This logging level is disabled, directly exit and unlock
-          // the mutex to speed-up things. The stream is set to "/dev/null"
-          lock_.unlock();
+          // No trace level in plugins, directly exit as the stream is
+          // set to "/dev/null"
           return;
         }
-
-        // Compute the prefix of the line, temporary release the lock as
-        // this is a time-consuming operation
-        lock_.unlock();
-        std::string prefix;
-        GetLinePrefix(prefix, level, file, line);
+        else
+        {
+          pluginStream_.reset(new std::stringstream);
+          stream_ = pluginStream_.get();
+        }
+      }
+      else
+      {
+        // We are logging in a standalone application, not inside an Orthanc plugin
 
-        // The prefix is computed, we now re-lock the mutex to access
-        // the stream objects. Pay attention that "loggingContext_",
-        // "infoEnabled_" or "traceEnabled_" might have changed while
-        // the mutex was unlocked.
-        lock_.lock();
-
-        if (loggingContext_.get() == NULL)
+        if ((level == LogLevel_INFO  && !infoEnabled_) ||
+            (level == LogLevel_TRACE && !traceEnabled_))
         {
-          fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n");
+          // This logging level is disabled, directly exit as the
+          // stream is set to "/dev/null"
           return;
         }
 
-        switch (level)
+        std::string prefix;
+        GetLinePrefix(prefix, level, file, line);
+
         {
-          case LogLevel_ERROR:
-            stream_ = loggingContext_->error_;
-            break;
-
-          case LogLevel_WARNING:
-            stream_ = loggingContext_->warning_;
-            break;
+          // We lock the global mutex. The mutex is locked until the
+          // destructor is called: No change in the output can be done.
+          lock_.lock();
+      
+          if (loggingStreamsContext_.get() == NULL)
+          {
+            fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n");
+            lock_.unlock();
+            return;
+          }
 
-          case LogLevel_INFO:
-            if (loggingContext_->infoEnabled_)
-            {
-              stream_ = loggingContext_->info_;
-            }
+          switch (level)
+          {
+            case LogLevel_ERROR:
+              stream_ = loggingStreamsContext_->error_;
+              break;
+              
+            case LogLevel_WARNING:
+              stream_ = loggingStreamsContext_->warning_;
+              break;
+              
+            case LogLevel_INFO:
+            case LogLevel_TRACE:
+              stream_ = loggingStreamsContext_->info_;
+              break;
+              
+            default:
+              throw OrthancException(ErrorCode_InternalError);
+          }
 
-            break;
-
-          case LogLevel_TRACE:
-            if (loggingContext_->traceEnabled_)
+          if (stream_ == &nullStream_)
+          {
+            // The logging is disabled for this level, we can release
+            // the global mutex.
+            lock_.unlock();
+          }
+          else
+          {
+            try
             {
-              stream_ = loggingContext_->info_;
+              (*stream_) << prefix;
             }
-
-            break;
-
-          default:
-            throw OrthancException(ErrorCode_InternalError);
+            catch (...)
+            { 
+              // Something is going really wrong, probably running out of
+              // memory. Fallback to a degraded mode.
+              stream_ = loggingStreamsContext_->error_;
+              (*stream_) << "E???? ??:??:??.?????? ] ";
+            }
+          }
         }
-
-        if (stream_ == &null_)
-        {
-          // The logging is disabled for this level. The stream is the
-          // "null_" member of this object, so we can release the global
-          // mutex.
-          lock_.unlock();
-        }
-
-        (*stream_) << prefix;
-      }
-      catch (...)
-      { 
-        // Something is going really wrong, probably running out of
-        // memory. Fallback to a degraded mode.
-        stream_ = loggingContext_->error_;
-        (*stream_) << "E???? ??:??:??.?????? ] ";
       }
     }
 
 
     InternalLogger::~InternalLogger()
     {
-      if (stream_ != &null_)
+      if (pluginStream_.get() != NULL)
+      {
+        // We are logging through the Orthanc SDK
+        
+        std::string message = pluginStream_->str();
+
+        if (pluginContext_ != NULL)
+        {
+          switch (level_)
+          {
+            case LogLevel_ERROR:
+              pluginContext_->InvokeService(pluginContext_, _OrthancPluginService_LogError, message.c_str());
+              break;
+
+            case LogLevel_WARNING:
+              pluginContext_->InvokeService(pluginContext_, _OrthancPluginService_LogWarning, message.c_str());
+              break;
+
+            case LogLevel_INFO:
+              pluginContext_->InvokeService(pluginContext_, _OrthancPluginService_LogInfo, message.c_str());
+              break;
+
+            default:
+              break;
+          }
+        }
+      }
+      else if (stream_ != &nullStream_)
       {
         *stream_ << "\n";
         stream_->flush();
@@ -825,38 +782,29 @@
 
     void Flush()
     {
-      boost::mutex::scoped_lock lock(loggingMutex_);
+      if (pluginContext_ != NULL)
+      {
+        boost::mutex::scoped_lock lock(loggingStreamsMutex_);
 
-      if (loggingContext_.get() != NULL &&
-          loggingContext_->file_.get() != NULL)
-      {
-        loggingContext_->file_->flush();
+        if (loggingStreamsContext_.get() != NULL &&
+            loggingStreamsContext_->file_.get() != NULL)
+        {
+          loggingStreamsContext_->file_->flush();
+        }
       }
     }
+    
 
     void SetErrorWarnInfoLoggingStreams(std::ostream& errorStream,
                                         std::ostream& warningStream,
                                         std::ostream& infoStream)
     {
-      std::unique_ptr<LoggingContext> old;
-
-      {
-        boost::mutex::scoped_lock lock(loggingMutex_);
+      boost::mutex::scoped_lock lock(loggingStreamsMutex_);
 
-#if __cplusplus < 201103L
-        old.reset(loggingContext_.release());
-#else
-        old = std::move(loggingContext_);
-#endif
-      
-        loggingContext_.reset(new LoggingContext);
-        loggingContext_->error_ = &errorStream;
-        loggingContext_->warning_ = &warningStream;
-        loggingContext_->info_ = &infoStream;
-      }
-      
-      EnableInfoLevel(old->infoEnabled_);
-      EnableTraceLevel(old->traceEnabled_);
+      loggingStreamsContext_.reset(new LoggingStreamsContext);
+      loggingStreamsContext_->error_ = &errorStream;
+      loggingStreamsContext_->warning_ = &warningStream;
+      loggingStreamsContext_->info_ = &infoStream;
     }
   }
 }
--- a/Core/Logging.h	Tue Jun 09 08:46:52 2020 +0200
+++ b/Core/Logging.h	Tue Jun 09 11:54:58 2020 +0200
@@ -42,14 +42,6 @@
 #  error The macro ORTHANC_ENABLE_LOGGING must be defined
 #endif
 
-#if !defined(ORTHANC_ENABLE_LOGGING_PLUGIN)
-#  if ORTHANC_ENABLE_LOGGING == 1
-#    error The macro ORTHANC_ENABLE_LOGGING_PLUGIN must be defined
-#  else
-#    define ORTHANC_ENABLE_LOGGING_PLUGIN 0
-#  endif
-#endif
-
 #if !defined(ORTHANC_ENABLE_LOGGING_STDIO)
 #  if ORTHANC_ENABLE_LOGGING == 1
 #    error The macro ORTHANC_ENABLE_LOGGING_STDIO must be defined
@@ -58,7 +50,6 @@
 #  endif
 #endif
 
-#include <boost/lexical_cast.hpp>
 
 namespace Orthanc
 {
@@ -76,12 +67,10 @@
 
     ORTHANC_PUBLIC LogLevel StringToLogLevel(const char* level);
 
-#if ORTHANC_ENABLE_LOGGING_PLUGIN == 1
     // "pluginContext" must be of type "OrthancPluginContext"
-    ORTHANC_PUBLIC void Initialize(void* pluginContext);
-#else
+    ORTHANC_PUBLIC void InitializePluginContext(void* pluginContext);
+
     ORTHANC_PUBLIC void Initialize();
-#endif
 
     ORTHANC_PUBLIC void Finalize();
 
@@ -122,7 +111,7 @@
 #if ORTHANC_ENABLE_LOGGING != 1
 #  define LOG(level)   ::Orthanc::Logging::NullStream()
 #  define VLOG(level)  ::Orthanc::Logging::NullStream()
-#else
+#else /* ORTHANC_ENABLE_LOGGING == 1 */
 #  define LOG(level)  ::Orthanc::Logging::InternalLogger        \
   (::Orthanc::Logging::LogLevel_ ## level, __FILE__, __LINE__)
 #  define VLOG(level) ::Orthanc::Logging::InternalLogger        \
@@ -130,11 +119,14 @@
 #endif
 
 
+
 #if (ORTHANC_ENABLE_LOGGING == 1 &&             \
-     (ORTHANC_ENABLE_LOGGING_PLUGIN == 1 ||     \
-      ORTHANC_ENABLE_LOGGING_STDIO == 1))
+     ORTHANC_ENABLE_LOGGING_STDIO == 1)
+// This is notably for WebAssembly
 
+#include <boost/lexical_cast.hpp>
 #include <boost/noncopyable.hpp>
+#include <sstream>
 
 namespace Orthanc
 {
@@ -148,16 +140,18 @@
 
     public:
       InternalLogger(LogLevel level,
-                     const char* file,
-                     int line);
+                     const char* file  /* ignored */,
+                     int line  /* ignored */) :
+        level_(level)
+      {
+      }
 
       ~InternalLogger();
       
       template <typename T>
         std::ostream& operator<< (const T& message)
       {
-        messageStream_ << message;
-        return messageStream_;
+        return messageStream_ << boost::lexical_cast<std::string>(message);
       }
     };
   }
@@ -167,23 +161,27 @@
 
 
 
-
 #if (ORTHANC_ENABLE_LOGGING == 1 &&             \
-     ORTHANC_ENABLE_LOGGING_PLUGIN == 0 &&      \
      ORTHANC_ENABLE_LOGGING_STDIO == 0)
 
+#include "Compatibility.h"  // For std::unique_ptr<>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/noncopyable.hpp>
 #include <boost/thread/mutex.hpp>
+#include <sstream>
 
 namespace Orthanc
 {
   namespace Logging
   {
-    class ORTHANC_PUBLIC InternalLogger
+    class ORTHANC_PUBLIC InternalLogger : public boost::noncopyable
     {
     private:
-      boost::mutex::scoped_lock lock_;
-      NullStream                null_;
-      std::ostream*             stream_;
+      boost::mutex::scoped_lock           lock_;
+      LogLevel                            level_;
+      std::unique_ptr<std::stringstream>  pluginStream_;
+      std::ostream*                       stream_;
 
     public:
       InternalLogger(LogLevel level,
@@ -211,7 +209,8 @@
      * Orthanc::Logging::Reset() before the stream objects are
      * destroyed and the references become invalid.
      *
-     * This function must only be used by unit tests.
+     * This function must only be used by unit tests. It is ignored if
+     * InitializePluginContext() was called.
      **/
     ORTHANC_PUBLIC void SetErrorWarnInfoLoggingStreams(std::ostream& errorStream,
                                                        std::ostream& warningStream, 
--- a/OrthancServer/OrthancFindRequestHandler.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/OrthancServer/OrthancFindRequestHandler.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -303,7 +303,8 @@
                         const DicomArray& query,
                         const std::list<DicomTag>& sequencesToReturn,
                         const DicomMap* counters,
-                        const std::string& defaultPrivateCreator)
+                        const std::string& defaultPrivateCreator,
+                        const std::map<uint16_t, std::string>& privateCreators)
   {
     DicomMap match;
 
@@ -398,7 +399,14 @@
 
           if (tag->IsPrivate())
           {
-            dicom.Replace(*tag, content, false, DicomReplaceMode_InsertIfAbsent, defaultPrivateCreator); // TODO: instead of taking the default private creator, we should get the private createor of the current "group"
+            if (privateCreators.find(tag->GetGroup()) != privateCreators.end())
+            {
+              dicom.Replace(*tag, content, false, DicomReplaceMode_InsertIfAbsent, privateCreators.at(tag->GetGroup()).c_str());
+            }
+            else
+            {
+              dicom.Replace(*tag, content, false, DicomReplaceMode_InsertIfAbsent, defaultPrivateCreator);
+            }
           }
           else
           {
@@ -492,20 +500,23 @@
     const DicomMap&             query_;
     DicomArray                  queryAsArray_;
     const std::list<DicomTag>&  sequencesToReturn_;
-    std::string                 defaultPrivateCreator_;
+    std::string                 defaultPrivateCreator_;       // the private creator to use if the group is not defined in the query itself
+    const std::map<uint16_t, std::string>& privateCreators_;  // the private creators defined in the query itself
 
   public:
     LookupVisitor(DicomFindAnswers&  answers,
                   ServerContext& context,
                   ResourceType level,
                   const DicomMap& query,
-                  const std::list<DicomTag>& sequencesToReturn) :
+                  const std::list<DicomTag>& sequencesToReturn,
+                  const std::map<uint16_t, std::string>& privateCreators) :
       answers_(answers),
       context_(context),
       level_(level),
       query_(query),
       queryAsArray_(query),
-      sequencesToReturn_(sequencesToReturn)
+      sequencesToReturn_(sequencesToReturn),
+      privateCreators_(privateCreators)
     {
       answers_.SetComplete(false);
 
@@ -554,7 +565,7 @@
       std::unique_ptr<DicomMap> counters(ComputeCounters(context_, instanceId, level_, query_));
 
       AddAnswer(answers_, mainDicomTags, dicomAsJson,
-                queryAsArray_, sequencesToReturn_, counters.get(), defaultPrivateCreator_);
+                queryAsArray_, sequencesToReturn_, counters.get(), defaultPrivateCreator_, privateCreators_);
     }
   };
 
@@ -628,6 +639,16 @@
                 << " : sequence tag whose content will be copied";
     }
 
+    // collect the private creators from the query itself
+    std::map<uint16_t, std::string> privateCreators;
+    for (size_t i = 0; i < query.GetSize(); i++)
+    {
+      const DicomElement& element = query.GetElement(i);
+      if (element.GetTag().IsPrivate() && element.GetTag().GetElement() == 0x10)
+      {
+        privateCreators[element.GetTag().GetGroup()] = element.GetValue().GetContent();
+      }
+    }
 
     /**
      * Build up the query object.
@@ -690,7 +711,7 @@
     size_t limit = (level == ResourceType_Instance) ? maxInstances_ : maxResults_;
 
 
-    LookupVisitor visitor(answers, context_, level, *filteredInput, sequencesToReturn);
+    LookupVisitor visitor(answers, context_, level, *filteredInput, sequencesToReturn, privateCreators);
     context_.Apply(visitor, lookup, level, 0 /* "since" is not relevant to C-FIND */, limit);
   }
 
--- a/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Tue Jun 09 08:46:52 2020 +0200
+++ b/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Tue Jun 09 11:54:58 2020 +0200
@@ -64,6 +64,16 @@
 #endif
 
 
+#if !defined(ORTHANC_FRAMEWORK_VERSION_IS_ABOVE)
+#define ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(major, minor, revision)      \
+  (ORTHANC_VERSION_MAJOR > major ||                                     \
+   (ORTHANC_VERSION_MAJOR == major &&                                   \
+    (ORTHANC_VERSION_MINOR > minor ||                                   \
+     (ORTHANC_VERSION_MINOR == minor &&                                 \
+      ORTHANC_VERSION_REVISION >= revision))))
+#endif
+
+
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0)
 // The "OrthancPluginFindMatcher()" primitive was introduced in Orthanc 1.2.0
 #  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  1
--- a/Plugins/Samples/ConnectivityChecks/CMakeLists.txt	Tue Jun 09 08:46:52 2020 +0200
+++ b/Plugins/Samples/ConnectivityChecks/CMakeLists.txt	Tue Jun 09 11:54:58 2020 +0200
@@ -34,7 +34,6 @@
 
 add_definitions(
   -DHAS_ORTHANC_EXCEPTION=1
-  -DORTHANC_ENABLE_LOGGING_PLUGIN=1
   -DORTHANC_PLUGIN_NAME="${PLUGIN_NAME}"
   -DORTHANC_PLUGIN_VERSION="${PLUGIN_VERSION}"
   )
--- a/Resources/CMake/DcmtkConfiguration.cmake	Tue Jun 09 08:46:52 2020 +0200
+++ b/Resources/CMake/DcmtkConfiguration.cmake	Tue Jun 09 11:54:58 2020 +0200
@@ -29,6 +29,13 @@
     ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/dcdict_orthanc.cc
     )
 
+  if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
+    message(${DCMTK_SOURCES_DIR})
+    list(REMOVE_ITEM DCMTK_SOURCES 
+      ${DCMTK_SOURCES_DIR}/ofstd/libsrc/offilsys.cc
+      )
+  endif()
+
   if (ENABLE_DCMTK_NETWORKING)
     AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmnet/libsrc DCMTK_SOURCES)
     include_directories(
--- a/Resources/CMake/OrthancFrameworkConfiguration.cmake	Tue Jun 09 08:46:52 2020 +0200
+++ b/Resources/CMake/OrthancFrameworkConfiguration.cmake	Tue Jun 09 11:54:58 2020 +0200
@@ -544,7 +544,6 @@
 if (ORTHANC_SANDBOXED)
   add_definitions(
     -DORTHANC_SANDBOXED=1
-    -DORTHANC_ENABLE_LOGGING_PLUGIN=0
     )
 
   if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
--- a/Resources/CMake/ZlibConfiguration.cmake	Tue Jun 09 08:46:52 2020 +0200
+++ b/Resources/CMake/ZlibConfiguration.cmake	Tue Jun 09 11:54:58 2020 +0200
@@ -14,10 +14,6 @@
     ${ZLIB_SOURCES_DIR}/compress.c
     ${ZLIB_SOURCES_DIR}/crc32.c 
     ${ZLIB_SOURCES_DIR}/deflate.c 
-    ${ZLIB_SOURCES_DIR}/gzclose.c 
-    ${ZLIB_SOURCES_DIR}/gzlib.c 
-    ${ZLIB_SOURCES_DIR}/gzread.c 
-    ${ZLIB_SOURCES_DIR}/gzwrite.c 
     ${ZLIB_SOURCES_DIR}/infback.c 
     ${ZLIB_SOURCES_DIR}/inffast.c 
     ${ZLIB_SOURCES_DIR}/inflate.c 
@@ -27,6 +23,16 @@
     ${ZLIB_SOURCES_DIR}/zutil.c
     )
 
+  if (NOT ORTHANC_SANDBOXED)
+    # The source files below require access to the filesystem
+    list(APPEND ZLIB_SOURCES
+      ${ZLIB_SOURCES_DIR}/gzlib.c 
+      ${ZLIB_SOURCES_DIR}/gzclose.c 
+      ${ZLIB_SOURCES_DIR}/gzread.c 
+      ${ZLIB_SOURCES_DIR}/gzwrite.c 
+      )
+  endif()
+
   source_group(ThirdParty\\zlib REGULAR_EXPRESSION ${ZLIB_SOURCES_DIR}/.*)
 
   if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
--- a/Resources/Patches/dcmtk-3.6.5.patch	Tue Jun 09 08:46:52 2020 +0200
+++ b/Resources/Patches/dcmtk-3.6.5.patch	Tue Jun 09 11:54:58 2020 +0200
@@ -1,6 +1,26 @@
+diff -urEb dcmtk-3.6.5.orig/CMake/GenerateDCMTKConfigure.cmake dcmtk-3.6.5/CMake/GenerateDCMTKConfigure.cmake
+--- dcmtk-3.6.5.orig/CMake/GenerateDCMTKConfigure.cmake	2020-06-08 22:19:03.265799573 +0200
++++ dcmtk-3.6.5/CMake/GenerateDCMTKConfigure.cmake	2020-06-08 22:21:22.670025141 +0200
+@@ -169,6 +169,8 @@
+ endif()
+ 
+ # Check the sizes of various types
++if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
++  # This doesn't work for wasm, Orthanc defines the macros manually
+ include (CheckTypeSize)
+ CHECK_TYPE_SIZE("char" SIZEOF_CHAR)
+ CHECK_TYPE_SIZE("double" SIZEOF_DOUBLE)
+@@ -177,6 +179,7 @@
+ CHECK_TYPE_SIZE("long" SIZEOF_LONG)
+ CHECK_TYPE_SIZE("short" SIZEOF_SHORT)
+ CHECK_TYPE_SIZE("void*" SIZEOF_VOID_P)
++endif()
+ 
+ # Check for include files, libraries, and functions
+ include("${DCMTK_CMAKE_INCLUDE}CMake/dcmtkTryCompile.cmake")
 diff -urEb dcmtk-3.6.5.orig/dcmdata/include/dcmtk/dcmdata/dcdict.h dcmtk-3.6.5/dcmdata/include/dcmtk/dcmdata/dcdict.h
---- dcmtk-3.6.5.orig/dcmdata/include/dcmtk/dcmdata/dcdict.h	2020-03-18 10:22:41.555166774 +0100
-+++ dcmtk-3.6.5/dcmdata/include/dcmtk/dcmdata/dcdict.h	2020-03-18 10:22:53.395131056 +0100
+--- dcmtk-3.6.5.orig/dcmdata/include/dcmtk/dcmdata/dcdict.h	2020-06-08 22:19:03.229799498 +0200
++++ dcmtk-3.6.5/dcmdata/include/dcmtk/dcmdata/dcdict.h	2020-06-08 22:19:35.317862998 +0200
 @@ -152,6 +152,12 @@
      /// returns an iterator to the end of the repeating tag dictionary
      DcmDictEntryListIterator repeatingEnd() { return repDict.end(); }
@@ -15,8 +35,8 @@
  
      /** private undefined assignment operator
 diff -urEb dcmtk-3.6.5.orig/dcmdata/libsrc/dcdict.cc dcmtk-3.6.5/dcmdata/libsrc/dcdict.cc
---- dcmtk-3.6.5.orig/dcmdata/libsrc/dcdict.cc	2020-03-18 10:22:41.559166762 +0100
-+++ dcmtk-3.6.5/dcmdata/libsrc/dcdict.cc	2020-03-18 10:22:53.395131056 +0100
+--- dcmtk-3.6.5.orig/dcmdata/libsrc/dcdict.cc	2020-06-08 22:19:03.245799531 +0200
++++ dcmtk-3.6.5/dcmdata/libsrc/dcdict.cc	2020-06-08 22:19:35.317862998 +0200
 @@ -900,3 +900,6 @@
    wrlock().clear();
    wrunlock();
@@ -25,8 +45,8 @@
 +
 +#include "dcdict_orthanc.cc"
 diff -urEb dcmtk-3.6.5.orig/dcmdata/libsrc/dcpxitem.cc dcmtk-3.6.5/dcmdata/libsrc/dcpxitem.cc
---- dcmtk-3.6.5.orig/dcmdata/libsrc/dcpxitem.cc	2020-03-18 10:22:41.559166762 +0100
-+++ dcmtk-3.6.5/dcmdata/libsrc/dcpxitem.cc	2020-03-18 10:22:53.395131056 +0100
+--- dcmtk-3.6.5.orig/dcmdata/libsrc/dcpxitem.cc	2020-06-08 22:19:03.245799531 +0200
++++ dcmtk-3.6.5/dcmdata/libsrc/dcpxitem.cc	2020-06-08 22:19:35.317862998 +0200
 @@ -36,6 +36,9 @@
  #include "dcmtk/dcmdata/dcostrma.h"    /* for class DcmOutputStream */
  #include "dcmtk/dcmdata/dcwcache.h"    /* for class DcmWriteCache */
@@ -38,8 +58,8 @@
  // ********************************
  
 diff -urEb dcmtk-3.6.5.orig/oflog/include/dcmtk/oflog/thread/syncpub.h dcmtk-3.6.5/oflog/include/dcmtk/oflog/thread/syncpub.h
---- dcmtk-3.6.5.orig/oflog/include/dcmtk/oflog/thread/syncpub.h	2020-03-18 10:22:41.543166810 +0100
-+++ dcmtk-3.6.5/oflog/include/dcmtk/oflog/thread/syncpub.h	2020-03-18 10:22:53.395131056 +0100
+--- dcmtk-3.6.5.orig/oflog/include/dcmtk/oflog/thread/syncpub.h	2020-06-08 22:19:03.261799565 +0200
++++ dcmtk-3.6.5/oflog/include/dcmtk/oflog/thread/syncpub.h	2020-06-08 22:19:35.317862998 +0200
 @@ -63,7 +63,7 @@
  
  DCMTK_LOG4CPLUS_INLINE_EXPORT
@@ -86,8 +106,8 @@
  
  
 diff -urEb dcmtk-3.6.5.orig/oflog/libsrc/oflog.cc dcmtk-3.6.5/oflog/libsrc/oflog.cc
---- dcmtk-3.6.5.orig/oflog/libsrc/oflog.cc	2020-03-18 10:22:41.547166798 +0100
-+++ dcmtk-3.6.5/oflog/libsrc/oflog.cc	2020-03-18 11:55:50.116856932 +0100
+--- dcmtk-3.6.5.orig/oflog/libsrc/oflog.cc	2020-06-08 22:19:03.261799565 +0200
++++ dcmtk-3.6.5/oflog/libsrc/oflog.cc	2020-06-08 22:19:35.317862998 +0200
 @@ -19,6 +19,10 @@
   *
   */
@@ -100,8 +120,8 @@
  #include "dcmtk/oflog/oflog.h"
  
 diff -urEb dcmtk-3.6.5.orig/ofstd/include/dcmtk/ofstd/offile.h dcmtk-3.6.5/ofstd/include/dcmtk/ofstd/offile.h
---- dcmtk-3.6.5.orig/ofstd/include/dcmtk/ofstd/offile.h	2020-03-18 10:22:41.587166677 +0100
-+++ dcmtk-3.6.5/ofstd/include/dcmtk/ofstd/offile.h	2020-03-18 10:22:53.395131056 +0100
+--- dcmtk-3.6.5.orig/ofstd/include/dcmtk/ofstd/offile.h	2020-06-08 22:19:03.293799632 +0200
++++ dcmtk-3.6.5/ofstd/include/dcmtk/ofstd/offile.h	2020-06-08 22:19:35.317862998 +0200
 @@ -575,7 +575,7 @@
     */
    void setlinebuf()
--- a/Resources/Testing/Issue32/Cpp/CMakeLists.txt	Tue Jun 09 08:46:52 2020 +0200
+++ b/Resources/Testing/Issue32/Cpp/CMakeLists.txt	Tue Jun 09 11:54:58 2020 +0200
@@ -8,13 +8,10 @@
 set(ENABLE_WEB_CLIENT ON)
 include(${ORTHANC_ROOT}/OrthancFrameworkConfiguration.cmake)
 
-add_definitions(
-  -DORTHANC_ENABLE_LOGGING_PLUGIN=OFF
-  )
-
 include_directories(${ORTHANC_ROOT})
 
 add_executable(Sample
   main.cpp
   ${ORTHANC_CORE_SOURCES}
-  )
\ No newline at end of file
+  ${AUTOGENERATED_SOURCES}
+  )
--- a/UnitTestsSources/FrameworkTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/FrameworkTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/ImageProcessingTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/ImageProcessingTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/JpegLosslessTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/JpegLosslessTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/LoggingTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/LoggingTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/LuaTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/LuaTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/PluginsTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/PluginsTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/RestApiTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/RestApiTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/SQLiteChromiumTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/SQLiteChromiumTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/SQLiteTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/SQLiteTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/StreamTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/StreamTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/ToolboxTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/ToolboxTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/VersionsTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/VersionsTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"
--- a/UnitTestsSources/ZipTests.cpp	Tue Jun 09 08:46:52 2020 +0200
+++ b/UnitTestsSources/ZipTests.cpp	Tue Jun 09 11:54:58 2020 +0200
@@ -32,7 +32,7 @@
 
 
 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
-#  include <OrthancFramework/OrthancFramework.h>
+#  include <OrthancFramework.h>
 #endif
 
 #include "PrecompiledHeadersUnitTests.h"