From fa67b8f5c384c55bb353061cbc04acfa40532b64 Mon Sep 17 00:00:00 2001
From: David Kocik <kocikdav@gmail.com>
Date: Thu, 5 Jan 2023 15:45:24 +0100
Subject: [PATCH] Miniz: Get filename from Extra Field.

Co-authored-by: lane.wei <lane.wei@bambulab.com>
---
 src/miniz/miniz.c                    | 34 ++++++++++++++++++++++++++++
 src/miniz/miniz.h                    |  3 +++
 src/slic3r/GUI/FileArchiveDialog.cpp | 15 ++++++++----
 src/slic3r/GUI/Plater.cpp            | 10 ++++++++
 4 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/src/miniz/miniz.c b/src/miniz/miniz.c
index 0d6fc7d9b..09794bea0 100644
--- a/src/miniz/miniz.c
+++ b/src/miniz/miniz.c
@@ -7922,6 +7922,40 @@ mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, cha
     return n + 1;
 }
 
+mz_uint mz_zip_reader_get_filename_from_extra(mz_zip_archive* pZip, mz_uint file_index, char* buffer, mz_uint extra_buf_size)
+{
+    if (extra_buf_size == 0)
+        return 0;
+    mz_uint nf;
+    mz_uint ne;
+    const mz_uint8* p = mz_zip_get_cdh(pZip, file_index);
+    if (!p)
+    {
+        if (extra_buf_size)
+            buffer[0] = '\0';
+        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
+        return 0;
+    }
+    nf = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+    ne = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
+
+    int copy = 0;
+    char const* p_nf = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + nf;
+    char const* e = p_nf + ne + 1;
+    while (p_nf + 4 < e) {
+        mz_uint16 len = ((mz_uint16)p_nf[2]) | ((mz_uint16)p_nf[3] << 8);
+        if (p_nf[0] == '\x75' && p_nf[1] == '\x70' && len >= 5 && p_nf + 4 + len < e && p_nf[4] == '\x01') {
+            mz_uint length = MZ_MIN(len - 5, extra_buf_size - 1);
+            memcpy(buffer, p_nf + 9, length);
+            return length;
+        }
+        else {
+            p_nf += 4 + len;
+        }
+    }
+    return 0;
+}
+
 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
 {
     return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
diff --git a/src/miniz/miniz.h b/src/miniz/miniz.h
index 8fe0461ad..62d579f9e 100644
--- a/src/miniz/miniz.h
+++ b/src/miniz/miniz.h
@@ -1166,6 +1166,9 @@ mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, cha
 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
 int mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *file_index);
 
+/* Retrieves the filename of an archive file entry from EXTRA ID. */
+mz_uint mz_zip_reader_get_filename_from_extra(mz_zip_archive * pZip, mz_uint file_index, char* buffer, mz_uint extra_buf_size);
+
 /* Returns detailed information about an archive file entry. */
 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
 
diff --git a/src/slic3r/GUI/FileArchiveDialog.cpp b/src/slic3r/GUI/FileArchiveDialog.cpp
index 2813887df..2b861692a 100644
--- a/src/slic3r/GUI/FileArchiveDialog.cpp
+++ b/src/slic3r/GUI/FileArchiveDialog.cpp
@@ -212,10 +212,17 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
     std::vector<boost::filesystem::path> filtered_entries;
     for (mz_uint i = 0; i < num_entries; ++i) {
         if (mz_zip_reader_file_stat(archive, i, &stat)) {
-            wxString wname = boost::nowide::widen(stat.m_filename);
-            std::string name = GUI::format(wname);
-            //std::replace(name.begin(), name.end(), '\\', '/');
-            boost::filesystem::path path(name);
+            std::string extra(1024, 0);
+            boost::filesystem::path path;
+            size_t extra_size = mz_zip_reader_get_filename_from_extra(archive, i, extra.data(), extra.size());
+            if (extra_size > 0) {
+                path = boost::filesystem::path(extra.substr(0, extra_size));
+            } else {
+                wxString wname = boost::nowide::widen(stat.m_filename);
+                std::string name = GUI::format(wname);
+                path = boost::filesystem::path(name);
+            }
+            assert(!path.empty());
             if (!path.has_extension())
                 continue;
             // filter out MACOS specific hidden files
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index ee8e5a842..ed280697a 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -5769,6 +5769,16 @@ bool Plater::preview_zip_archive(const boost::filesystem::path& archive_path)
                     wxString wname = boost::nowide::widen(stat.m_filename);
                     std::string name = GUI::format(wname);
                     fs::path archive_path(name);
+
+                    std::string extra(1024, 0);
+                    size_t extra_size = mz_zip_reader_get_filename_from_extra(&archive, i, extra.data(), extra.size());
+                    if (extra_size > 0) {
+                        archive_path = fs::path(extra.substr(0, extra_size));
+                        name = archive_path.string();
+                    }
+
+                    if (archive_path.empty())
+                        continue;
                     for (const auto& path : selected_paths) {
                         if (path == archive_path) {
                             try