Mercurial > hg > orthanc-python
changeset 134:55de4be5608c
integration fix-leak->mainline
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Wed, 30 Aug 2023 14:46:39 +0200 |
| parents | 4cf3c2bc119f (diff) a26163d2ecd9 (current diff) |
| children | 69c9e376b73e 286368f6f019 |
| files | |
| diffstat | 91 files changed, 1283 insertions(+), 268 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Wed Aug 30 14:46:07 2023 +0200 +++ b/CMakeLists.txt Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) project(OrthancPython) -set(PLUGIN_VERSION "4.0") +set(PLUGIN_VERSION "mainline") if (PLUGIN_VERSION STREQUAL "mainline") set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline") @@ -187,6 +187,7 @@ Sources/ReceivedInstanceCallback.cpp Sources/RestCallbacks.cpp Sources/StorageArea.cpp + Sources/StorageCommitmentScpCallback.cpp # Third-party sources ${CMAKE_SOURCE_DIR}/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp
--- a/CodeAnalysis/Class.mustache Wed Aug 30 14:46:07 2023 +0200 +++ b/CodeAnalysis/Class.mustache Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/CodeAnalysis/Enumeration.mustache Wed Aug 30 14:46:07 2023 +0200 +++ b/CodeAnalysis/Enumeration.mustache Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/CodeAnalysis/GlobalFunctions.mustache Wed Aug 30 14:46:07 2023 +0200 +++ b/CodeAnalysis/GlobalFunctions.mustache Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/CodeAnalysis/ParseOrthancSDK.py Wed Aug 30 14:46:07 2023 +0200 +++ b/CodeAnalysis/ParseOrthancSDK.py Wed Aug 30 14:46:39 2023 +0200 @@ -2,8 +2,8 @@ ## ## Python plugin for Orthanc -## Copyright (C) 2020-2022 Osimis S.A., Belgium -## Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +## Copyright (C) 2020-2023 Osimis S.A., Belgium +## Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium ## ## This program is free software: you can redistribute it and/or ## modify it under the terms of the GNU Affero General Public License
--- a/CodeAnalysis/sdk.cpp.mustache Wed Aug 30 14:46:07 2023 +0200 +++ b/CodeAnalysis/sdk.cpp.mustache Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/CodeAnalysis/sdk.h.mustache Wed Aug 30 14:46:07 2023 +0200 +++ b/CodeAnalysis/sdk.h.mustache Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/NEWS Wed Aug 30 14:46:07 2023 +0200 +++ b/NEWS Wed Aug 30 14:46:39 2023 +0200 @@ -1,12 +1,21 @@ Pending changes in the mainline =============================== +* New functions from the SDK wrapped in Python: + - orthanc.RegisterStorageCommitmentScpCallback() * New configuration section "Python" to group settings related to the plugin: - "Python.Path" is an alias for global option "PythonScript" - "Python.Verbose" is an alias for global option "PythonVerbose" * New configuration option "Python.DisplayMemoryUsage" to periodically display memory allocations that stem from Python plugins +Maintenance +----------- + +* Fix memory leaks when a python script calls orthanc.RestApiPost() and sibling methods, + in IncomingHttpRequestFilter and in the CMove callback. +* New builders for Windows: Supporting 32 / 64bit with Python 3.9 / 3.10 / 3.11 + Version 4.0 (2022-02-23) ========================
--- a/README Wed Aug 30 14:46:07 2023 +0200 +++ b/README Wed Aug 30 14:46:39 2023 +0200 @@ -18,6 +18,14 @@ http://book.orthanc-server.com/plugins/python.html +Contributing +------------ + +Instructions for contributing to the Orthanc project are included in +the Orthanc Book: +https://book.orthanc-server.com/developers/repositories.html + + Licensing ---------
--- a/Resources/Orthanc/CMake/AutoGeneratedCode.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/CMake/AutoGeneratedCode.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License
--- a/Resources/Orthanc/CMake/Compiler.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/CMake/Compiler.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License @@ -237,7 +237,8 @@ if (DEFINED ENABLE_PROFILING AND ENABLE_PROFILING) - if (CMAKE_COMPILER_IS_GNUCXX) + if (CMAKE_COMPILER_IS_GNUCXX OR + CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") @@ -262,3 +263,24 @@ # preceding batches. https://cmake.org/Bug/view.php?id=14874 set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> <LINK_FLAGS> q <TARGET> <OBJECTS>") endif() + + +# This function defines macro "__ORTHANC_FILE__" as a replacement to +# macro "__FILE__", as the latter leaks the full path of the source +# files in the binaries +# https://stackoverflow.com/questions/8487986/file-macro-shows-full-path +# https://twitter.com/wget42/status/1676877802375634944?s=20 +function(DefineSourceBasenameForTarget targetname) + # Microsoft Visual Studio is extremely slow if using + # "set_property()", we only enable this feature for gcc and clang + if (CMAKE_COMPILER_IS_GNUCXX OR + CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + get_target_property(source_files "${targetname}" SOURCES) + foreach(sourcefile ${source_files}) + get_filename_component(basename "${sourcefile}" NAME) + set_property( + SOURCE "${sourcefile}" APPEND + PROPERTY COMPILE_DEFINITIONS "__ORTHANC_FILE__=\"${basename}\"") + endforeach() + endif() +endfunction()
--- a/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License @@ -144,6 +144,20 @@ set(ORTHANC_FRAMEWORK_MD5 "c912bbb860d640d3ae3003b5c9698205") elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.10.0") set(ORTHANC_FRAMEWORK_MD5 "8610c82d9153f22e929f2110f8f60279") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.10.1") + set(ORTHANC_FRAMEWORK_MD5 "caf667fc5ea452b3d0c2f70bfd02599c") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.11.0") + set(ORTHANC_FRAMEWORK_MD5 "962c4a4a706a2ef28b390d8515dd7091") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.11.1") + set(ORTHANC_FRAMEWORK_MD5 "a39661c406adf22cf574fde290cf4bbf") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.11.2") + set(ORTHANC_FRAMEWORK_MD5 "ede3de356493a8868545f8cb4b8bc8b5") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.11.3") + set(ORTHANC_FRAMEWORK_MD5 "f941c0f5771db7616e7b7961026a60e2") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.0") + set(ORTHANC_FRAMEWORK_MD5 "d32a0cde03b6eb603d8dd2b33d38bf1b") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.1") + set(ORTHANC_FRAMEWORK_MD5 "8a435140efc8ff4a01d8242f092f21de") # Below this point are development snapshots that were used to # release some plugin, before an official release of the Orthanc @@ -167,6 +181,9 @@ elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "b2e08d83e21d") # WSI 1.1 (framework pre-1.10.0), to remove "-std=c++11" set(ORTHANC_FRAMEWORK_MD5 "2eaa073cbb4b44ffba199ad93393b2b1") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "daf4807631c5") + # DICOMweb 1.15 (framework pre-1.12.2) + set(ORTHANC_FRAMEWORK_MD5 "c644aff2817306b3207c98c92e43f35f") endif() endif() endif() @@ -303,7 +320,7 @@ else() # Default case: Download from the official Web site set(ORTHANC_FRAMEMORK_FILENAME Orthanc-${ORTHANC_FRAMEWORK_VERSION}.tar.gz) - set(ORTHANC_FRAMEWORK_URL "http://orthanc.osimis.io/ThirdPartyDownloads/orthanc-framework/${ORTHANC_FRAMEMORK_FILENAME}") + set(ORTHANC_FRAMEWORK_URL "https://orthanc.uclouvain.be/third-party-downloads/orthanc-framework/${ORTHANC_FRAMEMORK_FILENAME}") endif() set(ORTHANC_FRAMEWORK_ARCHIVE "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${ORTHANC_FRAMEMORK_FILENAME}")
--- a/Resources/Orthanc/CMake/DownloadPackage.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/CMake/DownloadPackage.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License @@ -101,19 +101,26 @@ message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON") endif() - if ("${MD5}" STREQUAL "no-check") - message(WARNING "Not checking the MD5 of: ${Url}") - file(DOWNLOAD "${Url}" "${TMP_PATH}" - SHOW_PROGRESS TIMEOUT 300 INACTIVITY_TIMEOUT 60 - STATUS Failure) - else() - file(DOWNLOAD "${Url}" "${TMP_PATH}" - SHOW_PROGRESS TIMEOUT 300 INACTIVITY_TIMEOUT 60 - EXPECTED_MD5 "${MD5}" STATUS Failure) - endif() + foreach (retry RANGE 1 5) # Retries 5 times + if ("${MD5}" STREQUAL "no-check") + message(WARNING "Not checking the MD5 of: ${Url}") + file(DOWNLOAD "${Url}" "${TMP_PATH}" + SHOW_PROGRESS TIMEOUT 30 INACTIVITY_TIMEOUT 10 + STATUS Failure) + else() + file(DOWNLOAD "${Url}" "${TMP_PATH}" + SHOW_PROGRESS TIMEOUT 30 INACTIVITY_TIMEOUT 10 + EXPECTED_MD5 "${MD5}" STATUS Failure) + endif() - list(GET Failure 0 Status) + list(GET Failure 0 Status) + if (Status EQUAL 0) + break() # Successful download + endif() + endforeach() + if (NOT Status EQUAL 0) + file(REMOVE ${TMP_PATH}) message(FATAL_ERROR "Cannot download file: ${Url}") endif()
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -2,8 +2,8 @@ * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -250,26 +250,53 @@ } } + // helper class to convert std::map of headers to the plugin SDK C structure + class PluginHttpHeaders + { + private: + std::vector<const char*> headersKeys_; + std::vector<const char*> headersValues_; + + public: + explicit PluginHttpHeaders(const std::map<std::string, std::string>& httpHeaders) + { + for (std::map<std::string, std::string>::const_iterator + it = httpHeaders.begin(); it != httpHeaders.end(); ++it) + { + headersKeys_.push_back(it->first.c_str()); + headersValues_.push_back(it->second.c_str()); + } + } + + const char* const* GetKeys() + { + return (headersKeys_.empty() ? NULL : &headersKeys_[0]); + } + + const char* const* GetValues() + { + return (headersValues_.empty() ? NULL : &headersValues_[0]); + } + + uint32_t GetSize() + { + return static_cast<uint32_t>(headersKeys_.size()); + } + }; + bool MemoryBuffer::RestApiGet(const std::string& uri, const std::map<std::string, std::string>& httpHeaders, bool applyPlugins) { Clear(); - std::vector<const char*> headersKeys; - std::vector<const char*> headersValues; - - for (std::map<std::string, std::string>::const_iterator - it = httpHeaders.begin(); it != httpHeaders.end(); it++) - { - headersKeys.push_back(it->first.c_str()); - headersValues.push_back(it->second.c_str()); - } + PluginHttpHeaders headers(httpHeaders); return CheckHttp(OrthancPluginRestApiGet2( - GetGlobalContext(), &buffer_, uri.c_str(), httpHeaders.size(), - (headersKeys.empty() ? NULL : &headersKeys[0]), - (headersValues.empty() ? NULL : &headersValues[0]), applyPlugins)); + GetGlobalContext(), &buffer_, uri.c_str(), + headers.GetSize(), + headers.GetKeys(), + headers.GetValues(), applyPlugins)); } bool MemoryBuffer::RestApiPost(const std::string& uri, @@ -292,6 +319,41 @@ } } +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + + bool MemoryBuffer::RestApiPost(const std::string& uri, + const void* body, + size_t bodySize, + const std::map<std::string, std::string>& httpHeaders, + bool applyPlugins) + { + MemoryBuffer answerHeaders; + uint16_t httpStatus; + + PluginHttpHeaders headers(httpHeaders); + + return CheckHttp(OrthancPluginCallRestApi(GetGlobalContext(), + &buffer_, + *answerHeaders, + &httpStatus, + OrthancPluginHttpMethod_Post, + uri.c_str(), + headers.GetSize(), headers.GetKeys(), headers.GetValues(), + body, bodySize, + applyPlugins)); + } + + + bool MemoryBuffer::RestApiPost(const std::string& uri, + const Json::Value& body, + const std::map<std::string, std::string>& httpHeaders, + bool applyPlugins) + { + std::string s; + WriteFastJson(s, body); + return RestApiPost(uri, s.c_str(), s.size(), httpHeaders, applyPlugins); + } +#endif bool MemoryBuffer::RestApiPut(const std::string& uri, const void* body, @@ -511,6 +573,22 @@ } + void OrthancString::ToJsonWithoutComments(Json::Value& target) const + { + if (str_ == NULL) + { + LogError("Cannot convert an empty memory buffer to JSON"); + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + + if (!ReadJsonWithoutComments(target, str_)) + { + LogError("Cannot convert some memory buffer to JSON"); + ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); + } + } + + void MemoryBuffer::DicomToJson(Json::Value& target, OrthancPluginDicomToJsonFormat format, OrthancPluginDicomToJsonFlags flags, @@ -645,7 +723,7 @@ ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } - str.ToJson(configuration_); + str.ToJsonWithoutComments(configuration_); if (configuration_.type() != Json::objectValue) { @@ -673,6 +751,12 @@ } } + OrthancConfiguration::OrthancConfiguration(const Json::Value& configuration, const std::string& path) : + configuration_(configuration), + path_(path) + { + } + std::string OrthancConfiguration::GetPath(const std::string& key) const { @@ -1028,7 +1112,7 @@ if (configuration_[key].type() != Json::objectValue) { LogError("The configuration option \"" + GetPath(key) + - "\" is not a string as expected"); + "\" is not an object as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -1374,6 +1458,27 @@ } + bool RestApiGet(Json::Value& result, + const std::string& uri, + const std::map<std::string, std::string>& httpHeaders, + bool applyPlugins) + { + MemoryBuffer answer; + + if (!answer.RestApiGet(uri, httpHeaders, applyPlugins)) + { + return false; + } + else + { + if (!answer.IsEmpty()) + { + answer.ToJson(result); + } + return true; + } + } + bool RestApiGet(Json::Value& result, const std::string& uri, @@ -1441,6 +1546,30 @@ } } +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + bool RestApiPost(Json::Value& result, + const std::string& uri, + const Json::Value& body, + const std::map<std::string, std::string>& httpHeaders, + bool applyPlugins) + { + MemoryBuffer answer; + + if (!answer.RestApiPost(uri, body, httpHeaders, applyPlugins)) + { + return false; + } + else + { + if (!answer.IsEmpty()) + { + answer.ToJson(result); + } + return true; + } + } +#endif + bool RestApiPost(Json::Value& result, const std::string& uri, @@ -1530,32 +1659,27 @@ " is required)"); } - - bool CheckMinimalOrthancVersion(unsigned int major, - unsigned int minor, - unsigned int revision) + bool CheckMinimalVersion(const char* version, + unsigned int major, + unsigned int minor, + unsigned int revision) { - if (!HasGlobalContext()) - { - LogError("Bad Orthanc context in the plugin"); - return false; - } - - if (!strcmp(GetGlobalContext()->orthancVersion, "mainline")) + if (!strcmp(version, "mainline")) { // Assume compatibility with the mainline return true; } - // Parse the version of the Orthanc core - int aa, bb, cc; - if ( #ifdef _MSC_VER - sscanf_s +#define ORTHANC_SCANF sscanf_s #else - sscanf +#define ORTHANC_SCANF sscanf #endif - (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 || + + // Parse the version + int aa, bb, cc = 0; + if ((ORTHANC_SCANF(version, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 && + ORTHANC_SCANF(version, "%4d.%4d", &aa, &bb) != 2) || aa < 0 || bb < 0 || cc < 0) @@ -1579,7 +1703,6 @@ return false; } - // Check the minor version number assert(a == major); @@ -1607,6 +1730,21 @@ } + bool CheckMinimalOrthancVersion(unsigned int major, + unsigned int minor, + unsigned int revision) + { + if (!HasGlobalContext()) + { + LogError("Bad Orthanc context in the plugin"); + return false; + } + + return CheckMinimalVersion(GetGlobalContext()->orthancVersion, + major, minor, revision); + } + + #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0) const char* AutodetectMimeType(const std::string& path) { @@ -1776,7 +1914,8 @@ bool OrthancPeers::DoGet(MemoryBuffer& target, size_t index, - const std::string& uri) const + const std::string& uri, + const std::map<std::string, std::string>& headers) const { if (index >= index_.size()) { @@ -1785,10 +1924,12 @@ OrthancPlugins::MemoryBuffer answer; uint16_t status; + PluginHttpHeaders pluginHeaders(headers); + OrthancPluginErrorCode code = OrthancPluginCallPeerApi (GetGlobalContext(), *answer, NULL, &status, peers_, static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(), - 0, NULL, NULL, NULL, 0, timeout_); + pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), NULL, 0, timeout_); if (code == OrthancPluginErrorCode_Success) { @@ -1804,21 +1945,23 @@ bool OrthancPeers::DoGet(MemoryBuffer& target, const std::string& name, - const std::string& uri) const + const std::string& uri, + const std::map<std::string, std::string>& headers) const { size_t index; return (LookupName(index, name) && - DoGet(target, index, uri)); + DoGet(target, index, uri, headers)); } bool OrthancPeers::DoGet(Json::Value& target, size_t index, - const std::string& uri) const + const std::string& uri, + const std::map<std::string, std::string>& headers) const { MemoryBuffer buffer; - if (DoGet(buffer, index, uri)) + if (DoGet(buffer, index, uri, headers)) { buffer.ToJson(target); return true; @@ -1832,11 +1975,12 @@ bool OrthancPeers::DoGet(Json::Value& target, const std::string& name, - const std::string& uri) const + const std::string& uri, + const std::map<std::string, std::string>& headers) const { MemoryBuffer buffer; - if (DoGet(buffer, name, uri)) + if (DoGet(buffer, name, uri, headers)) { buffer.ToJson(target); return true; @@ -1851,22 +1995,24 @@ bool OrthancPeers::DoPost(MemoryBuffer& target, const std::string& name, const std::string& uri, - const std::string& body) const + const std::string& body, + const std::map<std::string, std::string>& headers) const { size_t index; return (LookupName(index, name) && - DoPost(target, index, uri, body)); + DoPost(target, index, uri, body, headers)); } bool OrthancPeers::DoPost(Json::Value& target, size_t index, const std::string& uri, - const std::string& body) const + const std::string& body, + const std::map<std::string, std::string>& headers) const { MemoryBuffer buffer; - if (DoPost(buffer, index, uri, body)) + if (DoPost(buffer, index, uri, body, headers)) { buffer.ToJson(target); return true; @@ -1881,11 +2027,12 @@ bool OrthancPeers::DoPost(Json::Value& target, const std::string& name, const std::string& uri, - const std::string& body) const + const std::string& body, + const std::map<std::string, std::string>& headers) const { MemoryBuffer buffer; - if (DoPost(buffer, name, uri, body)) + if (DoPost(buffer, name, uri, body, headers)) { buffer.ToJson(target); return true; @@ -1900,7 +2047,8 @@ bool OrthancPeers::DoPost(MemoryBuffer& target, size_t index, const std::string& uri, - const std::string& body) const + const std::string& body, + const std::map<std::string, std::string>& headers) const { if (index >= index_.size()) { @@ -1915,10 +2063,12 @@ OrthancPlugins::MemoryBuffer answer; uint16_t status; + PluginHttpHeaders pluginHeaders(headers); + OrthancPluginErrorCode code = OrthancPluginCallPeerApi (GetGlobalContext(), *answer, NULL, &status, peers_, static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(), - 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); + pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_); if (code == OrthancPluginErrorCode_Success) { @@ -1934,7 +2084,8 @@ bool OrthancPeers::DoPut(size_t index, const std::string& uri, - const std::string& body) const + const std::string& body, + const std::map<std::string, std::string>& headers) const { if (index >= index_.size()) { @@ -1949,10 +2100,12 @@ OrthancPlugins::MemoryBuffer answer; uint16_t status; + PluginHttpHeaders pluginHeaders(headers); + OrthancPluginErrorCode code = OrthancPluginCallPeerApi (GetGlobalContext(), *answer, NULL, &status, peers_, static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(), - 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); + pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_); if (code == OrthancPluginErrorCode_Success) { @@ -1967,16 +2120,18 @@ bool OrthancPeers::DoPut(const std::string& name, const std::string& uri, - const std::string& body) const + const std::string& body, + const std::map<std::string, std::string>& headers) const { size_t index; return (LookupName(index, name) && - DoPut(index, uri, body)); + DoPut(index, uri, body, headers)); } bool OrthancPeers::DoDelete(size_t index, - const std::string& uri) const + const std::string& uri, + const std::map<std::string, std::string>& headers) const { if (index >= index_.size()) { @@ -1985,10 +2140,12 @@ OrthancPlugins::MemoryBuffer answer; uint16_t status; + PluginHttpHeaders pluginHeaders(headers); + OrthancPluginErrorCode code = OrthancPluginCallPeerApi (GetGlobalContext(), *answer, NULL, &status, peers_, static_cast<uint32_t>(index), OrthancPluginHttpMethod_Delete, uri.c_str(), - 0, NULL, NULL, NULL, 0, timeout_); + pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), NULL, 0, timeout_); if (code == OrthancPluginErrorCode_Success) { @@ -2002,11 +2159,12 @@ bool OrthancPeers::DoDelete(const std::string& name, - const std::string& uri) const + const std::string& uri, + const std::map<std::string, std::string>& headers) const { size_t index; return (LookupName(index, name) && - DoDelete(index, uri)); + DoDelete(index, uri, headers)); } #endif @@ -2043,6 +2201,36 @@ } +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3) + static OrthancPluginErrorCode CopyStringToMemoryBuffer(OrthancPluginMemoryBuffer* target, + const std::string& source) + { + if (OrthancPluginCreateMemoryBuffer(globalContext_, target, source.size()) != OrthancPluginErrorCode_Success) + { + return OrthancPluginErrorCode_NotEnoughMemory; + } + else + { + if (!source.empty()) + { + memcpy(target->data, source.c_str(), source.size()); + } + + return OrthancPluginErrorCode_Success; + } + } +#endif + + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3) + OrthancPluginErrorCode OrthancJob::CallbackGetContent(OrthancPluginMemoryBuffer* target, + void* job) + { + assert(job != NULL); + OrthancJob& that = *reinterpret_cast<OrthancJob*>(job); + return CopyStringToMemoryBuffer(target, that.content_); + } +#else const char* OrthancJob::CallbackGetContent(void* job) { assert(job != NULL); @@ -2056,8 +2244,33 @@ return 0; } } - - +#endif + + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3) + int32_t OrthancJob::CallbackGetSerialized(OrthancPluginMemoryBuffer* target, + void* job) + { + assert(job != NULL); + OrthancJob& that = *reinterpret_cast<OrthancJob*>(job); + + if (that.hasSerialized_) + { + if (CopyStringToMemoryBuffer(target, that.serialized_) == OrthancPluginErrorCode_Success) + { + return 1; + } + else + { + return -1; + } + } + else + { + return 0; + } + } +#else const char* OrthancJob::CallbackGetSerialized(void* job) { assert(job != NULL); @@ -2080,6 +2293,7 @@ return 0; } } +#endif OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job) @@ -2211,10 +2425,15 @@ ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer); } - OrthancPluginJob* orthanc = OrthancPluginCreateJob( - GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(), - CallbackGetProgress, CallbackGetContent, CallbackGetSerialized, - CallbackStep, CallbackStop, CallbackReset); + OrthancPluginJob* orthanc = +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3) + OrthancPluginCreateJob2 +#else + OrthancPluginCreateJob +#endif + (GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(), + CallbackGetProgress, CallbackGetContent, CallbackGetSerialized, + CallbackStep, CallbackStop, CallbackReset); if (orthanc == NULL) { @@ -2510,7 +2729,7 @@ } catch (...) { - return OrthancPluginErrorCode_InternalError; + return OrthancPluginErrorCode_Plugin; } } } @@ -3532,4 +3751,275 @@ } } #endif + + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 1) + DicomInstance* DicomInstance::Load(const std::string& instanceId, + OrthancPluginLoadDicomInstanceMode mode) + { + OrthancPluginDicomInstance* instance = OrthancPluginLoadDicomInstance( + GetGlobalContext(), instanceId.c_str(), mode); + + if (instance == NULL) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin); + } + else + { + boost::movelib::unique_ptr<DicomInstance> result(new DicomInstance(instance)); + result->toFree_ = true; + return result.release(); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + static std::vector<std::string> WebDavConvertPath(uint32_t pathSize, + const char* const* pathItems) + { + std::vector<std::string> result(pathSize); + + for (uint32_t i = 0; i < pathSize; i++) + { + result[i] = pathItems[i]; + } + + return result; + } +#endif + + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + static OrthancPluginErrorCode WebDavIsExistingFolder(uint8_t* isExisting, + uint32_t pathSize, + const char* const* pathItems, + void* payload) + { + IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload); + + try + { + *isExisting = (that.IsExistingFolder(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0); + return OrthancPluginErrorCode_Success; + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (...) + { + return OrthancPluginErrorCode_Plugin; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + static OrthancPluginErrorCode WebDavListFolder(uint8_t* isExisting, + OrthancPluginWebDavCollection* collection, + OrthancPluginWebDavAddFile addFile, + OrthancPluginWebDavAddFolder addFolder, + uint32_t pathSize, + const char* const* pathItems, + void* payload) + { + IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload); + + try + { + std::list<IWebDavCollection::FileInfo> files; + std::list<IWebDavCollection::FolderInfo> subfolders; + + if (!that.ListFolder(files, subfolders, WebDavConvertPath(pathSize, pathItems))) + { + *isExisting = 0; + } + else + { + *isExisting = 1; + + for (std::list<IWebDavCollection::FileInfo>::const_iterator + it = files.begin(); it != files.end(); ++it) + { + OrthancPluginErrorCode code = addFile( + collection, it->GetName().c_str(), it->GetContentSize(), + it->GetMimeType().c_str(), it->GetDateTime().c_str()); + + if (code != OrthancPluginErrorCode_Success) + { + return code; + } + } + + for (std::list<IWebDavCollection::FolderInfo>::const_iterator it = + subfolders.begin(); it != subfolders.end(); ++it) + { + OrthancPluginErrorCode code = addFolder( + collection, it->GetName().c_str(), it->GetDateTime().c_str()); + + if (code != OrthancPluginErrorCode_Success) + { + return code; + } + } + } + + return OrthancPluginErrorCode_Success; + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (...) + { + return OrthancPluginErrorCode_Plugin; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + static OrthancPluginErrorCode WebDavRetrieveFile(OrthancPluginWebDavCollection* collection, + OrthancPluginWebDavRetrieveFile retrieveFile, + uint32_t pathSize, + const char* const* pathItems, + void* payload) + { + IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload); + + try + { + std::string content, mime, dateTime; + + if (that.GetFile(content, mime, dateTime, WebDavConvertPath(pathSize, pathItems))) + { + return retrieveFile(collection, content.empty() ? NULL : content.c_str(), + content.size(), mime.c_str(), dateTime.c_str()); + } + else + { + // Inexisting file + return OrthancPluginErrorCode_Success; + } + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (...) + { + return OrthancPluginErrorCode_InternalError; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + static OrthancPluginErrorCode WebDavStoreFileCallback(uint8_t* isReadOnly, /* out */ + uint32_t pathSize, + const char* const* pathItems, + const void* data, + uint64_t size, + void* payload) + { + IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload); + + try + { + if (static_cast<uint64_t>(static_cast<size_t>(size)) != size) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory); + } + + *isReadOnly = (that.StoreFile(WebDavConvertPath(pathSize, pathItems), data, + static_cast<size_t>(size)) ? 1 : 0); + return OrthancPluginErrorCode_Success; + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (...) + { + return OrthancPluginErrorCode_InternalError; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + static OrthancPluginErrorCode WebDavCreateFolderCallback(uint8_t* isReadOnly, /* out */ + uint32_t pathSize, + const char* const* pathItems, + void* payload) + { + IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload); + + try + { + *isReadOnly = (that.CreateFolder(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0); + return OrthancPluginErrorCode_Success; + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (...) + { + return OrthancPluginErrorCode_InternalError; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + static OrthancPluginErrorCode WebDavDeleteItemCallback(uint8_t* isReadOnly, /* out */ + uint32_t pathSize, + const char* const* pathItems, + void* payload) + { + IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload); + + try + { + *isReadOnly = (that.DeleteItem(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0); + return OrthancPluginErrorCode_Success; + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (...) + { + return OrthancPluginErrorCode_InternalError; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + void IWebDavCollection::Register(const std::string& uri, + IWebDavCollection& collection) + { + OrthancPluginErrorCode code = OrthancPluginRegisterWebDavCollection( + GetGlobalContext(), uri.c_str(), WebDavIsExistingFolder, WebDavListFolder, WebDavRetrieveFile, + WebDavStoreFileCallback, WebDavCreateFolderCallback, WebDavDeleteItemCallback, &collection); + + if (code != OrthancPluginErrorCode_Success) + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + } +#endif + + void GetHttpHeaders(std::map<std::string, std::string>& result, const OrthancPluginHttpRequest* request) + { + result.clear(); + + for (uint32_t i = 0; i < request->headersCount; ++i) + { + result[request->headersKeys[i]] = request->headersValues[i]; + } + } }
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Wed Aug 30 14:46:39 2023 +0200 @@ -2,8 +2,8 @@ * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -115,6 +115,18 @@ # define HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP 0 #endif +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) +# define HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API 1 +#else +# define HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API 0 +#endif + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 10, 1) +# define HAS_ORTHANC_PLUGIN_WEBDAV 1 +#else +# define HAS_ORTHANC_PLUGIN_WEBDAV 0 +#endif + namespace OrthancPlugins @@ -218,6 +230,19 @@ const Json::Value& body, bool applyPlugins); +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + bool RestApiPost(const std::string& uri, + const Json::Value& body, + const std::map<std::string, std::string>& httpHeaders, + bool applyPlugins); + + bool RestApiPost(const std::string& uri, + const void* body, + size_t bodySize, + const std::map<std::string, std::string>& httpHeaders, + bool applyPlugins); +#endif + bool RestApiPut(const std::string& uri, const Json::Value& body, bool applyPlugins); @@ -297,10 +322,17 @@ return str_; } + bool IsNullOrEmpty() const + { + return str_ == NULL || str_[0] == 0; + } + void ToString(std::string& target) const; void ToJson(Json::Value& target) const; - }; + + void ToJsonWithoutComments(Json::Value& target) const; +}; class OrthancConfiguration : public boost::noncopyable @@ -314,10 +346,12 @@ void LoadConfiguration(); public: - OrthancConfiguration(); + OrthancConfiguration(); // loads the full Orthanc configuration explicit OrthancConfiguration(bool load); + explicit OrthancConfiguration(const Json::Value& configuration, const std::string& path); // e.g. to load a section from a default json content + const Json::Value& GetJson() const { return configuration_; @@ -501,6 +535,11 @@ const std::string& uri, bool applyPlugins); + bool RestApiGet(Json::Value& result, + const std::string& uri, + const std::map<std::string, std::string>& httpHeaders, + bool applyPlugins); + bool RestApiGetString(std::string& result, const std::string& uri, bool applyPlugins); @@ -522,6 +561,14 @@ size_t bodySize, bool applyPlugins); +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + bool RestApiPost(Json::Value& result, + const std::string& uri, + const Json::Value& body, + const std::map<std::string, std::string>& httpHeaders, + bool applyPlugins); +#endif + bool RestApiPost(Json::Value& result, const std::string& uri, const Json::Value& body, @@ -602,6 +649,10 @@ unsigned int minor, unsigned int revision); + bool CheckMinimalVersion(const char* version, + unsigned int major, + unsigned int minor, + unsigned int revision); namespace Internals { @@ -711,53 +762,65 @@ bool DoGet(MemoryBuffer& target, size_t index, - const std::string& uri) const; + const std::string& uri, + const std::map<std::string, std::string>& headers) const; bool DoGet(MemoryBuffer& target, const std::string& name, - const std::string& uri) const; + const std::string& uri, + const std::map<std::string, std::string>& headers) const; bool DoGet(Json::Value& target, size_t index, - const std::string& uri) const; + const std::string& uri, + const std::map<std::string, std::string>& headers) const; bool DoGet(Json::Value& target, const std::string& name, - const std::string& uri) const; + const std::string& uri, + const std::map<std::string, std::string>& headers) const; bool DoPost(MemoryBuffer& target, size_t index, const std::string& uri, - const std::string& body) const; + const std::string& body, + const std::map<std::string, std::string>& headers) const; bool DoPost(MemoryBuffer& target, const std::string& name, const std::string& uri, - const std::string& body) const; + const std::string& body, + const std::map<std::string, std::string>& headers) const; bool DoPost(Json::Value& target, size_t index, const std::string& uri, - const std::string& body) const; + const std::string& body, + const std::map<std::string, std::string>& headers) const; bool DoPost(Json::Value& target, const std::string& name, const std::string& uri, - const std::string& body) const; + const std::string& body, + const std::map<std::string, std::string>& headers) const; bool DoPut(size_t index, const std::string& uri, - const std::string& body) const; + const std::string& body, + const std::map<std::string, std::string>& headers) const; bool DoPut(const std::string& name, const std::string& uri, - const std::string& body) const; + const std::string& body, + const std::map<std::string, std::string>& headers) const; bool DoDelete(size_t index, - const std::string& uri) const; + const std::string& uri, + const std::map<std::string, std::string>& headers) const; bool DoDelete(const std::string& name, - const std::string& uri) const; + const std::string& uri, + const std::map<std::string, std::string>& headers) const; }; #endif @@ -777,9 +840,19 @@ static float CallbackGetProgress(void* job); +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3) + static OrthancPluginErrorCode CallbackGetContent(OrthancPluginMemoryBuffer* target, + void* job); +#else static const char* CallbackGetContent(void* job); +#endif +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3) + static int32_t CallbackGetSerialized(OrthancPluginMemoryBuffer* target, + void* job); +#else static const char* CallbackGetSerialized(void* job); +#endif static OrthancPluginJobStepStatus CallbackStep(void* job); @@ -1191,6 +1264,11 @@ ~DicomInstance(); + const OrthancPluginDicomInstance* GetObject() const + { + return instance_; + } + std::string GetRemoteAet() const; const void* GetBuffer() const @@ -1245,5 +1323,114 @@ size_t size, const std::string& transferSyntax); #endif + +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 1) + static DicomInstance* Load(const std::string& instanceId, + OrthancPluginLoadDicomInstanceMode mode); +#endif }; + +// helper method to convert Http headers from the plugin SDK to a std::map +void GetHttpHeaders(std::map<std::string, std::string>& result, const OrthancPluginHttpRequest* request); + +#if HAS_ORTHANC_PLUGIN_WEBDAV == 1 + class IWebDavCollection : public boost::noncopyable + { + public: + class FileInfo + { + private: + std::string name_; + uint64_t contentSize_; + std::string mime_; + std::string dateTime_; + + public: + FileInfo(const std::string& name, + uint64_t contentSize, + const std::string& dateTime) : + name_(name), + contentSize_(contentSize), + dateTime_(dateTime) + { + } + + const std::string& GetName() const + { + return name_; + } + + uint64_t GetContentSize() const + { + return contentSize_; + } + + void SetMimeType(const std::string& mime) + { + mime_ = mime; + } + + const std::string& GetMimeType() const + { + return mime_; + } + + const std::string& GetDateTime() const + { + return dateTime_; + } + }; + + class FolderInfo + { + private: + std::string name_; + std::string dateTime_; + + public: + FolderInfo(const std::string& name, + const std::string& dateTime) : + name_(name), + dateTime_(dateTime) + { + } + + const std::string& GetName() const + { + return name_; + } + + const std::string& GetDateTime() const + { + return dateTime_; + } + }; + + virtual ~IWebDavCollection() + { + } + + virtual bool IsExistingFolder(const std::vector<std::string>& path) = 0; + + virtual bool ListFolder(std::list<FileInfo>& files, + std::list<FolderInfo>& subfolders, + const std::vector<std::string>& path) = 0; + + virtual bool GetFile(std::string& content /* out */, + std::string& mime /* out */, + std::string& dateTime /* out */, + const std::vector<std::string>& path) = 0; + + virtual bool StoreFile(const std::vector<std::string>& path, + const void* data, + size_t size) = 0; + + virtual bool CreateFolder(const std::vector<std::string>& path) = 0; + + virtual bool DeleteItem(const std::vector<std::string>& path) = 0; + + static void Register(const std::string& uri, + IWebDavCollection& collection); + }; +#endif }
--- a/Resources/Orthanc/Plugins/OrthancPluginException.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/Plugins/OrthancPluginException.h Wed Aug 30 14:46:39 2023 +0200 @@ -2,8 +2,8 @@ * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as
--- a/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU General Public License as
--- a/Resources/Orthanc/Toolchains/LinuxStandardBaseToolchain.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/Toolchains/LinuxStandardBaseToolchain.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License @@ -22,11 +22,11 @@ # # Full build, as used on the BuildBot CIS: # -# $ LSB_CC=gcc-4.8 LSB_CXX=g++-4.8 cmake ../OrthancServer/ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake -DUSE_LEGACY_JSONCPP=ON -DUSE_LEGACY_LIBICU=ON -DBOOST_LOCALE_BACKEND=icu -DENABLE_PKCS11=ON -G Ninja +# $ LSB_CC=gcc-4.8 LSB_CXX=g++-4.8 cmake ../OrthancServer/ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake -DUSE_LEGACY_JSONCPP=ON -DUSE_LEGACY_LIBICU=ON -DUSE_LEGACY_BOOST=ON -DBOOST_LOCALE_BACKEND=icu -DENABLE_PKCS11=ON -G Ninja # # Or, more lightweight version (without libp11 and ICU): # -# $ LSB_CC=gcc-4.8 LSB_CXX=g++-4.8 cmake ../OrthancServer/ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake -DUSE_LEGACY_JSONCPP=ON -G Ninja +# $ LSB_CC=gcc-4.8 LSB_CXX=g++-4.8 cmake ../OrthancServer/ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake -DUSE_LEGACY_JSONCPP=ON -DUSE_LEGACY_BOOST=ON -G Ninja # INCLUDE(CMakeForceCompiler)
--- a/Resources/Orthanc/Toolchains/MinGW-W64-Toolchain32.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/Toolchains/MinGW-W64-Toolchain32.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License
--- a/Resources/Orthanc/Toolchains/MinGW-W64-Toolchain64.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/Toolchains/MinGW-W64-Toolchain64.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License
--- a/Resources/Orthanc/Toolchains/MinGWToolchain.cmake Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/Orthanc/Toolchains/MinGWToolchain.cmake Wed Aug 30 14:46:39 2023 +0200 @@ -1,8 +1,8 @@ # Orthanc - A Lightweight, RESTful DICOM Store # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium -# Copyright (C) 2017-2022 Osimis S.A., Belgium -# Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2017-2023 Osimis S.A., Belgium +# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License
--- a/Resources/SyncOrthancFolder.py Wed Aug 30 14:46:07 2023 +0200 +++ b/Resources/SyncOrthancFolder.py Wed Aug 30 14:46:39 2023 +0200 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # This maintenance script updates the content of the "Orthanc" folder @@ -8,7 +8,7 @@ import multiprocessing import os import stat -import urllib2 +import urllib.request import subprocess TARGET = os.path.join(os.path.dirname(__file__), 'Orthanc') @@ -43,7 +43,7 @@ branch = x[0] source = x[1] target = os.path.join(TARGET, x[2]) - print target + print(target) try: os.makedirs(os.path.dirname(target)) @@ -52,8 +52,12 @@ url = '%s/%s/%s' % (REPOSITORY, branch, source) - with open(target, 'w') as f: - f.write(urllib2.urlopen(url).read()) + with open(target, 'wb') as f: + try: + f.write(urllib.request.urlopen(url).read()) + except: + print('ERROR %s' % url) + raise commands = []
--- a/Sources/Autogenerated/sdk.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_GlobalFunctions.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_GlobalFunctions.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginChangeType.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginChangeType.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginCompressionType.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginCompressionType.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginConstraintType.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginConstraintType.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginContentType.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginContentType.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginCreateDicomFlags.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginCreateDicomFlags.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomInstance.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginDicomInstance.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomToJsonFlags.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginDicomToJsonFlags.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomToJsonFormat.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginDicomToJsonFormat.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomWebBinaryMode.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginDicomWebBinaryMode.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomWebNode.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginDicomWebNode.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginErrorCode.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginErrorCode.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginFindAnswers.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginFindAnswers.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginFindMatcher.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginFindMatcher.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginFindQuery.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginFindQuery.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginHttpMethod.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginHttpMethod.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginIdentifierConstraint.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginIdentifierConstraint.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginImage.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginImage.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginImageFormat.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginImageFormat.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginInstanceOrigin.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginInstanceOrigin.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginJob.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginJob.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginJobStepStatus.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginJobStepStatus.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginJobStopReason.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginJobStopReason.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginMetricsType.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginMetricsType.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginPeers.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginPeers.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginPixelFormat.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginPixelFormat.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginReceivedInstanceAction.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginReceivedInstanceAction.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginResourceType.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginResourceType.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginRestOutput.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginRestOutput.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginServerChunkedRequestReader.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginServerChunkedRequestReader.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginStorageArea.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginStorageArea.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginStorageCommitmentFailureReason.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginStorageCommitmentFailureReason.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginValueRepresentation.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginValueRepresentation.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginWorklistAnswers.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginWorklistAnswers.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.impl.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.impl.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/DicomScpCallbacks.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/DicomScpCallbacks.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/DicomScpCallbacks.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/DicomScpCallbacks.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/ICallbackRegistration.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/ICallbackRegistration.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License @@ -58,6 +58,46 @@ } +PyObject *ICallbackRegistration::Apply2(ICallbackRegistration& registration, + PyObject* args, + PyObject*& singletonCallback1, + PyObject*& singletonCallback2, + const std::string& details) +{ + // https://docs.python.org/3/extending/extending.html#calling-python-functions-from-c + PyObject* callback1 = NULL; + PyObject* callback2 = NULL; + + if (!PyArg_ParseTuple(args, "OO", &callback1, &callback2) || + callback1 == NULL || callback2 == NULL) + { + const std::string message = "Expected two callback functions to register " + details; + PyErr_SetString(PyExc_ValueError, message.c_str()); + return NULL; + } + else if (singletonCallback1 != NULL || singletonCallback2 != NULL) + { + const std::string message = "Can only register once for " + details; + PyErr_SetString(PyExc_RuntimeError, message.c_str()); + return NULL; + } + else + { + OrthancPlugins::LogInfo("Registering callbacks " + details); + registration.Register(); + + singletonCallback1 = callback1; + Py_XINCREF(singletonCallback1); + + singletonCallback2 = callback2; + Py_XINCREF(singletonCallback2); + + Py_INCREF(Py_None); + return Py_None; + } +} + + void ICallbackRegistration::Unregister(PyObject*& singletonCallback) { PythonLock lock;
--- a/Sources/ICallbackRegistration.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/ICallbackRegistration.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License @@ -40,5 +40,12 @@ PyObject*& singletonCallback, const std::string& details); + // The GIL must be locked + static PyObject *Apply2(ICallbackRegistration& registration, + PyObject* args, + PyObject*& singletonCallback1, + PyObject*& singletonCallback2, + const std::string& details); + static void Unregister(PyObject*& singletonCallback); };
--- a/Sources/IncomingHttpRequestFilter.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/IncomingHttpRequestFilter.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/IncomingHttpRequestFilter.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/IncomingHttpRequestFilter.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/IncomingInstanceFilter.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/IncomingInstanceFilter.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/IncomingInstanceFilter.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/IncomingInstanceFilter.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/OnChangeCallback.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/OnChangeCallback.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/OnChangeCallback.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/OnChangeCallback.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/OnStoredInstanceCallback.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/OnStoredInstanceCallback.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/OnStoredInstanceCallback.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/OnStoredInstanceCallback.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/Plugin.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/Plugin.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License @@ -32,6 +32,7 @@ #include "IncomingInstanceFilter.h" #include "ReceivedInstanceCallback.h" #include "StorageArea.h" +#include "StorageCommitmentScpCallback.h" #include "RestCallbacks.h" #include "PythonModule.h" @@ -414,6 +415,15 @@ } /** + * New in release 4.1 + **/ + + { + PyMethodDef f = { "RegisterStorageCommitmentScpCallback", RegisterStorageCommitmentScpCallback, METH_VARARGS, "" }; + functions.push_back(f); + } + + /** * Append all the global functions that were automatically generated **/
--- a/Sources/PythonFunction.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonFunction.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonFunction.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonFunction.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonHeaderWrapper.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonHeaderWrapper.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonLock.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonLock.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonLock.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonLock.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonModule.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonModule.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonModule.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonModule.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** 2 * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonObject.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonObject.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonObject.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonObject.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonString.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonString.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/PythonString.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/PythonString.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/ReceivedInstanceCallback.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/ReceivedInstanceCallback.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/ReceivedInstanceCallback.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/ReceivedInstanceCallback.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/RestCallbacks.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/RestCallbacks.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/RestCallbacks.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/RestCallbacks.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/StorageArea.cpp Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/StorageArea.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- a/Sources/StorageArea.h Wed Aug 30 14:46:07 2023 +0200 +++ b/Sources/StorageArea.h Wed Aug 30 14:46:39 2023 +0200 @@ -1,7 +1,7 @@ /** * Python plugin for Orthanc - * Copyright (C) 2020-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sources/StorageCommitmentScpCallback.cpp Wed Aug 30 14:46:39 2023 +0200 @@ -0,0 +1,186 @@ +/** + * Python plugin for Orthanc + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "StorageCommitmentScpCallback.h" + +#include "../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h" +#include "ICallbackRegistration.h" +#include "PythonString.h" + + +static PyObject* storageCommitmentScpCallback_ = NULL; +static PyObject* storageCommitmentLookupCallback_ = NULL; + + +static OrthancPluginErrorCode StorageCommitmentSCPCallback( + void** handler /* out */, + const char* jobId, + const char* transactionUid, + const char* const* sopClassUids, + const char* const* sopInstanceUids, + uint32_t countInstances, + const char* remoteAet, + const char* calledAet) +{ + try + { + PythonLock lock; + + PythonObject args(lock, PyTuple_New(6)); + { + PythonString str(lock, jobId); + PyTuple_SetItem(args.GetPyObject(), 0, str.Release()); + } + { + PythonString str(lock, transactionUid); + PyTuple_SetItem(args.GetPyObject(), 1, str.Release()); + } + { + PythonObject sopClassUidList(lock, PyList_New(countInstances)); + for (uint32_t i = 0; i < countInstances; i++) + { + PythonString str(lock, sopClassUids[i]); + PyList_SetItem(sopClassUidList.GetPyObject(), i, str.Release()); + } + PyTuple_SetItem(args.GetPyObject(), 2, sopClassUidList.Release()); + PythonObject sopInstanceUidList(lock, PyList_New(countInstances)); + for (uint32_t i = 0; i < countInstances; i++) + { + PythonString str(lock, sopInstanceUids[i]); + PyList_SetItem(sopInstanceUidList.GetPyObject(), i, str.Release()); + } + PyTuple_SetItem(args.GetPyObject(), 3, sopInstanceUidList.Release()); + } + { + PythonString str(lock, remoteAet); + PyTuple_SetItem(args.GetPyObject(), 4, str.Release()); + } + { + PythonString str(lock, calledAet); + PyTuple_SetItem(args.GetPyObject(), 5, str.Release()); + } + + PythonObject result(lock, PyObject_CallObject(storageCommitmentScpCallback_, args.GetPyObject())); + *handler = result.Release(); + + std::string traceback; + if (lock.HasErrorOccurred(traceback)) + { + OrthancPlugins::LogError("Error in the Python storage commitment SCP callback, " + "traceback:\n" + traceback); + return OrthancPluginErrorCode_Plugin; + } + } + catch (OrthancPlugins::PluginException& e) + { + OrthancPlugins::LogError("Error in the Python storage commitment SCP callback: " + + std::string(e.What(OrthancPlugins::GetGlobalContext()))); + } + return OrthancPluginErrorCode_Success; +} + +static OrthancPluginErrorCode StorageCommitmentLookupCallback( + OrthancPluginStorageCommitmentFailureReason* target /* out */, + void* handler, + const char* sopClassUid, + const char* sopInstanceUid) +{ + try + { + PythonLock lock; + + PythonObject args(lock, PyTuple_New(3)); + { + PythonString str(lock, sopClassUid); + PyTuple_SetItem(args.GetPyObject(), 0, str.Release()); + } + { + PythonString str(lock, sopInstanceUid); + PyTuple_SetItem(args.GetPyObject(), 1, str.Release()); + } + { + PyObject* data = (PyObject*) handler; + Py_INCREF(data); // Keep a reference before it was stolen by PyTuple_SetItem. + PyTuple_SetItem(args.GetPyObject(), 2, data); + } + + PythonObject result(lock, PyObject_CallObject(storageCommitmentLookupCallback_, args.GetPyObject())); + + if (!PyLong_Check(result.GetPyObject())) + { + OrthancPlugins::LogError("The Python storage commitment Lookup callback has not returned an int as the return value"); + return OrthancPluginErrorCode_Plugin; + } + + *target = static_cast<OrthancPluginStorageCommitmentFailureReason>(PyLong_AsLong(result.GetPyObject())); + + std::string traceback; + if (lock.HasErrorOccurred(traceback)) + { + OrthancPlugins::LogError("Error in the Python storage commitment Lookup callback, " + "traceback:\n" + traceback); + return OrthancPluginErrorCode_Plugin; + } + } + catch (OrthancPlugins::PluginException& e) + { + OrthancPlugins::LogError("Error in the Python storage commitment Lookup callback: " + + std::string(e.What(OrthancPlugins::GetGlobalContext()))); + } + return OrthancPluginErrorCode_Success; +} + +static void StorageCommitmentDestructor(void *handler) +{ + PythonLock lock; + Py_DECREF((PyObject*)handler); // Release the reference +} + +PyObject* RegisterStorageCommitmentScpCallback(PyObject* module, PyObject* args) +{ + // The GIL is locked at this point (no need to create "PythonLock") + + class Registration : public ICallbackRegistration + { + public: + virtual void Register() ORTHANC_OVERRIDE + { + OrthancPluginRegisterStorageCommitmentScpCallback( + OrthancPlugins::GetGlobalContext(), + StorageCommitmentSCPCallback, + StorageCommitmentDestructor, + StorageCommitmentLookupCallback); + } + }; + + { + Registration registration; + return ICallbackRegistration::Apply2(registration, args, + storageCommitmentScpCallback_, + storageCommitmentLookupCallback_, + "Python storage commitment SCP & Lookup callback"); + } +} + +void FinalizeStorageCommitmentScpCallback() +{ + ICallbackRegistration::Unregister(storageCommitmentScpCallback_); + ICallbackRegistration::Unregister(storageCommitmentLookupCallback_); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sources/StorageCommitmentScpCallback.h Wed Aug 30 14:46:39 2023 +0200 @@ -0,0 +1,27 @@ +/** + * Python plugin for Orthanc + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "PythonHeaderWrapper.h" + +PyObject* RegisterStorageCommitmentScpCallback(PyObject* module, PyObject* args); + +void FinalizeStorageCommitmentScpCallback(); \ No newline at end of file
