Mercurial > hg > orthanc
changeset 6139:e030b8efe019 attach-custom-data
adapting new MD5 computations to sandboxed environments
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 30 May 2025 11:38:18 +0200 |
parents | db4eb6c5ca65 |
children | 98776c72a9bc |
files | OrthancFramework/Sources/SystemToolbox.cpp OrthancFramework/Sources/SystemToolbox.h OrthancFramework/Sources/Toolbox.cpp OrthancFramework/Sources/Toolbox.h OrthancFramework/UnitTestsSources/FrameworkTests.cpp |
diffstat | 5 files changed, 177 insertions(+), 85 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Sources/SystemToolbox.cpp Wed May 28 19:28:59 2025 +0200 +++ b/OrthancFramework/Sources/SystemToolbox.cpp Fri May 30 11:38:18 2025 +0200 @@ -455,27 +455,60 @@ } #if ORTHANC_ENABLE_MD5 == 1 + void SystemToolbox::ComputeStreamMD5(std::string& result, + std::istream& inputStream) + { + Toolbox::MD5Context context; + + const size_t bufferSize = 1024; + char buffer[bufferSize]; + + while (inputStream.good()) + { + inputStream.read(buffer, bufferSize); + std::streamsize bytesRead = inputStream.gcount(); + + if (bytesRead > 0) + { + context.Append(buffer, bytesRead); + } + } + + context.Export(result); + } + + void SystemToolbox::ComputeFileMD5(std::string& result, const std::string& path) { - std::ifstream fileStream(path, std::ifstream::binary); - Toolbox::ComputeMD5(result, fileStream); + boost::filesystem::ifstream fileStream; + fileStream.open(path, std::ifstream::in | std::ifstream::binary); + + if (!fileStream.good()) + { + throw OrthancException(ErrorCode_InexistentFile, "File not found: " + path); + } + + ComputeStreamMD5(result, fileStream); } + bool SystemToolbox::CompareFilesMD5(const std::string& path1, const std::string& path2) { - if (SystemToolbox::GetFileSize(path1) != SystemToolbox::GetFileSize(path2)) + if (GetFileSize(path1) != GetFileSize(path2)) { return false; } - - std::string path1md5, path2md5; + else + { + std::string path1md5, path2md5; - SystemToolbox::ComputeFileMD5(path1md5, path1); - SystemToolbox::ComputeFileMD5(path2md5, path2); + ComputeFileMD5(path1md5, path1); + ComputeFileMD5(path2md5, path2); - return path1md5 == path2md5; + return path1md5 == path2md5; + } } #endif
--- a/OrthancFramework/Sources/SystemToolbox.h Wed May 28 19:28:59 2025 +0200 +++ b/OrthancFramework/Sources/SystemToolbox.h Fri May 30 11:38:18 2025 +0200 @@ -30,6 +30,10 @@ # error The macro ORTHANC_SANDBOXED must be defined #endif +#if !defined(ORTHANC_ENABLE_MD5) +# error The macro ORTHANC_ENABLE_MD5 must be defined +#endif + #if ORTHANC_SANDBOXED == 1 # error The namespace SystemToolbox cannot be used in sandboxed environments #endif @@ -84,6 +88,9 @@ static uint64_t GetFileSize(const std::string& path); #if ORTHANC_ENABLE_MD5 == 1 + static void ComputeStreamMD5(std::string& result, + std::istream& stream); + static void ComputeFileMD5(std::string& result, const std::string& path);
--- a/OrthancFramework/Sources/Toolbox.cpp Wed May 28 19:28:59 2025 +0200 +++ b/OrthancFramework/Sources/Toolbox.cpp Fri May 30 11:38:18 2025 +0200 @@ -207,6 +207,95 @@ namespace Orthanc { +#if ORTHANC_ENABLE_MD5 == 1 + static char GetHexadecimalCharacter(uint8_t value) + { + assert(value < 16); + + if (value < 10) + { + return value + '0'; + } + else + { + return (value - 10) + 'a'; + } + } + + + struct Toolbox::MD5Context::PImpl + { + md5_state_s state_; + bool done_; + + PImpl() : + done_(false) + { + md5_init(&state_); + } + }; + + + Toolbox::MD5Context::MD5Context() : + pimpl_(new PImpl) + { + } + + + void Toolbox::MD5Context::Append(const void* data, + size_t size) + { + if (pimpl_->done_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + if (static_cast<size_t>(static_cast<int>(size)) != size) + { + throw OrthancException(ErrorCode_InternalError, + "The built-in implementation of MD5 does not support buffers larger than 32bits"); + } + + if (size > 0) + { + md5_append(&pimpl_->state_, + reinterpret_cast<const md5_byte_t*>(data), + static_cast<int>(size)); + } + } + + + void Toolbox::MD5Context::Append(const std::string& source) + { + if (source.size() > 0) + { + Append(source.c_str(), source.size()); + } + } + + + void Toolbox::MD5Context::Export(std::string& target) + { + if (pimpl_->done_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + pimpl_->done_ = true; + + md5_byte_t actualHash[16]; + md5_finish(&pimpl_->state_, actualHash); + + target.resize(32); + for (unsigned int i = 0; i < 16; i++) + { + target[2 * i] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] / 16)); + target[2 * i + 1] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] % 16)); + } + } +#endif /* ORTHANC_ENABLE_MD5 */ + + void Toolbox::LinesIterator::FindEndOfLine() { lineEnd_ = lineStart_; @@ -444,21 +533,6 @@ #if ORTHANC_ENABLE_MD5 == 1 - static char GetHexadecimalCharacter(uint8_t value) - { - assert(value < 16); - - if (value < 10) - { - return value + '0'; - } - else - { - return (value - 10) + 'a'; - } - } - - void Toolbox::ComputeMD5(std::string& result, const std::string& data) { @@ -477,62 +551,12 @@ const void* data, size_t size) { - md5_state_s state; - md5_init(&state); - - if (size > 0) - { - md5_append(&state, - reinterpret_cast<const md5_byte_t*>(data), - static_cast<int>(size)); - } - - md5_byte_t actualHash[16]; - md5_finish(&state, actualHash); - - result.resize(32); - for (unsigned int i = 0; i < 16; i++) - { - result[2 * i] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] / 16)); - result[2 * i + 1] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] % 16)); - } + MD5Context context; + context.Append(data, size); + context.Export(result); } void Toolbox::ComputeMD5(std::string& result, - std::istream& inputStream) - { - md5_state_s state; - md5_init(&state); - - const size_t bufferSize = 1024; - char buffer[bufferSize]; - - while (inputStream.good()) - { - inputStream.read(buffer, bufferSize); - std::streamsize bytesRead = inputStream.gcount(); - - if (bytesRead > 0) - { - md5_append(&state, - reinterpret_cast<const md5_byte_t*>(buffer), - static_cast<int>(bytesRead)); - } - } - - md5_byte_t actualHash[16]; - md5_finish(&state, actualHash); - - result.resize(32); - for (unsigned int i = 0; i < 16; i++) - { - result[2 * i] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] / 16)); - result[2 * i + 1] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] % 16)); - } - } - - - void Toolbox::ComputeMD5(std::string& result, const std::set<std::string>& data) { std::string s;
--- a/OrthancFramework/Sources/Toolbox.h Wed May 28 19:28:59 2025 +0200 +++ b/OrthancFramework/Sources/Toolbox.h Fri May 30 11:38:18 2025 +0200 @@ -82,6 +82,25 @@ class ORTHANC_PUBLIC Toolbox { public: +#if ORTHANC_ENABLE_MD5 == 1 + class ORTHANC_PUBLIC MD5Context : public boost::noncopyable + { + private: + class PImpl; + boost::shared_ptr<PImpl> pimpl_; + + public: + MD5Context(); + + void Append(const void* data, + size_t size); + + void Append(const std::string& source); + + void Export(std::string& target); + }; +#endif + class ORTHANC_PUBLIC LinesIterator : public boost::noncopyable { private: @@ -134,9 +153,6 @@ static void ComputeMD5(std::string& result, const std::set<std::string>& data); - - static void ComputeMD5(std::string& result, - std::istream& stream); #endif static void ComputeSHA1(std::string& result,
--- a/OrthancFramework/UnitTestsSources/FrameworkTests.cpp Wed May 28 19:28:59 2025 +0200 +++ b/OrthancFramework/UnitTestsSources/FrameworkTests.cpp Fri May 30 11:38:18 2025 +0200 @@ -398,9 +398,24 @@ Toolbox::ComputeMD5(s, set); ASSERT_EQ("d1aaf4767a3c10a473407a4e47b02da6", s); // set md5 same as string with the values sorted - std::istringstream iss(std::string("aaabbbccc")); - Toolbox::ComputeMD5(s, iss); - ASSERT_EQ("d1aaf4767a3c10a473407a4e47b02da6", s); + { + Toolbox::MD5Context context; + context.Append(""); + context.Append(NULL, 0); + context.Append("Hello"); + context.Export(s); + ASSERT_EQ("8b1a9953c4611296a827abf8c47804d7", s); + ASSERT_THROW(context.Append("World"), OrthancException); + ASSERT_THROW(context.Export(s), OrthancException); + } + +#if ORTHANC_SANDBOXED != 1 + { + std::istringstream iss(std::string("aaabbbccc")); + SystemToolbox::ComputeStreamMD5(s, iss); + ASSERT_EQ("d1aaf4767a3c10a473407a4e47b02da6", s); + } +#endif } TEST(Toolbox, ComputeSHA1) @@ -1598,8 +1613,6 @@ #if ORTHANC_SANDBOXED != 1 && ORTHANC_ENABLE_MD5 == 1 TEST(Toolbox, FileMD5) { - std::string path; - { TemporaryFile tmp1, tmp2; std::string s = "aaabbbccc"; @@ -1635,7 +1648,6 @@ ASSERT_FALSE(SystemToolbox::CompareFilesMD5(tmp1.GetPath(), tmp2.GetPath())); } - } #endif