changeset 6591:76fd43aea734

Use boost to compute MD5
author Alain Mazy <am@orthanc.team>
date Thu, 19 Feb 2026 15:48:21 +0100
parents bf8c7cc07596
children 681cf6db8aa6
files OrthancFramework/Sources/Toolbox.cpp TODO
diffstat 2 files changed, 87 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/Toolbox.cpp	Wed Feb 18 20:21:08 2026 +0100
+++ b/OrthancFramework/Sources/Toolbox.cpp	Thu Feb 19 15:48:21 2026 +0100
@@ -82,9 +82,11 @@
 
 
 #if ORTHANC_ENABLE_MD5 == 1
-// TODO - Could be replaced by <boost/uuid/detail/md5.hpp> starting
-// with Boost >= 1.66.0
-#  include "../Resources/ThirdParty/md5/md5.h"
+#  if BOOST_VERSION >= 106600
+#    include <boost/uuid/detail/md5.hpp>
+#  else
+#    include "../Resources/ThirdParty/md5/md5.h"
+#  endif
 #endif
 
 #if ORTHANC_ENABLE_BASE64 == 1
@@ -215,6 +217,86 @@
 namespace Orthanc
 {
 #if ORTHANC_ENABLE_MD5 == 1
+#  if BOOST_VERSION >= 106600
+  
+  struct Toolbox::MD5Context::PImpl
+  {
+    boost::uuids::detail::md5  md5_;
+    bool                       done_;
+
+    PImpl() :
+      done_(false)
+    {
+    }
+  };
+
+
+  Toolbox::MD5Context::MD5Context() :
+    pimpl_(new PImpl)
+  {
+  }
+
+
+  void Toolbox::MD5Context::Append(const void* data,
+                                   size_t size)
+  {
+    if (pimpl_->done_)
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+
+    pimpl_->md5_.process_bytes(data, size);
+  }
+
+  void Toolbox::MD5Context::Append(const std::string& source)
+  {
+    Append(reinterpret_cast<const void*>(source.c_str()), source.size());
+  }
+
+  void Toolbox::MD5Context::Export(std::string& target)
+  {
+    if (pimpl_->done_)
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+
+    pimpl_->done_ = true;
+
+#    if BOOST_VERSION >= 108600
+    unsigned char digest[16];
+
+    // Sanity check for the memory layout: A MD5 digest is 128 bits wide
+    assert(sizeof(digest) == (128 / 8));
+    assert(sizeof(boost::uuids::detail::md5::digest_type) == 16);
+
+    pimpl_->md5_.get_digest(digest);
+
+    target.resize(32);
+    sprintf(&target[0], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+            digest[0], digest[1], digest[2], digest[3],
+            digest[4], digest[5], digest[6], digest[7],
+            digest[8], digest[9], digest[10], digest[11],
+            digest[12], digest[13], digest[14], digest[15]);
+
+#    else  // BOOST_VERSION >= 108600
+    unsigned int digest[4];
+
+    // Sanity check for the memory layout: A MD5 digest is 128 bits wide
+    assert(sizeof(digest) == (128 / 8));
+    assert(sizeof(boost::uuids::detail::md5::digest_type) == 16);
+
+    pimpl_->md5_.get_digest(digest);
+
+    target.resize(32);
+    sprintf(&target[0], "%08x%08x%08x%08x",
+            digest[0],
+            digest[1],
+            digest[2],
+            digest[3]);
+
+#    endif //BOOST_VERSION >= 108600
+  }
+#  else // BOOST_VERSION >= 106600
   static char GetHexadecimalCharacter(uint8_t value)
   {
     assert(value < 16);
@@ -317,6 +399,8 @@
       target[2 * i + 1] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] % 16));
     }
   }
+
+#  endif // BOOST_VERSION >= 106600
 #endif  /* ORTHANC_ENABLE_MD5 */
 
 
--- a/TODO	Wed Feb 18 20:21:08 2026 +0100
+++ b/TODO	Thu Feb 19 15:48:21 2026 +0100
@@ -22,7 +22,6 @@
 * Support retry counter in Orthanc::HttpClient
 * Option to enable DNS lookups in DICOM:
   https://orthanc.uclouvain.be/hg/orthanc/file/Orthanc-1.9.3/OrthancFramework/Sources/OrthancFramework.cpp#l88
-* Toolbox::ComputeMD5() fails on files larger than 4GB
 * Logging: add more specific information to contextualize the logs.
   For a DICOM Transfer, that would be nice to include the modality in the context + a study identifier or a job id.
   Note that the thread id greatly helps already wrt this topic.