Mercurial > hg > orthanc-object-storage
diff Common/StoragePlugin.cpp @ 1:fc26a8fc54d5
initial release
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Fri, 03 Jul 2020 10:08:44 +0200 |
parents | |
children | 987cb95c1aee |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Common/StoragePlugin.cpp Fri Jul 03 10:08:44 2020 +0200 @@ -0,0 +1,230 @@ +/** + * Cloud storage plugins for Orthanc + * 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 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/>. + **/ + +#if GOOGLE_STORAGE_PLUGIN==1 +#include "../Google/GoogleStoragePlugin.h" +#define StoragePluginFactory GoogleStoragePluginFactory +#elif AZURE_STORAGE_PLUGIN==1 +#include "../Azure/AzureBlobStoragePlugin.h" +#define StoragePluginFactory AzureBlobStoragePluginFactory +#elif AWS_STORAGE_PLUGIN==1 +#include "../Aws/AwsS3StoragePlugin.h" +#define StoragePluginFactory AwsS3StoragePluginFactory +#else +#pragma message(error "define a plugin") +#endif + +#include <string.h> +#include <stdio.h> +#include <string> + +#include <iostream> +#include "../Common/EncryptionHelpers.h" +#include "../Common/EncryptionConfigurator.h" + +static std::unique_ptr<IStoragePlugin> plugin; + +static std::unique_ptr<EncryptionHelpers> crypto; +static bool cryptoEnabled = false; + + +static OrthancPluginErrorCode StorageCreate(const char* uuid, + const void* content, + int64_t size, + OrthancPluginContentType type) +{ + try + { + std::unique_ptr<IStoragePlugin::IWriter> writer(plugin->GetWriterForObject(uuid, type, cryptoEnabled)); + + if (cryptoEnabled) + { + std::string encryptedFile; + + try + { + crypto->Encrypt(encryptedFile, (const char*)content, size); + } + catch (EncryptionException& ex) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while encrypting object " + std::string(uuid) + ": " + ex.what()); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + + writer->Write(encryptedFile.data(), encryptedFile.size()); + } + else + { + writer->Write(reinterpret_cast<const char*>(content), size); + } + } + catch (StoragePluginException& ex) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while creating object " + std::string(uuid) + ": " + ex.what()); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + + return OrthancPluginErrorCode_Success; +} + + +static OrthancPluginErrorCode StorageRead(void** content, + int64_t* size, + const char* uuid, + OrthancPluginContentType type) +{ + try + { + std::unique_ptr<IStoragePlugin::IReader> reader(plugin->GetReaderForObject(uuid, type, cryptoEnabled)); + + size_t fileSize = reader->GetSize(); + + if (cryptoEnabled) + { + *size = fileSize - crypto->OVERHEAD_SIZE; + } + else + { + *size = fileSize; + } + + if (*size <= 0) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ", size of file is too small: " + boost::lexical_cast<std::string>(fileSize) + " bytes"); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + + *content = malloc(static_cast<uint64_t>(*size)); + if (*content == nullptr) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while reading object " + std::string(uuid) + ", cannot allocate memory of size " + boost::lexical_cast<std::string>(*size) + " bytes"); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + + if (cryptoEnabled) + { + std::vector<char> encrypted(fileSize); + reader->Read(encrypted.data(), fileSize); + + try + { + crypto->Decrypt((char*)(*content), encrypted.data(), fileSize); + } + catch (EncryptionException& ex) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while decrypting object " + std::string(uuid) + ": " + ex.what()); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + } + else + { + reader->Read(*(reinterpret_cast<char**>(content)), fileSize); + } + } + catch (StoragePluginException& ex) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while creating object " + std::string(uuid) + ": " + ex.what()); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + + return OrthancPluginErrorCode_Success; + +} + + +static OrthancPluginErrorCode StorageRemove(const char* uuid, + OrthancPluginContentType type) +{ + try + { + plugin->DeleteObject(uuid, type, cryptoEnabled); + } + catch (StoragePluginException& ex) + { + OrthancPlugins::LogError(std::string(StoragePluginFactory::GetStoragePluginName()) + ": error while deleting object " + std::string(uuid) + ": " + ex.what()); + return OrthancPluginErrorCode_StorageAreaPlugin; + } + + return OrthancPluginErrorCode_Success; +} + + +extern "C" +{ + ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) + { + OrthancPlugins::SetGlobalContext(context); + + OrthancPlugins::OrthancConfiguration orthancConfig; + + OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is initializing"); + + /* Check the version of the Orthanc core */ + if (OrthancPluginCheckVersion(context) == 0) + { + char info[1024]; + sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", + context->orthancVersion, + ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); + OrthancPlugins::LogError(info); + return -1; + } + + plugin.reset(StoragePluginFactory::CreateStoragePlugin(orthancConfig)); + + static const char* const ENCRYPTION_SECTION = "StorageEncryption"; + + if (orthancConfig.IsSection(ENCRYPTION_SECTION)) + { + OrthancPlugins::OrthancConfiguration cryptoSection; + orthancConfig.GetSection(cryptoSection, ENCRYPTION_SECTION); + + crypto.reset(EncryptionConfigurator::CreateEncryptionHelpers(cryptoSection)); + cryptoEnabled = crypto.get() != nullptr; + } + else + { + OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + ": client-side encryption is disabled"); + } + + OrthancPluginRegisterStorageArea(context, StorageCreate, StorageRead, StorageRemove); + + return 0; + } + + + ORTHANC_PLUGINS_API void OrthancPluginFinalize() + { + OrthancPlugins::LogWarning(std::string(StoragePluginFactory::GetStoragePluginName()) + " plugin is finalizing"); + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetName() + { + return StoragePluginFactory::GetStoragePluginName(); + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() + { + return PLUGIN_VERSION; + } +} +