| 546 | } |
| 547 | |
| 548 | auto ExtractZipTask::extractZip() -> ZipResult |
| 549 | { |
| 550 | auto target = m_output_dir.absolutePath(); |
| 551 | auto target_top_dir = QUrl::fromLocalFile(target); |
| 552 | |
| 553 | QStringList extracted; |
| 554 | |
| 555 | qDebug() << "Extracting subdir" << m_subdirectory << "from" << m_input->getZipName() << "to" << target; |
| 556 | auto numEntries = m_input->getEntriesCount(); |
| 557 | if (numEntries < 0) { |
| 558 | return ZipResult(tr("Failed to enumerate files in archive")); |
| 559 | } |
| 560 | if (numEntries == 0) { |
| 561 | logWarning(tr("Extracting empty archives seems odd...")); |
| 562 | return ZipResult(); |
| 563 | } |
| 564 | if (!m_input->goToFirstFile()) { |
| 565 | return ZipResult(tr("Failed to seek to first file in zip")); |
| 566 | } |
| 567 | |
| 568 | setStatus("Extracting files..."); |
| 569 | setProgress(0, numEntries); |
| 570 | do { |
| 571 | if (m_zip_future.isCanceled()) |
| 572 | return ZipResult(); |
| 573 | setProgress(m_progress + 1, m_progressTotal); |
| 574 | QString file_name = m_input->getCurrentFileName(); |
| 575 | if (!file_name.startsWith(m_subdirectory)) |
| 576 | continue; |
| 577 | |
| 578 | auto relative_file_name = QDir::fromNativeSeparators(file_name.mid(m_subdirectory.size())); |
| 579 | auto original_name = relative_file_name; |
| 580 | setStatus("Unpacking: " + relative_file_name); |
| 581 | |
| 582 | // Fix subdirs/files ending with a / getting transformed into absolute paths |
| 583 | if (relative_file_name.startsWith('/')) |
| 584 | relative_file_name = relative_file_name.mid(1); |
| 585 | |
| 586 | // Fix weird "folders with a single file get squashed" thing |
| 587 | QString sub_path; |
| 588 | if (relative_file_name.contains('/') && !relative_file_name.endsWith('/')) { |
| 589 | sub_path = relative_file_name.section('/', 0, -2) + '/'; |
| 590 | FS::ensureFolderPathExists(FS::PathCombine(target, sub_path)); |
| 591 | |
| 592 | relative_file_name = relative_file_name.split('/').last(); |
| 593 | } |
| 594 | |
| 595 | QString target_file_path; |
| 596 | if (relative_file_name.isEmpty()) { |
| 597 | target_file_path = target + '/'; |
| 598 | } else { |
| 599 | target_file_path = FS::PathCombine(target_top_dir.toLocalFile(), sub_path, relative_file_name); |
| 600 | if (relative_file_name.endsWith('/') && !target_file_path.endsWith('/')) |
| 601 | target_file_path += '/'; |
| 602 | } |
| 603 | |
| 604 | if (!target_top_dir.isParentOf(QUrl::fromLocalFile(target_file_path))) { |
| 605 | return ZipResult(tr("Extracting %1 was cancelled, because it was effectively outside of the target path %2") |
nothing calls this directly
no test coverage detected