1 |
/* |
2 |
Copyright (C) 2005-2014 Sergey A. Tachenov |
3 |
|
4 |
This file is part of QuaZIP test suite. |
5 |
|
6 |
QuaZIP is free software: you can redistribute it and/or modify |
7 |
it under the terms of the GNU Lesser General Public License as published by |
8 |
the Free Software Foundation, either version 2.1 of the License, or |
9 |
(at your option) any later version. |
10 |
|
11 |
QuaZIP is distributed in the hope that it will be useful, |
12 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
GNU Lesser General Public License for more details. |
15 |
|
16 |
You should have received a copy of the GNU Lesser General Public License |
17 |
along with QuaZIP. If not, see <http://www.gnu.org/licenses/>. |
18 |
|
19 |
See COPYING file for the full LGPL text. |
20 |
|
21 |
Original ZIP package is copyrighted by Gilles Vollant and contributors, |
22 |
see quazip/(un)zip.h files for details. Basically it's the zlib license. |
23 |
*/ |
24 |
|
25 |
#include "testquazipfile.h" |
26 |
|
27 |
#include "qztest.h" |
28 |
|
29 |
#include <quazip/JlCompress.h> |
30 |
#include <quazip/quazipfile.h> |
31 |
#include <quazip/quazip.h> |
32 |
|
33 |
#include <QFile> |
34 |
#include <QString> |
35 |
#include <QStringList> |
36 |
|
37 |
#include <QtTest/QtTest> |
38 |
|
39 |
void TestQuaZipFile::zipUnzip_data() |
40 |
{ |
41 |
QTest::addColumn<QString>("zipName"); |
42 |
QTest::addColumn<QStringList>("fileNames"); |
43 |
QTest::addColumn<QByteArray>("fileNameCodec"); |
44 |
QTest::addColumn<QByteArray>("password"); |
45 |
QTest::addColumn<bool>("zip64"); |
46 |
QTest::newRow("simple") << "simple.zip" << ( |
47 |
QStringList() << "test0.txt" << "testdir1/test1.txt" |
48 |
<< "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt") |
49 |
<< QByteArray() << QByteArray() << false; |
50 |
QTest::newRow("Cyrillic") << "cyrillic.zip" << ( |
51 |
QStringList() |
52 |
<< QString::fromUtf8("русское имя файла с пробелами.txt")) |
53 |
<< QByteArray("IBM866") << QByteArray() << false; |
54 |
QTest::newRow("password") << "password.zip" << ( |
55 |
QStringList() << "test.txt") |
56 |
<< QByteArray() << QByteArray("PassPass") << false; |
57 |
QTest::newRow("zip64") << "zip64.zip" << ( |
58 |
QStringList() << "test64.txt") |
59 |
<< QByteArray() << QByteArray() << true; |
60 |
} |
61 |
|
62 |
void TestQuaZipFile::zipUnzip() |
63 |
{ |
64 |
QFETCH(QString, zipName); |
65 |
QFETCH(QStringList, fileNames); |
66 |
QFETCH(QByteArray, fileNameCodec); |
67 |
QFETCH(QByteArray, password); |
68 |
QFETCH(bool, zip64); |
69 |
QFile testFile(zipName); |
70 |
if (testFile.exists()) { |
71 |
if (!testFile.remove()) { |
72 |
QFAIL("Couldn't remove existing archive to create a new one"); |
73 |
} |
74 |
} |
75 |
if (!createTestFiles(fileNames)) { |
76 |
QFAIL("Couldn't create test files for zipping"); |
77 |
} |
78 |
QuaZip testZip(&testFile); |
79 |
testZip.setZip64Enabled(zip64); |
80 |
if (!fileNameCodec.isEmpty()) |
81 |
testZip.setFileNameCodec(fileNameCodec); |
82 |
QVERIFY(testZip.open(QuaZip::mdCreate)); |
83 |
QString comment = "Test comment"; |
84 |
testZip.setComment(comment); |
85 |
foreach (QString fileName, fileNames) { |
86 |
QFile inFile("tmp/" + fileName); |
87 |
if (!inFile.open(QIODevice::ReadOnly)) { |
88 |
qDebug("File name: %s", fileName.toUtf8().constData()); |
89 |
QFAIL("Couldn't open input file"); |
90 |
} |
91 |
QuaZipFile outFile(&testZip); |
92 |
QVERIFY(outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileName, |
93 |
inFile.fileName()), |
94 |
password.isEmpty() ? NULL : password.constData())); |
95 |
for (qint64 pos = 0, len = inFile.size(); pos < len; ) { |
96 |
char buf[4096]; |
97 |
qint64 readSize = qMin(static_cast<qint64>(4096), len - pos); |
98 |
qint64 l; |
99 |
if ((l = inFile.read(buf, readSize)) != readSize) { |
100 |
qDebug("Reading %ld bytes from %s at %ld returned %ld", |
101 |
static_cast<long>(readSize), |
102 |
fileName.toUtf8().constData(), |
103 |
static_cast<long>(pos), |
104 |
static_cast<long>(l)); |
105 |
QFAIL("Read failure"); |
106 |
} |
107 |
QVERIFY(outFile.write(buf, readSize)); |
108 |
pos += readSize; |
109 |
} |
110 |
inFile.close(); |
111 |
outFile.close(); |
112 |
QCOMPARE(outFile.getZipError(), ZIP_OK); |
113 |
} |
114 |
testZip.close(); |
115 |
QCOMPARE(testZip.getZipError(), ZIP_OK); |
116 |
// now test unzip |
117 |
QuaZip testUnzip(&testFile); |
118 |
if (!fileNameCodec.isEmpty()) |
119 |
testUnzip.setFileNameCodec(fileNameCodec); |
120 |
QVERIFY(testUnzip.open(QuaZip::mdUnzip)); |
121 |
QCOMPARE(testUnzip.getComment(), comment); |
122 |
QVERIFY(testUnzip.goToFirstFile()); |
123 |
foreach (QString fileName, fileNames) { |
124 |
QuaZipFileInfo64 info; |
125 |
QVERIFY(testUnzip.getCurrentFileInfo(&info)); |
126 |
QCOMPARE(info.name, fileName); |
127 |
QCOMPARE(info.isEncrypted(), !password.isEmpty()); |
128 |
QFile original("tmp/" + fileName); |
129 |
QVERIFY(original.open(QIODevice::ReadOnly)); |
130 |
QuaZipFile archived(&testUnzip); |
131 |
QVERIFY(archived.open(QIODevice::ReadOnly, |
132 |
password.isEmpty() ? NULL : password.constData())); |
133 |
QByteArray originalData = original.readAll(); |
134 |
QByteArray archivedData = archived.readAll(); |
135 |
QCOMPARE(archivedData, originalData); |
136 |
testUnzip.goToNextFile(); |
137 |
} |
138 |
if (!password.isEmpty()) { |
139 |
QVERIFY(testUnzip.goToFirstFile()); |
140 |
QuaZipFileInfo64 info; |
141 |
QVERIFY(testUnzip.getCurrentFileInfo(&info)); |
142 |
QFile original("tmp/" + info.name); |
143 |
QVERIFY(original.open(QIODevice::ReadOnly)); |
144 |
QuaZipFile archived(&testUnzip); |
145 |
QVERIFY(archived.open(QIODevice::ReadOnly, "WrongPassword")); |
146 |
QByteArray originalData = original.readAll(); |
147 |
QByteArray archivedData = archived.readAll(); |
148 |
QVERIFY(archivedData != originalData); |
149 |
} |
150 |
testUnzip.close(); |
151 |
QCOMPARE(testUnzip.getZipError(), UNZ_OK); |
152 |
// clean up |
153 |
removeTestFiles(fileNames); |
154 |
testFile.remove(); |
155 |
} |
156 |
|
157 |
void TestQuaZipFile::bytesAvailable_data() |
158 |
{ |
159 |
QTest::addColumn<QString>("zipName"); |
160 |
QTest::addColumn<QStringList>("fileNames"); |
161 |
QTest::newRow("simple") << "test.zip" << ( |
162 |
QStringList() << "test0.txt" << "testdir1/test1.txt" |
163 |
<< "testdir2/test2.txt" << "testdir2/subdir/test2sub.txt"); |
164 |
} |
165 |
|
166 |
void TestQuaZipFile::bytesAvailable() |
167 |
{ |
168 |
QFETCH(QString, zipName); |
169 |
QFETCH(QStringList, fileNames); |
170 |
QDir curDir; |
171 |
if (!createTestFiles(fileNames)) { |
172 |
QFAIL("Couldn't create test files"); |
173 |
} |
174 |
if (!JlCompress::compressDir(zipName, "tmp")) { |
175 |
QFAIL("Couldn't create test archive"); |
176 |
} |
177 |
QuaZip testZip(zipName); |
178 |
QVERIFY(testZip.open(QuaZip::mdUnzip)); |
179 |
foreach (QString fileName, fileNames) { |
180 |
QFileInfo fileInfo("tmp/" + fileName); |
181 |
QVERIFY(testZip.setCurrentFile(fileName)); |
182 |
QuaZipFile zipFile(&testZip); |
183 |
QVERIFY(zipFile.open(QIODevice::ReadOnly)); |
184 |
QCOMPARE(zipFile.bytesAvailable(), fileInfo.size()); |
185 |
QCOMPARE(zipFile.read(1).size(), 1); |
186 |
QCOMPARE(zipFile.bytesAvailable(), fileInfo.size() - 1); |
187 |
QCOMPARE(zipFile.read(fileInfo.size() - 1).size(), |
188 |
static_cast<int>(fileInfo.size() - 1)); |
189 |
QCOMPARE(zipFile.bytesAvailable(), (qint64) 0); |
190 |
} |
191 |
removeTestFiles(fileNames); |
192 |
testZip.close(); |
193 |
curDir.remove(zipName); |
194 |
} |
195 |
|
196 |
void TestQuaZipFile::atEnd_data() |
197 |
{ |
198 |
bytesAvailable_data(); |
199 |
} |
200 |
|
201 |
void TestQuaZipFile::atEnd() |
202 |
{ |
203 |
QFETCH(QString, zipName); |
204 |
QFETCH(QStringList, fileNames); |
205 |
QDir curDir; |
206 |
if (!createTestFiles(fileNames)) { |
207 |
QFAIL("Couldn't create test files"); |
208 |
} |
209 |
if (!JlCompress::compressDir(zipName, "tmp")) { |
210 |
QFAIL("Couldn't create test archive"); |
211 |
} |
212 |
QuaZip testZip(zipName); |
213 |
QVERIFY(testZip.open(QuaZip::mdUnzip)); |
214 |
foreach (QString fileName, fileNames) { |
215 |
QFileInfo fileInfo("tmp/" + fileName); |
216 |
QVERIFY(testZip.setCurrentFile(fileName)); |
217 |
QuaZipFile zipFile(&testZip); |
218 |
QVERIFY(zipFile.open(QIODevice::ReadOnly)); |
219 |
QCOMPARE(zipFile.atEnd(), false); |
220 |
QCOMPARE(zipFile.read(1).size(), 1); |
221 |
QCOMPARE(zipFile.atEnd(), false); |
222 |
QCOMPARE(zipFile.read(fileInfo.size() - 1).size(), |
223 |
static_cast<int>(fileInfo.size() - 1)); |
224 |
QCOMPARE(zipFile.atEnd(), true); |
225 |
} |
226 |
removeTestFiles(fileNames); |
227 |
testZip.close(); |
228 |
curDir.remove(zipName); |
229 |
} |
230 |
|
231 |
void TestQuaZipFile::pos_data() |
232 |
{ |
233 |
bytesAvailable_data(); |
234 |
} |
235 |
|
236 |
void TestQuaZipFile::pos() |
237 |
{ |
238 |
QFETCH(QString, zipName); |
239 |
QFETCH(QStringList, fileNames); |
240 |
QDir curDir; |
241 |
if (!createTestFiles(fileNames)) { |
242 |
QFAIL("Couldn't create test files"); |
243 |
} |
244 |
if (!JlCompress::compressDir(zipName, "tmp")) { |
245 |
QFAIL("Couldn't create test archive"); |
246 |
} |
247 |
QuaZip testZip(zipName); |
248 |
QVERIFY(testZip.open(QuaZip::mdUnzip)); |
249 |
foreach (QString fileName, fileNames) { |
250 |
QFileInfo fileInfo("tmp/" + fileName); |
251 |
QVERIFY(testZip.setCurrentFile(fileName)); |
252 |
QuaZipFile zipFile(&testZip); |
253 |
QVERIFY(zipFile.open(QIODevice::ReadOnly)); |
254 |
QCOMPARE(zipFile.pos(), (qint64) 0); |
255 |
QCOMPARE(zipFile.read(1).size(), 1); |
256 |
QCOMPARE(zipFile.pos(), (qint64) 1); |
257 |
QCOMPARE(zipFile.read(fileInfo.size() - 1).size(), |
258 |
static_cast<int>(fileInfo.size() - 1)); |
259 |
QCOMPARE(zipFile.pos(), fileInfo.size()); |
260 |
} |
261 |
removeTestFiles(fileNames); |
262 |
testZip.close(); |
263 |
curDir.remove(zipName); |
264 |
} |
265 |
|
266 |
void TestQuaZipFile::getZip() |
267 |
{ |
268 |
QuaZip testZip; |
269 |
QuaZipFile f1(&testZip); |
270 |
QCOMPARE(f1.getZip(), &testZip); |
271 |
QuaZipFile f2("doesntexist.zip", "someFile"); |
272 |
QCOMPARE(f2.getZip(), static_cast<QuaZip*>(NULL)); |
273 |
f2.setZip(&testZip); |
274 |
QCOMPARE(f2.getZip(), &testZip); |
275 |
} |
276 |
|
277 |
void TestQuaZipFile::setZipName() |
278 |
{ |
279 |
QString testFileName = "testZipName.txt"; |
280 |
QString testZipName = "testZipName.zip"; |
281 |
QVERIFY(createTestFiles(QStringList() << testFileName)); |
282 |
QVERIFY(createTestArchive(testZipName, QStringList() << testFileName)); |
283 |
QuaZipFile testFile; |
284 |
testFile.setZipName(testZipName); |
285 |
QCOMPARE(testFile.getZipName(), testZipName); |
286 |
testFile.setFileName(testFileName); |
287 |
QVERIFY(testFile.open(QIODevice::ReadOnly)); |
288 |
testFile.close(); |
289 |
removeTestFiles(QStringList() << testFileName); |
290 |
QDir curDir; |
291 |
curDir.remove(testZipName); |
292 |
} |
293 |
|
294 |
void TestQuaZipFile::getFileInfo() |
295 |
{ |
296 |
QuaZipFileInfo info32; |
297 |
QuaZipFileInfo64 info64; |
298 |
QString testFileName = "testZipName.txt"; |
299 |
QStringList testFiles; |
300 |
testFiles << testFileName; |
301 |
QString testZipName = "testZipName.zip"; |
302 |
QVERIFY(createTestFiles(testFiles)); |
303 |
QVERIFY(createTestArchive(testZipName, testFiles)); |
304 |
QuaZipFile testFile; |
305 |
testFile.setZipName(testZipName); |
306 |
testFile.setFileName(testFileName); |
307 |
QVERIFY(testFile.open(QIODevice::ReadOnly)); |
308 |
QVERIFY(testFile.getFileInfo(&info32)); |
309 |
QVERIFY(testFile.getFileInfo(&info64)); |
310 |
QCOMPARE(info32.name, info64.name); |
311 |
QCOMPARE(info32.versionCreated, info64.versionCreated); |
312 |
QCOMPARE(info32.versionNeeded, info64.versionNeeded); |
313 |
QCOMPARE(info32.flags, info64.flags); |
314 |
QCOMPARE(info32.method, info64.method); |
315 |
QCOMPARE(info32.dateTime, info64.dateTime); |
316 |
QCOMPARE(info32.crc, info64.crc); |
317 |
QCOMPARE(info32.compressedSize, |
318 |
static_cast<quint32>(info64.compressedSize)); |
319 |
QCOMPARE(info32.uncompressedSize, |
320 |
static_cast<quint32>(info64.uncompressedSize)); |
321 |
QCOMPARE(info32.diskNumberStart, info64.diskNumberStart); |
322 |
QCOMPARE(info32.internalAttr, info64.internalAttr); |
323 |
QCOMPARE(info32.externalAttr, info64.externalAttr); |
324 |
QCOMPARE(info32.comment, info64.comment); |
325 |
QCOMPARE(info32.extra, info64.extra); |
326 |
testFile.close(); |
327 |
removeTestFiles(testFiles); |
328 |
QDir curDir; |
329 |
curDir.remove(testZipName); |
330 |
} |
331 |
|
332 |
void TestQuaZipFile::setFileName() |
333 |
{ |
334 |
QString testFileName = "testZipName.txt"; |
335 |
QString testZipName = "testZipName.zip"; |
336 |
QVERIFY(createTestFiles(QStringList() << testFileName)); |
337 |
QVERIFY(createTestArchive(testZipName, QStringList() << testFileName)); |
338 |
QuaZipFile testFile(testZipName); |
339 |
testFile.setFileName(testFileName.toUpper()); |
340 |
#ifdef Q_OS_WIN |
341 |
QVERIFY(testFile.open(QIODevice::ReadOnly)); |
342 |
testFile.close(); |
343 |
#else |
344 |
QVERIFY(!testFile.open(QIODevice::ReadOnly)); |
345 |
#endif |
346 |
testFile.setFileName(testFileName.toUpper(), QuaZip::csInsensitive); |
347 |
QCOMPARE(testFile.getCaseSensitivity(), QuaZip::csInsensitive); |
348 |
QVERIFY(testFile.open(QIODevice::ReadOnly)); |
349 |
QCOMPARE(testFile.getActualFileName(), testFileName); |
350 |
testFile.close(); |
351 |
testFile.setFileName(testFileName.toUpper(), QuaZip::csSensitive); |
352 |
QCOMPARE(testFile.getFileName(), testFileName.toUpper()); |
353 |
QCOMPARE(testFile.getActualFileName(), QString()); |
354 |
QVERIFY(!testFile.open(QIODevice::ReadOnly)); |
355 |
testFile.setFileName(testFileName); |
356 |
removeTestFiles(QStringList() << testFileName); |
357 |
QDir curDir; |
358 |
curDir.remove(testZipName); |
359 |
} |
360 |
|
361 |
void TestQuaZipFile::constructorDestructor() |
362 |
{ |
363 |
// Just test that all constructors and destructors are available. |
364 |
// (So there are none that are declared but not defined.) |
365 |
QuaZip testZip; |
366 |
QuaZipFile *f1 = new QuaZipFile(); |
367 |
delete f1; // test D0 destructor |
368 |
QObject parent; |
369 |
QuaZipFile f2(&testZip, &parent); |
370 |
QuaZipFile f3(&parent); |
371 |
QuaZipFile f4("zipName.zip"); |
372 |
QuaZipFile f5("zipName.zip", "fileName.txt", QuaZip::csDefault, &parent); |
373 |
} |
374 |
|
375 |
void TestQuaZipFile::setFileAttrs() |
376 |
{ |
377 |
QuaZip testZip("setFileAttrs.zip"); |
378 |
QVERIFY(testZip.open(QuaZip::mdCreate)); |
379 |
QuaZipFile zipFile(&testZip); |
380 |
QuaZipNewInfo newInfo("testPerm.txt"); |
381 |
newInfo.setPermissions(QFile::ReadOwner); |
382 |
QVERIFY(zipFile.open(QIODevice::WriteOnly, newInfo)); |
383 |
zipFile.close(); |
384 |
QString fileTestAttr = "testAttr.txt"; |
385 |
QStringList fileNames; |
386 |
fileNames << fileTestAttr; |
387 |
QVERIFY(createTestFiles(fileNames)); |
388 |
newInfo.name = fileTestAttr; |
389 |
newInfo.setFileDateTime("tmp/" + fileTestAttr); |
390 |
newInfo.setFilePermissions("tmp/" + fileTestAttr); |
391 |
QVERIFY(zipFile.open(QIODevice::WriteOnly, newInfo)); |
392 |
zipFile.close(); |
393 |
testZip.close(); |
394 |
QuaZipFileInfo64 info; |
395 |
{ |
396 |
QuaZipFile readFilePerm("setFileAttrs.zip", "testPerm.txt"); |
397 |
QVERIFY(readFilePerm.open(QIODevice::ReadOnly)); |
398 |
QVERIFY(readFilePerm.getFileInfo(&info)); |
399 |
QCOMPARE(info.getPermissions(), QFile::ReadOwner); |
400 |
readFilePerm.close(); |
401 |
} |
402 |
{ |
403 |
QuaZipFile readFileAttrs("setFileAttrs.zip", "testAttr.txt"); |
404 |
QVERIFY(readFileAttrs.open(QIODevice::ReadOnly)); |
405 |
QVERIFY(readFileAttrs.getFileInfo(&info)); |
406 |
QFileInfo srcInfo("tmp/" + fileTestAttr); |
407 |
QFile::Permissions usedPermissions = |
408 |
QFile::WriteOwner | QFile::ReadOwner | QFile::ExeOwner | |
409 |
QFile::WriteGroup | QFile::ReadGroup | QFile::ExeGroup | |
410 |
QFile::WriteOther | QFile::ReadOther | QFile::ExeOther; |
411 |
QCOMPARE(info.getPermissions() & usedPermissions, |
412 |
srcInfo.permissions() & usedPermissions); |
413 |
// I really hope Qt 6 will use quint64 for time_t! |
414 |
quint64 newTime = info.dateTime.toTime_t(); |
415 |
quint64 oldTime = srcInfo.lastModified().toTime_t(); |
416 |
// ZIP uses weird format with 2 second precision |
417 |
QCOMPARE(newTime / 2, oldTime / 2); |
418 |
readFileAttrs.close(); |
419 |
} |
420 |
removeTestFiles(fileNames); |
421 |
QDir().remove(testZip.getZipName()); |
422 |
} |
423 |
|
424 |
void TestQuaZipFile::largeFile() |
425 |
{ |
426 |
QDir curDir; |
427 |
QVERIFY(curDir.mkpath("tmp")); |
428 |
QFile fakeLargeFile("tmp/large.zip"); |
429 |
QVERIFY(fakeLargeFile.open(QIODevice::WriteOnly)); |
430 |
QDataStream ds(&fakeLargeFile); |
431 |
ds.setByteOrder(QDataStream::LittleEndian); |
432 |
QList<qint64> localOffsets; |
433 |
const int numFiles = 2; // name fixed to 5 bytes, so MAX 10 FILES!!! |
434 |
for (int i = 0; i < numFiles; ++i) { |
435 |
localOffsets.append(fakeLargeFile.pos()); |
436 |
QBuffer extra; |
437 |
extra.open(QIODevice::WriteOnly); |
438 |
QDataStream es(&extra); |
439 |
es.setByteOrder(QDataStream::LittleEndian); |
440 |
// prepare extra |
441 |
es << static_cast<quint16>(0x0001u); // zip64 |
442 |
es << static_cast<quint16>(16); // extra data size |
443 |
es << static_cast<quint64>(0); // uncompressed size |
444 |
es << static_cast<quint64>(0); // compressed size |
445 |
// now the local header |
446 |
ds << static_cast<quint32>(0x04034b50u); // local magic |
447 |
ds << static_cast<quint16>(45); // version needed |
448 |
ds << static_cast<quint16>(0); // flags |
449 |
ds << static_cast<quint16>(0); // method |
450 |
ds << static_cast<quint16>(0); // time 00:00:00 |
451 |
ds << static_cast<quint16>(0x21); // date 1980-01-01 |
452 |
ds << static_cast<quint32>(0); // CRC-32 |
453 |
ds << static_cast<quint32>(0xFFFFFFFFu); // compressed size |
454 |
ds << static_cast<quint32>(0xFFFFFFFFu); // uncompressed size |
455 |
ds << static_cast<quint16>(5); // name length |
456 |
ds << static_cast<quint16>(extra.size()); // extra length |
457 |
ds.writeRawData("file", 4); // name |
458 |
ds << static_cast<qint8>('0' + i); // name (contd.) |
459 |
ds.writeRawData(extra.buffer(), extra.size()); |
460 |
} |
461 |
// central dir: |
462 |
qint64 centralStart = fakeLargeFile.pos(); |
463 |
for (int i = 0; i < numFiles; ++i) { |
464 |
QBuffer extra; |
465 |
extra.open(QIODevice::WriteOnly); |
466 |
QDataStream es(&extra); |
467 |
es.setByteOrder(QDataStream::LittleEndian); |
468 |
// prepare extra |
469 |
es << static_cast<quint16>(0x0001u); // zip64 |
470 |
es << static_cast<quint16>(24); // extra data size |
471 |
es << static_cast<quint64>(0); // uncompressed size |
472 |
es << static_cast<quint64>(0); // compressed size |
473 |
es << static_cast<quint64>(localOffsets[i]); |
474 |
// now the central dir header |
475 |
ds << static_cast<quint32>(0x02014b50u); // central magic |
476 |
ds << static_cast<quint16>(45); // version made by |
477 |
ds << static_cast<quint16>(45); // version needed |
478 |
ds << static_cast<quint16>(0); // flags |
479 |
ds << static_cast<quint16>(0); // method |
480 |
ds << static_cast<quint16>(0); // time 00:00:00 |
481 |
ds << static_cast<quint16>(0x21); // date 1980-01-01 |
482 |
ds << static_cast<quint32>(0); // CRC-32 |
483 |
ds << static_cast<quint32>(0xFFFFFFFFu); // compressed size |
484 |
ds << static_cast<quint32>(0xFFFFFFFFu); // uncompressed size |
485 |
ds << static_cast<quint16>(5); // name length |
486 |
ds << static_cast<quint16>(extra.size()); // extra length |
487 |
ds << static_cast<quint16>(0); // comment length |
488 |
ds << static_cast<quint16>(0); // disk number |
489 |
ds << static_cast<quint16>(0); // internal attrs |
490 |
ds << static_cast<quint32>(0); // external attrs |
491 |
ds << static_cast<quint32>(0xFFFFFFFFu); // local offset |
492 |
ds.writeRawData("file", 4); // name |
493 |
ds << static_cast<qint8>('0' + i); // name (contd.) |
494 |
ds.writeRawData(extra.buffer(), extra.size()); |
495 |
} |
496 |
qint64 centralEnd = fakeLargeFile.pos(); |
497 |
// zip64 end |
498 |
ds << static_cast<quint32>(0x06064b50); // zip64 end magic |
499 |
ds << static_cast<quint64>(44); // size of the zip64 end |
500 |
ds << static_cast<quint16>(45); // version made by |
501 |
ds << static_cast<quint16>(45); // version needed |
502 |
ds << static_cast<quint32>(0); // disk number |
503 |
ds << static_cast<quint32>(0); // central dir disk number |
504 |
ds << static_cast<quint64>(2); // number of entries on disk |
505 |
ds << static_cast<quint64>(2); // total number of entries |
506 |
ds << static_cast<quint64>(centralEnd - centralStart); // size |
507 |
ds << static_cast<quint64>(centralStart); // offset |
508 |
// zip64 locator |
509 |
ds << static_cast<quint32>(0x07064b50); // zip64 locator magic |
510 |
ds << static_cast<quint32>(0); // disk number |
511 |
ds << static_cast<quint64>(centralEnd); // offset |
512 |
ds << static_cast<quint32>(1); // number of disks |
513 |
// zip32 end |
514 |
ds << static_cast<quint32>(0x06054b50); // end magic |
515 |
ds << static_cast<quint16>(0); // disk number |
516 |
ds << static_cast<quint16>(0); // central dir disk number |
517 |
ds << static_cast<quint16>(2); // number of entries |
518 |
ds << static_cast<quint32>(0xFFFFFFFFu); // central dir size |
519 |
ds << static_cast<quint32>(0xFFFFFFFFu); // central dir offset |
520 |
ds << static_cast<quint16>(0); // comment length |
521 |
fakeLargeFile.close(); |
522 |
QuaZip fakeLargeZip("tmp/large.zip"); |
523 |
QVERIFY(fakeLargeZip.open(QuaZip::mdUnzip)); |
524 |
QCOMPARE(fakeLargeZip.getFileInfoList().size(), numFiles); |
525 |
QCOMPARE(fakeLargeZip.getFileInfoList()[0].uncompressedSize, |
526 |
static_cast<quint32>(0)); |
527 |
fakeLargeZip.close(); |
528 |
curDir.remove("tmp/large.zip"); |
529 |
} |