# HG changeset patch # User Alain Mazy # Date 1598958529 -7200 # Node ID 2a02b21f0a19a696b61d56c010329dc703f111dc # Parent 234946ea20387ef4f43952b25a5a603f4dd86e90 migration + storage structure diff -r 234946ea2038 -r 2a02b21f0a19 Aws/AwsS3StoragePlugin.cpp --- a/Aws/AwsS3StoragePlugin.cpp Wed Aug 26 12:52:37 2020 +0200 +++ b/Aws/AwsS3StoragePlugin.cpp Tue Sep 01 13:08:49 2020 +0200 @@ -32,8 +32,9 @@ #include const char* ALLOCATION_TAG = "OrthancS3"; +static const char* const PLUGIN_SECTION = "AwsS3Storage"; -class AwsS3StoragePlugin : public IStoragePlugin +class AwsS3StoragePlugin : public BaseStoragePlugin { public: @@ -42,13 +43,12 @@ public: - AwsS3StoragePlugin(const Aws::S3::S3Client& client, const std::string& bucketName); + AwsS3StoragePlugin(const Aws::S3::S3Client& client, const std::string& bucketName, bool enableLegacyStorageStructure); 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); -private: - virtual std::string GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); + virtual const char* GetConfigurationSectionName() {return PLUGIN_SECTION;}; }; @@ -178,7 +178,8 @@ IStoragePlugin* AwsS3StoragePluginFactory::CreateStoragePlugin(const OrthancPlugins::OrthancConfiguration& orthancConfig) { - static const char* const PLUGIN_SECTION = "AwsS3Storage"; + bool enableLegacyStorageStructure; + if (!orthancConfig.IsSection(PLUGIN_SECTION)) { OrthancPlugins::LogWarning(std::string(GetStoragePluginName()) + " plugin, section missing. Plugin is not enabled."); @@ -188,6 +189,11 @@ OrthancPlugins::OrthancConfiguration pluginSection; orthancConfig.GetSection(pluginSection, PLUGIN_SECTION); + if (!BaseStoragePlugin::ReadCommonConfiguration(enableLegacyStorageStructure, pluginSection)) + { + return nullptr; + } + std::string bucketName; std::string region; std::string accessKey; @@ -242,7 +248,7 @@ OrthancPlugins::LogInfo("AWS S3 storage initialized"); - return new AwsS3StoragePlugin(client, bucketName); + return new AwsS3StoragePlugin(client, bucketName, enableLegacyStorageStructure); } catch (const std::exception& e) { @@ -252,8 +258,9 @@ } -AwsS3StoragePlugin::AwsS3StoragePlugin(const Aws::S3::S3Client& client, const std::string& bucketName) - : client_(client), +AwsS3StoragePlugin::AwsS3StoragePlugin(const Aws::S3::S3Client& client, const std::string& bucketName, bool enableLegacyStorageStructure) + : BaseStoragePlugin(enableLegacyStorageStructure), + client_(client), bucketName_(bucketName) { @@ -285,27 +292,3 @@ } } - -std::string AwsS3StoragePlugin::GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) -{ - std::string path = std::string(uuid); - - if (type == OrthancPluginContentType_Dicom) - { - path += ".dcm"; - } - else if (type == OrthancPluginContentType_DicomAsJson) - { - path += ".json"; - } - else - { - path += ".unk"; - } - - if (encryptionEnabled) - { - path += ".enc"; - } - return path; -} diff -r 234946ea2038 -r 2a02b21f0a19 Aws/AwsS3StoragePlugin.h --- a/Aws/AwsS3StoragePlugin.h Wed Aug 26 12:52:37 2020 +0200 +++ b/Aws/AwsS3StoragePlugin.h Tue Sep 01 13:08:49 2020 +0200 @@ -18,7 +18,7 @@ #pragma once -#include "../Common/IStoragePlugin.h" +#include "../Common/BaseStoragePlugin.h" class AwsS3StoragePluginFactory { diff -r 234946ea2038 -r 2a02b21f0a19 Aws/CMakeLists.txt --- a/Aws/CMakeLists.txt Wed Aug 26 12:52:37 2020 +0200 +++ b/Aws/CMakeLists.txt Tue Sep 01 13:08:49 2020 +0200 @@ -9,32 +9,31 @@ include(CheckIncludeFileCXX) set(ORTHANC_FRAMEWORK_SOURCE "hg" CACHE STRING "orthanc source") -set(ORTHANC_FRAMEWORK_VERSION "7176ebf" CACHE STRING "orthanc framework version") +set(ORTHANC_FRAMEWORK_VERSION "1.7.3" CACHE STRING "orthanc framework version") set(ALLOW_DOWNLOADS ON) # Download and setup the Orthanc framework include(${CMAKE_SOURCE_DIR}/../Common/Resources/DownloadOrthancFramework.cmake) -include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake) +include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkParameters.cmake) set(ENABLE_GOOGLE_TEST ON) set(ORTHANC_FRAMEWORK_PLUGIN ON) -include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkConfiguration.cmake) +include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkConfiguration.cmake) add_definitions( -DHAS_ORTHANC_EXCEPTION=1 - -DORTHANC_ENABLE_LOGGING_PLUGIN=1 + -DORTHANC_ENABLE_LOGGING=1 -DAWS_STORAGE_PLUGIN=1 ) add_definitions(-DPLUGIN_VERSION="${PLUGIN_VERSION}") include_directories( - ${ORTHANC_ROOT} - ${ORTHANC_ROOT}/Core - ${ORTHANC_ROOT}/Plugins/Include - ${ORTHANC_ROOT}/Plugins/Samples/Common + ${ORTHANC_FRAMEWORK_ROOT} + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Include + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common ) @@ -45,11 +44,13 @@ set(COMMON_SOURCES ${CMAKE_SOURCE_DIR}/../Common/IStoragePlugin.h + ${CMAKE_SOURCE_DIR}/../Common/BaseStoragePlugin.h + ${CMAKE_SOURCE_DIR}/../Common/BaseStoragePlugin.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionHelpers.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionHelpers.h ${CMAKE_SOURCE_DIR}/../Common/EncryptionConfigurator.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionConfigurator.h - ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp ${ORTHANC_CORE_SOURCES} ) diff -r 234946ea2038 -r 2a02b21f0a19 Azure/AzureBlobStoragePlugin.cpp --- a/Azure/AzureBlobStoragePlugin.cpp Wed Aug 26 12:52:37 2020 +0200 +++ b/Azure/AzureBlobStoragePlugin.cpp Tue Sep 01 13:08:49 2020 +0200 @@ -27,9 +27,9 @@ // Create aliases to make the code easier to read. namespace as = azure::storage; - +static const char* const PLUGIN_SECTION = "AzureBlobStorage"; -class AzureBlobStoragePlugin : public IStoragePlugin +class AzureBlobStoragePlugin : public BaseStoragePlugin { public: @@ -40,13 +40,12 @@ // AzureBlobStoragePlugin(const std::string& connectionString, // const std::string& containerName // ); - AzureBlobStoragePlugin(const as::cloud_blob_client& blobClient, const as::cloud_blob_container& blobContainer); + AzureBlobStoragePlugin(const as::cloud_blob_client& blobClient, const as::cloud_blob_container& blobContainer, bool enableLegacyStorageStructure); 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); -private: - virtual std::string GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); + virtual const char* GetConfigurationSectionName() {return PLUGIN_SECTION;}; }; @@ -152,13 +151,18 @@ { std::string connectionString; std::string containerName; + bool enableLegacyStorageStructure; - static const char* const PLUGIN_SECTION = "AzureBlobStorage"; if (orthancConfig.IsSection(PLUGIN_SECTION)) { OrthancPlugins::OrthancConfiguration pluginSection; orthancConfig.GetSection(pluginSection, PLUGIN_SECTION); + if (!BaseStoragePlugin::ReadCommonConfiguration(enableLegacyStorageStructure, pluginSection)) + { + return nullptr; + } + if (!pluginSection.LookupStringValue(connectionString, "ConnectionString")) { OrthancPlugins::LogError("AzureBlobStorage/ConnectionString configuration missing. Unable to initialize plugin"); @@ -235,7 +239,7 @@ OrthancPlugins::LogInfo("Blob storage initialized"); - return new AzureBlobStoragePlugin(blobClient, blobContainer); + return new AzureBlobStoragePlugin(blobClient, blobContainer, enableLegacyStorageStructure); } catch (const std::exception& e) { @@ -245,8 +249,9 @@ } -AzureBlobStoragePlugin::AzureBlobStoragePlugin(const as::cloud_blob_client& blobClient, const as::cloud_blob_container& blobContainer) //const std::string &containerName) //, google::cloud::storage::Client& mainClient) - : blobClient_(blobClient), +AzureBlobStoragePlugin::AzureBlobStoragePlugin(const as::cloud_blob_client& blobClient, const as::cloud_blob_container& blobContainer, bool enableLegacyStorageStructure) + : BaseStoragePlugin(enableLegacyStorageStructure), + blobClient_(blobClient), blobContainer_(blobContainer) { @@ -277,27 +282,3 @@ throw StoragePluginException("AzureBlobStorage: error while deleting file " + std::string(path) + ": " + ex.what()); } } - -std::string AzureBlobStoragePlugin::GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) -{ - std::string path = std::string(uuid); - - if (type == OrthancPluginContentType_Dicom) - { - path += ".dcm"; - } - else if (type == OrthancPluginContentType_DicomAsJson) - { - path += ".json"; - } - else - { - path += ".unk"; - } - - if (encryptionEnabled) - { - path += ".enc"; - } - return path; -} diff -r 234946ea2038 -r 2a02b21f0a19 Azure/AzureBlobStoragePlugin.h --- a/Azure/AzureBlobStoragePlugin.h Wed Aug 26 12:52:37 2020 +0200 +++ b/Azure/AzureBlobStoragePlugin.h Tue Sep 01 13:08:49 2020 +0200 @@ -18,7 +18,7 @@ #pragma once -#include "../Common/IStoragePlugin.h" +#include "../Common/BaseStoragePlugin.h" class AzureBlobStoragePluginFactory { diff -r 234946ea2038 -r 2a02b21f0a19 Azure/CMakeLists.txt --- a/Azure/CMakeLists.txt Wed Aug 26 12:52:37 2020 +0200 +++ b/Azure/CMakeLists.txt Tue Sep 01 13:08:49 2020 +0200 @@ -7,32 +7,31 @@ include(CheckIncludeFileCXX) set(ORTHANC_FRAMEWORK_SOURCE "hg" CACHE STRING "orthanc source") -set(ORTHANC_FRAMEWORK_VERSION "7176ebf" CACHE STRING "orthanc framework version") +set(ORTHANC_FRAMEWORK_VERSION "1.7.3" CACHE STRING "orthanc framework version") set(ALLOW_DOWNLOADS ON) # Download and setup the Orthanc framework include(${CMAKE_SOURCE_DIR}/../Common/Resources/DownloadOrthancFramework.cmake) -include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake) +include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkParameters.cmake) set(ENABLE_GOOGLE_TEST ON) set(ORTHANC_FRAMEWORK_PLUGIN ON) -include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkConfiguration.cmake) +include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkConfiguration.cmake) add_definitions( -DHAS_ORTHANC_EXCEPTION=1 - -DORTHANC_ENABLE_LOGGING_PLUGIN=1 + -DORTHANC_ENABLE_LOGGING=1 -DAZURE_STORAGE_PLUGIN=1 ) add_definitions(-DPLUGIN_VERSION="${PLUGIN_VERSION}") include_directories( - ${ORTHANC_ROOT} - ${ORTHANC_ROOT}/Core - ${ORTHANC_ROOT}/Plugins/Include - ${ORTHANC_ROOT}/Plugins/Samples/Common + ${ORTHANC_FRAMEWORK_ROOT} + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Include + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common ) @@ -50,11 +49,13 @@ set(COMMON_SOURCES ${CMAKE_SOURCE_DIR}/../Common/IStoragePlugin.h + ${CMAKE_SOURCE_DIR}/../Common/BaseStoragePlugin.h + ${CMAKE_SOURCE_DIR}/../Common/BaseStoragePlugin.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionHelpers.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionHelpers.h ${CMAKE_SOURCE_DIR}/../Common/EncryptionConfigurator.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionConfigurator.h - ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp ${ORTHANC_CORE_SOURCES} ) diff -r 234946ea2038 -r 2a02b21f0a19 Common/BaseStoragePlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Common/BaseStoragePlugin.cpp Tue Sep 01 13:08:49 2020 +0200 @@ -0,0 +1,67 @@ +#include "BaseStoragePlugin.h" +#include + +std::string BaseStoragePlugin::GetOrthancFileSystemPath(const std::string& uuid, const std::string& fileSystemRootPath) +{ + boost::filesystem::path path = fileSystemRootPath; + + path /= std::string(&uuid[0], &uuid[2]); + path /= std::string(&uuid[2], &uuid[4]); + path /= uuid; + + path.make_preferred(); + + return path.string(); +} + + +std::string BaseStoragePlugin::GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) +{ + if (enableLegacyStorageStructure_) + { + return GetOrthancFileSystemPath(uuid, std::string()); // there's no "root" path in an object store + } + else + { + std::string path = std::string(uuid); + + if (type == OrthancPluginContentType_Dicom) + { + path += ".dcm"; + } + else if (type == OrthancPluginContentType_DicomAsJson) + { + path += ".json"; + } + else + { + path += ".unk"; + } + + if (encryptionEnabled) + { + path += ".enc"; + } + return path; + } +} + +bool BaseStoragePlugin::ReadCommonConfiguration(bool& enableLegacyStorageStructure, const OrthancPlugins::OrthancConfiguration& pluginSection) +{ + std::string storageStructure = pluginSection.GetStringValue("StorageStructure", "flat"); + if (storageStructure == "flat") + { + enableLegacyStorageStructure = false; + } + else + { + enableLegacyStorageStructure = true; + if (storageStructure != "legacy") + { + OrthancPlugins::LogError("ObjectStorage/StorageStructure configuration invalid value: " + storageStructure + ", allowed values are 'flat' and 'legacy'"); + return false; + } + } + + return true; +} diff -r 234946ea2038 -r 2a02b21f0a19 Common/BaseStoragePlugin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Common/BaseStoragePlugin.h Tue Sep 01 13:08:49 2020 +0200 @@ -0,0 +1,22 @@ +#pragma once + +#include "IStoragePlugin.h" + +class BaseStoragePlugin : public IStoragePlugin +{ + bool enableLegacyStorageStructure_; + +protected: + + BaseStoragePlugin(bool enableLegacyStorageStructure): + enableLegacyStorageStructure_(enableLegacyStorageStructure) + {} + + std::string GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); + +public: + static std::string GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled, bool legacyFileStructure, const std::string& rootFolder); + static std::string GetOrthancFileSystemPath(const std::string& uuid, const std::string& fileSystemRootPath); + + static bool ReadCommonConfiguration(bool& enableLegacyStorageStructure, const OrthancPlugins::OrthancConfiguration& pluginSection); +}; diff -r 234946ea2038 -r 2a02b21f0a19 Common/EncryptionHelpers.h --- a/Common/EncryptionHelpers.h Wed Aug 26 12:52:37 2020 +0200 +++ b/Common/EncryptionHelpers.h Tue Sep 01 13:08:49 2020 +0200 @@ -21,7 +21,7 @@ #include #include "cryptopp/osrng.h" #include -#include "Core/MultiThreading/Semaphore.h" +#include class EncryptionException : public std::runtime_error { diff -r 234946ea2038 -r 2a02b21f0a19 Common/IStoragePlugin.h --- a/Common/IStoragePlugin.h Wed Aug 26 12:52:37 2020 +0200 +++ b/Common/IStoragePlugin.h Tue Sep 01 13:08:49 2020 +0200 @@ -70,4 +70,5 @@ virtual IWriter* GetWriterForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) = 0; virtual IReader* GetReaderForObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) = 0; virtual void DeleteObject(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) = 0; + virtual const char* GetConfigurationSectionName() = 0; }; diff -r 234946ea2038 -r 2a02b21f0a19 Common/Resources/DownloadOrthancFramework.cmake --- a/Common/Resources/DownloadOrthancFramework.cmake Wed Aug 26 12:52:37 2020 +0200 +++ b/Common/Resources/DownloadOrthancFramework.cmake Tue Sep 01 13:08:49 2020 +0200 @@ -4,29 +4,18 @@ # Copyright (C) 2017-2020 Osimis S.A., Belgium # # This program is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. # -# In addition, as a special exception, the copyright holders of this -# program give permission to link the code of its release with the -# OpenSSL project's "OpenSSL" library (or with modified versions of it -# that use the same license as the "OpenSSL" library), and distribute -# the linked executables. You must obey the GNU General Public License -# in all respects for all of the code used other than "OpenSSL". If you -# modify file(s) with this exception, you may extend this exception to -# your version of the file(s), but you are not obligated to do so. If -# you do not wish to do so, delete this exception statement from your -# version. If you delete this exception statement from all source files -# in the program, then also delete it here. -# # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# Lesser General Public License for more details. # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# You should have received a copy of the GNU Lesser General Public +# License along with this program. If not, see +# . @@ -35,11 +24,12 @@ ## if (NOT DEFINED ORTHANC_FRAMEWORK_SOURCE OR - (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" AND + (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "system" AND + NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" AND NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "web" AND NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" AND NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "path")) - message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_SOURCE must be set to \"hg\", \"web\", \"archive\" or \"path\"") + message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_SOURCE must be set to \"system\", \"hg\", \"web\", \"archive\" or \"path\"") endif() @@ -118,6 +108,12 @@ set(ORTHANC_FRAMEWORK_MD5 "3971f5de96ba71dc9d3f3690afeaa7c0") elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.7.0") set(ORTHANC_FRAMEWORK_MD5 "ce5f689e852b01d3672bd3d2f952a5ef") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.7.1") + set(ORTHANC_FRAMEWORK_MD5 "3c171217f930abe80246997bdbcaf7cc") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.7.2") + set(ORTHANC_FRAMEWORK_MD5 "328f94dcbd78c169655a13f7ad58a2c2") + elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.7.3") + set(ORTHANC_FRAMEWORK_MD5 "3f1ba9502ec7c5449971d3b56087bcde") # Below this point are development snapshots that were used to # release some plugin, before an official release of the Orthanc @@ -132,7 +128,8 @@ endif() endif() endif() -else() + +elseif (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path") message("Using the Orthanc framework from a path of the filesystem. Assuming mainline version.") set(ORTHANC_FRAMEWORK_MAJOR 999) set(ORTHANC_FRAMEWORK_MINOR 999) @@ -182,19 +179,14 @@ ## if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path") - if (NOT DEFINED ORTHANC_FRAMEWORK_ROOT) + if (NOT DEFINED ORTHANC_FRAMEWORK_ROOT OR + ORTHANC_FRAMEWORK_ROOT STREQUAL "") message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ROOT must provide the path to the sources of Orthanc") endif() if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}) message(FATAL_ERROR "Non-existing directory: ${ORTHANC_FRAMEWORK_ROOT}") endif() - - if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake) - message(FATAL_ERROR "Directory not containing the source code of Orthanc: ${ORTHANC_FRAMEWORK_ROOT}") - endif() - - set(ORTHANC_ROOT ${ORTHANC_FRAMEWORK_ROOT}) endif() @@ -251,7 +243,8 @@ ## if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive") - if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE) + if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE OR + ORTHANC_FRAMEWORK_ARCHIVE STREQUAL "") message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ARCHIVE must provide the path to the sources of Orthanc") endif() endif() @@ -370,3 +363,206 @@ endif() endif() + + +## +## Determine the path to the sources of the Orthanc framework +## + +if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR + ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR + ORTHANC_FRAMEWORK_SOURCE STREQUAL "web") + if (NOT DEFINED ORTHANC_ROOT OR + NOT DEFINED ORTHANC_FRAMEWORK_MAJOR OR + NOT DEFINED ORTHANC_FRAMEWORK_MINOR OR + NOT DEFINED ORTHANC_FRAMEWORK_REVISION) + message(FATAL_ERROR "Internal error in the DownloadOrthancFramework.cmake file") + endif() + + unset(ORTHANC_FRAMEWORK_ROOT CACHE) + + if ("${ORTHANC_FRAMEWORK_MAJOR}.${ORTHANC_FRAMEWORK_MINOR}.${ORTHANC_FRAMEWORK_REVISION}" VERSION_LESS "1.7.2") + set(ORTHANC_FRAMEWORK_ROOT "${ORTHANC_ROOT}/Core" CACHE + STRING "Path to the Orthanc framework source directory") + set(ENABLE_PLUGINS_VERSION_SCRIPT OFF) + else() + set(ORTHANC_FRAMEWORK_ROOT "${ORTHANC_ROOT}/OrthancFramework/Sources" CACHE + STRING "Path to the Orthanc framework source directory") + endif() + + unset(ORTHANC_ROOT) +endif() + +if (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "system") + if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/OrthancException.h OR + NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkParameters.cmake) + message(FATAL_ERROR "Directory not containing the source code of the Orthanc framework: ${ORTHANC_FRAMEWORK_ROOT}") + endif() +endif() + + + +## +## Case of the Orthanc framework installed as a shared library in a +## GNU/Linux distribution (typically Debian). New in Orthanc 1.7.2. +## + +if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "system") + set(ORTHANC_FRAMEWORK_LIBDIR "" CACHE PATH "") + + if (CMAKE_SYSTEM_NAME STREQUAL "Windows" AND + CMAKE_COMPILER_IS_GNUCXX) # MinGW + set(DYNAMIC_MINGW_STDLIB ON) # Disable static linking against libc (to throw exceptions) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++") + endif() + + include(CheckIncludeFile) + include(CheckIncludeFileCXX) + include(FindPythonInterp) + include(${CMAKE_CURRENT_LIST_DIR}/Compiler.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/DownloadPackage.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/AutoGeneratedCode.cmake) + set(EMBED_RESOURCES_PYTHON ${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py) + + if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" OR + ORTHANC_FRAMEWORK_STATIC) + include_directories(${ORTHANC_FRAMEWORK_ROOT}/..) + else() + # Look for mandatory dependency JsonCpp (cf. JsonCppConfiguration.cmake) + find_path(JSONCPP_INCLUDE_DIR json/reader.h + /usr/include/jsoncpp + /usr/local/include/jsoncpp + ) + + message("JsonCpp include dir: ${JSONCPP_INCLUDE_DIR}") + include_directories(${JSONCPP_INCLUDE_DIR}) + link_libraries(jsoncpp) + + CHECK_INCLUDE_FILE_CXX(${JSONCPP_INCLUDE_DIR}/json/reader.h HAVE_JSONCPP_H) + if (NOT HAVE_JSONCPP_H) + message(FATAL_ERROR "Please install the libjsoncpp-dev package") + endif() + + # Switch to the C++11 standard if the version of JsonCpp is 1.y.z + # (same as variable JSONCPP_CXX11 in the source code of Orthanc) + if (EXISTS ${JSONCPP_INCLUDE_DIR}/json/version.h) + file(STRINGS + "${JSONCPP_INCLUDE_DIR}/json/version.h" + JSONCPP_VERSION_MAJOR1 REGEX + ".*define JSONCPP_VERSION_MAJOR.*") + + if (NOT JSONCPP_VERSION_MAJOR1) + message(FATAL_ERROR "Unable to extract the major version of JsonCpp") + endif() + + string(REGEX REPLACE + ".*JSONCPP_VERSION_MAJOR.*([0-9]+)$" "\\1" + JSONCPP_VERSION_MAJOR ${JSONCPP_VERSION_MAJOR1}) + message("JsonCpp major version: ${JSONCPP_VERSION_MAJOR}") + + if (JSONCPP_VERSION_MAJOR GREATER 0) + message("Switching to C++11 standard, as version of JsonCpp is >= 1.0.0") + if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + else() + message("Unable to detect the major version of JsonCpp, assuming < 1.0.0") + endif() + + # Look for mandatory dependency Boost (cf. BoostConfiguration.cmake) + include(FindBoost) + find_package(Boost COMPONENTS filesystem thread system date_time regex ${ORTHANC_BOOST_COMPONENTS}) + + if (NOT Boost_FOUND) + message(FATAL_ERROR "Unable to locate Boost on this system") + endif() + + include_directories(${Boost_INCLUDE_DIRS}) + link_libraries(${Boost_LIBRARIES}) + + # Optional component - Lua + if (ENABLE_LUA) + include(FindLua) + + if (NOT LUA_FOUND) + message(FATAL_ERROR "Please install the liblua-dev package") + endif() + + include_directories(${LUA_INCLUDE_DIR}) + link_libraries(${LUA_LIBRARIES}) + endif() + + # Optional component - SQLite + if (ENABLE_SQLITE) + CHECK_INCLUDE_FILE(sqlite3.h HAVE_SQLITE_H) + if (NOT HAVE_SQLITE_H) + message(FATAL_ERROR "Please install the libsqlite3-dev package") + endif() + link_libraries(sqlite3) + endif() + + # Optional component - Pugixml + if (ENABLE_PUGIXML) + CHECK_INCLUDE_FILE_CXX(pugixml.hpp HAVE_PUGIXML_H) + if (NOT HAVE_PUGIXML_H) + message(FATAL_ERROR "Please install the libpugixml-dev package") + endif() + link_libraries(pugixml) + endif() + + # Optional component - DCMTK + if (ENABLE_DCMTK) + include(FindDCMTK) + include_directories(${DCMTK_INCLUDE_DIRS}) + link_libraries(${DCMTK_LIBRARIES}) + endif() + endif() + + # Look for Orthanc framework shared library + include(CheckCXXSymbolExists) + + if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + set(ORTHANC_FRAMEWORK_INCLUDE_DIR ${ORTHANC_FRAMEWORK_ROOT}) + else() + find_path(ORTHANC_FRAMEWORK_INCLUDE_DIR OrthancFramework.h + /usr/include/orthanc-framework + /usr/local/include/orthanc-framework + ${ORTHANC_FRAMEWORK_ROOT} + ) + endif() + + if (${ORTHANC_FRAMEWORK_INCLUDE_DIR} STREQUAL "ORTHANC_FRAMEWORK_INCLUDE_DIR-NOTFOUND") + message(FATAL_ERROR "Cannot locate the OrthancFramework.h header") + endif() + + message("Orthanc framework include dir: ${ORTHANC_FRAMEWORK_INCLUDE_DIR}") + include_directories(${ORTHANC_FRAMEWORK_INCLUDE_DIR}) + + if ("${ORTHANC_FRAMEWORK_LIBDIR}" STREQUAL "") + set(ORTHANC_FRAMEWORK_LIBRARIES OrthancFramework) + else() + if (MSVC) + set(Suffix ".lib") + set(Prefix "") + else() + list(GET CMAKE_FIND_LIBRARY_PREFIXES 0 Prefix) + list(GET CMAKE_FIND_LIBRARY_SUFFIXES 0 Suffix) + endif() + set(ORTHANC_FRAMEWORK_LIBRARIES ${ORTHANC_FRAMEWORK_LIBDIR}/${Prefix}OrthancFramework${Suffix}) + endif() + + set(CMAKE_REQUIRED_INCLUDES "${ORTHANC_FRAMEWORK_INCLUDE_DIR}") + set(CMAKE_REQUIRED_LIBRARIES "${ORTHANC_FRAMEWORK_LIBRARIES}") + + check_cxx_symbol_exists("Orthanc::InitializeFramework" "OrthancFramework.h" HAVE_ORTHANC_FRAMEWORK) + if (NOT HAVE_ORTHANC_FRAMEWORK) + message(FATAL_ERROR "Cannot find the Orthanc framework") + endif() + + unset(CMAKE_REQUIRED_INCLUDES) + unset(CMAKE_REQUIRED_LIBRARIES) +endif() diff -r 234946ea2038 -r 2a02b21f0a19 Common/StoragePlugin.cpp --- a/Common/StoragePlugin.cpp Wed Aug 26 12:52:37 2020 +0200 +++ b/Common/StoragePlugin.cpp Tue Sep 01 13:08:49 2020 +0200 @@ -34,14 +34,43 @@ #include #include +#include +#include + #include "../Common/EncryptionHelpers.h" #include "../Common/EncryptionConfigurator.h" +#include static std::unique_ptr plugin; static std::unique_ptr crypto; static bool cryptoEnabled = false; +static std::string fileSystemRootPath; +static bool migrationFromFileSystemEnabled = false; +// class to free memory allocated by malloc if an exception occurs +// This is to avoid an issue in which the blob storage read method +// crashed if the buffer was allocated through: +// auto buffer = std::unique_ptr{malloc(static_cast(*size)), free}; + +class ScopedFree +{ + void* buffer_; +public: + ScopedFree(void* buffer) + : buffer_(buffer) + { + } + ~ScopedFree() + { + free(buffer_); + } + + void Release() // abandon ownership + { + buffer_ = nullptr; + } +}; static OrthancPluginErrorCode StorageCreate(const char* uuid, const void* content, @@ -110,6 +139,8 @@ } *content = malloc(static_cast(*size)); + ScopedFree freeContent(*content); + if (*content == nullptr) { OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ", cannot allocate memory of size " + boost::lexical_cast(*size) + " bytes"); @@ -135,15 +166,52 @@ { reader->Read(*(reinterpret_cast(content)), fileSize); } + + // transmit ownership to content + freeContent.Release(); } catch (StoragePluginException& ex) { - OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while creating object " + std::string(uuid) + ": " + ex.what()); - return OrthancPluginErrorCode_StorageAreaPlugin; + if (migrationFromFileSystemEnabled) + { + try + { + OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ": " + ex.what() + ", will now try to read it from legacy orthanc storage"); + std::string path = BaseStoragePlugin::GetOrthancFileSystemPath(uuid, fileSystemRootPath); + + std::string stringBuffer; + Orthanc::SystemToolbox::ReadFile(stringBuffer, path); + + *content = malloc(static_cast(stringBuffer.size())); + ScopedFree freeContent(*content); + + if (*content == nullptr) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ", cannot allocate memory of size " + boost::lexical_cast(*size) + " bytes"); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + *size = stringBuffer.size(); + memcpy(*content, stringBuffer.data(), stringBuffer.size()); + + // transmit ownership to content + freeContent.Release(); + + return OrthancPluginErrorCode_Success; + } + catch(Orthanc::OrthancException& e) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ": " + std::string(e.What())); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + } + else + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ": " + ex.what()); + return OrthancPluginErrorCode_StorageAreaPlugin; + } } return OrthancPluginErrorCode_Success; - } @@ -156,8 +224,51 @@ } catch (StoragePluginException& ex) { - OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while deleting object " + std::string(uuid) + ": " + ex.what()); - return OrthancPluginErrorCode_StorageAreaPlugin; + if (migrationFromFileSystemEnabled) + { + try + { + OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while deleting object " + std::string(uuid) + ": " + ex.what() + ", will now try to delete it from legacy orthanc storage"); + namespace fs = boost::filesystem; + + fs::path path = BaseStoragePlugin::GetOrthancFileSystemPath(uuid, fileSystemRootPath); + + try + { + fs::remove(path); + } + catch (...) + { + // Ignore the error + } + + // Remove the two parent directories, ignoring the error code if + // these directories are not empty + + try + { + boost::system::error_code err; + fs::remove(path.parent_path(), err); + fs::remove(path.parent_path().parent_path(), err); + } + catch (...) + { + // Ignore the error + } + + return OrthancPluginErrorCode_Success; + } + catch(Orthanc::OrthancException& e) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while deleting object " + std::string(uuid) + ": " + std::string(e.What())); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + } + else + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while deleting object " + std::string(uuid) + ": " + ex.what()); + return OrthancPluginErrorCode_StorageAreaPlugin; + } } return OrthancPluginErrorCode_Success; @@ -170,6 +281,8 @@ { OrthancPlugins::SetGlobalContext(context); + Orthanc::Logging::InitializePluginContext(context); + OrthancPlugins::OrthancConfiguration orthancConfig; OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is initializing"); @@ -194,19 +307,39 @@ return -1; } + const char* pluginSectionName = plugin->GetConfigurationSectionName(); static const char* const ENCRYPTION_SECTION = "StorageEncryption"; - if (orthancConfig.IsSection(ENCRYPTION_SECTION)) + if (orthancConfig.IsSection(pluginSectionName)) { - OrthancPlugins::OrthancConfiguration cryptoSection; - orthancConfig.GetSection(cryptoSection, ENCRYPTION_SECTION); + OrthancPlugins::OrthancConfiguration pluginSection; + orthancConfig.GetSection(pluginSection, pluginSectionName); + + migrationFromFileSystemEnabled = pluginSection.GetBooleanValue("MigrationFromFileSystemEnabled", false); + + if (migrationFromFileSystemEnabled) + { + fileSystemRootPath = orthancConfig.GetStringValue("StorageDirectory", "OrthancStorageNotDefined"); + OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": migration from file system enabled, source: " + fileSystemRootPath); + } - crypto.reset(EncryptionConfigurator::CreateEncryptionHelpers(cryptoSection)); - cryptoEnabled = crypto.get() != nullptr; - } - else - { - OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is disabled"); + if (pluginSection.IsSection(ENCRYPTION_SECTION)) + { + OrthancPlugins::OrthancConfiguration cryptoSection; + pluginSection.GetSection(cryptoSection, ENCRYPTION_SECTION); + + crypto.reset(EncryptionConfigurator::CreateEncryptionHelpers(cryptoSection)); + cryptoEnabled = crypto.get() != nullptr; + } + + if (cryptoEnabled) + { + OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is enabled"); + } + else + { + OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is disabled"); + } } OrthancPluginRegisterStorageArea(context, StorageCreate, StorageRead, StorageRemove); diff -r 234946ea2038 -r 2a02b21f0a19 Google/CMakeLists.txt --- a/Google/CMakeLists.txt Wed Aug 26 12:52:37 2020 +0200 +++ b/Google/CMakeLists.txt Tue Sep 01 13:08:49 2020 +0200 @@ -7,32 +7,31 @@ include(CheckIncludeFileCXX) set(ORTHANC_FRAMEWORK_SOURCE "hg" CACHE STRING "orthanc source") -set(ORTHANC_FRAMEWORK_VERSION "7176ebf" CACHE STRING "orthanc framework version") +set(ORTHANC_FRAMEWORK_VERSION "1.7.3" CACHE STRING "orthanc framework version") set(ALLOW_DOWNLOADS ON) # Download and setup the Orthanc framework include(${CMAKE_SOURCE_DIR}/../Common/Resources/DownloadOrthancFramework.cmake) -include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake) +include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkParameters.cmake) set(ENABLE_GOOGLE_TEST ON) set(ORTHANC_FRAMEWORK_PLUGIN ON) -include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkConfiguration.cmake) +include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkConfiguration.cmake) add_definitions( -DHAS_ORTHANC_EXCEPTION=1 - -DORTHANC_ENABLE_LOGGING_PLUGIN=1 + -DORTHANC_ENABLE_LOGGING=1 -DGOOGLE_STORAGE_PLUGIN=1 ) add_definitions(-DPLUGIN_VERSION="${PLUGIN_VERSION}") include_directories( - ${ORTHANC_ROOT} - ${ORTHANC_ROOT}/Core - ${ORTHANC_ROOT}/Plugins/Include - ${ORTHANC_ROOT}/Plugins/Samples/Common + ${ORTHANC_FRAMEWORK_ROOT} + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Include + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common ) find_package(CURL REQUIRED) @@ -41,11 +40,13 @@ set(COMMON_SOURCES ${CMAKE_SOURCE_DIR}/../Common/IStoragePlugin.h + ${CMAKE_SOURCE_DIR}/../Common/BaseStoragePlugin.h + ${CMAKE_SOURCE_DIR}/../Common/BaseStoragePlugin.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionHelpers.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionHelpers.h ${CMAKE_SOURCE_DIR}/../Common/EncryptionConfigurator.cpp ${CMAKE_SOURCE_DIR}/../Common/EncryptionConfigurator.h - ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp + ${ORTHANC_FRAMEWORK_ROOT}/../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp ${ORTHANC_CORE_SOURCES} ) diff -r 234946ea2038 -r 2a02b21f0a19 Google/GoogleStoragePlugin.cpp --- a/Google/GoogleStoragePlugin.cpp Wed Aug 26 12:52:37 2020 +0200 +++ b/Google/GoogleStoragePlugin.cpp Tue Sep 01 13:08:49 2020 +0200 @@ -22,6 +22,12 @@ // Create aliases to make the code easier to read. namespace gcs = google::cloud::storage; +static const char* const PLUGIN_SECTION = "GoogleCloudStorage"; + +const char* GoogleStoragePlugin::GetConfigurationSectionName() +{ + return PLUGIN_SECTION; +} class Writer : public IStoragePlugin::IWriter { @@ -125,7 +131,8 @@ IStoragePlugin* GoogleStoragePluginFactory::CreateStoragePlugin(const OrthancPlugins::OrthancConfiguration& orthancConfig) { - static const char* const PLUGIN_SECTION = "GoogleCloudStorage"; + bool enableLegacyStorageStructure; + if (!orthancConfig.IsSection(PLUGIN_SECTION)) { OrthancPlugins::LogWarning(std::string(GetStoragePluginName()) + " plugin, section missing. Plugin is not enabled."); @@ -135,6 +142,11 @@ OrthancPlugins::OrthancConfiguration pluginSection; orthancConfig.GetSection(pluginSection, PLUGIN_SECTION); + if (!BaseStoragePlugin::ReadCommonConfiguration(enableLegacyStorageStructure, pluginSection)) + { + return nullptr; + } + std::string pathToGoogleCredentials; if (!pluginSection.LookupStringValue(pathToGoogleCredentials, "ServiceAccountFile")) @@ -167,11 +179,12 @@ return nullptr; } - return new GoogleStoragePlugin(googleBucketName, mainClient.value()); + return new GoogleStoragePlugin(googleBucketName, mainClient.value(), enableLegacyStorageStructure); } -GoogleStoragePlugin::GoogleStoragePlugin(const std::string &bucketName, google::cloud::storage::Client& mainClient) - : bucketName_(bucketName), +GoogleStoragePlugin::GoogleStoragePlugin(const std::string &bucketName, google::cloud::storage::Client& mainClient, bool enableLegacyStorageStructure) + : BaseStoragePlugin(enableLegacyStorageStructure), + bucketName_(bucketName), mainClient_(mainClient) { @@ -201,27 +214,3 @@ } } - -std::string GoogleStoragePlugin::GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled) -{ - std::string path = std::string(uuid); - - if (type == OrthancPluginContentType_Dicom) - { - path += ".dcm"; - } - else if (type == OrthancPluginContentType_DicomAsJson) - { - path += ".json"; - } - else - { - path += ".unk"; - } - - if (encryptionEnabled) - { - path += ".enc"; - } - return path; -} diff -r 234946ea2038 -r 2a02b21f0a19 Google/GoogleStoragePlugin.h --- a/Google/GoogleStoragePlugin.h Wed Aug 26 12:52:37 2020 +0200 +++ b/Google/GoogleStoragePlugin.h Tue Sep 01 13:08:49 2020 +0200 @@ -18,7 +18,7 @@ #pragma once -#include "../Common/IStoragePlugin.h" +#include "../Common/BaseStoragePlugin.h" #include "google/cloud/storage/client.h" @@ -30,7 +30,7 @@ }; -class GoogleStoragePlugin : public IStoragePlugin +class GoogleStoragePlugin : public BaseStoragePlugin { public: @@ -40,12 +40,12 @@ public: GoogleStoragePlugin(const std::string& bucketName, - google::cloud::storage::Client& mainClient + google::cloud::storage::Client& mainClient, + bool enableLegacyStorageStructure ); 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); -private: - virtual std::string GetPath(const char* uuid, OrthancPluginContentType type, bool encryptionEnabled); + virtual const char* GetConfigurationSectionName(); }; diff -r 234946ea2038 -r 2a02b21f0a19 NEWS --- a/NEWS Wed Aug 26 12:52:37 2020 +0200 +++ b/NEWS Tue Sep 01 13:08:49 2020 +0200 @@ -1,6 +1,15 @@ Pending changes in the mainline =============================== +2020-09-01 - v 1.0.0 +==================== + +* BREAKING CHANGE: the "StorageEncryption" configuration section is now a subsection of the "AwsS3Storage" +Azure: now removing spaces and CR at the end of the connectionString since it prevented the plugin to initialize. +* Added "MigrationFromFileSystemEnabled" configuration +* Added "StorageStructure" configuration (flat-legacy) + + 2020-08-26 - v 0.9.3 ==================== diff -r 234946ea2038 -r 2a02b21f0a19 README.md --- a/README.md Wed Aug 26 12:52:37 2020 +0200 +++ b/README.md Tue Sep 01 13:08:49 2020 +0200 @@ -10,14 +10,16 @@ ``` { - "StorageEncryption" : { - "Enable": true, - "MasterKey": [3, "/path/to/master.key"], // key id - path to the base64 encoded key - "PreviousMasterKeys" : [ - [ 1, "/path/to/previous1.key"], - [ 2, "/path/to/previous2.key"] - ], - "MaxConcurrentInputSize" : 1024 // size in MB + "GoogleCloudStorage" : { + "StorageEncryption" : { + "Enable": true, + "MasterKey": [3, "/path/to/master.key"], // key id - path to the base64 encoded key + "PreviousMasterKeys" : [ + [ 1, "/path/to/previous1.key"], + [ 2, "/path/to/previous2.key"] + ], + "MaxConcurrentInputSize" : 1024 // size in MB + } } } ``` @@ -29,14 +31,17 @@ * `hg clone ...` * `mkdir -p build/google` * `cd build/google` -* `cmake -DCMAKE_TOOLCHAIN_FILE=[vcpkg root]\scripts\buildsystems\vcpkg.cmake ../../orthanc-object-storage/google` +* `cmake -DCMAKE_TOOLCHAIN_FILE=[vcpkg root]\scripts\buildsystems\vcpkg.cmake ../../orthanc-object-storage/Google` ### Google plugin configuration ### ``` "GoogleCloudStorage" : { - "ServiceAccountFile": "/.../googleServiceAccountFile.json", - "BucketName": "test-orthanc-storage-plugin" + "ServiceAccountFile" : "/.../googleServiceAccountFile.json", + "BucketName": "test-orthanc-storage-plugin", + "StorageEncryption" : {...}, + "StorageStructure" : "flat", + "MigrationFromFileSystemEnabled" : false } ``` @@ -60,7 +65,10 @@ ``` "AzureBlobStorage" : { "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=xxxxxxxxx;AccountKey=yyyyyyyy===;EndpointSuffix=core.windows.net", - "ContainerName" : "test-orthanc-storage-plugin" + "ContainerName" : "test-orthanc-storage-plugin", + "StorageEncryption" : {...}, + "StorageStructure" : "flat", + "MigrationFromFileSystemEnabled" : false } ``` @@ -103,6 +111,9 @@ "SecretKey" : "RhYYYY", "Endpoint": "", // optional: custom endpoint "ConnectionTimeout": 30, // optional: connection timeout in seconds - "RequestTimeout": 1200 // optional: request timeout in seconds (max time to upload/download a file) + "RequestTimeout": 1200, // optional: request timeout in seconds (max time to upload/download a file) + "StorageEncryption" : {...}, + "StorageStructure" : "flat", + "MigrationFromFileSystemEnabled" : false } ``` \ No newline at end of file