# HG changeset patch # User Alain Mazy # Date 1591696498 -7200 # Node ID cbdf62468d7793451d1cb520eb1c01fd1672a305 # Parent a2e4edc7b9aa58b6bd382d7b99c671795fa0d099# Parent ceba3213cb9ecd266ac3ef9f1a5d67fdfd95c134 merge diff -r a2e4edc7b9aa -r cbdf62468d77 CMakeLists.txt --- 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 diff -r a2e4edc7b9aa -r cbdf62468d77 Core/DicomParsing/FromDcmtkBridge.cpp --- 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(); } diff -r a2e4edc7b9aa -r cbdf62468d77 Core/Logging.cpp --- 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 -#include #ifdef __EMSCRIPTEN__ # include @@ -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 @@ -335,83 +341,8 @@ } -#include -#include - -namespace Orthanc -{ - namespace Logging - { - static OrthancPluginContext* context_ = NULL; - - void Initialize(void* context) - { - assert(sizeof(_OrthancPluginService) == sizeof(int32_t)); - context_ = reinterpret_cast(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(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 -#else -# include "SystemToolbox.h" -#endif +#include "SystemToolbox.h" #include #include @@ -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 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_; -static boost::mutex loggingMutex_; - +static std::unique_ptr 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& 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(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 old; + std::unique_ptr 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 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; } } } diff -r a2e4edc7b9aa -r cbdf62468d77 Core/Logging.h --- 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 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 #include +#include 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 std::ostream& operator<< (const T& message) { - messageStream_ << message; - return messageStream_; + return messageStream_ << boost::lexical_cast(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 +#include #include +#include 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 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, diff -r a2e4edc7b9aa -r cbdf62468d77 OrthancServer/OrthancFindRequestHandler.cpp --- 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& sequencesToReturn, const DicomMap* counters, - const std::string& defaultPrivateCreator) + const std::string& defaultPrivateCreator, + const std::map& 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& 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& privateCreators_; // the private creators defined in the query itself public: LookupVisitor(DicomFindAnswers& answers, ServerContext& context, ResourceType level, const DicomMap& query, - const std::list& sequencesToReturn) : + const std::list& sequencesToReturn, + const std::map& 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 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 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); } diff -r a2e4edc7b9aa -r cbdf62468d77 Plugins/Samples/Common/OrthancPluginCppWrapper.h --- 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 diff -r a2e4edc7b9aa -r cbdf62468d77 Plugins/Samples/ConnectivityChecks/CMakeLists.txt --- 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}" ) diff -r a2e4edc7b9aa -r cbdf62468d77 Resources/CMake/DcmtkConfiguration.cmake --- 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( diff -r a2e4edc7b9aa -r cbdf62468d77 Resources/CMake/OrthancFrameworkConfiguration.cmake --- 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") diff -r a2e4edc7b9aa -r cbdf62468d77 Resources/CMake/ZlibConfiguration.cmake --- 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 diff -r a2e4edc7b9aa -r cbdf62468d77 Resources/Patches/dcmtk-3.6.5.patch --- 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() diff -r a2e4edc7b9aa -r cbdf62468d77 Resources/Testing/Issue32/Cpp/CMakeLists.txt --- 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} + ) diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/FrameworkTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/ImageProcessingTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/JpegLosslessTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/LoggingTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/LuaTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/PluginsTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/RestApiTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/SQLiteChromiumTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/SQLiteTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/StreamTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/ToolboxTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/VersionsTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h" diff -r a2e4edc7b9aa -r cbdf62468d77 UnitTestsSources/ZipTests.cpp --- 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 +# include #endif #include "PrecompiledHeadersUnitTests.h"