|
29 | 29 | #include <QStorageInfo> |
30 | 30 | #include <QProcessEnvironment> |
31 | 31 |
|
| 32 | +#include <zip.h> // libzip header |
| 33 | + |
32 | 34 | #include <KEncodingProber> |
33 | 35 |
|
34 | 36 | DCORE_USE_NAMESPACE |
@@ -223,6 +225,14 @@ ReadOnlyArchiveInterface *UiTools::createInterface(const QString &fileName, bool |
223 | 225 |
|
224 | 226 | const CustomMimeType mimeType = determineMimeType(fileName); |
225 | 227 |
|
| 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 | + |
226 | 236 | QVector<Plugin *> offers; |
227 | 237 | if (bWrite) { |
228 | 238 | offers = PluginManager::get_instance().preferredWritePluginsFor(mimeType); |
@@ -460,3 +470,51 @@ bool UiTools::isWayland() |
460 | 470 | return false; |
461 | 471 | } |
462 | 472 | } |
| 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 | +} |
0 commit comments