Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ include_directories(${GOBJECT_INCLUDE_DIRS})
pkg_search_module(GIO REQUIRED gio-unix-2.0)
include_directories(${GIO_INCLUDE_DIRS})

pkg_search_module(ZIP REQUIRED libzip)
include_directories(${ZIP_INCLUDE_DIRS})

#指定头文件路径
include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/source)
Expand Down Expand Up @@ -77,6 +80,7 @@ target_link_libraries(${EXE_NAME}
${DtkWidget_LIBRARIES}
${GOBJECT_LIBRARIES}
${GIO_LIBRARIES}
${ZIP_LIBRARIES}
compressor-interface
)

Expand Down
58 changes: 58 additions & 0 deletions src/source/common/uitools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
#include <QTextCodec>
#include <QRegularExpression>
#include <QUuid>
#include <QStorageInfo>

Check warning on line 29 in src/source/common/uitools.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QStorageInfo> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QProcessEnvironment>

Check warning on line 30 in src/source/common/uitools.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QProcessEnvironment> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <zip.h> // libzip header

Check warning on line 32 in src/source/common/uitools.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <zip.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <KEncodingProber>

Check warning on line 34 in src/source/common/uitools.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <KEncodingProber> not found. Please note: Cppcheck does not need standard library headers to get proper results.

DCORE_USE_NAMESPACE
Q_DECLARE_METATYPE(KPluginMetaData)
Expand Down Expand Up @@ -223,6 +225,14 @@

const CustomMimeType mimeType = determineMimeType(fileName);

// 提前检测 ZIP 文件是否需要替代插件(如 Deflate64)
if (!bWrite && eType == APT_Auto && mimeType.name() == "application/zip") {
if (checkZipNeedsAlternativePlugin(fileName)) {
qInfo() << "Detected need for alternative plugin, switching to cli7z";
eType = APT_Cli7z; // 自动切换到 cli7z 插件
}
}

QVector<Plugin *> offers;
if (bWrite) {
offers = PluginManager::get_instance().preferredWritePluginsFor(mimeType);
Expand Down Expand Up @@ -460,3 +470,51 @@
return false;
}
}

bool UiTools::checkZipNeedsAlternativePlugin(const QString &strFileName)
{
// 使用 libzip API 检测压缩方法
int errcode = 0;
zip_t *archive = zip_open(QFile::encodeName(strFileName).constData(), ZIP_RDONLY, &errcode);

if (!archive) {
qWarning() << "Failed to open ZIP file for compression method check:" << strFileName;
return false; // 无法打开文件,使用默认插件
}

// 获取文件数量
zip_int64_t num_entries = zip_get_num_entries(archive, 0);

// 检查前几个文件,跳过 stored(未压缩)文件,找到第一个实际压缩的文件
bool needsAlternative = false;
const int maxCheck = 20; // 最多检查前 20 个文件

for (zip_int64_t i = 0; i < num_entries && i < maxCheck; i++) {
struct zip_stat stat_buffer;
zip_stat_init(&stat_buffer);

if (zip_stat_index(archive, static_cast<zip_uint64_t>(i), 0, &stat_buffer) == 0) {
// 跳过 stored 文件(comp_method == 0)
if (stat_buffer.comp_method == ZIP_CM_STORE) {
continue;
}

// 检查压缩方法
// ZIP_CM_DEFLATE (8) = 标准 Deflate
// ZIP_CM_DEFLATE64 (9) = Deflate64
if (stat_buffer.comp_method == ZIP_CM_DEFLATE64) { // ZIP_CM_DEFLATE64
qInfo() << "Detected Deflate64 compression method, switching to cli7z plugin"
<< "file:" << strFileName
<< "entry:" << stat_buffer.name;
needsAlternative = true;
break;
}

// 如果找到第一个非 stored 的文件,且不是 Deflate64,则停止检查,通常 ZIP 文件使用统一的压缩方法
break;
}
}

zip_close(archive);
return needsAlternative;
}
7 changes: 7 additions & 0 deletions src/source/common/uitools.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ class UiTools : public QObject
static ReadOnlyArchiveInterface *createInterface(const QString &fileName, bool bWrite = false, AssignPluginType eType = APT_Auto/*bool bUseLibArchive = false*/);
static ReadOnlyArchiveInterface *createInterface(const QString &fileName, const CustomMimeType &mimeType, Plugin *plugin);

/**
* @brief checkZipNeedsAlternativePlugin 检测 ZIP 文件是否需要替代插件
* @param strFileName ZIP 文件路径
* @return 是否需要使用 cli7z 等替代插件
*/
static bool checkZipNeedsAlternativePlugin(const QString &strFileName);

/**
* @brief transSplitFileName 处理7z、rar分卷压缩包名称
* @param fileName 原始名称
Expand Down
Loading