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>
This commit is contained in:
Ivan Solovev 2021-12-17 11:38:34 +01:00
parent c52fcb2ad9
commit 5cc7510801

View File

@ -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
}
}