From 5cc75108012251bef96c56a71cb3f92274990064 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Fri, 17 Dec 2021 11:38:34 +0100 Subject: 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 --- src/gui/text/qzip.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/gui/text/qzip.cpp') 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 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 } } -- cgit v1.2.3