From fa67b8f5c384c55bb353061cbc04acfa40532b64 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 5 Jan 2023 15:45:24 +0100 Subject: [PATCH] Miniz: Get filename from Extra Field. Co-authored-by: lane.wei --- 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 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