# HG changeset patch # User Sebastien Jodogne # Date 1764163216 -3600 # Node ID da9d68c3bf6ba3776fdf47c1416722f69555c05d # Parent d2a5adaeb056140d925f84f7ecc1a7bf1b5dd4c8 sync diff -r d2a5adaeb056 -r da9d68c3bf6b Resources/Orthanc/CMake/Compiler.cmake --- a/Resources/Orthanc/CMake/Compiler.cmake Wed Nov 12 13:05:08 2025 +0100 +++ b/Resources/Orthanc/CMake/Compiler.cmake Wed Nov 26 14:20:16 2025 +0100 @@ -246,6 +246,9 @@ # fix this error that appears with recent compilers on MacOS: boost/mpl/aux_/integral_wrapper.hpp:73:31: error: integer value -1 is outside the valid range of values [0, 3] for this enumeration type [-Wenum-constexpr-conversion] SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-enum-constexpr-conversion") + # it seems that some recent MacOS compilers don't set these flags correctly which prevents zlib from building correctly + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64") + add_definitions( -D_XOPEN_SOURCE=1 ) diff -r d2a5adaeb056 -r da9d68c3bf6b Resources/Orthanc/CMake/DownloadOrthancFramework.cmake --- a/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Wed Nov 12 13:05:08 2025 +0100 +++ b/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Wed Nov 26 14:20:16 2025 +0100 @@ -207,6 +207,18 @@ # DICOMweb 1.15 (framework pre-1.12.2) set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) set(ORTHANC_FRAMEWORK_MD5 "ebe8bdf388319f1c9536b2b680451848") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "36cd91a53403") + # Advanced storage 0.2.0 (framework pre-1.12.10) + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) + set(ORTHANC_FRAMEWORK_MD5 "911105f18a154b5e106985d8fcfcb620") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "9eb77f159b9d") + # Advanced storage 0.2.2 (framework pre-1.12.10) + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) + set(ORTHANC_FRAMEWORK_MD5 "bd5ba2cec329010b912209345acbdeaf") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "0ebe8cfd9bf7") + # Worklists plugin 0.9.0 (framework pre-1.12.10) + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) + set(ORTHANC_FRAMEWORK_MD5 "17a5ca9254e881ab89c93d052d4655cb") endif() endif() endif() diff -r d2a5adaeb056 -r da9d68c3bf6b Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp --- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Wed Nov 12 13:05:08 2025 +0100 +++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Wed Nov 26 14:20:16 2025 +0100 @@ -221,6 +221,19 @@ } + MemoryBuffer::~MemoryBuffer() + { + try + { + Clear(); + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&) + { + // Don't throw exceptions in destructors + } + } + + void MemoryBuffer::Clear() { if (buffer_.data != NULL) @@ -351,6 +364,38 @@ } } + +#if (HAS_ORTHANC_PLUGIN_PEERS == 1) || (HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1) || (HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1) + static void DecodeHttpHeaders(HttpHeaders& target, + const MemoryBuffer& source) + { + Json::Value v; + source.ToJson(v); + + if (v.type() != Json::objectValue) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + + Json::Value::Members members = v.getMemberNames(); + target.clear(); + + for (size_t i = 0; i < members.size(); i++) + { + const Json::Value& h = v[members[i]]; + if (h.type() != Json::stringValue) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + else + { + target[members[i]] = h.asString(); + } + } + } +#endif + + // helper class to convert std::map of headers to the plugin SDK C structure class PluginHttpHeaders { @@ -624,6 +669,19 @@ } + OrthancString::~OrthancString() + { + try + { + Clear(); + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&) + { + // Don't throw exceptions in destructors + } + } + + void OrthancString::Assign(char* str) { Clear(); @@ -1273,6 +1331,20 @@ } } + + OrthancImage::~OrthancImage() + { + try + { + Clear(); + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&) + { + // Don't throw exceptions in destructors + } + } + + void OrthancImage::UncompressPngImage(const void* data, size_t size) { @@ -2084,8 +2156,30 @@ unsigned int timeout) const { MemoryBuffer buffer; - - if (DoPost(buffer, index, uri, body, headers, timeout)) + HttpHeaders answerHeaders; + + if (DoPost(buffer, answerHeaders, index, uri, body, headers, timeout)) + { + buffer.ToJson(target); + return true; + } + else + { + return false; + } + } + + bool OrthancPeers::DoPost(Json::Value& target, + HttpHeaders& answerHeaders, + size_t index, + const std::string& uri, + const std::string& body, + const HttpHeaders& headers, + unsigned int timeout) const + { + MemoryBuffer buffer; + + if (DoPost(buffer, answerHeaders, index, uri, body, headers, timeout)) { buffer.ToJson(target); return true; @@ -2143,9 +2237,9 @@ const std::string& body, const HttpHeaders& headers) const { - return DoPost(target, index, uri, body, headers, timeout_); - } - + HttpHeaders answerHeaders; + return DoPost(target, answerHeaders, index, uri, body, headers, timeout_); + } bool OrthancPeers::DoPost(MemoryBuffer& target, size_t index, @@ -2154,6 +2248,18 @@ const HttpHeaders& headers, unsigned int timeout) const { + HttpHeaders answerHeaders; + return DoPost(target, answerHeaders, index, uri, body, headers, timeout); + } + + bool OrthancPeers::DoPost(MemoryBuffer& target, + HttpHeaders& answerHeaders, + size_t index, + const std::string& uri, + const std::string& body, + const HttpHeaders& headers, + unsigned int timeout) const + { if (index >= index_.size()) { ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); @@ -2166,17 +2272,20 @@ } OrthancPlugins::MemoryBuffer answer; + OrthancPlugins::MemoryBuffer answerHeadersBuffer; uint16_t status; PluginHttpHeaders pluginHeaders(headers); OrthancPluginErrorCode code = OrthancPluginCallPeerApi - (GetGlobalContext(), *answer, NULL, &status, peers_, + (GetGlobalContext(), *answer, *answerHeadersBuffer, &status, peers_, static_cast(index), OrthancPluginHttpMethod_Post, uri.c_str(), pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout); if (code == OrthancPluginErrorCode_Success) { target.Swap(answer); + DecodeHttpHeaders(answerHeaders, answerHeadersBuffer); + return (status == 200); } else @@ -2611,32 +2720,42 @@ return; } - else if (state == "Running") + else if (state == "Running" || + state == "Pending" || + state == "Paused" || + state == "Retry") { continue; } - else if (!status.isMember("ErrorCode") || - status["ErrorCode"].type() != Json::intValue) + else if (state == "Failure") { - ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError); + if (!status.isMember("ErrorCode") || + status["ErrorCode"].type() != Json::intValue) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError); + } + else + { + if (!status.isMember("ErrorDescription") || + status["ErrorDescription"].type() != Json::stringValue) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt()); + } + else + { + #if HAS_ORTHANC_EXCEPTION == 1 + throw Orthanc::OrthancException(static_cast(status["ErrorCode"].asInt()), + status["ErrorDescription"].asString()); + #else + ORTHANC_PLUGINS_LOG_ERROR("Exception while executing the job: " + status["ErrorDescription"].asString()); + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt()); + #endif + } + } } else { - if (!status.isMember("ErrorDescription") || - status["ErrorDescription"].type() != Json::stringValue) - { - ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt()); - } - else - { -#if HAS_ORTHANC_EXCEPTION == 1 - throw Orthanc::OrthancException(static_cast(status["ErrorCode"].asInt()), - status["ErrorDescription"].asString()); -#else - ORTHANC_PLUGINS_LOG_ERROR("Exception while executing the job: " + status["ErrorDescription"].asString()); - ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt()); -#endif - } + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError); } } } @@ -3223,36 +3342,6 @@ } #endif - - static void DecodeHttpHeaders(HttpHeaders& target, - const MemoryBuffer& source) - { - Json::Value v; - source.ToJson(v); - - if (v.type() != Json::objectValue) - { - ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); - } - - Json::Value::Members members = v.getMemberNames(); - target.clear(); - - for (size_t i = 0; i < members.size(); i++) - { - const Json::Value& h = v[members[i]]; - if (h.type() != Json::stringValue) - { - ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); - } - else - { - target[members[i]] = h.asString(); - } - } - } - - void HttpClient::ExecuteWithoutStream(uint16_t& httpStatus, HttpHeaders& answerHeaders, std::string& answerBody, @@ -4572,8 +4661,11 @@ uint8_t found = false; OrthancPlugins::MemoryBuffer valueBuffer; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" OrthancPluginErrorCode code = OrthancPluginDequeueValue(OrthancPlugins::GetGlobalContext(), &found, *valueBuffer, queueId_.c_str(), origin); +#pragma GCC diagnostic pop if (code != OrthancPluginErrorCode_Success) { @@ -4608,4 +4700,54 @@ } } #endif + + +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + bool Queue::ReserveInternal(std::string& value, uint64_t& valueId, OrthancPluginQueueOrigin origin, uint32_t releaseTimeout) + { + uint8_t found = false; + OrthancPlugins::MemoryBuffer valueBuffer; + + OrthancPluginErrorCode code = OrthancPluginReserveQueueValue(OrthancPlugins::GetGlobalContext(), &found, + *valueBuffer, &valueId, queueId_.c_str(), origin, releaseTimeout); + + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + else if (found) + { + valueBuffer.ToString(value); + return true; + } + else + { + return false; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + bool Queue::ReserveBack(std::string& value, uint64_t& valueId, uint32_t releaseTimeout) + { + return ReserveInternal(value, valueId, OrthancPluginQueueOrigin_Back, releaseTimeout); + } +#endif + + +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + bool Queue::ReserveFront(std::string& value, uint64_t& valueId, uint32_t releaseTimeout) + { + return ReserveInternal(value, valueId, OrthancPluginQueueOrigin_Front, releaseTimeout); + } +#endif + + +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + void Queue::Acknowledge(uint64_t valueId) + { + OrthancPluginAcknowledgeQueueValue(OrthancPlugins::GetGlobalContext(), queueId_.c_str(), valueId); + } +#endif } diff -r d2a5adaeb056 -r da9d68c3bf6b Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h --- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Wed Nov 12 13:05:08 2025 +0100 +++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Wed Nov 26 14:20:16 2025 +0100 @@ -142,6 +142,12 @@ # define HAS_ORTHANC_PLUGIN_QUEUES 0 #endif +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 10) +# define HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE 1 +#else +# define HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE 0 +#endif + // Macro to tag a function as having been deprecated #if (__cplusplus >= 201402L) // C++14 @@ -213,10 +219,7 @@ public: MemoryBuffer(); - ~MemoryBuffer() - { - Clear(); - } + ~MemoryBuffer(); OrthancPluginMemoryBuffer* operator*() { @@ -371,10 +374,7 @@ { } - ~OrthancString() - { - Clear(); - } + ~OrthancString(); // This transfers ownership, warning: The string must have been // allocated by the Orthanc core @@ -491,10 +491,7 @@ uint32_t pitch, void* buffer); - ~OrthancImage() - { - Clear(); - } + ~OrthancImage(); void UncompressPngImage(const void* data, size_t size); @@ -879,6 +876,14 @@ unsigned int timeout) const; bool DoPost(MemoryBuffer& target, + HttpHeaders& answerHeaders, + size_t index, + const std::string& uri, + const std::string& body, + const HttpHeaders& headers, + unsigned int timeout) const; + + bool DoPost(MemoryBuffer& target, const std::string& name, const std::string& uri, const std::string& body, @@ -896,6 +901,14 @@ const std::string& body, const HttpHeaders& headers, unsigned int timeout) const; + + bool DoPost(Json::Value& target, + HttpHeaders& answerHeaders, + size_t index, + const std::string& uri, + const std::string& body, + const HttpHeaders& headers, + unsigned int timeout) const; bool DoPost(Json::Value& target, const std::string& name, @@ -1710,6 +1723,10 @@ bool DequeueInternal(std::string& value, OrthancPluginQueueOrigin origin); +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + bool ReserveInternal(std::string& value, uint64_t& valueId, OrthancPluginQueueOrigin origin, uint32_t releaseTimeout); +#endif + public: explicit Queue(const std::string& queueId) : queueId_(queueId) @@ -1729,17 +1746,37 @@ Enqueue(value.empty() ? NULL : value.c_str(), value.size()); } +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + // Use ReserveBack() instead + ORTHANC_PLUGIN_DEPRECATED +#endif bool DequeueBack(std::string& value) { return DequeueInternal(value, OrthancPluginQueueOrigin_Back); } +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + // Use ReserveFront() instead + ORTHANC_PLUGIN_DEPRECATED +#endif bool DequeueFront(std::string& value) { return DequeueInternal(value, OrthancPluginQueueOrigin_Front); } uint64_t GetSize(); + +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + bool ReserveBack(std::string& value, uint64_t& valueId, uint32_t releaseTimeout); +#endif + +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + bool ReserveFront(std::string& value, uint64_t& valueId, uint32_t releaseTimeout); +#endif + +#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1 + void Acknowledge(uint64_t valueId); +#endif }; #endif }