diff --git a/quazip/unzip.c b/quazip/unzip.c index ee7b487..432ab89 100644 --- a/quazip/unzip.c +++ b/quazip/unzip.c @@ -679,7 +679,21 @@ extern unzFile unzOpenInternal (voidpf file, if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO; + /* For ZIP64 archives, we still need to read the comment size from the regular + end of central directory record if it exists */ us.gi.size_comment = 0; + { + ZPOS64_T regular_central_pos = unz64local_SearchCentralDir(&us.z_filefunc, us.filestream); + if (regular_central_pos != 0) + { + /* Found regular end of central directory, read the comment length. Comment length is at offset 20. */ + if (ZSEEK64(us.z_filefunc, us.filestream, regular_central_pos + 20, ZLIB_FILEFUNC_SEEK_SET) == 0) + { + /* Read comment length field (2 bytes at offset 20) */ + unz64local_getShort(&us.z_filefunc, us.filestream, &us.gi.size_comment); + } + } + } } else { @@ -2066,7 +2080,23 @@ extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uS if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment; - if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + /* For ZIP64 archives, the central_pos points to ZIP64 EOCD, but comment is in regular EOCD */ + ZPOS64_T comment_pos = s->central_pos + 22; + if (s->gi.size_comment > 0) { + /* Check if this might be a ZIP64 archive by looking for ZIP64 EOCD signature */ + uLong signature = 0; + if (ZSEEK64(s->z_filefunc, s->filestream, s->central_pos, ZLIB_FILEFUNC_SEEK_SET) == 0 && + unz64local_getLong(&s->z_filefunc, s->filestream, &signature) == UNZ_OK && + signature == 0x06064b50) { + /* This is ZIP64 EOCD, need to find regular EOCD for comment */ + ZPOS64_T regular_eocd_pos = unz64local_SearchCentralDir(&s->z_filefunc, s->filestream); + if (regular_eocd_pos != 0) { + comment_pos = regular_eocd_pos + 22; + } + } + } + + if (ZSEEK64(s->z_filefunc,s->filestream,comment_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (uReadThis>0) diff --git a/qztest/testquazipfile.cpp b/qztest/testquazipfile.cpp index 61fda88..cd55764 100644 --- a/qztest/testquazipfile.cpp +++ b/qztest/testquazipfile.cpp @@ -201,6 +201,8 @@ void TestQuaZipFile::zipUnzipLarge() QFETCH(QString, zipName); QFETCH(QString, fileName); QFETCH(long long, size); + + QString testComment = "ZIP64 large file test comment"; QFile testFile(zipName); if (testFile.exists()) { if (!testFile.remove()) { @@ -214,6 +216,8 @@ void TestQuaZipFile::zipUnzipLarge() QuaZip testZip(&testFile); testZip.setZip64Enabled(true); QVERIFY(testZip.open(QuaZip::mdCreate)); + + testZip.setComment(testComment); QFile inFile("tmp/" + fileName); if (!inFile.open(QIODevice::ReadOnly)) { qDebug("File name: %s", fileName.toUtf8().constData()); @@ -255,6 +259,11 @@ void TestQuaZipFile::zipUnzipLarge() // now test unzip QuaZip testUnzip(&testFile); QVERIFY(testUnzip.open(QuaZip::mdUnzip)); + + // Verify comment is preserved in ZIP64 archive (issue #158) + QString readComment = testUnzip.getComment(); + QCOMPARE(readComment, testComment); + QVERIFY(testUnzip.goToFirstFile()); QuaZipFileInfo64 info;