Mercurial > hg > orthanc
changeset 6182:0d540324c14f attach-custom-data
integration mainline->attach-custom-data
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 12 Jun 2025 12:29:39 +0200 |
parents | 8bd3a683778d (current diff) 39efb66b8322 (diff) |
children | 7f985407c885 |
files | OrthancServer/CMakeLists.txt OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Engine/OrthancPlugins.h OrthancServer/Sources/ServerContext.cpp |
diffstat | 9 files changed, 640 insertions(+), 271 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/CMakeLists.txt Wed Jun 11 20:51:30 2025 +0200 +++ b/OrthancServer/CMakeLists.txt Thu Jun 12 12:29:39 2025 +0200 @@ -203,6 +203,8 @@ ${CMAKE_SOURCE_DIR}/Plugins/Engine/OrthancPluginDatabaseV3.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/OrthancPluginDatabaseV4.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/OrthancPlugins.cpp + ${CMAKE_SOURCE_DIR}/Plugins/Engine/PluginMemoryBuffer32.cpp + ${CMAKE_SOURCE_DIR}/Plugins/Engine/PluginMemoryBuffer64.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/PluginsEnumerations.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/PluginsErrorDictionary.cpp ${CMAKE_SOURCE_DIR}/Plugins/Engine/PluginsJob.cpp
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Wed Jun 11 20:51:30 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Thu Jun 12 12:29:39 2025 +0200 @@ -65,6 +65,7 @@ #include "OrthancPluginDatabase.h" #include "OrthancPluginDatabaseV3.h" #include "OrthancPluginDatabaseV4.h" +#include "PluginMemoryBuffer32.h" #include "PluginsEnumerations.h" #include "PluginsJob.h" @@ -536,78 +537,45 @@ }; - static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target, + static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer* target, const void* data, size_t size) { - if (static_cast<uint32_t>(size) != size) - { - throw OrthancException(ErrorCode_NotEnoughMemory, ERROR_MESSAGE_64BIT); - } - - target.size = size; - - if (size == 0) - { - target.data = NULL; - } - else - { - target.data = malloc(size); - if (target.data != NULL) - { - memcpy(target.data, data, size); - } - else - { - throw OrthancException(ErrorCode_NotEnoughMemory); - } - } + PluginMemoryBuffer32 buffer; + buffer.Assign(data, size); + buffer.Release(target); } - static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target, + static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer* target, const std::string& str) { - if (str.size() == 0) - { - target.size = 0; - target.data = NULL; - } - else - { - CopyToMemoryBuffer(target, str.c_str(), str.size()); - } + PluginMemoryBuffer32 buffer; + buffer.Assign(str); + buffer.Release(target); } static char* CopyString(const std::string& str) { - if (static_cast<uint32_t>(str.size()) != str.size()) - { - throw OrthancException(ErrorCode_NotEnoughMemory, ERROR_MESSAGE_64BIT); - } - char *result = reinterpret_cast<char*>(malloc(str.size() + 1)); if (result == NULL) { throw OrthancException(ErrorCode_NotEnoughMemory); } - if (str.size() == 0) - { - result[0] = '\0'; - } - else - { - memcpy(result, &str[0], str.size() + 1); - } + if (!str.empty()) + { + memcpy(result, str.c_str(), str.size()); + } + + result[str.size() - 1] = '\0'; // Add the null terminator of the string return result; } - static void CopyDictionary(OrthancPluginMemoryBuffer& target, + static void CopyDictionary(PluginMemoryBuffer32& target, const std::map<std::string, std::string>& dictionary) { Json::Value json = Json::objectValue; @@ -618,58 +586,12 @@ json[it->first] = it->second; } - std::string s = json.toStyledString(); - CopyToMemoryBuffer(target, s); + target.Assign(json.toStyledString()); } namespace { - class MemoryBufferRaii : public boost::noncopyable - { - private: - OrthancPluginMemoryBuffer buffer_; - - public: - MemoryBufferRaii() - { - buffer_.size = 0; - buffer_.data = NULL; - } - - ~MemoryBufferRaii() - { - if (buffer_.size != 0) - { - free(buffer_.data); - } - } - - OrthancPluginMemoryBuffer* GetObject() - { - return &buffer_; - } - - void ToString(std::string& target) const - { - if ((buffer_.data == NULL && buffer_.size != 0) || - (buffer_.data != NULL && buffer_.size == 0)) - { - throw OrthancException(ErrorCode_Plugin); - } - else - { - target.resize(buffer_.size); - - if (buffer_.size != 0) - { - memcpy(&target[0], buffer_.data, buffer_.size); - } - } - } - }; - - static IMemoryBuffer* GetRangeFromWhole(std::unique_ptr<MallocMemoryBuffer>& whole, uint64_t start /* inclusive */, uint64_t end /* exclusive */) @@ -863,30 +785,27 @@ } else { + std::unique_ptr<PluginMemoryBuffer64> buffer(new PluginMemoryBuffer64); + if (start > end) { throw OrthancException(ErrorCode_BadRange); } else if (start == end) { - return new StringMemoryBuffer; + return buffer.release(); } else { - std::string range; - range.resize(end - start); - assert(!range.empty()); - - OrthancPluginMemoryBuffer64 buffer; - buffer.data = &range[0]; - buffer.size = static_cast<uint64_t>(range.size()); + buffer->Resize(end - start); + assert(buffer->GetSize() > 0); OrthancPluginErrorCode error = - readRange_(&buffer, uuid.c_str(), Plugins::Convert(type), start); + readRange_(buffer->GetObject(), uuid.c_str(), Plugins::Convert(type), start); if (error == OrthancPluginErrorCode_Success) { - return StringMemoryBuffer::CreateFromSwap(range); + return buffer.release(); } else { @@ -944,7 +863,7 @@ CompressionType compression, const DicomInstanceToStore* dicomInstance /* can be NULL if not a DICOM instance */) ORTHANC_OVERRIDE { - MemoryBufferRaii customDataBuffer; + PluginMemoryBuffer32 customDataBuffer; OrthancPluginErrorCode error; if (dicomInstance != NULL) @@ -965,7 +884,7 @@ } else { - customDataBuffer.ToString(customData); + customDataBuffer.MoveToString(customData); } } @@ -1954,7 +1873,7 @@ } } - void GetDicomQuery(OrthancPluginMemoryBuffer& target) const + void GetDicomQuery(OrthancPluginMemoryBuffer* target) const { if (currentQuery_ == NULL) { @@ -2855,32 +2774,22 @@ } - OrthancPluginReceivedInstanceAction OrthancPlugins::ApplyReceivedInstanceCallbacks( - MallocMemoryBuffer& modified, - const void* receivedDicom, - size_t receivedDicomSize, - RequestOrigin origin) + OrthancPluginReceivedInstanceAction OrthancPlugins::ApplyReceivedInstanceCallbacks(PluginMemoryBuffer64& modified, + const void* receivedDicom, + size_t receivedDicomSize, + RequestOrigin origin) { boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_); + modified.Clear(); + if (pimpl_->receivedInstanceCallback_ == NULL) { return OrthancPluginReceivedInstanceAction_KeepAsIs; } else { - OrthancPluginReceivedInstanceAction action; - - { - OrthancPluginMemoryBuffer64 buffer; - buffer.size = 0; - buffer.data = NULL; - - action = (*pimpl_->receivedInstanceCallback_) (&buffer, receivedDicom, receivedDicomSize, Plugins::Convert(origin)); - modified.Assign(buffer.data, buffer.size, ::free); - } - - return action; + return (*pimpl_->receivedInstanceCallback_) (modified.GetObject(), receivedDicom, receivedDicomSize, Plugins::Convert(origin)); } } @@ -3344,7 +3253,7 @@ lock.GetContext().ReadDicom(dicom, p.instanceId); } - CopyToMemoryBuffer(*p.target, dicom); + CopyToMemoryBuffer(p.target, dicom); } static void ThrowOnHttpError(HttpStatus httpStatus) @@ -3394,7 +3303,7 @@ std::string result; ThrowOnHttpError(IHttpHandler::SimpleGet(result, NULL, *handler, RequestOrigin_Plugins, p.uri, httpHeaders)); - CopyToMemoryBuffer(*p.target, result); + CopyToMemoryBuffer(p.target, result); } @@ -3425,7 +3334,7 @@ std::string result; ThrowOnHttpError(IHttpHandler::SimpleGet(result, NULL, *handler, RequestOrigin_Plugins, p.uri, headers)); - CopyToMemoryBuffer(*p.target, result); + CopyToMemoryBuffer(p.target, result); } @@ -3455,7 +3364,7 @@ p.body, p.bodySize, httpHeaders) : IHttpHandler::SimplePut(result, NULL, *handler, RequestOrigin_Plugins, p.uri, p.body, p.bodySize, httpHeaders))); - CopyToMemoryBuffer(*p.target, result); + CopyToMemoryBuffer(p.target, result); } @@ -3737,7 +3646,7 @@ case OrthancPluginCompressionType_None: { - CopyToMemoryBuffer(*p.target, p.source, p.size); + CopyToMemoryBuffer(p.target, p.source, p.size); return; } @@ -3755,7 +3664,7 @@ } } - CopyToMemoryBuffer(*p.target, result); + CopyToMemoryBuffer(p.target, result); } @@ -3816,7 +3725,7 @@ MimeType mime; std::string frame; instance.GetParsedDicomFile().GetRawFrame(frame, mime, p.frameIndex); - CopyToMemoryBuffer(*p.targetBuffer, frame); + CopyToMemoryBuffer(p.targetBuffer, frame); return; } @@ -3846,7 +3755,7 @@ p.targetBuffer->data = NULL; p.targetBuffer->size = 0; - CopyToMemoryBuffer(*p.targetBuffer, instance.GetBufferData(), instance.GetBufferSize()); + CopyToMemoryBuffer(p.targetBuffer, instance.GetBufferData(), instance.GetBufferSize()); return; } @@ -3955,7 +3864,7 @@ throw OrthancException(ErrorCode_ParameterOutOfRange); } - CopyToMemoryBuffer(*p.target, compressed); + CopyToMemoryBuffer(p.target, compressed); } @@ -4052,29 +3961,29 @@ } // Copy the HTTP headers of the answer, if the plugin requested them + PluginMemoryBuffer32 tmpHeaders; if (answerHeaders != NULL) { - CopyDictionary(*answerHeaders, headers); + CopyDictionary(tmpHeaders, headers); } // Copy the body of the answer if it makes sense - if (client.GetMethod() != HttpMethod_Delete) - { - try - { - if (answerBody != NULL) - { - CopyToMemoryBuffer(*answerBody, body); - } - } - catch (OrthancException&) - { - if (answerHeaders != NULL) - { - free(answerHeaders->data); - } - throw; - } + PluginMemoryBuffer32 tmpBody; + if (client.GetMethod() != HttpMethod_Delete && + answerBody != NULL) + { + tmpBody.Assign(body); + } + + // All the memory has been allocated at this point, so we can safely release the buffers + if (answerHeaders != NULL) + { + tmpHeaders.Release(answerHeaders); + } + + if (answerBody != NULL) + { + tmpBody.Release(answerBody); } } @@ -4273,25 +4182,28 @@ *p.httpStatus = static_cast<uint16_t>(status); + PluginMemoryBuffer32 tmpHeaders; if (p.answerHeaders != NULL) { - CopyDictionary(*p.answerHeaders, answerHeaders); - } - - try - { - if (p.answerBody != NULL) - { - CopyToMemoryBuffer(*p.answerBody, answerBody); - } - } - catch (OrthancException&) - { - if (p.answerHeaders != NULL) - { - free(p.answerHeaders->data); - } - throw; + CopyDictionary(tmpHeaders, answerHeaders); + } + + PluginMemoryBuffer32 tmpBody; + if (p.method != OrthancPluginHttpMethod_Delete && + p.answerBody != NULL) + { + tmpBody.Assign(answerBody); + } + + // All the memory has been allocated at this point, so we can safely release the buffers + if (p.answerHeaders != NULL) + { + tmpHeaders.Release(p.answerHeaders); + } + + if (p.answerBody != NULL) + { + tmpBody.Release(p.answerBody); } } @@ -4358,29 +4270,29 @@ } // Copy the HTTP headers of the answer, if the plugin requested them + PluginMemoryBuffer32 tmpHeaders; if (p.answerHeaders != NULL) { - CopyDictionary(*p.answerHeaders, headers); + CopyDictionary(tmpHeaders, headers); } // Copy the body of the answer if it makes sense - if (p.method != OrthancPluginHttpMethod_Delete) - { - try - { - if (p.answerBody != NULL) - { - CopyToMemoryBuffer(*p.answerBody, body); - } - } - catch (OrthancException&) - { - if (p.answerHeaders != NULL) - { - free(p.answerHeaders->data); - } - throw; - } + PluginMemoryBuffer32 tmpBody; + if (p.method != OrthancPluginHttpMethod_Delete && + p.answerBody != NULL) + { + tmpBody.Assign(body); + } + + // All the memory has been allocated at this point, so we can safely release the buffers + if (p.answerHeaders != NULL) + { + tmpHeaders.Release(p.answerHeaders); + } + + if (p.answerBody != NULL) + { + tmpBody.Release(p.answerBody); } } @@ -4521,7 +4433,7 @@ file->SaveToMemoryBuffer(dicom); } - CopyToMemoryBuffer(*parameters.target, dicom); + CopyToMemoryBuffer(parameters.target, dicom); } @@ -4680,8 +4592,8 @@ ServerContext::StoreResult result = lock.GetContext().AdoptAttachment(resultPublicId, *dicom, StoreInstanceMode_Default, adoptedFile); - CopyToMemoryBuffer(*parameters.attachmentUuid, adoptedFile.GetUuid()); - CopyToMemoryBuffer(*parameters.createdResourceId, resultPublicId); + CopyToMemoryBuffer(parameters.attachmentUuid, adoptedFile.GetUuid()); + CopyToMemoryBuffer(parameters.createdResourceId, resultPublicId); *(parameters.storeStatus) = Plugins::Convert(result.GetStatus()); } } @@ -4705,7 +4617,7 @@ if (lock.GetContext().GetIndex().GetAttachment(fileInfo, revision, parameters.attachmentUuid)) { - CopyToMemoryBuffer(*parameters.customData, fileInfo.GetCustomData()); + CopyToMemoryBuffer(parameters.customData, fileInfo.GetCustomData()); } else { @@ -4758,7 +4670,7 @@ if (lock.GetContext().GetIndex().GetKeyValue(value, parameters.storeId, parameters.key)) { - CopyToMemoryBuffer(*parameters.target, value); + CopyToMemoryBuffer(parameters.target, value); *parameters.found = true; } else @@ -4804,7 +4716,7 @@ if (lock.GetContext().GetIndex().DequeueValue(value, parameters.queueId, Plugins::Convert(parameters.origin))) { - CopyToMemoryBuffer(*parameters.target, value); + CopyToMemoryBuffer(parameters.target, value); *parameters.found = true; } else @@ -5270,7 +5182,7 @@ std::string content; SystemToolbox::ReadFile(content, p.path); - CopyToMemoryBuffer(*p.target, content); + CopyToMemoryBuffer(p.target, content); return true; } @@ -5446,7 +5358,7 @@ { const _OrthancPluginWorklistQueryOperation& p = *reinterpret_cast<const _OrthancPluginWorklistQueryOperation*>(parameters); - reinterpret_cast<const WorklistHandler*>(p.query)->GetDicomQuery(*p.target); + reinterpret_cast<const WorklistHandler*>(p.query)->GetDicomQuery(p.target); return true; } @@ -5829,20 +5741,10 @@ const _OrthancPluginCreateMemoryBuffer& p = *reinterpret_cast<const _OrthancPluginCreateMemoryBuffer*>(parameters); - p.target->data = NULL; - p.target->size = 0; - - if (p.size != 0) - { - p.target->data = malloc(p.size); - if (p.target->data == NULL) - { - throw OrthancException(ErrorCode_NotEnoughMemory); - } - - p.target->size = p.size; - } - + PluginMemoryBuffer32 buffer; + buffer.Resize(p.size); + buffer.Release(p.target); + return true; } @@ -5851,19 +5753,9 @@ const _OrthancPluginCreateMemoryBuffer64& p = *reinterpret_cast<const _OrthancPluginCreateMemoryBuffer64*>(parameters); - p.target->data = NULL; - p.target->size = 0; - - if (p.size != 0) - { - p.target->data = malloc(p.size); - if (p.target->data == NULL) - { - throw OrthancException(ErrorCode_NotEnoughMemory); - } - - p.target->size = p.size; - } + PluginMemoryBuffer64 buffer; + buffer.Resize(p.size); + buffer.Release(p.target); return true; } @@ -5966,7 +5858,7 @@ { const _OrthancPluginKeysValuesIteratorGetValue& p = *reinterpret_cast<const _OrthancPluginKeysValuesIteratorGetValue*>(parameters); StatelessDatabaseOperations::KeysValuesIterator& iterator = *reinterpret_cast<StatelessDatabaseOperations::KeysValuesIterator*>(p.iterator); - CopyToMemoryBuffer(*p.target, iterator.GetValue()); + CopyToMemoryBuffer(p.target, iterator.GetValue()); return true; } @@ -6910,13 +6802,13 @@ transcoder = pimpl_->transcoderCallbacks_.begin(); transcoder != pimpl_->transcoderCallbacks_.end(); ++transcoder) { - MemoryBufferRaii a; + PluginMemoryBuffer32 a; if ((*transcoder) (a.GetObject(), buffer, size, uids.empty() ? NULL : &uids[0], static_cast<uint32_t>(uids.size()), allowNewSopInstanceUid) == OrthancPluginErrorCode_Success) { - a.ToString(target); + a.MoveToString(target); return true; } }
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.h Wed Jun 11 20:51:30 2025 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.h Thu Jun 12 12:29:39 2025 +0200 @@ -56,6 +56,7 @@ #include "../../Sources/IDicomImageDecoder.h" #include "../../Sources/IServerListener.h" #include "../../Sources/ServerJobs/IStorageCommitmentFactory.h" +#include "PluginMemoryBuffer64.h" #include "PluginsManager.h" #include <list> @@ -307,7 +308,7 @@ const DicomInstanceToStore& instance, const Json::Value& simplified) ORTHANC_OVERRIDE; - OrthancPluginReceivedInstanceAction ApplyReceivedInstanceCallbacks(MallocMemoryBuffer& modified, + OrthancPluginReceivedInstanceAction ApplyReceivedInstanceCallbacks(PluginMemoryBuffer64& modified, const void* receivedDicomBuffer, size_t receivedDicomBufferSize, RequestOrigin origin);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Engine/PluginMemoryBuffer32.cpp Thu Jun 12 12:29:39 2025 +0200 @@ -0,0 +1,200 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2025 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 + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "../../Sources/PrecompiledHeadersServer.h" +#include "PluginMemoryBuffer32.h" + +#include "../../../OrthancFramework/Sources/OrthancException.h" +#include "../../../OrthancFramework/Sources/Toolbox.h" + +#define ERROR_MESSAGE_64BIT "A 64bit version of the Orthanc SDK is necessary to use buffers > 4GB, but is currently not available" + + +namespace Orthanc +{ + void PluginMemoryBuffer32::Clear() + { + if (buffer_.size != 0) + { + ::free(buffer_.data); + } + + buffer_.data = NULL; + buffer_.size = 0; + } + + + void PluginMemoryBuffer32::SanityCheck() const + { + if ((buffer_.data == NULL && buffer_.size != 0) || + (buffer_.data != NULL && buffer_.size == 0)) + { + throw OrthancException(ErrorCode_Plugin); + } + } + + + PluginMemoryBuffer32::PluginMemoryBuffer32() + { + buffer_.size = 0; + buffer_.data = NULL; + } + + + void PluginMemoryBuffer32::MoveToString(std::string& target) + { + SanityCheck(); + + target.resize(buffer_.size); + + if (buffer_.size != 0) + { + memcpy(&target[0], buffer_.data, buffer_.size); + } + + Clear(); + } + + + const void* PluginMemoryBuffer32::GetData() const + { + SanityCheck(); + + if (buffer_.size == 0) + { + return NULL; + } + else + { + return buffer_.data; + } + } + + + size_t PluginMemoryBuffer32::GetSize() const + { + SanityCheck(); + return buffer_.size; + } + + + void PluginMemoryBuffer32::Release(OrthancPluginMemoryBuffer* target) + { + SanityCheck(); + + if (target == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + + target->data = buffer_.data; + target->size = buffer_.size; + + buffer_.data = NULL; + buffer_.size = 0; + } + + + void PluginMemoryBuffer32::Release(OrthancPluginMemoryBuffer64* target) + { + SanityCheck(); + + if (target == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + + target->data = buffer_.data; + target->size = buffer_.size; + + buffer_.data = NULL; + buffer_.size = 0; + } + + + void PluginMemoryBuffer32::Resize(size_t size) + { + if (static_cast<size_t>(static_cast<uint32_t>(size)) != size) + { + throw OrthancException(ErrorCode_NotEnoughMemory, ERROR_MESSAGE_64BIT); + } + + if (size != buffer_.size) + { + Clear(); + + if (size == 0) + { + buffer_.data = NULL; + } + else + { + buffer_.data = ::malloc(size); + + if (buffer_.data == NULL) + { + throw OrthancException(ErrorCode_NotEnoughMemory); + } + } + + buffer_.size = size; + } + } + + + void PluginMemoryBuffer32::Assign(const void* data, + size_t size) + { + Resize(size); + + if (size != 0) + { + memcpy(buffer_.data, data, size); + } + } + + + void PluginMemoryBuffer32::Assign(const std::string& data) + { + if (data.empty()) + { + Assign(NULL, 0); + } + else + { + Assign(data.c_str(), data.size()); + } + } + + + void PluginMemoryBuffer32::ToJsonObject(Json::Value& target) const + { + SanityCheck(); + + if (!Toolbox::ReadJson(target, buffer_.data, buffer_.size) || + target.type() != Json::objectValue) + { + throw OrthancException(ErrorCode_Plugin, "The plugin has not provided a valid JSON object"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Engine/PluginMemoryBuffer32.h Thu Jun 12 12:29:39 2025 +0200 @@ -0,0 +1,78 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2025 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 + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#if ORTHANC_ENABLE_PLUGINS != 1 +# error The plugin support is disabled +#endif + +#include "../../../OrthancFramework/Sources/MallocMemoryBuffer.h" +#include "../Include/orthanc/OrthancCPlugin.h" + +#include <json/value.h> + +namespace Orthanc +{ + class PluginMemoryBuffer32 : public IMemoryBuffer + { + private: + OrthancPluginMemoryBuffer buffer_; + + void SanityCheck() const; + + public: + PluginMemoryBuffer32(); + + virtual ~PluginMemoryBuffer32() + { + Clear(); + } + + virtual void MoveToString(std::string& target) ORTHANC_OVERRIDE; + + virtual const void* GetData() const ORTHANC_OVERRIDE; + + virtual size_t GetSize() const ORTHANC_OVERRIDE; + + OrthancPluginMemoryBuffer* GetObject() + { + return &buffer_; + } + + void Release(OrthancPluginMemoryBuffer* target); + + void Release(OrthancPluginMemoryBuffer64* target); + + void Clear(); + + void Resize(size_t size); + + void Assign(const void* data, + size_t size); + + void Assign(const std::string& data); + + void ToJsonObject(Json::Value& target) const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Engine/PluginMemoryBuffer64.cpp Thu Jun 12 12:29:39 2025 +0200 @@ -0,0 +1,163 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2025 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 + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "../../Sources/PrecompiledHeadersServer.h" +#include "PluginMemoryBuffer64.h" + +#include "../../../OrthancFramework/Sources/OrthancException.h" + + +namespace Orthanc +{ + void PluginMemoryBuffer64::Clear() + { + if (buffer_.size != 0) + { + ::free(buffer_.data); + } + + buffer_.data = NULL; + buffer_.size = 0; + } + + + void PluginMemoryBuffer64::SanityCheck() const + { + if ((buffer_.data == NULL && buffer_.size != 0) || + (buffer_.data != NULL && buffer_.size == 0)) + { + throw OrthancException(ErrorCode_Plugin); + } + } + + + PluginMemoryBuffer64::PluginMemoryBuffer64() + { + buffer_.size = 0; + buffer_.data = NULL; + } + + + void PluginMemoryBuffer64::MoveToString(std::string& target) + { + SanityCheck(); + + target.resize(buffer_.size); + + if (buffer_.size != 0) + { + memcpy(&target[0], buffer_.data, buffer_.size); + } + + Clear(); + } + + + const void* PluginMemoryBuffer64::GetData() const + { + SanityCheck(); + + if (buffer_.size == 0) + { + return NULL; + } + else + { + return buffer_.data; + } + } + + + size_t PluginMemoryBuffer64::GetSize() const + { + SanityCheck(); + return buffer_.size; + } + + + void PluginMemoryBuffer64::Release(OrthancPluginMemoryBuffer64* target) + { + SanityCheck(); + + if (target == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + + target->data = buffer_.data; + target->size = buffer_.size; + + buffer_.data = NULL; + buffer_.size = 0; + } + + + void PluginMemoryBuffer64::Resize(size_t size) + { + if (size != buffer_.size) + { + Clear(); + + if (size == 0) + { + buffer_.data = NULL; + } + else + { + buffer_.data = ::malloc(size); + + if (buffer_.data == NULL) + { + throw OrthancException(ErrorCode_NotEnoughMemory); + } + } + + buffer_.size = size; + } + } + + + void PluginMemoryBuffer64::Assign(const void* data, + size_t size) + { + Resize(size); + + if (size != 0) + { + memcpy(buffer_.data, data, size); + } + } + + + void PluginMemoryBuffer64::Assign(const std::string& data) + { + if (data.empty()) + { + Assign(NULL, 0); + } + else + { + Assign(data.c_str(), data.size()); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Engine/PluginMemoryBuffer64.h Thu Jun 12 12:29:39 2025 +0200 @@ -0,0 +1,74 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2025 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 + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#if ORTHANC_ENABLE_PLUGINS != 1 +# error The plugin support is disabled +#endif + +#include "../../../OrthancFramework/Sources/MallocMemoryBuffer.h" +#include "../Include/orthanc/OrthancCPlugin.h" + +#include <json/value.h> + +namespace Orthanc +{ + class PluginMemoryBuffer64 : public IMemoryBuffer + { + private: + OrthancPluginMemoryBuffer64 buffer_; + + void SanityCheck() const; + + public: + PluginMemoryBuffer64(); + + virtual ~PluginMemoryBuffer64() + { + Clear(); + } + + virtual void MoveToString(std::string& target) ORTHANC_OVERRIDE; + + virtual const void* GetData() const ORTHANC_OVERRIDE; + + virtual size_t GetSize() const ORTHANC_OVERRIDE; + + OrthancPluginMemoryBuffer64* GetObject() + { + return &buffer_; + } + + void Release(OrthancPluginMemoryBuffer64* target); + + void Clear(); + + void Resize(size_t size); + + void Assign(const void* data, + size_t size); + + void Assign(const std::string& data); + }; +}
--- a/OrthancServer/Plugins/Engine/PluginsJob.cpp Wed Jun 11 20:51:30 2025 +0200 +++ b/OrthancServer/Plugins/Engine/PluginsJob.cpp Thu Jun 12 12:29:39 2025 +0200 @@ -32,6 +32,7 @@ #include "../../../OrthancFramework/Sources/Logging.h" #include "../../../OrthancFramework/Sources/OrthancException.h" #include "../../../OrthancFramework/Sources/Toolbox.h" +#include "PluginMemoryBuffer32.h" #include <cassert> @@ -152,53 +153,11 @@ return parameters_.getProgress(parameters_.job); } - - namespace - { - class MemoryBufferRaii : public boost::noncopyable - { - private: - OrthancPluginMemoryBuffer buffer_; - - public: - MemoryBufferRaii() - { - buffer_.size = 0; - buffer_.data = NULL; - } - - ~MemoryBufferRaii() - { - if (buffer_.size != 0) - { - free(buffer_.data); - } - } - - OrthancPluginMemoryBuffer* GetObject() - { - return &buffer_; - } - - void ToJsonObject(Json::Value& target) const - { - if ((buffer_.data == NULL && buffer_.size != 0) || - (buffer_.data != NULL && buffer_.size == 0) || - !Toolbox::ReadJson(target, buffer_.data, buffer_.size) || - target.type() != Json::objectValue) - { - throw OrthancException(ErrorCode_Plugin, - "A job plugin must provide a JSON object as its public content and as its serialization"); - } - } - }; - } - void PluginsJob::GetPublicContent(Json::Value& value) const { if (parameters_.getContent != NULL) { - MemoryBufferRaii target; + PluginMemoryBuffer32 target; OrthancPluginErrorCode code = parameters_.getContent(target.GetObject(), parameters_.job); @@ -236,7 +195,7 @@ { if (parameters_.getSerialized != NULL) { - MemoryBufferRaii target; + PluginMemoryBuffer32 target; int32_t code = parameters_.getContent(target.GetObject(), parameters_.job);
--- a/OrthancServer/Sources/ServerContext.cpp Wed Jun 11 20:51:30 2025 +0200 +++ b/OrthancServer/Sources/ServerContext.cpp Thu Jun 12 12:29:39 2025 +0200 @@ -910,7 +910,7 @@ // WARNING: The scope of "modifiedBuffer" and "modifiedDicom" must // be the same as that of "dicom" - MallocMemoryBuffer modifiedBuffer; + PluginMemoryBuffer64 modifiedBuffer; std::unique_ptr<DicomInstanceToStore> modifiedDicom; #if ORTHANC_ENABLE_PLUGINS == 1