summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2021-12-17 11:38:34 +0100
committerIvan Solovev <ivan.solovev@qt.io>2021-12-19 18:58:40 +0100
commit5cc75108012251bef96c56a71cb3f92274990064 (patch)
tree9b3beaae17b3ea6430c30cb808acbaae78ea5761
parentc52fcb2ad9f4a1c166ac0438db3889b13d7f9270 (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.cpp20
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
}
}