diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2021-12-17 11:38:34 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2021-12-19 18:58:40 +0100 |
commit | 5cc75108012251bef96c56a71cb3f92274990064 (patch) | |
tree | 9b3beaae17b3ea6430c30cb808acbaae78ea5761 | |
parent | c52fcb2ad9f4a1c166ac0438db3889b13d7f9270 (diff) |
QZipReader: update to unzip partly broken archives
The problem was discovered while providing a fix for the linked issue.
The original zip archive is very old, and it does not contain separate
entries for directories, only for files.
As a result, QZipReader algorithm was failing to create all the
necessary subdirectory structures, and unzipping failed.
This patch detects such case, and creates a directory hierarchy based
on the file paths.
Task-number: QTBUG-81503
Pick-to: 6.3 6.2 5.15
Change-Id: I204f9b620853b3ffcbb9cbf6fe08fb5958776ea0
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r-- | src/gui/text/qzip.cpp | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp index 711482af8a..1fe7a6d042 100644 --- a/src/gui/text/qzip.cpp +++ b/src/gui/text/qzip.cpp @@ -1024,13 +1024,33 @@ bool QZipReader::extractAll(const QString &destinationDir) const // create directories first const QList<FileInfo> allFiles = fileInfoList(); + bool foundDirs = false; + bool hasDirs = false; for (const FileInfo &fi : allFiles) { const QString absPath = destinationDir + QDir::separator() + fi.filePath; if (fi.isDir) { + foundDirs = true; if (!baseDir.mkpath(fi.filePath)) return false; if (!QFile::setPermissions(absPath, fi.permissions)) return false; + } else if (!hasDirs && fi.filePath.contains(u"/")) { + // filePath does not have leading or trailing '/', so if we find + // one, than the file path contains directories. + hasDirs = true; + } + } + + // Some zip archives can be broken in the sense that they do not report + // separate entries for directories, only for files. In this case we + // need to recreate directory structure based on the file paths. + if (hasDirs && !foundDirs) { + for (const FileInfo &fi : allFiles) { + const auto dirPath = fi.filePath.left(fi.filePath.lastIndexOf(u"/")); + if (!baseDir.mkpath(dirPath)) + return false; + // We will leave the directory permissions default in this case, + // because setting dir permissions based on file is incorrect } } |