Mercurial > hg > orthanc-transfers
changeset 88:c1af338d4ad1
sync + update framework
| author | Alain Mazy <am@orthanc.team> |
|---|---|
| date | Mon, 06 Oct 2025 09:52:05 +0200 |
| parents | c769a1351d6f |
| children | 12eb026957a3 1a95439d88bf |
| files | CMakeLists.txt Resources/Orthanc/CMake/AutoGeneratedCode.cmake Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Resources/SyncOrthancFolder.py |
| diffstat | 6 files changed, 438 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Wed Sep 10 14:32:24 2025 +0200 +++ b/CMakeLists.txt Mon Oct 06 09:52:05 2025 +0200 @@ -17,7 +17,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8...4.0) project(OrthancTransfers) set(ORTHANC_PLUGIN_VERSION "mainline") @@ -26,7 +26,7 @@ set(ORTHANC_FRAMEWORK_VERSION "mainline") set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") else() - set(ORTHANC_FRAMEWORK_VERSION "1.12.1") + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "9eb77f159b9d") # while waiting for 1.12.10 (for Orthanc::SystemToolbox::PathToUtf8()) set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") endif()
--- a/Resources/Orthanc/CMake/AutoGeneratedCode.cmake Wed Sep 10 14:32:24 2025 +0200 +++ b/Resources/Orthanc/CMake/AutoGeneratedCode.cmake Mon Oct 06 09:52:05 2025 +0200 @@ -20,7 +20,7 @@ # <http://www.gnu.org/licenses/>. -set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/../EmbedResources.py" +set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py" CACHE INTERNAL "Path to the EmbedResources.py script from Orthanc") set(AUTOGENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/AUTOGENERATED") set(AUTOGENERATED_SOURCES)
--- a/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Wed Sep 10 14:32:24 2025 +0200 +++ b/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Mon Oct 06 09:52:05 2025 +0200 @@ -171,6 +171,10 @@ set(ORTHANC_FRAMEWORK_MD5 "0e971f32f4f3e4951e0f3b5de49a3da6") elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.7") set(ORTHANC_FRAMEWORK_MD5 "f27c27d7a7a694dab1fd7f0a99d9715a") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.8") + set(ORTHANC_FRAMEWORK_MD5 "eb1c719234338e8277b80d3453563e9f") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.9") + set(ORTHANC_FRAMEWORK_MD5 "66b5a2ee60706c4a502896083b9e1a01") # Below this point are development snapshots that were used to # release some plugin, before an official release of the Orthanc @@ -203,6 +207,14 @@ # 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") endif() endif() endif() @@ -515,7 +527,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/Compiler.cmake) include(${CMAKE_CURRENT_LIST_DIR}/DownloadPackage.cmake) include(${CMAKE_CURRENT_LIST_DIR}/AutoGeneratedCode.cmake) - set(EMBED_RESOURCES_PYTHON ${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py) if (ORTHANC_FRAMEWORK_USE_SHARED) list(GET CMAKE_FIND_LIBRARY_PREFIXES 0 Prefix)
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Wed Sep 10 14:32:24 2025 +0200 +++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Mon Oct 06 09:52:05 2025 +0200 @@ -23,6 +23,7 @@ #include "OrthancPluginCppWrapper.h" +#include <cassert> #include <boost/algorithm/string/predicate.hpp> #include <boost/move/unique_ptr.hpp> #include <boost/thread.hpp> @@ -220,28 +221,6 @@ } -#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0) - MemoryBuffer::MemoryBuffer(const void* buffer, - size_t size) - { - uint32_t s = static_cast<uint32_t>(size); - if (static_cast<size_t>(s) != size) - { - ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory); - } - else if (OrthancPluginCreateMemoryBuffer(GetGlobalContext(), &buffer_, s) != - OrthancPluginErrorCode_Success) - { - ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory); - } - else - { - memcpy(buffer_.data, buffer, size); - } - } -#endif - - void MemoryBuffer::Clear() { if (buffer_.data != NULL) @@ -253,6 +232,51 @@ } +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0) + void MemoryBuffer::Assign(const void* buffer, + size_t size) + { + uint32_t s = static_cast<uint32_t>(size); + if (static_cast<size_t>(s) != size) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory); + } + + Clear(); + + if (OrthancPluginCreateMemoryBuffer(GetGlobalContext(), &buffer_, s) != + OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory); + } + else + { + if (size > 0) + { + memcpy(buffer_.data, buffer, size); + } + } + } +#endif + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0) + void MemoryBuffer::Assign(const std::string& s) + { + Assign(s.empty() ? NULL : s.c_str(), s.size()); + } +#endif + + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0) + void MemoryBuffer::AssignJson(const Json::Value& value) + { + std::string s; + WriteFastJson(s, value); + Assign(s); + } +#endif + + void MemoryBuffer::Assign(OrthancPluginMemoryBuffer& other) { Clear(); @@ -701,7 +725,7 @@ { OrthancString str; str.Assign(OrthancPluginDicomBufferToJson - (GetGlobalContext(), GetData(), GetSize(), format, flags, maxStringLength)); + (GetGlobalContext(), reinterpret_cast<const char*>(GetData()), GetSize(), format, flags, maxStringLength)); str.ToJson(target); } @@ -1594,7 +1618,7 @@ { if (!answer.IsEmpty()) { - result.assign(answer.GetData(), answer.GetSize()); + result.assign(reinterpret_cast<const char*>(answer.GetData()), answer.GetSize()); } return true; } @@ -4134,6 +4158,16 @@ } #endif + void GetGetArguments(GetArguments& result, const OrthancPluginHttpRequest* request) + { + result.clear(); + + for (uint32_t i = 0; i < request->getCount; ++i) + { + result[request->getKeys[i]] = request->getValues[i]; + } + } + void GetHttpHeaders(HttpHeaders& result, const OrthancPluginHttpRequest* request) { result.clear(); @@ -4234,6 +4268,11 @@ { path_ += "?" + getArguments; } + + if (request->bodySize > 0 && request->body != NULL) + { + requestBody_.assign(reinterpret_cast<const char*>(request->body), request->bodySize); + } } #endif @@ -4255,6 +4294,15 @@ #if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + void RestApiClient::SetRequestHeader(const std::string& key, + const std::string& value) + { + requestHeaders_[key] = value; + } +#endif + + +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 bool RestApiClient::Execute() { if (requestBody_.size() > 0xffffffffu) @@ -4301,9 +4349,17 @@ } } - void RestApiClient::Forward(OrthancPluginContext* context, OrthancPluginRestOutput* output) - { - if (Execute() && httpStatus_ == 200) + void RestApiClient::ExecuteAndForwardAnswer(OrthancPluginContext* context, OrthancPluginRestOutput* output) + { + if (Execute()) + { + ForwardAnswer(context, output); + } + } + + void RestApiClient::ForwardAnswer(OrthancPluginContext* context, OrthancPluginRestOutput* output) + { + if (httpStatus_ == 200) { const char* mimeType = NULL; for (HttpHeaders::const_iterator h = answerHeaders_.begin(); h != answerHeaders_.end(); ++h) @@ -4382,4 +4438,209 @@ } } #endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + KeyValueStore::Iterator::Iterator(OrthancPluginKeysValuesIterator *iterator) : + iterator_(iterator) + { + if (iterator_ == NULL) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + KeyValueStore::Iterator::~Iterator() + { + OrthancPluginFreeKeysValuesIterator(OrthancPlugins::GetGlobalContext(), iterator_); + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + bool KeyValueStore::Iterator::Next() + { + uint8_t done; + OrthancPluginErrorCode code = OrthancPluginKeysValuesIteratorNext(OrthancPlugins::GetGlobalContext(), &done, iterator_); + + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + else + { + return (done != 0); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + std::string KeyValueStore::Iterator::GetKey() const + { + const char* s = OrthancPluginKeysValuesIteratorGetKey(OrthancPlugins::GetGlobalContext(), iterator_); + if (s == NULL) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + else + { + return s; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + void KeyValueStore::Iterator::GetValue(std::string& value) const + { + OrthancPlugins::MemoryBuffer valueBuffer; + OrthancPluginErrorCode code = OrthancPluginKeysValuesIteratorGetValue(OrthancPlugins::GetGlobalContext(), *valueBuffer, iterator_); + + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + else + { + valueBuffer.ToString(value); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + void KeyValueStore::Store(const std::string& key, + const void* value, + size_t valueSize) + { + if (static_cast<size_t>(static_cast<uint32_t>(valueSize)) != valueSize) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory); + } + + OrthancPluginErrorCode code = OrthancPluginStoreKeyValue(OrthancPlugins::GetGlobalContext(), storeId_.c_str(), + key.c_str(), value, static_cast<uint32_t>(valueSize)); + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + bool KeyValueStore::GetValue(std::string& value, + const std::string& key) + { + uint8_t found = false; + OrthancPlugins::MemoryBuffer valueBuffer; + OrthancPluginErrorCode code = OrthancPluginGetKeyValue(OrthancPlugins::GetGlobalContext(), &found, + *valueBuffer, storeId_.c_str(), key.c_str()); + + 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_KEY_VALUE_STORES == 1 + void KeyValueStore::DeleteKey(const std::string& key) + { + OrthancPluginErrorCode code = OrthancPluginDeleteKeyValue(OrthancPlugins::GetGlobalContext(), + storeId_.c_str(), key.c_str()); + + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + KeyValueStore::Iterator* KeyValueStore::CreateIterator() + { + return new Iterator(OrthancPluginCreateKeysValuesIterator(OrthancPlugins::GetGlobalContext(), storeId_.c_str())); + } +#endif + + +#if HAS_ORTHANC_PLUGIN_QUEUES == 1 + void Queue::Enqueue(const void* value, + size_t valueSize) + { + if (static_cast<size_t>(static_cast<uint32_t>(valueSize)) != valueSize) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory); + } + + OrthancPluginErrorCode code = OrthancPluginEnqueueValue(OrthancPlugins::GetGlobalContext(), + queueId_.c_str(), value, static_cast<uint32_t>(valueSize)); + + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_QUEUES == 1 + bool Queue::DequeueInternal(std::string& value, + OrthancPluginQueueOrigin origin) + { + uint8_t found = false; + OrthancPlugins::MemoryBuffer valueBuffer; + + OrthancPluginErrorCode code = OrthancPluginDequeueValue(OrthancPlugins::GetGlobalContext(), &found, + *valueBuffer, queueId_.c_str(), origin); + + 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_QUEUES == 1 + uint64_t Queue::GetSize() + { + uint64_t size = 0; + OrthancPluginErrorCode code = OrthancPluginGetQueueSize(OrthancPlugins::GetGlobalContext(), queueId_.c_str(), &size); + + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + else + { + return size; + } + } +#endif }
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Wed Sep 10 14:32:24 2025 +0200 +++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Mon Oct 06 09:52:05 2025 +0200 @@ -134,6 +134,14 @@ # define HAS_ORTHANC_PLUGIN_LOG_MESSAGE 0 #endif +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 8) +# define HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES 1 +# define HAS_ORTHANC_PLUGIN_QUEUES 1 +#else +# define HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES 0 +# define HAS_ORTHANC_PLUGIN_QUEUES 0 +#endif + // Macro to tag a function as having been deprecated #if (__cplusplus >= 201402L) // C++14 @@ -172,6 +180,8 @@ { typedef std::map<std::string, std::string> HttpHeaders; + typedef std::map<std::string, std::string> GetArguments; + typedef void (*RestCallback) (OrthancPluginRestOutput* output, const char* url, const OrthancPluginHttpRequest* request); @@ -203,13 +213,6 @@ public: MemoryBuffer(); -#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0) - // This constructor makes a copy of the given buffer in the memory - // handled by the Orthanc core - MemoryBuffer(const void* buffer, - size_t size); -#endif - ~MemoryBuffer() { Clear(); @@ -220,6 +223,20 @@ return &buffer_; } +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0) + // Copy of the given buffer into the memory managed by the Orthanc core + void Assign(const void* buffer, + size_t size); +#endif + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0) + void Assign(const std::string& s); +#endif + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0) + void AssignJson(const Json::Value& value); +#endif + // This transfers ownership from "other" to "this" void Assign(OrthancPluginMemoryBuffer& other); @@ -227,11 +244,11 @@ OrthancPluginMemoryBuffer Release(); - const char* GetData() const + const void* GetData() const { if (buffer_.size > 0) { - return reinterpret_cast<const char*>(buffer_.data); + return buffer_.data; } else { @@ -1432,6 +1449,9 @@ // helper method to re-serialize the get arguments from the SDK into a string void SerializeGetArguments(std::string& output, const OrthancPluginHttpRequest* request); +// helper method to convert Get arguments from the plugin SDK to a std::map +void GetGetArguments(GetArguments& result, const OrthancPluginHttpRequest* request); + #if HAS_ORTHANC_PLUGIN_WEBDAV == 1 class IWebDavCollection : public boost::noncopyable { @@ -1589,6 +1609,9 @@ void AddRequestHeader(const std::string& key, const std::string& value); + void SetRequestHeader(const std::string& key, + const std::string& value); + const HttpHeaders& GetRequestHeaders() const { return requestHeaders_; @@ -1619,10 +1642,14 @@ return requestBody_; } + // Execute only bool Execute(); + // Forward response as is + void ForwardAnswer(OrthancPluginContext* context, OrthancPluginRestOutput* output); + // Execute and forward the response as is - void Forward(OrthancPluginContext* context, OrthancPluginRestOutput* output); + void ExecuteAndForwardAnswer(OrthancPluginContext* context, OrthancPluginRestOutput* output); uint16_t GetHttpStatus() const; @@ -1634,4 +1661,101 @@ bool GetAnswerJson(Json::Value& output) const; }; #endif + + +#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1 + class KeyValueStore : public boost::noncopyable + { + public: + class Iterator : public boost::noncopyable + { + private: + OrthancPluginKeysValuesIterator *iterator_; + + public: + explicit Iterator(OrthancPluginKeysValuesIterator *iterator); + + ~Iterator(); + + bool Next(); + + std::string GetKey() const; + + void GetValue(std::string& target) const; + }; + + private: + std::string storeId_; + + public: + explicit KeyValueStore(const std::string& storeId) : + storeId_(storeId) + { + } + + const std::string& GetStoreId() const + { + return storeId_; + } + + void Store(const std::string& key, + const void* value, + size_t valueSize); + + void Store(const std::string& key, + const std::string& value) + { + Store(key, value.empty() ? NULL : value.c_str(), value.size()); + } + + bool GetValue(std::string& value, + const std::string& key); + + void DeleteKey(const std::string& key); + + Iterator* CreateIterator(); + }; +#endif + + +#if HAS_ORTHANC_PLUGIN_QUEUES == 1 + class Queue : public boost::noncopyable + { + private: + std::string queueId_; + + bool DequeueInternal(std::string& value, OrthancPluginQueueOrigin origin); + + public: + explicit Queue(const std::string& queueId) : + queueId_(queueId) + { + } + + const std::string& GetQueueId() const + { + return queueId_; + } + + void Enqueue(const void* value, + size_t valueSize); + + void Enqueue(const std::string& value) + { + Enqueue(value.empty() ? NULL : value.c_str(), value.size()); + } + + bool DequeueBack(std::string& value) + { + return DequeueInternal(value, OrthancPluginQueueOrigin_Back); + } + + bool DequeueFront(std::string& value) + { + return DequeueInternal(value, OrthancPluginQueueOrigin_Front); + } + + uint64_t GetSize(); + }; +#endif }
--- a/Resources/SyncOrthancFolder.py Wed Sep 10 14:32:24 2025 +0200 +++ b/Resources/SyncOrthancFolder.py Mon Oct 06 09:52:05 2025 +0200 @@ -20,7 +20,7 @@ ('OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake', 'CMake'), ('OrthancFramework/Resources/CMake/DownloadPackage.cmake', 'CMake'), ('OrthancFramework/Resources/CMake/GoogleTestConfiguration.cmake', 'CMake'), - ('OrthancFramework/Resources/EmbedResources.py', 'CMake'), + ('OrthancFramework/Resources/CMake/EmbedResources.py', 'CMake'), ('OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake', 'Toolchains'), ('OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain32.cmake', 'Toolchains'), ('OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain64.cmake', 'Toolchains'),
