Mercurial > hg > orthanc-object-storage
changeset 197:df0b6998fd27
integration 2.3.0: back to mainline
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 25 Jun 2024 12:38:31 +0200 |
parents | 6987a96423c7 (diff) addccb7ad900 (current diff) |
children | 63d0ffa8e2f2 |
files | Aws/AwsS3StoragePlugin.cpp Aws/CMakeLists.txt Azure/CMakeLists.txt Common/StoragePlugin.cpp Google/CMakeLists.txt NEWS |
diffstat | 60 files changed, 1489 insertions(+), 341 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Tue Nov 21 09:50:24 2023 +0100 +++ b/.hgignore Tue Jun 25 12:38:31 2024 +0200 @@ -2,4 +2,6 @@ CMakeLists.txt.user* *~ */ThirdPartyDownloads/* -.vscode/ \ No newline at end of file +.vscode/ +*.orig +Aws/i/
--- a/AUTHORS Tue Nov 21 09:50:24 2023 +0100 +++ b/AUTHORS Tue Jun 25 12:38:31 2024 +0200 @@ -5,7 +5,23 @@ Authors ------- -* Osimis <info@osimis.io> +* Sebastien Jodogne <s.jodogne@orthanc-labs.com> + + Overall design and lead developer. + +* Osimis S.A. Quai Banning 6 - 4000 Liège + 4000 Liege + Belgium + +* Orthanc Team SRL <info@orthanc.team> + Rue Joseph Marchal 14 + 4910 Theux Belgium + https://orthanc.team/ + +* ICTEAM, UCLouvain + Place de l'Universite 1 + 1348 Ottignies-Louvain-la-Neuve + Belgium + https://uclouvain.be/icteam
--- a/Aws/AwsS3StoragePlugin.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Aws/AwsS3StoragePlugin.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -17,6 +19,7 @@ **/ #include "AwsS3StoragePlugin.h" +#include <Logging.h> #include <aws/core/Aws.h> #include <aws/s3/S3Client.h> @@ -26,6 +29,9 @@ #include <aws/s3/model/DeleteObjectRequest.h> #include <aws/core/auth/AWSCredentialsProvider.h> #include <aws/core/utils/HashingUtils.h> +#include <aws/core/utils/logging/DefaultLogSystem.h> +#include <aws/core/utils/logging/DefaultCRTLogSystem.h> +#include <aws/core/utils/logging/AWSLogging.h> #include <aws/core/utils/memory/stl/AWSStreamFwd.h> #include <aws/core/utils/memory/stl/AWSStringStream.h> #include <aws/core/utils/memory/AWSMemory.h> @@ -33,6 +39,7 @@ #include <aws/core/utils/StringUtils.h> #include <aws/transfer/TransferManager.h> #include <aws/crt/Api.h> +#include <iostream> #include <fstream> #include <boost/lexical_cast.hpp> @@ -59,10 +66,14 @@ virtual ~AwsS3StoragePlugin(); - virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual bool HasFileExists() {return false;}; + virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + + virtual bool HasFileExists() ORTHANC_OVERRIDE + { + return false; + } }; @@ -84,7 +95,7 @@ { } - virtual void Write(const char* data, size_t size) + virtual void Write(const char* data, size_t size) ORTHANC_OVERRIDE { Aws::S3::Model::PutObjectRequest putObjectRequest; @@ -132,7 +143,7 @@ } - virtual size_t GetSize() + virtual size_t GetSize() ORTHANC_OVERRIDE { std::string firstExceptionMessage; @@ -154,12 +165,12 @@ throw StoragePluginException(firstExceptionMessage); } - virtual void ReadWhole(char* data, size_t size) + virtual void ReadWhole(char* data, size_t size) ORTHANC_OVERRIDE { _Read(data, size, 0, false); } - virtual void ReadRange(char* data, size_t size, size_t fromOffset) + virtual void ReadRange(char* data, size_t size, size_t fromOffset) ORTHANC_OVERRIDE { _Read(data, size, fromOffset, true); } @@ -276,7 +287,7 @@ { } - virtual void Write(const char* data, size_t size) + virtual void Write(const char* data, size_t size) ORTHANC_OVERRIDE { boost::interprocess::bufferstream buffer(const_cast<char*>(static_cast<const char*>(data)), static_cast<size_t>(size)); std::shared_ptr<Aws::IOStream> body = Aws::MakeShared<Aws::IOStream>(ALLOCATION_TAG, buffer.rdbuf()); @@ -308,7 +319,7 @@ } - virtual void ReadWhole(char* data, size_t size) + virtual void ReadWhole(char* data, size_t size) ORTHANC_OVERRIDE { std::string firstExceptionMessage; @@ -378,6 +389,87 @@ static std::unique_ptr<Aws::Crt::ApiHandle> api_; static std::unique_ptr<Aws::SDKOptions> sdkOptions_; +#include <stdarg.h> + +class AwsOrthancLogger : public Aws::Utils::Logging::LogSystemInterface +{ +public: + virtual ~AwsOrthancLogger() {} + + /** + * Gets the currently configured log level for this logger. + */ + virtual Aws::Utils::Logging::LogLevel GetLogLevel() const ORTHANC_OVERRIDE + { + return Aws::Utils::Logging::LogLevel::Trace; + } + /** + * Does a printf style output to the output stream. Don't use this, it's unsafe. See LogStream + */ + virtual void Log(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const char* formatStr, ...) ORTHANC_OVERRIDE + { + Aws::StringStream ss; + + va_list args; + va_start(args, formatStr); + + va_list tmp_args; //unfortunately you cannot consume a va_list twice + va_copy(tmp_args, args); //so we have to copy it + #ifdef _WIN32 + const int requiredLength = _vscprintf(formatStr, tmp_args) + 1; + #else + const int requiredLength = vsnprintf(nullptr, 0, formatStr, tmp_args) + 1; + #endif + va_end(tmp_args); + + assert(requiredLength > 0); + std::string outputBuff; + outputBuff.resize(requiredLength); + #ifdef _WIN32 + vsnprintf_s(&outputBuff[0], requiredLength, _TRUNCATE, formatStr, args); + #else + vsnprintf(&outputBuff[0], requiredLength, formatStr, args); + #endif // _WIN32 + + if (logLevel == Aws::Utils::Logging::LogLevel::Debug || logLevel == Aws::Utils::Logging::LogLevel::Trace) + { + LOG(INFO) << outputBuff; + } + else if (logLevel == Aws::Utils::Logging::LogLevel::Warn) + { + LOG(WARNING) << outputBuff; + } + else + { + LOG(ERROR) << outputBuff; + } + + va_end(args); + } + /** + * Writes the stream to the output stream. + */ + virtual void LogStream(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const Aws::OStringStream &messageStream) ORTHANC_OVERRIDE + { + if (logLevel == Aws::Utils::Logging::LogLevel::Debug || logLevel == Aws::Utils::Logging::LogLevel::Trace) + { + LOG(INFO) << tag << messageStream.str(); + } + else if (logLevel == Aws::Utils::Logging::LogLevel::Warn) + { + LOG(WARNING) << tag << messageStream.str(); + } + else + { + LOG(ERROR) << tag << messageStream.str(); + } + + } + /** + * Writes any buffered messages to the underlying device if the logger supports buffering. + */ + virtual void Flush() ORTHANC_OVERRIDE {} +}; IStorage* AwsS3StoragePluginFactory::CreateStorage(const std::string& nameForLogs, const OrthancPlugins::OrthancConfiguration& orthancConfig) { @@ -386,20 +478,12 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls, "Cannot initialize twice"); } - api_.reset(new Aws::Crt::ApiHandle); - - sdkOptions_.reset(new Aws::SDKOptions); - sdkOptions_->cryptoOptions.initAndCleanupOpenSSL = false; // Done by the Orthanc framework - sdkOptions_->httpOptions.initAndCleanupCurl = false; // Done by the Orthanc framework - - Aws::InitAPI(*sdkOptions_); - bool enableLegacyStorageStructure; bool storageContainsUnknownFiles; if (!orthancConfig.IsSection(GetConfigurationSectionName())) { - OrthancPlugins::LogWarning(std::string(GetStoragePluginName()) + " plugin, section missing. Plugin is not enabled."); + LOG(WARNING) << GetStoragePluginName() << " plugin, section missing. Plugin is not enabled."; return nullptr; } @@ -418,13 +502,13 @@ if (!pluginSection.LookupStringValue(bucketName, "BucketName")) { - OrthancPlugins::LogError("AwsS3Storage/BucketName configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "AwsS3Storage/BucketName configuration missing. Unable to initialize plugin"; return nullptr; } if (!pluginSection.LookupStringValue(region, "Region")) { - OrthancPlugins::LogError("AwsS3Storage/Region configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "AwsS3Storage/Region configuration missing. Unable to initialize plugin"; return nullptr; } @@ -432,8 +516,26 @@ const unsigned int connectTimeout = pluginSection.GetUnsignedIntegerValue("ConnectTimeout", 30); const unsigned int requestTimeout = pluginSection.GetUnsignedIntegerValue("RequestTimeout", 1200); const bool virtualAddressing = pluginSection.GetBooleanValue("VirtualAddressing", true); + const bool enableAwsSdkLogs = pluginSection.GetBooleanValue("EnableAwsSdkLogs", false); const std::string caFile = orthancConfig.GetStringValue("HttpsCACertificates", ""); - + + + api_.reset(new Aws::Crt::ApiHandle); + + sdkOptions_.reset(new Aws::SDKOptions); + sdkOptions_->cryptoOptions.initAndCleanupOpenSSL = false; // Done by the Orthanc framework + sdkOptions_->httpOptions.initAndCleanupCurl = false; // Done by the Orthanc framework + + if (enableAwsSdkLogs) + { + // Set up logging + Aws::Utils::Logging::InitializeAWSLogging(Aws::MakeShared<AwsOrthancLogger>(ALLOCATION_TAG)); + // strangely, this seems to disable logging !!!! sdkOptions_->loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace; + } + + Aws::InitAPI(*sdkOptions_); + + try { Aws::Client::ClientConfiguration configuration; @@ -467,7 +569,7 @@ if (pluginSection.LookupStringValue(accessKey, "AccessKey") && pluginSection.LookupStringValue(secretKey, "SecretKey")) { - OrthancPlugins::LogInfo("AWS S3 Storage: using credentials from the configuration file"); + LOG(INFO) << "AWS S3 Storage: using credentials from the configuration file"; Aws::Auth::AWSCredentials credentials(accessKey.c_str(), secretKey.c_str()); client = Aws::MakeShared<Aws::S3::S3Client>(ALLOCATION_TAG, credentials, configuration, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, virtualAddressing); @@ -475,20 +577,20 @@ else { // when using default credentials, credentials are not checked at startup but only the first time you try to access the bucket ! - OrthancPlugins::LogInfo("AWS S3 Storage: using default credentials provider"); + LOG(INFO) << "AWS S3 Storage: using default credentials provider"; client = Aws::MakeShared<Aws::S3::S3Client>(ALLOCATION_TAG, configuration, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, virtualAddressing); } - OrthancPlugins::LogInfo("AWS S3 storage initialized"); + LOG(INFO) << "AWS S3 storage initialized"; return new AwsS3StoragePlugin(nameForLogs, client, bucketName, enableLegacyStorageStructure, storageContainsUnknownFiles, useTransferManager, transferPoolSize, transferBufferSizeMB); } catch (const std::exception& e) { - OrthancPlugins::LogError(std::string("AWS S3 Storage plugin: failed to initialize plugin: ") + e.what()); + Aws::ShutdownAPI(*sdkOptions_); + LOG(ERROR) << "AWS S3 Storage plugin: failed to initialize plugin: " << e.what(); return nullptr; } - } @@ -497,6 +599,7 @@ assert(sdkOptions_.get() != NULL); Aws::ShutdownAPI(*sdkOptions_); api_.reset(); + sdkOptions_.reset(); }
--- a/Aws/AwsS3StoragePlugin.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Aws/AwsS3StoragePlugin.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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/Aws/AwsStaticConfiguration.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Aws/AwsStaticConfiguration.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -1,5 +1,7 @@ # Cloud storage plugins for Orthanc -# Copyright (C) 2020-2021 Osimis S.A., Belgium +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -15,72 +17,156 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. -# version numbers can be obtained from https://github.com/aws/aws-sdk-cpp/blob/main/prefetch_crt_dependency.sh +# The versions below must match those in "./DownloadStaticPackages.sh" +SET(AWS_CHECKSUMS_VERSION 0.1.18) +SET(AWS_CRT_CPP_VERSION 0.24.1) +SET(AWS_C_AUTH_VERSION 0.7.22) +SET(AWS_C_CAL_VERSION 0.7.0) +SET(AWS_C_COMMON_VERSION 0.9.23) +SET(AWS_C_COMPRESSION_VERSION 0.2.18) +SET(AWS_C_EVENT_STREAM_VERSION 0.4.2) +SET(AWS_C_HTTP_VERSION 0.8.2) +SET(AWS_C_IO_VERSION 0.14.9) +SET(AWS_C_MQTT_VERSION 0.10.4) +SET(AWS_C_S3_VERSION 0.5.10) +SET(AWS_C_SDKUTILS_VERSION 0.1.16) +SET(AWS_SDK_CPP_VERSION 1.11.178) -SET(AWS_C_COMMON_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-common-0.9.3) # source = https://github.com/awslabs/aws-c-common/archive/refs/tags/v0.9.3.tar.gz -SET(AWS_C_COMMON_URL "https://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-common-0.9.3.tar.gz") -SET(AWS_C_COMMON_MD5 "d872ff682d5beca8ada6b19464235ca0") -DownloadPackage(${AWS_C_COMMON_MD5} ${AWS_C_COMMON_URL} "${AWS_C_COMMON_SOURCES_DIR}") +SET(AWS_CHECKSUMS_MD5 "ab640e05f6e8ffc20d619599b5ff7c92") +SET(AWS_CRT_CPP_MD5 "fa2cda44386bd56f1d4609c6a54a59f9") +SET(AWS_C_AUTH_MD5 "d2655feb998f57af8f9e985bf358face") +SET(AWS_C_CAL_MD5 "522cad001d0b259e792b7468cd4d4c84") +SET(AWS_C_COMMON_MD5 "a36562c3eb99227cbb131c7c56602b86") +SET(AWS_C_COMPRESSION_MD5 "f1510a8769637d4997e43d2783807113") +SET(AWS_C_EVENT_STREAM_MD5 "9d0f9a4f81927fcffccfa989baebf024") +SET(AWS_C_HTTP_MD5 "20156836ae45b982cc56f2762cc9f27e") +SET(AWS_C_IO_MD5 "c95a51d07c1eace423205af3a5407121") +SET(AWS_C_MQTT_MD5 "43de8c035d383ac33652e0de0e4b2b7a") +SET(AWS_C_S3_MD5 "5db9d3ec2caa4ebe1b4b3bf27a45c513") +SET(AWS_C_SDKUTILS_MD5 "a215ee5a0d082df1bff812b24456c0a2") +SET(AWS_SDK_CPP_MD5 "a3f45888e939bb71506e0f7eaa630e48") -SET(AWS_CHECKSUMS_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-checksums-0.1.17) # source = https://github.com/awslabs/aws-checksums/archive/refs/tags/v0.1.17.tar.gz -SET(AWS_CHECKSUMS_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-checksums-0.1.17.tar.gz") -SET(AWS_CHECKSUMS_MD5 "c256144404dc74349a8344662111e353") + +SET(AWS_CHECKSUMS_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-checksums-${AWS_CHECKSUMS_VERSION}) +SET(AWS_CHECKSUMS_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-checksums-${AWS_CHECKSUMS_VERSION}.tar.gz") DownloadPackage(${AWS_CHECKSUMS_MD5} ${AWS_CHECKSUMS_URL} "${AWS_CHECKSUMS_SOURCES_DIR}") -SET(AWS_C_AUTH_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-auth-0.7.1) # source = https://github.com/awslabs/aws-c-auth/archive/refs/tags/v0.7.1.tar.gz -SET(AWS_C_AUTH_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-auth-0.7.1.tar.gz") -SET(AWS_C_AUTH_MD5 "aa690622a5f697d47ca3095ba2ef3cca") +SET(AWS_CRT_CPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-crt-cpp-${AWS_CRT_CPP_VERSION}) +SET(AWS_CRT_CPP_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-crt-cpp-${AWS_CRT_CPP_VERSION}.tar.gz") +DownloadPackage(${AWS_CRT_CPP_MD5} ${AWS_CRT_CPP_URL} "${AWS_CRT_CPP_SOURCES_DIR}") + +SET(AWS_C_AUTH_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-auth-${AWS_C_AUTH_VERSION}) +SET(AWS_C_AUTH_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-auth-${AWS_C_AUTH_VERSION}.tar.gz") DownloadPackage(${AWS_C_AUTH_MD5} ${AWS_C_AUTH_URL} "${AWS_C_AUTH_SOURCES_DIR}") -SET(AWS_C_CAL_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-cal-0.6.1) # source = https://github.com/awslabs/aws-c-cal/archive/refs/tags/v0.6.1.tar.gz -SET(AWS_C_CAL_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-cal-0.6.1.tar.gz") -SET(AWS_C_CAL_MD5 "6d7c05e2f1c173b923e77b6021cb660d") +SET(AWS_C_CAL_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-cal-${AWS_C_CAL_VERSION}) +SET(AWS_C_CAL_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-cal-${AWS_C_CAL_VERSION}.tar.gz") DownloadPackage(${AWS_C_CAL_MD5} ${AWS_C_CAL_URL} "${AWS_C_CAL_SOURCES_DIR}") -SET(AWS_C_COMPRESSION_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-compression-0.2.17) # source = https://github.com/awslabs/aws-c-compression/archive/refs/tags/v0.2.17.tar.gz -SET(AWS_C_COMPRESSION_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-compression-0.2.17.tar.gz") -SET(AWS_C_COMPRESSION_MD5 "b8bc8bc9cf3749eb2d3f36098c9ead27") + +SET(AWS_C_COMMON_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-common-${AWS_C_COMMON_VERSION}) +SET(AWS_C_COMMON_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-common-${AWS_C_COMMON_VERSION}.tar.gz") + +if (IS_DIRECTORY "${AWS_C_COMMON_SOURCES_DIR}") + set(FirstRun OFF) +else() + set(FirstRun ON) +endif() + +DownloadPackage(${AWS_C_COMMON_MD5} ${AWS_C_COMMON_URL} "${AWS_C_COMMON_SOURCES_DIR}") + +if (FirstRun) + # This is a patch for MinGW + execute_process( + COMMAND ${PATCH_EXECUTABLE} -p0 -N -i + ${CMAKE_CURRENT_LIST_DIR}/aws-c-common-${AWS_C_COMMON_VERSION}.patch + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + ) + + if (Failure) + message(FATAL_ERROR "Error while patching a file") + endif() +endif() + + + +SET(AWS_C_COMPRESSION_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-compression-${AWS_C_COMPRESSION_VERSION}) +SET(AWS_C_COMPRESSION_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-compression-${AWS_C_COMPRESSION_VERSION}.tar.gz") DownloadPackage(${AWS_C_COMPRESSION_MD5} ${AWS_C_COMPRESSION_URL} "${AWS_C_COMPRESSION_SOURCES_DIR}") -SET(AWS_C_EVENT_STREAM_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-event-stream-0.3.1) # source = https://github.com/awslabs/aws-c-event-stream/archive/refs/tags/v0.3.1.tar.gz -SET(AWS_C_EVENT_STREAM_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-event-stream-0.3.1.tar.gz") -SET(AWS_C_EVENT_STREAM_MD5 "e3261d89598a3331eebcd0476b523c73") +SET(AWS_C_EVENT_STREAM_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-event-stream-${AWS_C_EVENT_STREAM_VERSION}) +SET(AWS_C_EVENT_STREAM_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-event-stream-${AWS_C_EVENT_STREAM_VERSION}.tar.gz") DownloadPackage(${AWS_C_EVENT_STREAM_MD5} ${AWS_C_EVENT_STREAM_URL} "${AWS_C_EVENT_STREAM_SOURCES_DIR}") -SET(AWS_C_HTTP_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-http-0.7.11) # source = https://github.com/awslabs/aws-c-http/archive/refs/tags/v0.7.11.tar.gz -SET(AWS_C_HTTP_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-http-0.7.11.tar.gz") -SET(AWS_C_HTTP_MD5 "b8ef3268d4d64b7fabe743b03518d2d7") +SET(AWS_C_HTTP_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-http-${AWS_C_HTTP_VERSION}) +SET(AWS_C_HTTP_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-http-${AWS_C_HTTP_VERSION}.tar.gz") DownloadPackage(${AWS_C_HTTP_MD5} ${AWS_C_HTTP_URL} "${AWS_C_HTTP_SOURCES_DIR}") -SET(AWS_C_IO_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-io-0.13.31) # source = https://github.com/awslabs/aws-c-io/archive/refs/tags/v0.13.31.tar.gz -SET(AWS_C_IO_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-io-0.13.31.tar.gz") -SET(AWS_C_IO_MD5 "9ae415cb81404e1b76d8e8267e585e34") + +SET(AWS_C_IO_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-io-${AWS_C_IO_VERSION}) +SET(AWS_C_IO_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-io-${AWS_C_IO_VERSION}.tar.gz") + +if (IS_DIRECTORY "${AWS_C_IO_SOURCES_DIR}") + set(FirstRun OFF) +else() + set(FirstRun ON) +endif() + DownloadPackage(${AWS_C_IO_MD5} ${AWS_C_IO_URL} "${AWS_C_IO_SOURCES_DIR}") -SET(AWS_C_MQTT_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-mqtt-0.9.5) # source = https://github.com/awslabs/aws-c-mqtt/archive/refs/tags/v0.9.5.tar.gz -SET(AWS_C_MQTT_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-mqtt-0.9.5.tar.gz") -SET(AWS_C_MQTT_MD5 "76d59d9f14f3999b0f9618e386e71db6") +if (FirstRun) + # This is a patch for MinGW + execute_process( + COMMAND ${PATCH_EXECUTABLE} -p0 -N -i + ${CMAKE_CURRENT_LIST_DIR}/aws-c-io-${AWS_C_IO_VERSION}.patch + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + ) + + if (Failure) + message(FATAL_ERROR "Error while patching a file") + endif() +endif() + + +SET(AWS_C_MQTT_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-mqtt-${AWS_C_MQTT_VERSION}) +SET(AWS_C_MQTT_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-mqtt-${AWS_C_MQTT_VERSION}.tar.gz") DownloadPackage(${AWS_C_MQTT_MD5} ${AWS_C_MQTT_URL} "${AWS_C_MQTT_SOURCES_DIR}") -SET(AWS_C_S3_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-s3-0.3.14) # source = https://github.com/awslabs/aws-c-s3/archive/refs/tags/v0.3.14.tar.gz -SET(AWS_C_S3_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-s3-0.3.14.tar.gz") -SET(AWS_C_S3_MD5 "564bb0df1184ebe9ce41c23a0c18cf1a") +SET(AWS_C_S3_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-s3-${AWS_C_S3_VERSION}) +SET(AWS_C_S3_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-s3-${AWS_C_S3_VERSION}.tar.gz") DownloadPackage(${AWS_C_S3_MD5} ${AWS_C_S3_URL} "${AWS_C_S3_SOURCES_DIR}") -SET(AWS_C_SDKUTILS_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-sdkutils-0.1.11) # source = https://github.com/awslabs/aws-c-sdkutils/archive/refs/tags/v0.1.11.tar.gz -SET(AWS_C_SDKUTILS_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-c-sdkutils-0.1.11.tar.gz") -SET(AWS_C_SDKUTILS_MD5 "713cac3392aa20d5dda852cf21ac1957") +SET(AWS_C_SDKUTILS_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-c-sdkutils-${AWS_C_SDKUTILS_VERSION}) +SET(AWS_C_SDKUTILS_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-c-sdkutils-${AWS_C_SDKUTILS_VERSION}.tar.gz") DownloadPackage(${AWS_C_SDKUTILS_MD5} ${AWS_C_SDKUTILS_URL} "${AWS_C_SDKUTILS_SOURCES_DIR}") -SET(AWS_CRT_CPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-crt-cpp-0.24.1) # source = https://github.com/awslabs/aws-crt-cpp/archive/refs/tags/v0.24.1.tar.gz -SET(AWS_CRT_CPP_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-crt-cpp-0.24.1.tar.gz") -SET(AWS_CRT_CPP_MD5 "fa2cda44386bd56f1d4609c6a54a59f9") -DownloadPackage(${AWS_CRT_CPP_MD5} ${AWS_CRT_CPP_URL} "${AWS_CRT_CPP_SOURCES_DIR}") + +SET(AWS_SDK_CPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-sdk-cpp-${AWS_SDK_CPP_VERSION}) +SET(AWS_SDK_CPP_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/aws/aws-sdk-cpp-${AWS_SDK_CPP_VERSION}.tar.gz") + +if (IS_DIRECTORY "${AWS_SDK_CPP_SOURCES_DIR}") + set(FirstRun OFF) +else() + set(FirstRun ON) +endif() + +DownloadPackage(${AWS_SDK_CPP_MD5} ${AWS_SDK_CPP_URL} "${AWS_SDK_CPP_SOURCES_DIR}") -SET(AWS_SDK_CPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/aws-sdk-cpp-1.11.178) # source = https://github.com/aws/aws-sdk-cpp/archive/refs/tags/1.11.178.tar.gz -SET(AWS_SDK_CPP_URL "http://orthanc.osimis.io/ThirdPartyDownloads/aws/aws-sdk-cpp-1.11.178.tar.gz") -SET(AWS_SDK_CPP_MD5 "a3f45888e939bb71506e0f7eaa630e48") -DownloadPackage(${AWS_SDK_CPP_MD5} ${AWS_SDK_CPP_URL} "${AWS_SDK_CPP_SOURCES_DIR}") +if (FirstRun) + # This is a patch for Microsoft Visual Studio 2015 and MinGW + execute_process( + COMMAND ${PATCH_EXECUTABLE} -p0 -N -i + ${CMAKE_CURRENT_LIST_DIR}/aws-sdk-cpp-${AWS_SDK_CPP_VERSION}.patch + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + ) + + if (Failure) + message(FATAL_ERROR "Error while patching a file") + endif() +endif() configure_file( @@ -101,6 +187,7 @@ include_directories( ${AWS_C_COMMON_SOURCES_DIR}/include/ + ${AWS_C_COMMON_SOURCES_DIR}/source/external/libcbor ${AWS_C_AUTH_SOURCES_DIR}/include/ ${AWS_C_CAL_SOURCES_DIR}/include/ ${AWS_C_COMPRESSION_SOURCES_DIR}/include/ @@ -123,6 +210,9 @@ list(APPEND AWS_SOURCES_SUBDIRS ${AWS_C_COMMON_SOURCES_DIR}/source/ ${AWS_C_COMMON_SOURCES_DIR}/source/external/ + ${AWS_C_COMMON_SOURCES_DIR}/source/external/libcbor/ + ${AWS_C_COMMON_SOURCES_DIR}/source/external/libcbor/cbor/ + ${AWS_C_COMMON_SOURCES_DIR}/source/external/libcbor/cbor/internal/ ## C libraries @@ -166,8 +256,6 @@ ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/internal/ ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/monitoring/ ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/net/ - ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/platform/linux-shared/ - # ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/platform/windows/ ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/smithy/tracing/ ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/utils/ ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/utils/base64/ @@ -194,16 +282,46 @@ -DBYO_CRYPTO # To have "aws_tls_server_ctx_new()" defined -DENABLE_OPENSSL_ENCRYPTION=1 -DENABLE_CURL_CLIENT=1 + -DINTEL_NO_ITTNOTIFY_API=1 ) -list(APPEND AWS_SOURCES_SUBDIRS - #${AWS_C_CAL_SOURCES_DIR}/source/unix/ - #${AWS_SDK_CPP_SOURCES_DIR}/aws-cpp-sdk-core/source/net/linux-shared/ - ${AWS_C_COMMON_SOURCES_DIR}/source/posix/ - ${AWS_C_IO_SOURCES_DIR}/source/linux/ - ${AWS_C_IO_SOURCES_DIR}/source/posix/ - ${AWS_SDK_CPP_SOURCES_DIR}/aws-cpp-sdk-core/source/platform/linux-shared/ - ) +if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + list(APPEND AWS_SOURCES_SUBDIRS + ${AWS_C_COMMON_SOURCES_DIR}/source/windows/ + ${AWS_C_IO_SOURCES_DIR}/source/windows/ + ${AWS_C_IO_SOURCES_DIR}/source/windows/iocp/ + ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/platform/windows/ + ) + + add_definitions( + -DAWS_USE_IO_COMPLETION_PORTS=1 + # -DCJSON_AS4CPP_HIDE_SYMBOLS=1 # Disable "dllexport" in cJSON => doesn't seem to work + -DCJSON_HIDE_SYMBOLS=1 + ) + + set(AWSSDK_LINK_LIBRARIES + # secur32 + ncrypt + shlwapi + userenv + version + ) + + # Target Windows 7, as "PPROCESSOR_NUMBER" is needed by AWS + remove_definitions(-DWINVER=0x0501 -D_WIN32_WINNT=0x0501) + add_definitions(-DWINVER=0x0601 -D_WIN32_WINNT=0x0601) + +else() + list(APPEND AWS_SOURCES_SUBDIRS + #${AWS_C_CAL_SOURCES_DIR}/source/unix/ + #${AWS_SDK_CPP_SOURCES_DIR}/aws-cpp-sdk-core/source/net/linux-shared/ + ${AWS_C_COMMON_SOURCES_DIR}/source/linux/ + ${AWS_C_COMMON_SOURCES_DIR}/source/posix/ + ${AWS_C_IO_SOURCES_DIR}/source/linux/ + ${AWS_C_IO_SOURCES_DIR}/source/posix/ + ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/platform/linux-shared/ + ) +endif() foreach(d ${AWS_SOURCES_SUBDIRS}) @@ -215,3 +333,26 @@ ${AWS_C_COMMON_SOURCES_DIR}/source/arch/generic/cpuid.c ${AWS_CHECKSUMS_SOURCES_DIR}/source/generic/crc32c_null.c ) + + +if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + # WARNING: "//" *are* important below (don't replace them with "/") + if (MINGW) + list(REMOVE_ITEM AWS_SOURCES + ${AWS_C_COMMON_SOURCES_DIR}/source/windows//system_info.c + ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/platform/windows//Environment.cpp + ) + list(APPEND AWS_SOURCES + ${AWS_C_COMMON_SOURCES_DIR}/source/posix/system_info.c + ${AWS_SDK_CPP_SOURCES_DIR}/src/aws-cpp-sdk-core/source/platform/linux-shared/Environment.cpp + ) + endif() + + list(APPEND AWS_SOURCES + ${AWS_C_COMMON_SOURCES_DIR}/source/platform_fallback_stubs/system_info.c + ) + + list(REMOVE_ITEM AWS_SOURCES + ${AWS_C_IO_SOURCES_DIR}/source/windows//secure_channel_tls_handler.c + ) +endif()
--- a/Aws/CMakeLists.txt Tue Nov 21 09:50:24 2023 +0100 +++ b/Aws/CMakeLists.txt Tue Jun 25 12:38:31 2024 +0200 @@ -1,5 +1,7 @@ # Cloud storage plugins for Orthanc -# Copyright (C) 2020-2021 Osimis S.A., Belgium +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -19,13 +21,13 @@ project(OrthancAwsS3Storage) -set(PLUGIN_VERSION "2.3.0") +set(PLUGIN_VERSION "mainline") if (PLUGIN_VERSION STREQUAL "mainline") set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline") set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") else() - set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "daf4807631c5") + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "1.12.4") set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") endif() @@ -81,6 +83,7 @@ set(ENABLE_MODULE_DICOM OFF) set(ENABLE_MODULE_IMAGES OFF) set(ENABLE_MODULE_JOBS OFF) + set(ENABLE_OPENSSL_ENGINES ON) # Necessary since OpenSSL 3.1.x set(ENABLE_WEB_CLIENT ON) # Access options related to curl set(ORTHANC_FRAMEWORK_PLUGIN ON) @@ -148,8 +151,6 @@ ${COMMON_SOURCES} ) -DefineSourceBasenameForTarget(OrthancAwsS3Storage) - set_target_properties(OrthancAwsS3Storage PROPERTIES VERSION ${PLUGIN_VERSION} SOVERSION ${PLUGIN_VERSION} @@ -162,6 +163,14 @@ ${ORTHANC_FRAMEWORK_LIBRARIES} ) + +install( + TARGETS OrthancAwsS3Storage + RUNTIME DESTINATION lib # Destination for Windows + LIBRARY DESTINATION share/orthanc/plugins # Destination for Linux +) + + add_executable(UnitTests ${GOOGLE_TEST_SOURCES} ${COMMON_SOURCES} @@ -182,3 +191,8 @@ add_dependencies(OrthancAwsS3Storage AwsSdkCpp) add_dependencies(UnitTests AwsSdkCpp) endif() + +if (COMMAND DefineSourceBasenameForTarget) + DefineSourceBasenameForTarget(OrthancAwsS3Storage) + DefineSourceBasenameForTarget(UnitTests) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Aws/DownloadStaticPackages.sh Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,78 @@ +#!/bin/bash + +# Cloud storage plugins for Orthanc +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/>. + + +# This maintenance script downloads the AWS packages. +# +# NB: Older version numbers can be obtained from +# https://github.com/aws/aws-sdk-cpp/blob/main/prefetch_crt_dependency.sh + + +set -e + +AWS_CHECKSUMS_VERSION=0.1.18 # https://github.com/awslabs/aws-checksums/tags +AWS_CRT_CPP_VERSION=0.24.1 # https://github.com/awslabs/aws-crt-cpp/tags +AWS_C_AUTH_VERSION=0.7.22 # https://github.com/awslabs/aws-c-auth/tags +AWS_C_CAL_VERSION=0.7.0 # https://github.com/awslabs/aws-c-cal/tags +AWS_C_COMMON_VERSION=0.9.23 # https://github.com/awslabs/aws-c-common/tags +AWS_C_COMPRESSION_VERSION=0.2.18 # https://github.com/awslabs/aws-c-compression/tags +AWS_C_EVENT_STREAM_VERSION=0.4.2 # https://github.com/awslabs/aws-c-event-stream/tags +AWS_C_HTTP_VERSION=0.8.2 # https://github.com/awslabs/aws-c-http/tags +AWS_C_IO_VERSION=0.14.9 # https://github.com/awslabs/aws-c-io/tags +AWS_C_MQTT_VERSION=0.10.4 # https://github.com/awslabs/aws-c-mqtt/tags +AWS_C_S3_VERSION=0.5.10 # https://github.com/awslabs/aws-c-s3/tags +AWS_C_SDKUTILS_VERSION=0.1.16 # https://github.com/awslabs/aws-c-sdkutils/tags +AWS_SDK_CPP_VERSION=1.11.178 # https://github.com/awslabs/aws-sdk-cpp/tags + +TARGET=/tmp/aws + +if [ -d "${TARGET}" ]; then + echo "Directory exists, giving up: ${TARGET}" + exit -1 +fi + +mkdir -p ${TARGET} + +wget https://github.com/awslabs/aws-checksums/archive/refs/tags/v${AWS_CHECKSUMS_VERSION}.tar.gz \ + -O ${TARGET}/aws-checksums-${AWS_CHECKSUMS_VERSION}.tar.gz +wget https://github.com/awslabs/aws-crt-cpp/archive/refs/tags/v${AWS_CRT_CPP_VERSION}.tar.gz \ + -O ${TARGET}/aws-crt-cpp-${AWS_CRT_CPP_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-auth/archive/refs/tags/v${AWS_C_AUTH_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-auth-${AWS_C_AUTH_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-cal/archive/refs/tags/v${AWS_C_CAL_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-cal-${AWS_C_CAL_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-common/archive/refs/tags/v${AWS_C_COMMON_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-common-${AWS_C_COMMON_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-compression/archive/refs/tags/v${AWS_C_COMPRESSION_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-compression-${AWS_C_COMPRESSION_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-event-stream/archive/refs/tags/v${AWS_C_EVENT_STREAM_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-event-stream-${AWS_C_EVENT_STREAM_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-http/archive/refs/tags/v${AWS_C_HTTP_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-http-${AWS_C_HTTP_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-io/archive/refs/tags/v${AWS_C_IO_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-io-${AWS_C_IO_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-mqtt/archive/refs/tags/v${AWS_C_MQTT_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-mqtt-${AWS_C_MQTT_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-s3/archive/refs/tags/v${AWS_C_S3_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-s3-${AWS_C_S3_VERSION}.tar.gz +wget https://github.com/awslabs/aws-c-sdkutils/archive/refs/tags/v${AWS_C_SDKUTILS_VERSION}.tar.gz \ + -O ${TARGET}/aws-c-sdkutils-${AWS_C_SDKUTILS_VERSION}.tar.gz +wget https://github.com/awslabs/aws-sdk-cpp/archive/refs/tags/${AWS_SDK_CPP_VERSION}.tar.gz \ + -O ${TARGET}/aws-sdk-cpp-${AWS_SDK_CPP_VERSION}.tar.gz
--- a/Aws/Graveyard/AwsExternalProject.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Aws/Graveyard/AwsExternalProject.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -1,5 +1,7 @@ # Cloud storage plugins for Orthanc -# Copyright (C) 2020-2021 Osimis S.A., Belgium +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Aws/README.txt Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,39 @@ + +Native compilation under Ubuntu 22.04 +===================================== + +# mkdir Build +# cd Build +# cmake .. -DCMAKE_BUILD_TYPE=Release -DUSE_VCPKG_PACKAGES=OFF -G Ninja +# ninja + + +Linux Standard Base compilation +=============================== + +# ./holy-build-box-compile.sh Release + + +MinGW +===== + +The minimum MinGW version to compile the AWS C++ SDK is 13.x. + +To build Windows 32 binaries: + +# ./mingw-compile.sh Release i686 +# ls ../mingw-binaries-i686/ + +To build Windows 64 binaries: + +# ./mingw-compile.sh Release x86_64 +# ls ../mingw-binaries-x86_64/ + + +Microsoft Visual Studio +======================= + +The minimum version to compile the AWS C++ SDK is Visual Studio 2015. + +WARNING: The binaries that are produced with Visual Studio currently +do not work. They write empty files to the S3 storage.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Aws/aws-c-common-0.9.23.patch Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,12 @@ +diff -urEb aws-c-common-0.9.23.orig/include/aws/common/byte_order.inl aws-c-common-0.9.23/include/aws/common/byte_order.inl +--- aws-c-common-0.9.23.orig/include/aws/common/byte_order.inl 2024-06-20 20:25:49.000000000 +0200 ++++ aws-c-common-0.9.23/include/aws/common/byte_order.inl 2024-06-23 14:55:38.563418806 +0200 +@@ -39,7 +39,7 @@ + uint64_t v; + __asm__("bswap %q0" : "=r"(v) : "0"(x)); + return v; +-#elif defined(_MSC_VER) ++#elif defined(_MSC_VER) || defined(__MINGW32__) + return _byteswap_uint64(x); + #else + uint32_t low = x & UINT32_MAX;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Aws/aws-c-io-0.14.9.patch Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,92 @@ +diff -urEb aws-c-io-0.14.9.orig/include/aws/io/private/pki_utils.h aws-c-io-0.14.9/include/aws/io/private/pki_utils.h +--- aws-c-io-0.14.9.orig/include/aws/io/private/pki_utils.h 2024-06-04 18:27:58.000000000 +0200 ++++ aws-c-io-0.14.9/include/aws/io/private/pki_utils.h 2024-06-23 10:39:15.047978000 +0200 +@@ -9,7 +9,7 @@ + #ifdef _WIN32 + /* It's ok to include external headers because this is a PRIVATE header file + * (it is usually a crime to include windows.h from header file) */ +-# include <Windows.h> ++# include <windows.h> + #endif /* _WIN32 */ + + #ifdef AWS_OS_APPLE +diff -urEb aws-c-io-0.14.9.orig/source/windows/iocp/iocp_event_loop.c aws-c-io-0.14.9/source/windows/iocp/iocp_event_loop.c +--- aws-c-io-0.14.9.orig/source/windows/iocp/iocp_event_loop.c 2024-06-04 18:27:58.000000000 +0200 ++++ aws-c-io-0.14.9/source/windows/iocp/iocp_event_loop.c 2024-06-23 10:39:15.047978000 +0200 +@@ -12,7 +12,7 @@ + + #include <aws/io/logging.h> + +-#include <Windows.h> ++#include <windows.h> + + /* The next set of struct definitions are taken directly from the + windows documentation. We can't include the header files directly +diff -urEb aws-c-io-0.14.9.orig/source/windows/iocp/pipe.c aws-c-io-0.14.9/source/windows/iocp/pipe.c +--- aws-c-io-0.14.9.orig/source/windows/iocp/pipe.c 2024-06-04 18:27:58.000000000 +0200 ++++ aws-c-io-0.14.9/source/windows/iocp/pipe.c 2024-06-23 10:39:15.047978000 +0200 +@@ -11,7 +11,7 @@ + #include <stdbool.h> + #include <stdio.h> + +-#include <Windows.h> ++#include <windows.h> + + enum read_end_state { + /* Pipe is open. */ +diff -urEb aws-c-io-0.14.9.orig/source/windows/iocp/socket.c aws-c-io-0.14.9/source/windows/iocp/socket.c +--- aws-c-io-0.14.9.orig/source/windows/iocp/socket.c 2024-06-04 18:27:58.000000000 +0200 ++++ aws-c-io-0.14.9/source/windows/iocp/socket.c 2024-06-23 10:39:15.047978000 +0200 +@@ -9,9 +9,9 @@ + below, clang-format doesn't work (at least on my version) with the c-style comments.*/ + + // clang-format off +-#include <WS2tcpip.h> +-#include <MSWSock.h> +-#include <Mstcpip.h> ++#include <ws2tcpip.h> ++#include <mswsock.h> ++#include <mstcpip.h> + // clang-format on + + #include <aws/io/socket.h> +diff -urEb aws-c-io-0.14.9.orig/source/windows/shared_library.c aws-c-io-0.14.9/source/windows/shared_library.c +--- aws-c-io-0.14.9.orig/source/windows/shared_library.c 2024-06-04 18:27:58.000000000 +0200 ++++ aws-c-io-0.14.9/source/windows/shared_library.c 2024-06-23 10:39:15.047978000 +0200 +@@ -4,7 +4,7 @@ + */ + + // clang-format off +-#include <Windows.h> ++#include <windows.h> + #include <libloaderapi.h> + // clang-format on + +diff -urEb aws-c-io-0.14.9.orig/source/windows/windows_pki_utils.c aws-c-io-0.14.9/source/windows/windows_pki_utils.c +--- aws-c-io-0.14.9.orig/source/windows/windows_pki_utils.c 2024-06-04 18:27:58.000000000 +0200 ++++ aws-c-io-0.14.9/source/windows/windows_pki_utils.c 2024-06-23 10:39:15.047978000 +0200 +@@ -10,7 +10,7 @@ + + #include <aws/io/logging.h> + +-#include <Windows.h> ++#include <windows.h> + #include <stdio.h> + #include <string.h> + +diff -urEb aws-c-io-0.14.9.orig/source/windows/winsock_init.c aws-c-io-0.14.9/source/windows/winsock_init.c +--- aws-c-io-0.14.9.orig/source/windows/winsock_init.c 2024-06-04 18:27:58.000000000 +0200 ++++ aws-c-io-0.14.9/source/windows/winsock_init.c 2024-06-23 10:39:15.047978000 +0200 +@@ -8,9 +8,9 @@ + below, clang-format doesn't work (at least on my version) with the c-style comments. */ + + // clang-format off +-#include <WinSock2.h> +-#include <WS2tcpip.h> +-#include <MSWSock.h> ++#include <winsock2.h> ++#include <ws2tcpip.h> ++#include <mswsock.h> + // clang-format on + + #include <aws/io/logging.h>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Aws/aws-sdk-cpp-1.11.178.patch Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,116 @@ +Only in aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/include/aws/core: SDKConfig.h +diff -urEb aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-core/include/aws/core/utils/Array.h aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/include/aws/core/utils/Array.h +--- aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-core/include/aws/core/utils/Array.h 2023-10-06 20:16:49.000000000 +0200 ++++ aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/include/aws/core/utils/Array.h 2024-06-23 10:47:33.294537700 +0200 +@@ -14,7 +14,7 @@ + #include <cstring> + #include <algorithm> + +-#ifdef _WIN32 ++#ifdef _MSC_VER + + #include <iterator> + +@@ -54,7 +54,7 @@ + { + m_data.reset(Aws::NewArray<T>(m_size, ARRAY_ALLOCATION_TAG)); + +-#ifdef _WIN32 ++#ifdef _MSC_VER + std::copy(arrayToCopy, arrayToCopy + arraySize, stdext::checked_array_iterator< T * >(m_data.get(), m_size)); + #else + std::copy(arrayToCopy, arrayToCopy + arraySize, m_data.get()); +@@ -82,7 +82,7 @@ + if(arr->m_size > 0 && arr->m_data) + { + size_t arraySize = arr->m_size; +-#ifdef _WIN32 ++#ifdef _MSC_VER + std::copy(arr->m_data.get(), arr->m_data.get() + arraySize, stdext::checked_array_iterator< T * >(m_data.get() + location, m_size)); + #else + std::copy(arr->m_data.get(), arr->m_data.get() + arraySize, m_data.get() + location); +@@ -101,7 +101,7 @@ + { + m_data.reset(Aws::NewArray<T>(m_size, ARRAY_ALLOCATION_TAG)); + +-#ifdef _WIN32 ++#ifdef _MSC_VER + std::copy(other.m_data.get(), other.m_data.get() + other.m_size, stdext::checked_array_iterator< T * >(m_data.get(), m_size)); + #else + std::copy(other.m_data.get(), other.m_data.get() + other.m_size, m_data.get()); +@@ -134,7 +134,7 @@ + { + m_data.reset(Aws::NewArray<T>(m_size, ARRAY_ALLOCATION_TAG)); + +-#ifdef _WIN32 ++#ifdef _MSC_VER + std::copy(other.m_data.get(), other.m_data.get() + other.m_size, stdext::checked_array_iterator< T * >(m_data.get(), m_size)); + #else + std::copy(other.m_data.get(), other.m_data.get() + other.m_size, m_data.get()); +Only in aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/include/aws/core/utils: Array.h~ +diff -urEb aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-core/source/platform/windows/FileSystem.cpp aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/source/platform/windows/FileSystem.cpp +--- aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-core/source/platform/windows/FileSystem.cpp 2023-10-06 20:16:49.000000000 +0200 ++++ aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/source/platform/windows/FileSystem.cpp 2024-06-22 19:00:43.200750034 +0200 +@@ -10,7 +10,7 @@ + #include <aws/core/utils/memory/stl/AWSVector.h> + #include <cassert> + #include <iostream> +-#include <Userenv.h> ++#include <userenv.h> + + #pragma warning( disable : 4996) + +diff -urEb aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp +--- aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp 2023-10-06 20:16:49.000000000 +0200 ++++ aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp 2024-06-22 18:38:51.196880348 +0200 +@@ -221,7 +221,7 @@ + EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); + + auto currentPos = stream.tellg(); +- if (currentPos == -1) ++ if (currentPos == std::streampos(-1)) + { + currentPos = 0; + stream.clear(); +@@ -298,7 +298,7 @@ + EVP_DigestInit_ex(ctx, EVP_sha1(), nullptr); + + auto currentPos = stream.tellg(); +- if (currentPos == -1) ++ if (currentPos == std::streampos(-1)) + { + currentPos = 0; + stream.clear(); +@@ -376,7 +376,7 @@ + EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); + + auto currentPos = stream.tellg(); +- if (currentPos == -1) ++ if (currentPos == std::streampos(-1)) + { + currentPos = 0; + stream.clear(); +diff -urEb aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-core/source/utils/StringUtils.cpp aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/source/utils/StringUtils.cpp +--- aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-core/source/utils/StringUtils.cpp 2023-10-06 20:16:49.000000000 +0200 ++++ aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-core/source/utils/StringUtils.cpp 2024-06-22 18:55:21.912052713 +0200 +@@ -14,7 +14,7 @@ + #include <functional> + + #ifdef _WIN32 +-#include <Windows.h> ++#include <windows.h> + #endif + + using namespace Aws::Utils; +diff -urEb aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-text-to-speech/include/aws/text-to-speech/windows/WaveOutPCMOutputDriver.h aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-text-to-speech/include/aws/text-to-speech/windows/WaveOutPCMOutputDriver.h +--- aws-sdk-cpp-1.11.178.orig/src/aws-cpp-sdk-text-to-speech/include/aws/text-to-speech/windows/WaveOutPCMOutputDriver.h 2023-10-06 20:16:49.000000000 +0200 ++++ aws-sdk-cpp-1.11.178/src/aws-cpp-sdk-text-to-speech/include/aws/text-to-speech/windows/WaveOutPCMOutputDriver.h 2024-06-22 18:57:00.963064735 +0200 +@@ -10,7 +10,7 @@ + + #include <mutex> + +-#include <Windows.h> ++#include <windows.h> + + namespace Aws + {
--- a/Aws/holy-build-box-compile.sh Tue Nov 21 09:50:24 2023 +0100 +++ b/Aws/holy-build-box-compile.sh Tue Jun 25 12:38:31 2024 +0200 @@ -1,7 +1,9 @@ #!/bin/bash # Cloud storage plugins for Orthanc -# Copyright (C) 2020-2021 Osimis S.A., Belgium +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -41,7 +43,7 @@ ROOT_DIR=`dirname $(readlink -f $0)`/.. -DOCKER_IMAGE=phusion/holy-build-box-64:3.0.0 +DOCKER_IMAGE=phusion/holy-build-box-64:3.0.5 mkdir -p ${ROOT_DIR}/holy-build-box
--- a/Aws/holy-build-box-internal.sh Tue Nov 21 09:50:24 2023 +0100 +++ b/Aws/holy-build-box-internal.sh Tue Jun 25 12:38:31 2024 +0200 @@ -1,7 +1,9 @@ #!/bin/bash # Cloud storage plugins for Orthanc -# Copyright (C) 2020-2021 Osimis S.A., Belgium +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -44,12 +46,14 @@ cp /source/Aws/* /tmp/source-writeable/Aws/ || true # Ignore error about omitting directories cmake /tmp/source-writeable/Aws/ \ - -DORTHANC_FRAMEWORK_VERSION=1.9.3 \ + -DORTHANC_FRAMEWORK_VERSION=1.12.3 \ -DORTHANC_FRAMEWORK_SOURCE=web \ -DCMAKE_BUILD_TYPE=$1 -DSTATIC_BUILD=ON # Use only 2 processes (not `nproc`), as this is a very heavy compilation -make -j2 +# make -j2 + +make -j`nproc --all` ./UnitTests
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Aws/mingw-compile.sh Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,71 @@ +#!/bin/bash + +# Cloud storage plugins for Orthanc +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/>. + + +set -ex + + +if [ "$1" != "Debug" -a "$1" != "Release" ]; then + echo "Please provide build type as first argument: Debug or Release" + exit -1 +fi + +if [ "$2" != "i686" -a "$2" != "x86_64" ]; then + echo "Please provide architecture as second argument: i686 or x86_64" + exit -1 +fi + + +## +## Prepare a Docker container with mingw +## + +if [ -t 1 ]; then + # TTY is available => use interactive mode + DOCKER_FLAGS='-i' +fi + +ROOT_DIR=`dirname $(readlink -f $0)`/.. +IMAGE=orthanc-aws-mingw +TARGET=${ROOT_DIR}/mingw-binaries-$2/ + +if [ -e "${TARGET}" ]; then + echo "Target folder is already existing, aborting" + exit -1 +fi + +mkdir -p ${TARGET} + +( cd ${ROOT_DIR}/Aws/mingw-compile && \ + docker build -t ${IMAGE} . ) + + +## +## Build +## + +docker run -t ${DOCKER_FLAGS} --rm \ + --user $(id -u):$(id -g) \ + -v ${ROOT_DIR}/:/source:ro \ + -v ${TARGET}:/target:rw \ + ${IMAGE} \ + bash /source/Aws/mingw-compile/build.sh $1 $2 + +ls -lR ${TARGET}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Aws/mingw-compile/Dockerfile Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,31 @@ +# Cloud storage plugins for Orthanc +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/>. + + +# Debian 12.5 contains mingw 12.x, which is insufficient +# FROM debian:12.5 + +# Ubuntu 24.04 contains mingw 13.x, which is OK +FROM ubuntu:24.04 + +MAINTAINER Sebastien Jodogne <s.jodogne@gmail.com> +LABEL Description="Orthanc, free DICOM server" Vendor="The Orthanc project" + +RUN apt-get -y clean && apt-get -y update && \ + apt-get -y install cmake patch gcc-mingw-w64 g++-mingw-w64 unzip mercurial && \ + apt-get clean && rm -rf /var/lib/apt/lists/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Aws/mingw-compile/build.sh Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,50 @@ +# Cloud storage plugins for Orthanc +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/>. + + +set -ex + +if [ "$2" = "i686" ]; then + TOOLCHAIN=MinGW-W64-Toolchain32.cmake +elif [ "$2" = "x86_64" ]; then + TOOLCHAIN=MinGW-W64-Toolchain64.cmake +else + exit -1 +fi + + +mkdir /tmp/aws +mkdir /tmp/aws/Aws/ +mkdir /tmp/aws/Build/ + +# Ignore possible build directories in "Aws" folder +find /source/Aws/ -type f -maxdepth 1 | while read f +do + cp "$f" /tmp/aws/Aws/ +done + +cp -r /source/Common /tmp/aws/ +cp -r /source/UnitTestsSources /tmp/aws/ + +cd /tmp/aws/Build/ +cmake ../Aws -DCMAKE_BUILD_TYPE=Release -DUSE_VCPKG_PACKAGES=OFF -DSTATIC_BUILD=ON \ + -DCMAKE_TOOLCHAIN_FILE=/source/Common/Resources/Orthanc/Toolchains/${TOOLCHAIN} +make -j`nproc --all` + +cp ./libOrthancAwsS3Storage.dll /target +cp ./UnitTests.exe /target
--- a/Azure/AzureBlobStoragePlugin.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Azure/AzureBlobStoragePlugin.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -25,6 +27,8 @@ // #include "cpprest/rawptrstream.h" // #include "cpprest/details/basic_types.h" +#include <Logging.h> + // Create aliases to make the code easier to read. namespace as = Azure::Storage::Blobs; @@ -43,10 +47,10 @@ bool storageContainsUnknownFiles ); - virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual bool HasFileExists() {return false;}; + virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual bool HasFileExists() ORTHANC_OVERRIDE {return false;}; }; @@ -66,7 +70,7 @@ { } - virtual void Write(const char* data, size_t size) + virtual void Write(const char* data, size_t size) ORTHANC_OVERRIDE { try { @@ -119,7 +123,7 @@ { } - virtual size_t GetSize() + virtual size_t GetSize() ORTHANC_OVERRIDE { try { @@ -131,7 +135,7 @@ } } - virtual void ReadWhole(char* data, size_t size) + virtual void ReadWhole(char* data, size_t size) ORTHANC_OVERRIDE { try { @@ -144,7 +148,7 @@ } } - virtual void ReadRange(char* data, size_t size, size_t fromOffset) + virtual void ReadRange(char* data, size_t size, size_t fromOffset) ORTHANC_OVERRIDE { try { @@ -222,13 +226,13 @@ if (!pluginSection.LookupStringValue(connectionString, "ConnectionString")) { - OrthancPlugins::LogError("AzureBlobStorage/ConnectionString configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "AzureBlobStorage/ConnectionString configuration missing. Unable to initialize plugin"; return nullptr; } if (!pluginSection.LookupStringValue(containerName, "ContainerName")) { - OrthancPlugins::LogError("AzureBlobStorage/ContainerName configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "AzureBlobStorage/ContainerName configuration missing. Unable to initialize plugin"; return nullptr; } @@ -239,7 +243,7 @@ } else if (orthancConfig.IsSection("BlobStorage")) // backward compatibility with the old plugin: { - OrthancPlugins::LogWarning("AzureBlobStorage: you're using an old configuration format for the plugin."); + LOG(WARNING) << "AzureBlobStorage: you're using an old configuration format for the plugin."; OrthancPlugins::OrthancConfiguration pluginSection; orthancConfig.GetSection(pluginSection, "BlobStorage"); @@ -249,19 +253,19 @@ if (!pluginSection.LookupStringValue(containerName, "ContainerName")) { - OrthancPlugins::LogError("BlobStorage/AccountName configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "BlobStorage/AccountName configuration missing. Unable to initialize plugin"; return nullptr; } if (!pluginSection.LookupStringValue(accountName, "AccountName")) { - OrthancPlugins::LogError("BlobStorage/AccountName configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "BlobStorage/AccountName configuration missing. Unable to initialize plugin"; return nullptr; } if (!pluginSection.LookupStringValue(accountKey, "AccountKey")) { - OrthancPlugins::LogError("BlobStorage/ContainerName configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "BlobStorage/ContainerName configuration missing. Unable to initialize plugin"; return nullptr; } @@ -273,16 +277,16 @@ } else { - OrthancPlugins::LogWarning(std::string(GetStoragePluginName()) + " plugin, section missing. Plugin is not enabled."); + LOG(WARNING) << GetStoragePluginName() << " plugin, section missing. Plugin is not enabled."; return nullptr; } try { - OrthancPlugins::LogInfo("Connecting to Azure storage ..."); + LOG(INFO) << "Connecting to Azure storage ..."; as::BlobContainerClient client = as::BlobContainerClient::CreateFromConnectionString(connectionString, containerName); - OrthancPlugins::LogInfo("Blob client created"); + LOG(INFO) << "Blob client created"; if (createContainerIfNotExists) { @@ -298,17 +302,17 @@ auto createResult = client.CreateIfNotExists(); if (createResult.Value.Created) { - OrthancPlugins::LogWarning("Blob Storage Area container has been created. **** check in the Azure console that your container is private ****"); + LOG(WARNING) << "Blob Storage Area container has been created. **** check in the Azure console that your container is private ****"; } } - OrthancPlugins::LogInfo("Blob storage initialized"); + LOG(INFO) << "Blob storage initialized"; return new AzureBlobStoragePlugin(nameForLogs, client, enableLegacyStorageStructure, storageContainsUnknownFiles); } catch (const std::exception& e) { - OrthancPlugins::LogError(std::string("AzureBlobStorage plugin: failed to initialize plugin: ") + e.what()); + LOG(ERROR) << "AzureBlobStorage plugin: failed to initialize plugin: " << e.what(); return nullptr; }
--- a/Azure/AzureBlobStoragePlugin.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Azure/AzureBlobStoragePlugin.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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/Azure/CMakeLists.txt Tue Nov 21 09:50:24 2023 +0100 +++ b/Azure/CMakeLists.txt Tue Jun 25 12:38:31 2024 +0200 @@ -1,5 +1,7 @@ # Cloud storage plugins for Orthanc -# Copyright (C) 2020-2021 Osimis S.A., Belgium +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -19,14 +21,24 @@ project(OrthancAzureBlobStorage) -set(PLUGIN_VERSION "2.3.0") +set(PLUGIN_VERSION "mainline") + +if (PLUGIN_VERSION STREQUAL "mainline") + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline") + set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") +else() + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "1.12.4") + set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") +endif() + +set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc framework (can be \"system\", \"hg\", \"archive\", \"web\" or \"path\")") +set(ORTHANC_FRAMEWORK_VERSION "${ORTHANC_FRAMEWORK_DEFAULT_VERSION}" CACHE STRING "Version of the Orthanc framework") +set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") +set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") +set(ALLOW_DOWNLOADS ON) include(CheckIncludeFileCXX) -set(ORTHANC_FRAMEWORK_SOURCE "web" CACHE STRING "orthanc source") -set(ORTHANC_FRAMEWORK_VERSION "daf4807631c5" CACHE STRING "orthanc framework version") # TODO: update to 1.12.2 when available -set(ALLOW_DOWNLOADS ON) - # Download and setup the Orthanc framework include(${CMAKE_SOURCE_DIR}/../Common/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake) @@ -111,7 +123,9 @@ ${COMMON_SOURCES} ) -DefineSourceBasenameForTarget(OrthancAzureBlobStorage) +if (COMMAND DefineSourceBasenameForTarget) + DefineSourceBasenameForTarget(OrthancAzureBlobStorage) +endif() set_target_properties(OrthancAzureBlobStorage PROPERTIES VERSION ${PLUGIN_VERSION} @@ -140,6 +154,12 @@ endif() +install( + TARGETS OrthancAzureBlobStorage + RUNTIME DESTINATION lib # Destination for Windows + LIBRARY DESTINATION share/orthanc/plugins # Destination for Linux +) + # add_executable(UnitTests # ${GOOGLE_TEST_SOURCES}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CITATION.cff Tue Jun 25 12:38:31 2024 +0200 @@ -0,0 +1,14 @@ +cff-version: "1.1.0" +message: "If you use this software, please cite it using these metadata." +title: Orthanc +abstract: "Orthanc is a lightweight open-source DICOM server for medical imaging supporting representational state transfer (REST)." +authors: + - + affiliation: UCLouvain + family-names: Jodogne + given-names: "Sébastien" +doi: "10.1007/s10278-018-0082-y" +license: "GPL-3.0-or-later" +repository-code: "https://orthanc.uclouvain.be/hg/orthanc/" +version: 1.12.3 +date-released: 2024-01-31
--- a/Common/BaseStorage.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/BaseStorage.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -18,6 +20,9 @@ #include "BaseStorage.h" + +#include <Logging.h> + #include <boost/filesystem/fstream.hpp> boost::filesystem::path BaseStorage::GetOrthancFileSystemPath(const std::string& uuid, const std::string& fileSystemRootPath) @@ -84,7 +89,7 @@ enableLegacyStorageStructure = true; if (storageStructure != "legacy") { - OrthancPlugins::LogError("ObjectStorage/StorageStructure configuration invalid value: " + storageStructure + ", allowed values are 'flat' and 'legacy'"); + LOG(ERROR) << "ObjectStorage/StorageStructure configuration invalid value: " << storageStructure << ", allowed values are 'flat' and 'legacy'"; return false; } }
--- a/Common/BaseStorage.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/BaseStorage.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -20,6 +22,9 @@ #pragma once #include "IStorage.h" + +#include <Compatibility.h> + #include <boost/filesystem.hpp> namespace fs = boost::filesystem; @@ -39,7 +44,7 @@ std::string GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled, bool useAlternateExtension = false); public: - virtual void SetRootPath(const std::string& rootPath) + virtual void SetRootPath(const std::string& rootPath) ORTHANC_OVERRIDE { rootPath_ = rootPath; }
--- a/Common/CryptoPPConfiguration.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/CryptoPPConfiguration.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -1,5 +1,7 @@ # Cloud storage plugins for Orthanc -# Copyright (C) 2020-2021 Osimis S.A., Belgium +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -18,7 +20,7 @@ if (STATIC_BUILD OR NOT USE_SYSTEM_CRYPTOPP) # The .tar.gz package was created by "./CryptoPPPackage.sh" SET(CRYPTOPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/cryptopp-840) - SET(CRYPTOPP_URL "http://orthanc.osimis.io/ThirdPartyDownloads/cryptopp-840.tar.gz") + SET(CRYPTOPP_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/cryptopp-840.tar.gz") SET(CRYPTOPP_MD5 "d42363e8a12c06a000720335a4da70d3") DownloadPackage(${CRYPTOPP_MD5} ${CRYPTOPP_URL} "${CRYPTOPP_SOURCES_DIR}")
--- a/Common/EncryptionConfigurator.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/EncryptionConfigurator.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -22,11 +24,13 @@ #include "EncryptionConfigurator.h" +#include <Logging.h> + bool ReadMasterKey(uint32_t& id, std::string& keyPath, const Json::Value& node) { if (!node.isArray() || node.size() != 2 || !node[0].isUInt() || !node[1].isString()) { - OrthancPlugins::LogWarning("Encryption: Invalid master key configuration"); + LOG(WARNING) << "Encryption: Invalid master key configuration"; return false; } @@ -50,7 +54,7 @@ if (!cryptoJson.isMember("MasterKey") || !cryptoJson["MasterKey"].isArray()) { - OrthancPlugins::LogWarning("Encryption: MasterKey missing. Unable to initialize encryption"); + LOG(WARNING) << "Encryption: MasterKey missing. Unable to initialize encryption"; return nullptr; }
--- a/Common/EncryptionConfigurator.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/EncryptionConfigurator.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -20,10 +22,7 @@ #include "EncryptionHelpers.h" -class EncryptionConfigurator +namespace EncryptionConfigurator { - -public: - static EncryptionHelpers* CreateEncryptionHelpers(const OrthancPlugins::OrthancConfiguration& encryptionSection); - -}; + EncryptionHelpers* CreateEncryptionHelpers(const OrthancPlugins::OrthancConfiguration& encryptionSection); +}
--- a/Common/EncryptionHelpers.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/EncryptionHelpers.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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/Common/EncryptionHelpers.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/EncryptionHelpers.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -28,7 +30,7 @@ class EncryptionException : public std::runtime_error { public: - EncryptionException(const std::string& what) + explicit EncryptionException(const std::string& what) : std::runtime_error(what) { }
--- a/Common/FileSystemStorage.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/FileSystemStorage.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -19,7 +21,9 @@ #include "FileSystemStorage.h" #include "BaseStorage.h" +#include <Logging.h> #include <SystemToolbox.h> + #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> @@ -141,7 +145,7 @@ } catch(Orthanc::OrthancException& e) { - OrthancPlugins::LogError(GetNameForLogs() + ": error while deleting object " + std::string(uuid) + ": " + std::string(e.What())); + LOG(ERROR) << GetNameForLogs() << ": error while deleting object " << uuid << ": " << e.What(); } }
--- a/Common/FileSystemStorage.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/FileSystemStorage.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -39,21 +41,21 @@ {} virtual ~FileSystemWriter() {} - virtual void Write(const char* data, size_t size); + virtual void Write(const char* data, size_t size) ORTHANC_OVERRIDE; }; class FileSystemReader: public IStorage::IReader { const fs::path path_; public: - FileSystemReader(const fs::path& path) + explicit FileSystemReader(const fs::path& path) : path_(path) {} virtual ~FileSystemReader() {} - virtual size_t GetSize(); - virtual void ReadWhole(char* data, size_t size); - virtual void ReadRange(char* data, size_t size, size_t fromOffset); + virtual size_t GetSize() ORTHANC_OVERRIDE; + virtual void ReadWhole(char* data, size_t size) ORTHANC_OVERRIDE; + virtual void ReadRange(char* data, size_t size, size_t fromOffset) ORTHANC_OVERRIDE; }; std::string fileSystemRootPath_; @@ -65,12 +67,12 @@ fsync_(fsync) {} - virtual void SetRootPath(const std::string& rootPath) {} + virtual void SetRootPath(const std::string& rootPath) ORTHANC_OVERRIDE {} - virtual IStorage::IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual IStorage::IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); + virtual IStorage::IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual IStorage::IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; - virtual bool HasFileExists() {return true;}; - virtual bool FileExists(const std::string& uuid, OrthancPluginContentType type, bool encryptionEnabled); -}; \ No newline at end of file + virtual bool HasFileExists() ORTHANC_OVERRIDE {return true;}; + virtual bool FileExists(const std::string& uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; +};
--- a/Common/IStorage.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/IStorage.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -25,7 +27,7 @@ class StoragePluginException : public std::runtime_error { public: - StoragePluginException(const std::string& what) + explicit StoragePluginException(const std::string& what) : std::runtime_error(what) { } @@ -42,7 +44,7 @@ // IStorage* CreateStorage(const OrthancPlugins::OrthancConfiguration& orthancConfig); //}; -class IStorage +class IStorage : public boost::noncopyable { public: class IWriter @@ -73,6 +75,10 @@ nameForLogs_(nameForLogs) {} + virtual ~IStorage() + { + } + virtual void SetRootPath(const std::string& rootPath) = 0; virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) = 0;
--- a/Common/MoveStorageJob.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/MoveStorageJob.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -69,17 +71,20 @@ { if (sourceStorage->HasFileExists() && !sourceStorage->FileExists(uuid, static_cast<OrthancPluginContentType>(type), cryptoEnabled)) { - OrthancPlugins::LogInfo("Move attachment: " + sourceStorage->GetNameForLogs() + " " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type) + ", skipping, file is not on the source anymore"); + LOG(INFO) << "Move attachment: " << sourceStorage->GetNameForLogs() << " " << uuid + << " of type " << boost::lexical_cast<std::string>(type) << ", skipping, file is not on the source anymore"; return true; } else if (targetStorage->HasFileExists() && targetStorage->FileExists(uuid, static_cast<OrthancPluginContentType>(type), cryptoEnabled)) { - OrthancPlugins::LogInfo("Move attachment: " + targetStorage->GetNameForLogs() + " " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type) + ", skipping, file already on the target"); + LOG(INFO) << "Move attachment: " << targetStorage->GetNameForLogs() << " " << uuid + << " of type " << boost::lexical_cast<std::string>(type) << ", skipping, file already on the target"; return true; } else { - OrthancPlugins::LogInfo("Move attachment: " + sourceStorage->GetNameForLogs() + ": reading attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); + LOG(INFO) << "Move attachment: " << sourceStorage->GetNameForLogs() << ": reading attachment " + << uuid << " of type " << boost::lexical_cast<std::string>(type); } std::unique_ptr<IStorage::IReader> reader(sourceStorage->GetReaderForObject(uuid.c_str(), static_cast<OrthancPluginContentType>(type), cryptoEnabled)); @@ -91,7 +96,8 @@ } catch (StoragePluginException& ex) { - OrthancPlugins::LogInfo("Move attachment: " + sourceStorage->GetNameForLogs() + ": error while reading attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type) + ", this likely means that the file is already on the right storage"); + LOG(INFO) << "Move attachment: " << sourceStorage->GetNameForLogs() << ": error while reading attachment " << uuid + << " of type " << boost::lexical_cast<std::string>(type) << ", this likely means that the file is already on the right storage"; return true; } @@ -106,7 +112,8 @@ } catch (StoragePluginException& ex) { - OrthancPlugins::LogError("Move attachment: " + targetStorage->GetNameForLogs() + ": error while writing attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type) + ": " + ex.what()); + LOG(ERROR) << "Move attachment: " << targetStorage->GetNameForLogs() << ": error while writing attachment " + << uuid << " of type " << boost::lexical_cast<std::string>(type) << ": " << ex.what(); return false; } } @@ -120,7 +127,8 @@ } catch (StoragePluginException& ex) { - OrthancPlugins::LogError("Move attachment: " + sourceStorage->GetNameForLogs() + ": error while deleting attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type) + ": " + ex.what()); + LOG(ERROR) << "Move attachment: " << sourceStorage->GetNameForLogs() << ": error while deleting attachment " + << uuid << " of type " << boost::lexical_cast<std::string>(type) << ": " << ex.what(); return false; } }
--- a/Common/MoveStorageJob.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/MoveStorageJob.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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/Common/Resources/Orthanc/CMake/AutoGeneratedCode.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/CMake/AutoGeneratedCode.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Common/Resources/Orthanc/CMake/Compiler.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/CMake/Compiler.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -43,6 +44,13 @@ # use by "ExternalProject" in CMake SET(CMAKE_LSB_CC $ENV{LSB_CC} CACHE STRING "") SET(CMAKE_LSB_CXX $ENV{LSB_CXX} CACHE STRING "") + + # This is necessary to build "Orthanc mainline - Framework LSB + # Release" on "buildbot-worker-debian11" + set(LSB_PTHREAD_NONSHARED "${LSB_PATH}/lib64-${LSB_TARGET_VERSION}/libpthread_nonshared.a") + if (EXISTS ${LSB_PTHREAD_NONSHARED}) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LSB_PTHREAD_NONSHARED}") + endif() endif() @@ -124,12 +132,17 @@ ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") - if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" AND + if (# NOT ${CMAKE_SYSTEM_VERSION} STREQUAL "LinuxStandardBase" AND + NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") # The "--no-undefined" linker flag makes the shared libraries # (plugins ModalityWorklists and ServeFolders) fail to compile on # OpenBSD, and make the PostgreSQL plugin complain about missing - # "environ" global variable in FreeBSD + # "environ" global variable in FreeBSD. + # + # TODO - Furthermore, on Linux Standard Base running on Debian 12, + # the "-Wl,--no-undefined" seems to break the compilation (added + # after Orthanc 1.12.2). This is disabled for now. set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") endif()
--- a/Common/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -153,11 +154,17 @@ 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") + set(ORTHANC_FRAMEWORK_MD5 "e48fc0cb09c4856803791a1be28c07dc") 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") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.2") + set(ORTHANC_FRAMEWORK_MD5 "d2476b9e796e339ac320b5333489bdb3") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.3") + set(ORTHANC_FRAMEWORK_MD5 "975f5bf2142c22cb1777b4f6a0a614c5") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.4") + set(ORTHANC_FRAMEWORK_MD5 "1e61779ea4a7cd705720bdcfed8a6a73") # Below this point are development snapshots that were used to # release some plugin, before an official release of the Orthanc @@ -168,22 +175,28 @@ # elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "ae0e3fd609df") # DICOMweb 1.1 (framework pre-1.6.0) + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) set(ORTHANC_FRAMEWORK_MD5 "7e09e9b530a2f527854f0b782d7e0645") elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "82652c5fc04f") # Stone Web viewer 1.0 (framework pre-1.8.1) + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) set(ORTHANC_FRAMEWORK_MD5 "d77331d68917e66a3f4f9b807bbdab7f") elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "4a3ba4bf4ba7") # PostgreSQL 3.3 (framework pre-1.8.2) + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) set(ORTHANC_FRAMEWORK_MD5 "2d82bddf06f9cfe82095495cb3b8abde") elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "23ad1b9c7800") # For "Toolbox::ReadJson()" and "Toolbox::Write{...}Json()" (pre-1.9.0) + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) set(ORTHANC_FRAMEWORK_MD5 "9af92080e57c60dd288eba46ce606c00") elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "b2e08d83e21d") # WSI 1.1 (framework pre-1.10.0), to remove "-std=c++11" + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) set(ORTHANC_FRAMEWORK_MD5 "2eaa073cbb4b44ffba199ad93393b2b1") elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "daf4807631c5") # DICOMweb 1.15 (framework pre-1.12.2) - set(ORTHANC_FRAMEWORK_MD5 "c644aff2817306b3207c98c92e43f35f") + set(ORTHANC_FRAMEWORK_PRE_RELEASE ON) + set(ORTHANC_FRAMEWORK_MD5 "ebe8bdf388319f1c9536b2b680451848") endif() endif() endif() @@ -320,7 +333,11 @@ else() # Default case: Download from the official Web site set(ORTHANC_FRAMEMORK_FILENAME Orthanc-${ORTHANC_FRAMEWORK_VERSION}.tar.gz) - set(ORTHANC_FRAMEWORK_URL "https://orthanc.uclouvain.be/third-party-downloads/orthanc-framework/${ORTHANC_FRAMEMORK_FILENAME}") + if (ORTHANC_FRAMEWORK_PRE_RELEASE) + set(ORTHANC_FRAMEWORK_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/orthanc-framework/${ORTHANC_FRAMEMORK_FILENAME}") + else() + set(ORTHANC_FRAMEWORK_URL "https://orthanc.uclouvain.be/downloads/sources/orthanc/${ORTHANC_FRAMEMORK_FILENAME}") + endif() endif() set(ORTHANC_FRAMEWORK_ARCHIVE "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${ORTHANC_FRAMEMORK_FILENAME}")
--- a/Common/Resources/Orthanc/CMake/DownloadPackage.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/CMake/DownloadPackage.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Common/Resources/Orthanc/CMake/EmbedResources.py Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/CMake/EmbedResources.py Tue Jun 25 12:38:31 2024 +0200 @@ -4,7 +4,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Common/Resources/Orthanc/CMake/GoogleTestConfiguration.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/CMake/GoogleTestConfiguration.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -50,7 +51,7 @@ elseif (STATIC_BUILD OR NOT USE_SYSTEM_GOOGLE_TEST) set(GOOGLE_TEST_SOURCES_DIR ${CMAKE_BINARY_DIR}/googletest-release-1.8.1) - set(GOOGLE_TEST_URL "https://orthanc.uclouvain.be/third-party-downloads/gtest-1.8.1.tar.gz") + set(GOOGLE_TEST_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/gtest-1.8.1.tar.gz") set(GOOGLE_TEST_MD5 "2e6fbeb6a91310a16efe181886c59596") DownloadPackage(${GOOGLE_TEST_MD5} ${GOOGLE_TEST_URL} "${GOOGLE_TEST_SOURCES_DIR}")
--- a/Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -3,7 +3,8 @@ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2023 Osimis S.A., Belgium - * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -61,6 +62,7 @@ namespace OrthancPlugins { static OrthancPluginContext* globalContext_ = NULL; + static std::string pluginName_; void SetGlobalContext(OrthancPluginContext* context) @@ -79,9 +81,19 @@ } } + + void SetGlobalContext(OrthancPluginContext* context, + const char* pluginName) + { + SetGlobalContext(context); + pluginName_ = pluginName; + } + + void ResetGlobalContext() { globalContext_ = NULL; + pluginName_.clear(); } bool HasGlobalContext() @@ -103,6 +115,66 @@ } +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 + void LogMessage(OrthancPluginLogLevel level, + const char* file, + uint32_t line, + const std::string& message) + { + if (HasGlobalContext()) + { +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 + const char* pluginName = (pluginName_.empty() ? NULL : pluginName_.c_str()); + OrthancPluginLogMessage(GetGlobalContext(), message.c_str(), pluginName, file, line, OrthancPluginLogCategory_Generic, level); +#else + switch (level) + { + case OrthancPluginLogLevel_Error: + OrthancPluginLogError(GetGlobalContext(), message.c_str()); + break; + + case OrthancPluginLogLevel_Warning: + OrthancPluginLogWarning(GetGlobalContext(), message.c_str()); + break; + + case OrthancPluginLogLevel_Info: + OrthancPluginLogInfo(GetGlobalContext(), message.c_str()); + break; + + default: + ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); + } +#endif + } + } +#endif + + + void LogError(const std::string& message) + { + if (HasGlobalContext()) + { + OrthancPluginLogError(GetGlobalContext(), message.c_str()); + } + } + + void LogWarning(const std::string& message) + { + if (HasGlobalContext()) + { + OrthancPluginLogWarning(GetGlobalContext(), message.c_str()); + } + } + + void LogInfo(const std::string& message) + { + if (HasGlobalContext()) + { + OrthancPluginLogInfo(GetGlobalContext(), message.c_str()); + } + } + + void MemoryBuffer::Check(OrthancPluginErrorCode code) { if (code != OrthancPluginErrorCode_Success) @@ -233,7 +305,7 @@ if (!ReadJson(target, buffer_.data, buffer_.size)) { - LogError("Cannot convert some memory buffer to JSON"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot convert some memory buffer to JSON"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } } @@ -265,7 +337,7 @@ 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) + it = httpHeaders.begin(); it != httpHeaders.end(); ++it) { headersKeys_.push_back(it->first.c_str()); headersValues_.push_back(it->second.c_str()); @@ -404,7 +476,7 @@ } else { - LogError("Cannot parse JSON: " + std::string(err)); + ORTHANC_PLUGINS_LOG_ERROR("Cannot parse JSON: " + std::string(err)); return false; } #endif @@ -565,13 +637,13 @@ { if (str_ == NULL) { - LogError("Cannot convert an empty memory buffer to JSON"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot convert an empty memory buffer to JSON"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } if (!ReadJson(target, str_)) { - LogError("Cannot convert some memory buffer to JSON"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot convert some memory buffer to JSON"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } } @@ -581,13 +653,13 @@ { if (str_ == NULL) { - LogError("Cannot convert an empty memory buffer to JSON"); + ORTHANC_PLUGINS_LOG_ERROR("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_LOG_ERROR("Cannot convert some memory buffer to JSON"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } } @@ -625,7 +697,7 @@ if (body.size() > 0xffffffffu) { - LogError("Cannot handle body size > 4GB"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } @@ -645,7 +717,7 @@ if (body.size() > 0xffffffffu) { - LogError("Cannot handle body size > 4GB"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } @@ -688,34 +760,6 @@ } } - - void LogError(const std::string& message) - { - if (HasGlobalContext()) - { - OrthancPluginLogError(GetGlobalContext(), message.c_str()); - } - } - - - void LogWarning(const std::string& message) - { - if (HasGlobalContext()) - { - OrthancPluginLogWarning(GetGlobalContext(), message.c_str()); - } - } - - - void LogInfo(const std::string& message) - { - if (HasGlobalContext()) - { - OrthancPluginLogInfo(GetGlobalContext(), message.c_str()); - } - } - - void OrthancConfiguration::LoadConfiguration() { OrthancString str; @@ -723,7 +767,7 @@ if (str.GetContent() == NULL) { - LogError("Cannot access the Orthanc configuration"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot access the Orthanc configuration"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } @@ -731,7 +775,7 @@ if (configuration_.type() != Json::objectValue) { - LogError("Unable to read the Orthanc configuration"); + ORTHANC_PLUGINS_LOG_ERROR("Unable to read the Orthanc configuration"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } } @@ -799,8 +843,8 @@ { if (configuration_[key].type() != Json::objectValue) { - LogError("The configuration section \"" + target.path_ + - "\" is not an associative array as expected"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration section \"" + target.path_ + + "\" is not an associative array as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -822,8 +866,8 @@ if (configuration_[key].type() != Json::stringValue) { - LogError("The configuration option \"" + GetPath(key) + - "\" is not a string as expected"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) + + "\" is not a string as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -854,8 +898,8 @@ return true; default: - LogError("The configuration option \"" + GetPath(key) + - "\" is not an integer as expected"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) + + "\" is not an integer as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -873,8 +917,8 @@ if (tmp < 0) { - LogError("The configuration option \"" + GetPath(key) + - "\" is not a positive integer as expected"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) + + "\" is not a positive integer as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -898,8 +942,8 @@ if (configuration_[key].type() != Json::booleanValue) { - LogError("The configuration option \"" + GetPath(key) + - "\" is not a Boolean as expected"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) + + "\" is not a Boolean as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -934,8 +978,8 @@ return true; default: - LogError("The configuration option \"" + GetPath(key) + - "\" is not an integer as expected"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) + + "\" is not an integer as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -994,8 +1038,8 @@ break; } - LogError("The configuration option \"" + GetPath(key) + - "\" is not a list of strings as expected"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) + + "\" is not a list of strings as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -1115,8 +1159,8 @@ if (configuration_[key].type() != Json::objectValue) { - LogError("The configuration option \"" + GetPath(key) + - "\" is not an object as expected"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) + + "\" is not an object as expected"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -1133,8 +1177,8 @@ } else { - LogError("The configuration option \"" + GetPath(key) + - "\" is not a dictionary mapping strings to strings"); + ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) + + "\" is not a dictionary mapping strings to strings"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } @@ -1156,7 +1200,7 @@ { if (image_ == NULL) { - LogError("Trying to access a NULL image"); + ORTHANC_PLUGINS_LOG_ERROR("Trying to access a NULL image"); ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); } } @@ -1182,7 +1226,7 @@ if (image_ == NULL) { - LogError("Cannot create an image"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot create an image"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } } @@ -1199,7 +1243,7 @@ if (image_ == NULL) { - LogError("Cannot create an image accessor"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot create an image accessor"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } } @@ -1213,7 +1257,7 @@ if (image_ == NULL) { - LogError("Cannot uncompress a PNG image"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot uncompress a PNG image"); ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); } } @@ -1226,7 +1270,7 @@ image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Jpeg); if (image_ == NULL) { - LogError("Cannot uncompress a JPEG image"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot uncompress a JPEG image"); ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); } } @@ -1240,7 +1284,7 @@ image_ = OrthancPluginDecodeDicomImage(GetGlobalContext(), data, size, frame); if (image_ == NULL) { - LogError("Cannot uncompress a DICOM image"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot uncompress a DICOM image"); ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); } } @@ -1654,13 +1698,13 @@ unsigned int minor, unsigned int revision) { - LogError("Your version of the Orthanc core (" + - std::string(GetGlobalContext()->orthancVersion) + - ") is too old to run this plugin (version " + - boost::lexical_cast<std::string>(major) + "." + - boost::lexical_cast<std::string>(minor) + "." + - boost::lexical_cast<std::string>(revision) + - " is required)"); + ORTHANC_PLUGINS_LOG_ERROR("Your version of the Orthanc core (" + + std::string(GetGlobalContext()->orthancVersion) + + ") is too old to run this plugin (version " + + boost::lexical_cast<std::string>(major) + "." + + boost::lexical_cast<std::string>(minor) + "." + + boost::lexical_cast<std::string>(revision) + + " is required)"); } bool CheckMinimalVersion(const char* version, @@ -1684,9 +1728,9 @@ 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) + aa < 0 || + bb < 0 || + cc < 0) { return false; } @@ -1740,7 +1784,7 @@ { if (!HasGlobalContext()) { - LogError("Bad Orthanc context in the plugin"); + ORTHANC_PLUGINS_LOG_ERROR("Bad Orthanc context in the plugin"); return false; } @@ -1777,7 +1821,7 @@ } else { - LogError("Inexistent peer: " + name); + ORTHANC_PLUGINS_LOG_ERROR("Inexistent peer: " + name); ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource); } } @@ -2061,7 +2105,7 @@ if (body.size() > 0xffffffffu) { - LogError("Cannot handle body size > 4GB"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } @@ -2098,7 +2142,7 @@ if (body.size() > 0xffffffffu) { - LogError("Cannot handle body size > 4GB"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } @@ -2464,7 +2508,7 @@ if (id == NULL) { - LogError("Plugin cannot submit job"); + ORTHANC_PLUGINS_LOG_ERROR("Plugin cannot submit job"); OrthancPluginFreeJob(GetGlobalContext(), orthanc); ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin); } @@ -2533,7 +2577,7 @@ throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(status["ErrorCode"].asInt()), status["ErrorDescription"].asString()); #else - LogError("Exception while executing the job: " + status["ErrorDescription"].asString()); + ORTHANC_PLUGINS_LOG_ERROR("Exception while executing the job: " + status["ErrorDescription"].asString()); ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt()); #endif } @@ -2558,7 +2602,7 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Expected a JSON object in the body"); #else - LogError("Expected a JSON object in the body"); + ORTHANC_PLUGINS_LOG_ERROR("Expected a JSON object in the body"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); #endif } @@ -2574,7 +2618,7 @@ "Option \"" + std::string(KEY_SYNCHRONOUS) + "\" must be Boolean"); #else - LogError("Option \"" + std::string(KEY_SYNCHRONOUS) + "\" must be Boolean"); + ORTHANC_PLUGINS_LOG_ERROR("Option \"" + std::string(KEY_SYNCHRONOUS) + "\" must be Boolean"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); #endif } @@ -2593,7 +2637,7 @@ "Option \"" + std::string(KEY_ASYNCHRONOUS) + "\" must be Boolean"); #else - LogError("Option \"" + std::string(KEY_ASYNCHRONOUS) + "\" must be Boolean"); + ORTHANC_PLUGINS_LOG_ERROR("Option \"" + std::string(KEY_ASYNCHRONOUS) + "\" must be Boolean"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); #endif } @@ -2607,14 +2651,14 @@ if (body.isMember(KEY_PRIORITY)) { - if (body[KEY_PRIORITY].type() != Json::booleanValue) + if (body[KEY_PRIORITY].type() != Json::intValue) { #if HAS_ORTHANC_EXCEPTION == 1 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Option \"" + std::string(KEY_PRIORITY) + "\" must be an integer"); #else - LogError("Option \"" + std::string(KEY_PRIORITY) + "\" must be an integer"); + ORTHANC_PLUGINS_LOG_ERROR("Option \"" + std::string(KEY_PRIORITY) + "\" must be an integer"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); #endif } @@ -3135,7 +3179,7 @@ if (body.size() > 0xffffffffu) { - LogError("Cannot handle body size > 4GB"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB"); ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); } @@ -3280,7 +3324,7 @@ if (!ReadJson(answerBody, body)) { - LogError("Cannot convert HTTP answer body to JSON"); + ORTHANC_PLUGINS_LOG_ERROR("Cannot convert HTTP answer body to JSON"); ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); } } @@ -4026,4 +4070,48 @@ result[request->headersKeys[i]] = request->headersValues[i]; } } + +#if !ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) + static void SetPluginProperty(const std::string& pluginIdentifier, + _OrthancPluginProperty property, + const std::string& value) + { + _OrthancPluginSetPluginProperty params; + params.plugin = pluginIdentifier.c_str(); + params.property = property; + params.value = value.c_str(); + + GetGlobalContext()->InvokeService(GetGlobalContext(), _OrthancPluginService_SetPluginProperty, ¶ms); + } +#endif + + void SetRootUri(const std::string& pluginIdentifier, + const std::string& uri) + { +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) + OrthancPluginSetRootUri2(GetGlobalContext(), pluginIdentifier.c_str(), uri.c_str()); +#else + SetPluginProperty(pluginIdentifier, _OrthancPluginProperty_RootUri, uri); +#endif + } + + void SetDescription(const std::string& pluginIdentifier, + const std::string& description) + { +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) + OrthancPluginSetDescription2(GetGlobalContext(), pluginIdentifier.c_str(), description.c_str()); +#else + SetPluginProperty(pluginIdentifier, _OrthancPluginProperty_Description, description); +#endif + } + + void ExtendOrthancExplorer(const std::string& pluginIdentifier, + const std::string& javascript) + { +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) + OrthancPluginExtendOrthancExplorer2(GetGlobalContext(), pluginIdentifier.c_str(), javascript.c_str()); +#else + SetPluginProperty(pluginIdentifier, _OrthancPluginProperty_OrthancExplorer, javascript); +#endif + } }
--- a/Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Tue Jun 25 12:38:31 2024 +0200 @@ -3,7 +3,8 @@ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2023 Osimis S.A., Belgium - * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -127,6 +128,44 @@ # define HAS_ORTHANC_PLUGIN_WEBDAV 0 #endif +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) +# define HAS_ORTHANC_PLUGIN_LOG_MESSAGE 1 +#else +# define HAS_ORTHANC_PLUGIN_LOG_MESSAGE 0 +#endif + + +// Macro to tag a function as having been deprecated +#if (__cplusplus >= 201402L) // C++14 +# define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) [[deprecated]] f +#elif defined(__GNUC__) || defined(__clang__) +# define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) f __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) __declspec(deprecated) f +#else +# define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED +#endif + + +#if !defined(__ORTHANC_FILE__) +# if defined(_MSC_VER) +# pragma message("Warning: Macro __ORTHANC_FILE__ is not defined, this will leak the full path of the source files in the binaries") +# else +# warning Warning: Macro __ORTHANC_FILE__ is not defined, this will leak the full path of the source files in the binaries +# endif +# define __ORTHANC_FILE__ __FILE__ +#endif + + +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 +# define ORTHANC_PLUGINS_LOG_ERROR(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Error, __ORTHANC_FILE__, __LINE__, msg) +# define ORTHANC_PLUGINS_LOG_WARNING(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Warning, __ORTHANC_FILE__, __LINE__, msg) +# define ORTHANC_PLUGINS_LOG_INFO(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Info, __ORTHANC_FILE__, __LINE__, msg) +#else +# define ORTHANC_PLUGINS_LOG_ERROR(msg) ::OrthancPlugins::LogError(msg) +# define ORTHANC_PLUGINS_LOG_WARNING(msg) ::OrthancPlugins::LogWarning(msg) +# define ORTHANC_PLUGINS_LOG_INFO(msg) ::OrthancPlugins::LogInfo(msg) +#endif namespace OrthancPlugins @@ -137,6 +176,9 @@ void SetGlobalContext(OrthancPluginContext* context); + void SetGlobalContext(OrthancPluginContext* context, + const char* pluginName); + void ResetGlobalContext(); bool HasGlobalContext(); @@ -637,11 +679,33 @@ const char* AutodetectMimeType(const std::string& path); #endif +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 + void LogMessage(OrthancPluginLogLevel level, + const char* file, + uint32_t line, + const std::string& message); +#endif + +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 + // Use macro ORTHANC_PLUGINS_LOG_ERROR() instead + ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogError(const std::string& message)); +#else void LogError(const std::string& message); +#endif +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 + // Use macro ORTHANC_PLUGINS_LOG_WARNING() instead + ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogWarning(const std::string& message)); +#else void LogWarning(const std::string& message); +#endif +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 + // Use macro ORTHANC_PLUGINS_LOG_INFO() instead + ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogInfo(const std::string& message)); +#else void LogInfo(const std::string& message); +#endif void ReportMinimalOrthancVersion(unsigned int major, unsigned int minor, @@ -1435,4 +1499,13 @@ IWebDavCollection& collection); }; #endif + + void SetRootUri(const std::string& pluginIdentifier, + const std::string& uri); + + void SetDescription(const std::string& pluginIdentifier, + const std::string& description); + + void ExtendOrthancExplorer(const std::string& pluginIdentifier, + const std::string& javascript); }
--- a/Common/Resources/Orthanc/Plugins/OrthancPluginException.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/Plugins/OrthancPluginException.h Tue Jun 25 12:38:31 2024 +0200 @@ -3,7 +3,8 @@ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2023 Osimis S.A., Belgium - * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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/Common/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Common/Resources/Orthanc/Toolchains/LinuxStandardBaseToolchain.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/Toolchains/LinuxStandardBaseToolchain.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Common/Resources/Orthanc/Toolchains/MinGW-W64-Toolchain32.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/Toolchains/MinGW-W64-Toolchain32.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Common/Resources/Orthanc/Toolchains/MinGW-W64-Toolchain64.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/Toolchains/MinGW-W64-Toolchain64.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Common/Resources/Orthanc/Toolchains/MinGWToolchain.cmake Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/Orthanc/Toolchains/MinGWToolchain.cmake Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,8 @@ # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics # Department, University Hospital of Liege, Belgium # Copyright (C) 2017-2023 Osimis S.A., Belgium -# Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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/Common/Resources/SyncOrthancFolder.py Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/Resources/SyncOrthancFolder.py Tue Jun 25 12:38:31 2024 +0200 @@ -11,7 +11,7 @@ import urllib.request TARGET = os.path.join(os.path.dirname(__file__), 'Orthanc') -PLUGIN_SDK_VERSION = '1.12.1' +PLUGIN_SDK_VERSION = '1.12.3' REPOSITORY = 'https://orthanc.uclouvain.be/hg/orthanc/raw-file' FILES = [
--- a/Common/StoragePlugin.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/StoragePlugin.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -48,6 +50,12 @@ #include "StoragePlugin.h" #include <Toolbox.h> +#ifdef _WIN32 +// This is a hotfix for: https://orthanc.uclouvain.be/hg/orthanc/rev/e4d9a872998f +# undef ORTHANC_PLUGINS_API +# define ORTHANC_PLUGINS_API __declspec(dllexport) +#endif + static std::unique_ptr<IStorage> primaryStorage; static std::unique_ptr<IStorage> secondaryStorage; @@ -79,6 +87,16 @@ typedef void LogErrorFunction(const std::string& message); +static void LogErrorAsWarning(const std::string& message) +{ + LOG(WARNING) << message; +} + +static void LogErrorAsError(const std::string& message) +{ + LOG(ERROR) << message; +} + static OrthancPluginErrorCode StorageCreate(const char* uuid, @@ -88,7 +106,9 @@ { try { - OrthancPlugins::LogInfo(primaryStorage->GetNameForLogs() + ": creating attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); + Orthanc::Toolbox::ElapsedTimer timer; + LOG(INFO) << primaryStorage->GetNameForLogs() << ": creating attachment " << uuid + << " of type " << boost::lexical_cast<std::string>(type); std::unique_ptr<IStorage::IWriter> writer(primaryStorage->GetWriterForObject(uuid, type, cryptoEnabled)); if (cryptoEnabled) @@ -101,7 +121,7 @@ } catch (EncryptionException& ex) { - OrthancPlugins::LogError(primaryStorage->GetNameForLogs() + ": error while encrypting object " + std::string(uuid) + ": " + ex.what()); + LOG(ERROR) << primaryStorage->GetNameForLogs() << ": error while encrypting object " << uuid << ": " << ex.what(); return OrthancPluginErrorCode_StorageAreaPlugin; } @@ -111,10 +131,12 @@ { writer->Write(reinterpret_cast<const char*>(content), size); } + LOG(INFO) << primaryStorage->GetNameForLogs() << ": created attachment " << uuid + << " (" << timer.GetHumanTransferSpeed(true, size) << ")"; } catch (StoragePluginException& ex) { - OrthancPlugins::LogError(primaryStorage->GetNameForLogs() + ": error while creating object " + std::string(uuid) + ": " + ex.what()); + LOG(ERROR) << primaryStorage->GetNameForLogs() << ": error while creating object " << uuid << ": " << ex.what(); return OrthancPluginErrorCode_StorageAreaPlugin; } @@ -133,11 +155,15 @@ try { - OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": reading range of attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); + Orthanc::Toolbox::ElapsedTimer timer; + LOG(INFO) << storage->GetNameForLogs() << ": reading range of attachment " << uuid + << " of type " << boost::lexical_cast<std::string>(type); std::unique_ptr<IStorage::IReader> reader(storage->GetReaderForObject(uuid, type, cryptoEnabled)); reader->ReadRange(reinterpret_cast<char*>(target->data), target->size, rangeStart); + LOG(INFO) << storage->GetNameForLogs() << ": read range of attachment " << uuid + << " (" << timer.GetHumanTransferSpeed(true, target->size) << ")"; return OrthancPluginErrorCode_Success; } catch (StoragePluginException& ex) @@ -153,7 +179,7 @@ uint64_t rangeStart) { OrthancPluginErrorCode res = StorageReadRange(primaryStorage.get(), - (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try + (IsHybridModeEnabled() ? LogErrorAsWarning : LogErrorAsError), // log errors as warning on first try target, uuid, type, @@ -162,7 +188,7 @@ if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) { res = StorageReadRange(secondaryStorage.get(), - OrthancPlugins::LogError, // log errors as errors on second try + LogErrorAsError, // log errors as errors on second try target, uuid, type, @@ -181,7 +207,9 @@ { try { - OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": reading whole attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); + Orthanc::Toolbox::ElapsedTimer timer; + LOG(INFO) << storage->GetNameForLogs() << ": reading whole attachment " << uuid + << " of type " << boost::lexical_cast<std::string>(type); std::unique_ptr<IStorage::IReader> reader(storage->GetReaderForObject(uuid, type, cryptoEnabled)); size_t fileSize = reader->GetSize(); @@ -227,6 +255,9 @@ { reader->ReadWhole(reinterpret_cast<char*>(target->data), fileSize); } + + LOG(INFO) << storage->GetNameForLogs() << ": read whole attachment " << uuid + << " (" << timer.GetHumanTransferSpeed(true, fileSize) << ")"; } catch (StoragePluginException& ex) { @@ -242,7 +273,7 @@ OrthancPluginContentType type) { OrthancPluginErrorCode res = StorageReadWhole(primaryStorage.get(), - (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try + (IsHybridModeEnabled() ? LogErrorAsWarning : LogErrorAsError), // log errors as warning on first try target, uuid, type); @@ -250,7 +281,7 @@ if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) { res = StorageReadWhole(secondaryStorage.get(), - OrthancPlugins::LogError, // log errors as errors on second try + LogErrorAsError, // log errors as errors on second try target, uuid, type); @@ -283,7 +314,8 @@ { try { - OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": deleting attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); + LOG(INFO) << storage->GetNameForLogs() << ": deleting attachment " << uuid + << " of type " << boost::lexical_cast<std::string>(type); storage->DeleteObject(uuid, type, cryptoEnabled); if ((storage == primaryStorage.get()) && IsHybridModeEnabled()) { @@ -304,14 +336,14 @@ OrthancPluginContentType type) { OrthancPluginErrorCode res = StorageRemove(primaryStorage.get(), - (IsHybridModeEnabled() ? OrthancPlugins::LogWarning : OrthancPlugins::LogError), // log errors as warning on first try + (IsHybridModeEnabled() ? LogErrorAsWarning : LogErrorAsError), // log errors as warning on first try uuid, type); if (res != OrthancPluginErrorCode_Success && IsHybridModeEnabled()) { res = StorageRemove(secondaryStorage.get(), - OrthancPlugins::LogError, // log errors as errors on second try + LogErrorAsError, // log errors as errors on second try uuid, type); } @@ -443,7 +475,7 @@ } } - OrthancPlugins::LogInfo("Moving " + boost::lexical_cast<std::string>(instances.size()) + " instances to " + targetStorage); + LOG(INFO) << "Moving " << instances.size() << " instances to " << targetStorage; std::unique_ptr<MoveStorageJob> job(CreateMoveStorageJob(targetStorage, instances, resourcesForJobContent)); @@ -521,13 +553,13 @@ { OrthancPlugins::SetGlobalContext(context); - Orthanc::InitializeFramework("", false); +#if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4) + Orthanc::Logging::InitializePluginContext(context, StoragePluginFactory::GetStoragePluginName()); +#elif ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 7, 2) Orthanc::Logging::InitializePluginContext(context); - - OrthancPlugins::OrthancConfiguration orthancConfig; - - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is initializing"); - OrthancPluginSetDescription(context, StoragePluginFactory::GetStorageDescription()); +#else + Orthanc::Logging::Initialize(context); +#endif /* Check the version of the Orthanc core */ if (OrthancPluginCheckVersion(context) == 0) @@ -538,10 +570,17 @@ ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); - OrthancPlugins::LogError(info); + LOG(ERROR) << info; return -1; } + Orthanc::InitializeFramework("", false); + + OrthancPlugins::OrthancConfiguration orthancConfig; + + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << " plugin is initializing"; + OrthancPlugins::SetDescription(StoragePluginFactory::GetStoragePluginName(), StoragePluginFactory::GetStorageDescription()); + try { const char* pluginSectionName = StoragePluginFactory::GetConfigurationSectionName(); @@ -549,7 +588,8 @@ if (!orthancConfig.IsSection(pluginSectionName)) { - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": no \"" + pluginSectionName + "\" section found in configuration, plugin is disabled"); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": no \"" << pluginSectionName + << "\" section found in configuration, plugin is disabled"; return 0; } @@ -562,34 +602,34 @@ if (migrationFromFileSystemEnabled && hybridModeString == "Disabled") { hybridMode = HybridMode_WriteToObjectStorage; - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": 'MigrationFromFileSystemEnabled' configuration is deprecated, use 'HybridMode': 'WriteToObjectStorage' instead"); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": 'MigrationFromFileSystemEnabled' configuration is deprecated, use 'HybridMode': 'WriteToObjectStorage' instead"; } else if (hybridModeString == "WriteToObjectStorage") { hybridMode = HybridMode_WriteToObjectStorage; - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": WriteToObjectStorage HybridMode is enabled: writing to object-storage, try reading first from object-storage and, then, from file system"); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": WriteToObjectStorage HybridMode is enabled: writing to object-storage, try reading first from object-storage and, then, from file system"; } else if (hybridModeString == "WriteToFileSystem") { hybridMode = HybridMode_WriteToFileSystem; - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": WriteToFileSystem HybridMode is enabled: writing to file system, try reading first from file system and, then, from object-storage"); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": WriteToFileSystem HybridMode is enabled: writing to file system, try reading first from file system and, then, from object-storage"; } else { - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": HybridMode is disabled: writing to object-storage and reading only from object-storage"); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": HybridMode is disabled: writing to object-storage and reading only from object-storage"; } if (IsReadFromDisk()) { fileSystemRootPath = orthancConfig.GetStringValue("StorageDirectory", "OrthancStorageNotDefined"); - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": HybridMode: reading from file system is enabled, source: " + fileSystemRootPath); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": HybridMode: reading from file system is enabled, source: " << fileSystemRootPath; } objectsRootPath = pluginSection.GetStringValue("RootPath", std::string()); if (objectsRootPath.size() >= 1 && objectsRootPath[0] == '/') { - OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": The RootPath shall not start with a '/': " + objectsRootPath); + LOG(ERROR) << StoragePluginFactory::GetStoragePluginName() << ": The RootPath shall not start with a '/': " << objectsRootPath; return -1; } @@ -656,11 +696,11 @@ if (cryptoEnabled) { - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is enabled"); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": client-side encryption is enabled"; } else { - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is disabled"); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << ": client-side encryption is disabled"; } @@ -692,7 +732,7 @@ ORTHANC_PLUGINS_API void OrthancPluginFinalize() { - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is finalizing"); + LOG(WARNING) << StoragePluginFactory::GetStoragePluginName() << " plugin is finalizing"; primaryStorage.reset(); secondaryStorage.reset(); Orthanc::FinalizeFramework();
--- a/Common/StoragePlugin.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Common/StoragePlugin.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Transfers accelerator plugin for Orthanc - * Copyright (C) 2018-2021 Osimis S.A., Belgium + * Copyright (C) 2018-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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/Dockerfile Tue Nov 21 09:50:24 2023 +0100 +++ b/Dockerfile Tue Jun 25 12:38:31 2024 +0200 @@ -11,7 +11,7 @@ WORKDIR /sources # (framework version used to build the cloud storage plugins) -RUN hg clone https://hg.orthanc-server.com/orthanc/ -r "Orthanc-1.10.1" +RUN hg clone https://orthanc.uclouvain.be/hg/orthanc/ -r "Orthanc-1.10.1" RUN mkdir orthanc-object-storage
--- a/Google/CMakeLists.txt Tue Nov 21 09:50:24 2023 +0100 +++ b/Google/CMakeLists.txt Tue Jun 25 12:38:31 2024 +0200 @@ -1,5 +1,7 @@ # Cloud storage plugins for Orthanc -# Copyright (C) 2020-2021 Osimis S.A., Belgium +# Copyright (C) 2020-2023 Osimis S.A., Belgium +# Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +# Copyright (C) 2021-2024 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 @@ -19,14 +21,25 @@ project(OrthancGoogleCloudStorage) -set(PLUGIN_VERSION "2.3.0") +set(PLUGIN_VERSION "mainline") + +if (PLUGIN_VERSION STREQUAL "mainline") + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline") + set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") +else() + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "1.12.4") + set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") +endif() + +set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc framework (can be \"system\", \"hg\", \"archive\", \"web\" or \"path\")") +set(ORTHANC_FRAMEWORK_VERSION "${ORTHANC_FRAMEWORK_DEFAULT_VERSION}" CACHE STRING "Version of the Orthanc framework") +set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") +set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") +set(ALLOW_DOWNLOADS ON) + include(CheckIncludeFileCXX) -set(ORTHANC_FRAMEWORK_SOURCE "web" CACHE STRING "orthanc source") -set(ORTHANC_FRAMEWORK_VERSION "daf4807631c5" CACHE STRING "orthanc framework version") # TODO: update to 1.12.2 when available -set(ALLOW_DOWNLOADS ON) - # Download and setup the Orthanc framework include(${CMAKE_SOURCE_DIR}/../Common/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake) @@ -86,7 +99,10 @@ ${COMMON_SOURCES} ) -DefineSourceBasenameForTarget(OrthancGoogleCloudStorage) +if (COMMAND DefineSourceBasenameForTarget) + DefineSourceBasenameForTarget(OrthancGoogleCloudStorage) +endif() + set_target_properties(OrthancGoogleCloudStorage PROPERTIES VERSION ${PLUGIN_VERSION} @@ -101,6 +117,12 @@ cryptopp::cryptopp ) +install( + TARGETS OrthancGoogleCloudStorage + RUNTIME DESTINATION lib # Destination for Windows + LIBRARY DESTINATION share/orthanc/plugins # Destination for Linux +) + add_executable(UnitTests ${GOOGLE_TEST_SOURCES} ${COMMON_SOURCES}
--- a/Google/GoogleStoragePlugin.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/Google/GoogleStoragePlugin.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -21,6 +23,8 @@ #include "google/cloud/storage/client.h" +#include <Logging.h> + // Create aliases to make the code easier to read. namespace gcs = google::cloud::storage; @@ -42,10 +46,10 @@ bool storageContainsUnknownFiles ); - virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); - virtual bool HasFileExists() {return false;}; + virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) ORTHANC_OVERRIDE; + virtual bool HasFileExists() ORTHANC_OVERRIDE {return false;}; }; @@ -67,7 +71,7 @@ { } - virtual void Write(const char* data, size_t size) + virtual void Write(const char* data, size_t size) ORTHANC_OVERRIDE { stream_ = client_.WriteObject(bucketName_, path_); @@ -108,7 +112,7 @@ } - virtual size_t GetSize() + virtual size_t GetSize() ORTHANC_OVERRIDE { std::string firstExceptionMessage; @@ -130,7 +134,7 @@ throw StoragePluginException(firstExceptionMessage); } - void ReadWhole(char* data, size_t size) + virtual void ReadWhole(char* data, size_t size) ORTHANC_OVERRIDE { std::string firstExceptionMessage; @@ -152,7 +156,7 @@ throw StoragePluginException(firstExceptionMessage); } - void ReadRange(char* data, size_t size, size_t fromOffset) + virtual void ReadRange(char* data, size_t size, size_t fromOffset) ORTHANC_OVERRIDE { std::string firstExceptionMessage; @@ -175,7 +179,7 @@ } private: - virtual void _ReadWhole(const std::string& path, char* data, size_t size) + void _ReadWhole(const std::string& path, char* data, size_t size) { auto reader = client_.ReadObject(bucketName_, path); @@ -192,7 +196,7 @@ } } - virtual void _ReadRange(const std::string& path, char* data, size_t size, size_t fromOffset) + void _ReadRange(const std::string& path, char* data, size_t size, size_t fromOffset) { auto reader = client_.ReadObject(bucketName_, path, gcs::ReadRange(fromOffset, fromOffset + size)); @@ -221,7 +225,7 @@ } else { - throw StoragePluginException("error while getting the size of " + std::string(path) + ": " + objectMetadata.status().message()); + throw StoragePluginException("error while getting the size of " + std::string(path) + ": " + objectMetadata.status().message()); } } @@ -246,7 +250,7 @@ if (!orthancConfig.IsSection(GetConfigurationSectionName())) { - OrthancPlugins::LogWarning(std::string(GetStoragePluginName()) + " plugin, section missing. Plugin is not enabled."); + LOG(WARNING) << GetStoragePluginName() << " plugin, section missing. Plugin is not enabled."; return nullptr; } @@ -262,14 +266,14 @@ if (!pluginSection.LookupStringValue(pathToGoogleCredentials, "ServiceAccountFile")) { - OrthancPlugins::LogError("GoogleCloudStorage/ServiceAccountFile configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "GoogleCloudStorage/ServiceAccountFile configuration missing. Unable to initialize plugin"; return nullptr; } std::string googleBucketName; if (!pluginSection.LookupStringValue(googleBucketName, "BucketName")) { - OrthancPlugins::LogError("GoogleCloudStorage/BucketName configuration missing. Unable to initialize plugin"); + LOG(ERROR) << "GoogleCloudStorage/BucketName configuration missing. Unable to initialize plugin"; return nullptr; } @@ -277,7 +281,7 @@ auto creds = gcs::oauth2::CreateServiceAccountCredentialsFromJsonFilePath(pathToGoogleCredentials); if (!creds) { - OrthancPlugins::LogError("GoogleCloudStorage plugin: unable to validate credentials. Check the ServiceAccountFile: " + creds.status().message()); + LOG(ERROR) << "GoogleCloudStorage plugin: unable to validate credentials. Check the ServiceAccountFile: " << creds.status().message(); return nullptr; } @@ -286,7 +290,7 @@ if (!mainClient) { - OrthancPlugins::LogError("GoogleCloudStorage plugin: unable to create client: " + mainClient.status().message()); + LOG(ERROR) << "GoogleCloudStorage plugin: unable to create client: " << mainClient.status().message(); return nullptr; }
--- a/Google/GoogleStoragePlugin.h Tue Nov 21 09:50:24 2023 +0100 +++ b/Google/GoogleStoragePlugin.h Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 Tue Nov 21 09:50:24 2023 +0100 +++ b/NEWS Tue Jun 25 12:38:31 2024 +0200 @@ -1,3 +1,14 @@ +Pending changes in the mainline +=============================== + + +2023-12-20 - v 2.3.1 +==================== + +* AWS plugin: + * New configuration "EnableAwsSdkLogs" to include AWS SDK logs in Orthanc logs. +* Now displaying size, duration and transfer speed for each read/write operation. + 2023-10-17 - v 2.3.0 ====================
--- a/README.md Tue Nov 21 09:50:24 2023 +0100 +++ b/README.md Tue Jun 25 12:38:31 2024 +0200 @@ -2,7 +2,7 @@ Orthanc object-storages plugin for main cloud providers (Google/Azure/AWS) -Check the [Orthanc book](https://book.orthanc-server.com/plugins/object-storage.html) for complete documentation. +Check the [Orthanc book](https://orthanc.uclouvain.be/book/plugins/object-storage.html) for complete documentation. ## info for developers ##
--- a/TODO Tue Nov 21 09:50:24 2023 +0100 +++ b/TODO Tue Jun 25 12:38:31 2024 +0200 @@ -5,3 +5,6 @@ - Test against AWS S3 Glacier: https://groups.google.com/g/orthanc-users/c/CT1lkzHLAUg/m/h75HuXYpBwAJ + +- AWS: use the latest aws S3-crt client ? + https://github.com/aws/aws-sdk-cpp/wiki/Improving-S3-Throughput-with-AWS-SDK-for-CPP-v1.9
--- a/UnitTestsSources/EncryptionTests.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/UnitTestsSources/EncryptionTests.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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 @@ -232,11 +234,12 @@ void MeasurePerformance(size_t sizeInMB, EncryptionHelpers& crypto) { - std::string largePlainText(sizeInMB * 1024 * 1024, 'A'); std::string encryptedMessage; std::string decryptedMessage; { + const std::string largePlainText(sizeInMB * 1024 * 1024, 'A'); + auto start = boost::posix_time::microsec_clock::local_time(); crypto.Encrypt(encryptedMessage, largePlainText);
--- a/UnitTestsSources/UnitTestsGcsClient.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/UnitTestsSources/UnitTestsGcsClient.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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/UnitTestsSources/UnitTestsMain.cpp Tue Nov 21 09:50:24 2023 +0100 +++ b/UnitTestsSources/UnitTestsMain.cpp Tue Jun 25 12:38:31 2024 +0200 @@ -1,6 +1,8 @@ /** * Cloud storage plugins for Orthanc - * Copyright (C) 2020-2021 Osimis S.A., Belgium + * Copyright (C) 2020-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 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