Skip to content

Commit 44d5705

Browse files
authored
fix: auto-detect Deflate64 in ZIP files (#389)
Use libzip API to detect Deflate64 compression and automatically switch to cli7z plugin for better compatibility. log: fix bug Bug:https://pms.uniontech.com//bug-view-357127.html
1 parent adbce1f commit 44d5705

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

src/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ include_directories(${GOBJECT_INCLUDE_DIRS})
4444
pkg_search_module(GIO REQUIRED gio-unix-2.0)
4545
include_directories(${GIO_INCLUDE_DIRS})
4646

47+
pkg_search_module(ZIP REQUIRED libzip)
48+
include_directories(${ZIP_INCLUDE_DIRS})
49+
4750
#指定头文件路径
4851
include_directories(${PROJECT_SOURCE_DIR})
4952
include_directories(${PROJECT_SOURCE_DIR}/source)
@@ -77,6 +80,7 @@ target_link_libraries(${EXE_NAME}
7780
${DtkWidget_LIBRARIES}
7881
${GOBJECT_LIBRARIES}
7982
${GIO_LIBRARIES}
83+
${ZIP_LIBRARIES}
8084
compressor-interface
8185
)
8286

src/source/common/uitools.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include <QStorageInfo>
3030
#include <QProcessEnvironment>
3131

32+
#include <zip.h> // libzip header
33+
3234
#include <KEncodingProber>
3335

3436
DCORE_USE_NAMESPACE
@@ -223,6 +225,14 @@ ReadOnlyArchiveInterface *UiTools::createInterface(const QString &fileName, bool
223225

224226
const CustomMimeType mimeType = determineMimeType(fileName);
225227

228+
// 提前检测 ZIP 文件是否需要替代插件(如 Deflate64)
229+
if (!bWrite && eType == APT_Auto && mimeType.name() == "application/zip") {
230+
if (checkZipNeedsAlternativePlugin(fileName)) {
231+
qInfo() << "Detected need for alternative plugin, switching to cli7z";
232+
eType = APT_Cli7z; // 自动切换到 cli7z 插件
233+
}
234+
}
235+
226236
QVector<Plugin *> offers;
227237
if (bWrite) {
228238
offers = PluginManager::get_instance().preferredWritePluginsFor(mimeType);
@@ -460,3 +470,51 @@ bool UiTools::isWayland()
460470
return false;
461471
}
462472
}
473+
474+
bool UiTools::checkZipNeedsAlternativePlugin(const QString &strFileName)
475+
{
476+
// 使用 libzip API 检测压缩方法
477+
int errcode = 0;
478+
zip_t *archive = zip_open(QFile::encodeName(strFileName).constData(), ZIP_RDONLY, &errcode);
479+
480+
if (!archive) {
481+
qWarning() << "Failed to open ZIP file for compression method check:" << strFileName;
482+
return false; // 无法打开文件,使用默认插件
483+
}
484+
485+
// 获取文件数量
486+
zip_int64_t num_entries = zip_get_num_entries(archive, 0);
487+
488+
// 检查前几个文件,跳过 stored(未压缩)文件,找到第一个实际压缩的文件
489+
bool needsAlternative = false;
490+
const int maxCheck = 20; // 最多检查前 20 个文件
491+
492+
for (zip_int64_t i = 0; i < num_entries && i < maxCheck; i++) {
493+
struct zip_stat stat_buffer;
494+
zip_stat_init(&stat_buffer);
495+
496+
if (zip_stat_index(archive, static_cast<zip_uint64_t>(i), 0, &stat_buffer) == 0) {
497+
// 跳过 stored 文件(comp_method == 0)
498+
if (stat_buffer.comp_method == ZIP_CM_STORE) {
499+
continue;
500+
}
501+
502+
// 检查压缩方法
503+
// ZIP_CM_DEFLATE (8) = 标准 Deflate
504+
// ZIP_CM_DEFLATE64 (9) = Deflate64
505+
if (stat_buffer.comp_method == ZIP_CM_DEFLATE64) { // ZIP_CM_DEFLATE64
506+
qInfo() << "Detected Deflate64 compression method, switching to cli7z plugin"
507+
<< "file:" << strFileName
508+
<< "entry:" << stat_buffer.name;
509+
needsAlternative = true;
510+
break;
511+
}
512+
513+
// 如果找到第一个非 stored 的文件,且不是 Deflate64,则停止检查,通常 ZIP 文件使用统一的压缩方法
514+
break;
515+
}
516+
}
517+
518+
zip_close(archive);
519+
return needsAlternative;
520+
}

src/source/common/uitools.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ class UiTools : public QObject
117117
static ReadOnlyArchiveInterface *createInterface(const QString &fileName, bool bWrite = false, AssignPluginType eType = APT_Auto/*bool bUseLibArchive = false*/);
118118
static ReadOnlyArchiveInterface *createInterface(const QString &fileName, const CustomMimeType &mimeType, Plugin *plugin);
119119

120+
/**
121+
* @brief checkZipNeedsAlternativePlugin 检测 ZIP 文件是否需要替代插件
122+
* @param strFileName ZIP 文件路径
123+
* @return 是否需要使用 cli7z 等替代插件
124+
*/
125+
static bool checkZipNeedsAlternativePlugin(const QString &strFileName);
126+
120127
/**
121128
* @brief transSplitFileName 处理7z、rar分卷压缩包名称
122129
* @param fileName 原始名称

0 commit comments

Comments
 (0)