changeset 6600:3f857772f59a

preparing for utf-8 in zip
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 20 Feb 2026 17:40:58 +0100
parents 4f5811d75978
children 17f41205ed0e
files OrthancFramework/Sources/Compression/ZipWriter.cpp OrthancFramework/UnitTestsSources/ZipTests.cpp OrthancServer/Sources/ServerJobs/ArchiveJob.cpp
diffstat 3 files changed, 75 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/Compression/ZipWriter.cpp	Fri Feb 20 16:55:34 2026 +0100
+++ b/OrthancFramework/Sources/Compression/ZipWriter.cpp	Fri Feb 20 17:40:58 2026 +0100
@@ -38,6 +38,7 @@
 #include "../Logging.h"
 #include "../OrthancException.h"
 #include "../SystemToolbox.h"
+#include "../Toolbox.h"
 
 
 static void PrepareFileInfo(zip_fileinfo& zfi)
@@ -607,6 +608,30 @@
   {
     Open();
 
+    std::string utf8;
+
+#if 0
+    if (Toolbox::IsValidUtf8(filename))
+    {
+      /**
+       * Starting with minizip 1.3.2 (released on 17 Feb 2026), bit 11
+       * of the ZIP header flags is appropriately set if the filename
+       * is encoded using UTF-8. This enables compatibility with UTF-8.
+       * https://zlib.net/ChangeLog.txt
+       * https://discourse.orthanc-server.org/t/seriesdescription-characters-and-removed-during-oe2-zip-export/6397
+       **/
+      utf8 = filename;
+    }
+    else
+    {
+      // Fallback if the filename is not encoded using valid UTF-8
+      utf8 = Toolbox::ConvertToAscii(filename);
+    }
+#else
+    // This was the code used in Orthanc <= 1.12.10
+    utf8 = Toolbox::ConvertToAscii(filename);
+#endif
+
     zip_fileinfo zfi;
     PrepareFileInfo(zfi);
 
@@ -614,7 +639,7 @@
 
     if (isZip64_)
     {
-      result = zipOpenNewFileInZip64(pimpl_->file_, filename.c_str(),
+      result = zipOpenNewFileInZip64(pimpl_->file_, utf8.c_str(),
                                      &zfi,
                                      NULL,   0,
                                      NULL,   0,
@@ -624,7 +649,7 @@
     }
     else
     {
-      result = zipOpenNewFileInZip(pimpl_->file_, filename.c_str(),
+      result = zipOpenNewFileInZip(pimpl_->file_, utf8.c_str(),
                                    &zfi,
                                    NULL,   0,
                                    NULL,   0,
--- a/OrthancFramework/UnitTestsSources/ZipTests.cpp	Fri Feb 20 16:55:34 2026 +0100
+++ b/OrthancFramework/UnitTestsSources/ZipTests.cpp	Fri Feb 20 17:40:58 2026 +0100
@@ -36,6 +36,8 @@
 #include "../Sources/TemporaryFile.h"
 #include "../Sources/Toolbox.h"
 
+#include "../Resources/CodeGeneration/EncodingTests.h"
+
 
 using namespace Orthanc;
 
@@ -413,3 +415,48 @@
     ASSERT_EQ(0u, buffer.GetPosition());
   }
 }
+
+
+TEST(HierarchicalZipWriter, DISABLED_Utf8)
+{
+  (void) toUpperResult;
+  (void) toUpperSource;
+  (void) testEncodingsExpected;
+
+  static const std::string path = "UnitTestsResults/hello-utf8.zip";
+
+  {
+    Orthanc::ZipWriter w;
+    w.SetOutputPath(path);
+
+    for (unsigned int i = 0; i < testEncodingsCount; i++)
+    {
+      std::string source(testEncodingsEncoded[i]);
+      std::string s = Toolbox::ConvertToUtf8(source, testEncodings[i], false, false);
+      ASSERT_TRUE(Orthanc::Toolbox::IsValidUtf8(s));
+      printf("[%s]\n", s.c_str());
+      w.OpenFile(s);
+      w.Write("Hello");
+    }
+  }
+
+  {
+    std::unique_ptr<ZipReader> reader(ZipReader::CreateFromFile(path));
+
+    ASSERT_EQ(testEncodingsCount, reader->GetFilesCount());
+
+    std::set<std::string> files;
+    std::string filename, content;
+    while (reader->ReadNextFile(filename, content))
+    {
+      files.insert(filename);
+    }
+
+    for (unsigned int i = 0; i < testEncodingsCount; i++)
+    {
+      std::string source(testEncodingsEncoded[i]);
+      std::string s = Toolbox::ConvertToUtf8(source, testEncodings[i], false, false);
+      ASSERT_TRUE(files.find(s) != files.end());
+    }
+  }
+}
--- a/OrthancServer/Sources/ServerJobs/ArchiveJob.cpp	Fri Feb 20 16:55:34 2026 +0100
+++ b/OrthancServer/Sources/ServerJobs/ArchiveJob.cpp	Fri Feb 20 17:40:58 2026 +0100
@@ -1020,7 +1020,7 @@
         }
       }
 
-      path = Toolbox::StripSpaces(Toolbox::ConvertToAscii(path));
+      path = Toolbox::StripSpaces(path);
 
       if (path.empty() 
           || (static_cast<size_t>(boost::count(path, '^')) == path.size()))  // this happens with non ASCII patient names: only the '^' remains and this is not a valid zip folder name