diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/rbutilqt/quazip/quazip.cpp | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/rbutilqt/quazip/quazip.cpp')
-rw-r--r-- | utils/rbutilqt/quazip/quazip.cpp | 846 |
1 files changed, 846 insertions, 0 deletions
diff --git a/utils/rbutilqt/quazip/quazip.cpp b/utils/rbutilqt/quazip/quazip.cpp new file mode 100644 index 0000000000..61c2ea87eb --- /dev/null +++ b/utils/rbutilqt/quazip/quazip.cpp | |||
@@ -0,0 +1,846 @@ | |||
1 | /* | ||
2 | Copyright (C) 2005-2014 Sergey A. Tachenov | ||
3 | |||
4 | This file is part of QuaZIP. | ||
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, see | ||
22 | quazip/(un)zip.h files for details, basically it's zlib license. | ||
23 | **/ | ||
24 | |||
25 | #include <QtCore/QFile> | ||
26 | #include <QtCore/QFlags> | ||
27 | #include <QtCore/QHash> | ||
28 | |||
29 | #include "quazip.h" | ||
30 | |||
31 | #define QUAZIP_OS_UNIX 3u | ||
32 | |||
33 | /// All the internal stuff for the QuaZip class. | ||
34 | /** | ||
35 | \internal | ||
36 | |||
37 | This class keeps all the private stuff for the QuaZip class so it can | ||
38 | be changed without breaking binary compatibility, according to the | ||
39 | Pimpl idiom. | ||
40 | */ | ||
41 | class QuaZipPrivate { | ||
42 | friend class QuaZip; | ||
43 | private: | ||
44 | Q_DISABLE_COPY(QuaZipPrivate) | ||
45 | /// The pointer to the corresponding QuaZip instance. | ||
46 | QuaZip *q; | ||
47 | /// The codec for file names (used when UTF-8 is not enabled). | ||
48 | QTextCodec *fileNameCodec; | ||
49 | /// The codec for comments (used when UTF-8 is not enabled). | ||
50 | QTextCodec *commentCodec; | ||
51 | /// The archive file name. | ||
52 | QString zipName; | ||
53 | /// The device to access the archive. | ||
54 | QIODevice *ioDevice; | ||
55 | /// The global comment. | ||
56 | QString comment; | ||
57 | /// The open mode. | ||
58 | QuaZip::Mode mode; | ||
59 | union { | ||
60 | /// The internal handle for UNZIP modes. | ||
61 | unzFile unzFile_f; | ||
62 | /// The internal handle for ZIP modes. | ||
63 | zipFile zipFile_f; | ||
64 | }; | ||
65 | /// Whether a current file is set. | ||
66 | bool hasCurrentFile_f; | ||
67 | /// The last error. | ||
68 | int zipError; | ||
69 | /// Whether \ref QuaZip::setDataDescriptorWritingEnabled() "the data descriptor writing mode" is enabled. | ||
70 | bool dataDescriptorWritingEnabled; | ||
71 | /// The zip64 mode. | ||
72 | bool zip64; | ||
73 | /// The auto-close flag. | ||
74 | bool autoClose; | ||
75 | /// The UTF-8 flag. | ||
76 | bool utf8; | ||
77 | /// The OS code. | ||
78 | uint osCode; | ||
79 | inline QTextCodec *getDefaultFileNameCodec() | ||
80 | { | ||
81 | if (defaultFileNameCodec == NULL) { | ||
82 | return QTextCodec::codecForLocale(); | ||
83 | } else { | ||
84 | return defaultFileNameCodec; | ||
85 | } | ||
86 | } | ||
87 | /// The constructor for the corresponding QuaZip constructor. | ||
88 | inline QuaZipPrivate(QuaZip *q): | ||
89 | q(q), | ||
90 | fileNameCodec(getDefaultFileNameCodec()), | ||
91 | commentCodec(QTextCodec::codecForLocale()), | ||
92 | ioDevice(NULL), | ||
93 | mode(QuaZip::mdNotOpen), | ||
94 | hasCurrentFile_f(false), | ||
95 | zipError(UNZ_OK), | ||
96 | dataDescriptorWritingEnabled(true), | ||
97 | zip64(false), | ||
98 | autoClose(true), | ||
99 | utf8(false), | ||
100 | osCode(defaultOsCode) | ||
101 | { | ||
102 | unzFile_f = NULL; | ||
103 | zipFile_f = NULL; | ||
104 | lastMappedDirectoryEntry.num_of_file = 0; | ||
105 | lastMappedDirectoryEntry.pos_in_zip_directory = 0; | ||
106 | } | ||
107 | /// The constructor for the corresponding QuaZip constructor. | ||
108 | inline QuaZipPrivate(QuaZip *q, const QString &zipName): | ||
109 | q(q), | ||
110 | fileNameCodec(getDefaultFileNameCodec()), | ||
111 | commentCodec(QTextCodec::codecForLocale()), | ||
112 | zipName(zipName), | ||
113 | ioDevice(NULL), | ||
114 | mode(QuaZip::mdNotOpen), | ||
115 | hasCurrentFile_f(false), | ||
116 | zipError(UNZ_OK), | ||
117 | dataDescriptorWritingEnabled(true), | ||
118 | zip64(false), | ||
119 | autoClose(true), | ||
120 | utf8(false), | ||
121 | osCode(defaultOsCode) | ||
122 | { | ||
123 | unzFile_f = NULL; | ||
124 | zipFile_f = NULL; | ||
125 | lastMappedDirectoryEntry.num_of_file = 0; | ||
126 | lastMappedDirectoryEntry.pos_in_zip_directory = 0; | ||
127 | } | ||
128 | /// The constructor for the corresponding QuaZip constructor. | ||
129 | inline QuaZipPrivate(QuaZip *q, QIODevice *ioDevice): | ||
130 | q(q), | ||
131 | fileNameCodec(getDefaultFileNameCodec()), | ||
132 | commentCodec(QTextCodec::codecForLocale()), | ||
133 | ioDevice(ioDevice), | ||
134 | mode(QuaZip::mdNotOpen), | ||
135 | hasCurrentFile_f(false), | ||
136 | zipError(UNZ_OK), | ||
137 | dataDescriptorWritingEnabled(true), | ||
138 | zip64(false), | ||
139 | autoClose(true), | ||
140 | utf8(false), | ||
141 | osCode(defaultOsCode) | ||
142 | { | ||
143 | unzFile_f = NULL; | ||
144 | zipFile_f = NULL; | ||
145 | lastMappedDirectoryEntry.num_of_file = 0; | ||
146 | lastMappedDirectoryEntry.pos_in_zip_directory = 0; | ||
147 | } | ||
148 | /// Returns either a list of file names or a list of QuaZipFileInfo. | ||
149 | template<typename TFileInfo> | ||
150 | bool getFileInfoList(QList<TFileInfo> *result) const; | ||
151 | |||
152 | /// Stores map of filenames and file locations for unzipping | ||
153 | inline void clearDirectoryMap(); | ||
154 | inline void addCurrentFileToDirectoryMap(const QString &fileName); | ||
155 | bool goToFirstUnmappedFile(); | ||
156 | QHash<QString, unz64_file_pos> directoryCaseSensitive; | ||
157 | QHash<QString, unz64_file_pos> directoryCaseInsensitive; | ||
158 | unz64_file_pos lastMappedDirectoryEntry; | ||
159 | static QTextCodec *defaultFileNameCodec; | ||
160 | static uint defaultOsCode; | ||
161 | }; | ||
162 | |||
163 | QTextCodec *QuaZipPrivate::defaultFileNameCodec = NULL; | ||
164 | uint QuaZipPrivate::defaultOsCode = QUAZIP_OS_UNIX; | ||
165 | |||
166 | void QuaZipPrivate::clearDirectoryMap() | ||
167 | { | ||
168 | directoryCaseInsensitive.clear(); | ||
169 | directoryCaseSensitive.clear(); | ||
170 | lastMappedDirectoryEntry.num_of_file = 0; | ||
171 | lastMappedDirectoryEntry.pos_in_zip_directory = 0; | ||
172 | } | ||
173 | |||
174 | void QuaZipPrivate::addCurrentFileToDirectoryMap(const QString &fileName) | ||
175 | { | ||
176 | if (!hasCurrentFile_f || fileName.isEmpty()) { | ||
177 | return; | ||
178 | } | ||
179 | // Adds current file to filename map as fileName | ||
180 | unz64_file_pos fileDirectoryPos; | ||
181 | unzGetFilePos64(unzFile_f, &fileDirectoryPos); | ||
182 | directoryCaseSensitive.insert(fileName, fileDirectoryPos); | ||
183 | // Only add lowercase to directory map if not already there | ||
184 | // ensures only map the first one seen | ||
185 | QString lower = fileName.toLower(); | ||
186 | if (!directoryCaseInsensitive.contains(lower)) | ||
187 | directoryCaseInsensitive.insert(lower, fileDirectoryPos); | ||
188 | // Mark last one | ||
189 | if (fileDirectoryPos.pos_in_zip_directory > lastMappedDirectoryEntry.pos_in_zip_directory) | ||
190 | lastMappedDirectoryEntry = fileDirectoryPos; | ||
191 | } | ||
192 | |||
193 | bool QuaZipPrivate::goToFirstUnmappedFile() | ||
194 | { | ||
195 | zipError = UNZ_OK; | ||
196 | if (mode != QuaZip::mdUnzip) { | ||
197 | qWarning("QuaZipPrivate::goToNextUnmappedFile(): ZIP is not open in mdUnzip mode"); | ||
198 | return false; | ||
199 | } | ||
200 | // If not mapped anything, go to beginning | ||
201 | if (lastMappedDirectoryEntry.pos_in_zip_directory == 0) { | ||
202 | unzGoToFirstFile(unzFile_f); | ||
203 | } else { | ||
204 | // Goto the last one mapped, plus one | ||
205 | unzGoToFilePos64(unzFile_f, &lastMappedDirectoryEntry); | ||
206 | unzGoToNextFile(unzFile_f); | ||
207 | } | ||
208 | hasCurrentFile_f=zipError==UNZ_OK; | ||
209 | if(zipError==UNZ_END_OF_LIST_OF_FILE) | ||
210 | zipError=UNZ_OK; | ||
211 | return hasCurrentFile_f; | ||
212 | } | ||
213 | |||
214 | QuaZip::QuaZip(): | ||
215 | p(new QuaZipPrivate(this)) | ||
216 | { | ||
217 | } | ||
218 | |||
219 | QuaZip::QuaZip(const QString& zipName): | ||
220 | p(new QuaZipPrivate(this, zipName)) | ||
221 | { | ||
222 | } | ||
223 | |||
224 | QuaZip::QuaZip(QIODevice *ioDevice): | ||
225 | p(new QuaZipPrivate(this, ioDevice)) | ||
226 | { | ||
227 | } | ||
228 | |||
229 | QuaZip::~QuaZip() | ||
230 | { | ||
231 | if(isOpen()) | ||
232 | close(); | ||
233 | delete p; | ||
234 | } | ||
235 | |||
236 | bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi) | ||
237 | { | ||
238 | p->zipError=UNZ_OK; | ||
239 | if(isOpen()) { | ||
240 | qWarning("QuaZip::open(): ZIP already opened"); | ||
241 | return false; | ||
242 | } | ||
243 | QIODevice *ioDevice = p->ioDevice; | ||
244 | if (ioDevice == NULL) { | ||
245 | if (p->zipName.isEmpty()) { | ||
246 | qWarning("QuaZip::open(): set either ZIP file name or IO device first"); | ||
247 | return false; | ||
248 | } else { | ||
249 | ioDevice = new QFile(p->zipName); | ||
250 | } | ||
251 | } | ||
252 | unsigned flags = 0; | ||
253 | switch(mode) { | ||
254 | case mdUnzip: | ||
255 | if (ioApi == NULL) { | ||
256 | if (p->autoClose) | ||
257 | flags |= UNZ_AUTO_CLOSE; | ||
258 | p->unzFile_f=unzOpenInternal(ioDevice, NULL, 1, flags); | ||
259 | } else { | ||
260 | // QuaZIP pre-zip64 compatibility mode | ||
261 | p->unzFile_f=unzOpen2(ioDevice, ioApi); | ||
262 | if (p->unzFile_f != NULL) { | ||
263 | if (p->autoClose) { | ||
264 | unzSetFlags(p->unzFile_f, UNZ_AUTO_CLOSE); | ||
265 | } else { | ||
266 | unzClearFlags(p->unzFile_f, UNZ_AUTO_CLOSE); | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | if(p->unzFile_f!=NULL) { | ||
271 | if (ioDevice->isSequential()) { | ||
272 | unzClose(p->unzFile_f); | ||
273 | if (!p->zipName.isEmpty()) | ||
274 | delete ioDevice; | ||
275 | qWarning("QuaZip::open(): " | ||
276 | "only mdCreate can be used with " | ||
277 | "sequential devices"); | ||
278 | return false; | ||
279 | } | ||
280 | p->mode=mode; | ||
281 | p->ioDevice = ioDevice; | ||
282 | return true; | ||
283 | } else { | ||
284 | p->zipError=UNZ_OPENERROR; | ||
285 | if (!p->zipName.isEmpty()) | ||
286 | delete ioDevice; | ||
287 | return false; | ||
288 | } | ||
289 | case mdCreate: | ||
290 | case mdAppend: | ||
291 | case mdAdd: | ||
292 | if (ioApi == NULL) { | ||
293 | if (p->autoClose) | ||
294 | flags |= ZIP_AUTO_CLOSE; | ||
295 | if (p->dataDescriptorWritingEnabled) | ||
296 | flags |= ZIP_WRITE_DATA_DESCRIPTOR; | ||
297 | if (p->utf8) | ||
298 | flags |= ZIP_ENCODING_UTF8; | ||
299 | p->zipFile_f=zipOpen3(ioDevice, | ||
300 | mode==mdCreate?APPEND_STATUS_CREATE: | ||
301 | mode==mdAppend?APPEND_STATUS_CREATEAFTER: | ||
302 | APPEND_STATUS_ADDINZIP, | ||
303 | NULL, NULL, flags); | ||
304 | } else { | ||
305 | // QuaZIP pre-zip64 compatibility mode | ||
306 | p->zipFile_f=zipOpen2(ioDevice, | ||
307 | mode==mdCreate?APPEND_STATUS_CREATE: | ||
308 | mode==mdAppend?APPEND_STATUS_CREATEAFTER: | ||
309 | APPEND_STATUS_ADDINZIP, | ||
310 | NULL, | ||
311 | ioApi); | ||
312 | if (p->zipFile_f != NULL) { | ||
313 | zipSetFlags(p->zipFile_f, flags); | ||
314 | } | ||
315 | } | ||
316 | if(p->zipFile_f!=NULL) { | ||
317 | if (ioDevice->isSequential()) { | ||
318 | if (mode != mdCreate) { | ||
319 | zipClose(p->zipFile_f, NULL); | ||
320 | qWarning("QuaZip::open(): " | ||
321 | "only mdCreate can be used with " | ||
322 | "sequential devices"); | ||
323 | if (!p->zipName.isEmpty()) | ||
324 | delete ioDevice; | ||
325 | return false; | ||
326 | } | ||
327 | zipSetFlags(p->zipFile_f, ZIP_SEQUENTIAL); | ||
328 | } | ||
329 | p->mode=mode; | ||
330 | p->ioDevice = ioDevice; | ||
331 | return true; | ||
332 | } else { | ||
333 | p->zipError=UNZ_OPENERROR; | ||
334 | if (!p->zipName.isEmpty()) | ||
335 | delete ioDevice; | ||
336 | return false; | ||
337 | } | ||
338 | default: | ||
339 | qWarning("QuaZip::open(): unknown mode: %d", (int)mode); | ||
340 | if (!p->zipName.isEmpty()) | ||
341 | delete ioDevice; | ||
342 | return false; | ||
343 | break; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | void QuaZip::close() | ||
348 | { | ||
349 | p->zipError=UNZ_OK; | ||
350 | switch(p->mode) { | ||
351 | case mdNotOpen: | ||
352 | qWarning("QuaZip::close(): ZIP is not open"); | ||
353 | return; | ||
354 | case mdUnzip: | ||
355 | p->zipError=unzClose(p->unzFile_f); | ||
356 | break; | ||
357 | case mdCreate: | ||
358 | case mdAppend: | ||
359 | case mdAdd: | ||
360 | p->zipError=zipClose(p->zipFile_f, p->comment.isNull() ? NULL : isUtf8Enabled() | ||
361 | ? p->comment.toUtf8().constData() | ||
362 | : p->commentCodec->fromUnicode(p->comment).constData()); | ||
363 | break; | ||
364 | default: | ||
365 | qWarning("QuaZip::close(): unknown mode: %d", (int)p->mode); | ||
366 | return; | ||
367 | } | ||
368 | // opened by name, need to delete the internal IO device | ||
369 | if (!p->zipName.isEmpty()) { | ||
370 | delete p->ioDevice; | ||
371 | p->ioDevice = NULL; | ||
372 | } | ||
373 | p->clearDirectoryMap(); | ||
374 | if(p->zipError==UNZ_OK) | ||
375 | p->mode=mdNotOpen; | ||
376 | } | ||
377 | |||
378 | void QuaZip::setZipName(const QString& zipName) | ||
379 | { | ||
380 | if(isOpen()) { | ||
381 | qWarning("QuaZip::setZipName(): ZIP is already open!"); | ||
382 | return; | ||
383 | } | ||
384 | p->zipName=zipName; | ||
385 | p->ioDevice = NULL; | ||
386 | } | ||
387 | |||
388 | void QuaZip::setIoDevice(QIODevice *ioDevice) | ||
389 | { | ||
390 | if(isOpen()) { | ||
391 | qWarning("QuaZip::setIoDevice(): ZIP is already open!"); | ||
392 | return; | ||
393 | } | ||
394 | p->ioDevice = ioDevice; | ||
395 | p->zipName = QString(); | ||
396 | } | ||
397 | |||
398 | int QuaZip::getEntriesCount()const | ||
399 | { | ||
400 | QuaZip *fakeThis=(QuaZip*)this; // non-const | ||
401 | fakeThis->p->zipError=UNZ_OK; | ||
402 | if(p->mode!=mdUnzip) { | ||
403 | qWarning("QuaZip::getEntriesCount(): ZIP is not open in mdUnzip mode"); | ||
404 | return -1; | ||
405 | } | ||
406 | unz_global_info64 globalInfo; | ||
407 | if((fakeThis->p->zipError=unzGetGlobalInfo64(p->unzFile_f, &globalInfo))!=UNZ_OK) | ||
408 | return p->zipError; | ||
409 | return (int)globalInfo.number_entry; | ||
410 | } | ||
411 | |||
412 | QString QuaZip::getComment()const | ||
413 | { | ||
414 | QuaZip *fakeThis=(QuaZip*)this; // non-const | ||
415 | fakeThis->p->zipError=UNZ_OK; | ||
416 | if(p->mode!=mdUnzip) { | ||
417 | qWarning("QuaZip::getComment(): ZIP is not open in mdUnzip mode"); | ||
418 | return QString(); | ||
419 | } | ||
420 | unz_global_info64 globalInfo; | ||
421 | QByteArray comment; | ||
422 | if((fakeThis->p->zipError=unzGetGlobalInfo64(p->unzFile_f, &globalInfo))!=UNZ_OK) | ||
423 | return QString(); | ||
424 | comment.resize(globalInfo.size_comment); | ||
425 | if((fakeThis->p->zipError=unzGetGlobalComment(p->unzFile_f, comment.data(), comment.size())) < 0) | ||
426 | return QString(); | ||
427 | fakeThis->p->zipError = UNZ_OK; | ||
428 | unsigned flags = 0; | ||
429 | return (unzGetFileFlags(p->unzFile_f, &flags) == UNZ_OK) && (flags & UNZ_ENCODING_UTF8) | ||
430 | ? QString::fromUtf8(comment) : p->commentCodec->toUnicode(comment); | ||
431 | } | ||
432 | |||
433 | bool QuaZip::setCurrentFile(const QString& fileName, CaseSensitivity cs) | ||
434 | { | ||
435 | p->zipError=UNZ_OK; | ||
436 | if(p->mode!=mdUnzip) { | ||
437 | qWarning("QuaZip::setCurrentFile(): ZIP is not open in mdUnzip mode"); | ||
438 | return false; | ||
439 | } | ||
440 | if(fileName.isEmpty()) { | ||
441 | p->hasCurrentFile_f=false; | ||
442 | return true; | ||
443 | } | ||
444 | // Unicode-aware reimplementation of the unzLocateFile function | ||
445 | if(p->unzFile_f==NULL) { | ||
446 | p->zipError=UNZ_PARAMERROR; | ||
447 | return false; | ||
448 | } | ||
449 | if(fileName.length()>MAX_FILE_NAME_LENGTH) { | ||
450 | p->zipError=UNZ_PARAMERROR; | ||
451 | return false; | ||
452 | } | ||
453 | // Find the file by name | ||
454 | bool sens = convertCaseSensitivity(cs) == Qt::CaseSensitive; | ||
455 | QString lower, current; | ||
456 | if(!sens) lower=fileName.toLower(); | ||
457 | p->hasCurrentFile_f=false; | ||
458 | |||
459 | // Check the appropriate Map | ||
460 | unz64_file_pos fileDirPos; | ||
461 | fileDirPos.pos_in_zip_directory = 0; | ||
462 | if (sens) { | ||
463 | if (p->directoryCaseSensitive.contains(fileName)) | ||
464 | fileDirPos = p->directoryCaseSensitive.value(fileName); | ||
465 | } else { | ||
466 | if (p->directoryCaseInsensitive.contains(lower)) | ||
467 | fileDirPos = p->directoryCaseInsensitive.value(lower); | ||
468 | } | ||
469 | |||
470 | if (fileDirPos.pos_in_zip_directory != 0) { | ||
471 | p->zipError = unzGoToFilePos64(p->unzFile_f, &fileDirPos); | ||
472 | p->hasCurrentFile_f = p->zipError == UNZ_OK; | ||
473 | } | ||
474 | |||
475 | if (p->hasCurrentFile_f) | ||
476 | return p->hasCurrentFile_f; | ||
477 | |||
478 | // Not mapped yet, start from where we have got to so far | ||
479 | for(bool more=p->goToFirstUnmappedFile(); more; more=goToNextFile()) { | ||
480 | current=getCurrentFileName(); | ||
481 | if(current.isEmpty()) return false; | ||
482 | if(sens) { | ||
483 | if(current==fileName) break; | ||
484 | } else { | ||
485 | if(current.toLower()==lower) break; | ||
486 | } | ||
487 | } | ||
488 | return p->hasCurrentFile_f; | ||
489 | } | ||
490 | |||
491 | bool QuaZip::goToFirstFile() | ||
492 | { | ||
493 | p->zipError=UNZ_OK; | ||
494 | if(p->mode!=mdUnzip) { | ||
495 | qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode"); | ||
496 | return false; | ||
497 | } | ||
498 | p->zipError=unzGoToFirstFile(p->unzFile_f); | ||
499 | p->hasCurrentFile_f=p->zipError==UNZ_OK; | ||
500 | return p->hasCurrentFile_f; | ||
501 | } | ||
502 | |||
503 | bool QuaZip::goToNextFile() | ||
504 | { | ||
505 | p->zipError=UNZ_OK; | ||
506 | if(p->mode!=mdUnzip) { | ||
507 | qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode"); | ||
508 | return false; | ||
509 | } | ||
510 | p->zipError=unzGoToNextFile(p->unzFile_f); | ||
511 | p->hasCurrentFile_f=p->zipError==UNZ_OK; | ||
512 | if(p->zipError==UNZ_END_OF_LIST_OF_FILE) | ||
513 | p->zipError=UNZ_OK; | ||
514 | return p->hasCurrentFile_f; | ||
515 | } | ||
516 | |||
517 | bool QuaZip::getCurrentFileInfo(QuaZipFileInfo *info)const | ||
518 | { | ||
519 | QuaZipFileInfo64 info64; | ||
520 | if (info == NULL) { // Very unlikely because of the overloads | ||
521 | return false; | ||
522 | } | ||
523 | if (getCurrentFileInfo(&info64)) { | ||
524 | info64.toQuaZipFileInfo(*info); | ||
525 | return true; | ||
526 | } else { | ||
527 | return false; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | bool QuaZip::getCurrentFileInfo(QuaZipFileInfo64 *info)const | ||
532 | { | ||
533 | QuaZip *fakeThis=(QuaZip*)this; // non-const | ||
534 | fakeThis->p->zipError=UNZ_OK; | ||
535 | if(p->mode!=mdUnzip) { | ||
536 | qWarning("QuaZip::getCurrentFileInfo(): ZIP is not open in mdUnzip mode"); | ||
537 | return false; | ||
538 | } | ||
539 | unz_file_info64 info_z; | ||
540 | QByteArray fileName; | ||
541 | QByteArray extra; | ||
542 | QByteArray comment; | ||
543 | if(info==NULL) return false; | ||
544 | if(!isOpen()||!hasCurrentFile()) return false; | ||
545 | if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, &info_z, NULL, 0, NULL, 0, NULL, 0))!=UNZ_OK) | ||
546 | return false; | ||
547 | fileName.resize(info_z.size_filename); | ||
548 | extra.resize(info_z.size_file_extra); | ||
549 | comment.resize(info_z.size_file_comment); | ||
550 | if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, NULL, | ||
551 | fileName.data(), fileName.size(), | ||
552 | extra.data(), extra.size(), | ||
553 | comment.data(), comment.size()))!=UNZ_OK) | ||
554 | return false; | ||
555 | info->versionCreated=info_z.version; | ||
556 | info->versionNeeded=info_z.version_needed; | ||
557 | info->flags=info_z.flag; | ||
558 | info->method=info_z.compression_method; | ||
559 | info->crc=info_z.crc; | ||
560 | info->compressedSize=info_z.compressed_size; | ||
561 | info->uncompressedSize=info_z.uncompressed_size; | ||
562 | info->diskNumberStart=info_z.disk_num_start; | ||
563 | info->internalAttr=info_z.internal_fa; | ||
564 | info->externalAttr=info_z.external_fa; | ||
565 | info->name=(info->flags & UNZ_ENCODING_UTF8) ? QString::fromUtf8(fileName) : p->fileNameCodec->toUnicode(fileName); | ||
566 | info->comment=(info->flags & UNZ_ENCODING_UTF8) ? QString::fromUtf8(comment) : p->commentCodec->toUnicode(comment); | ||
567 | info->extra=extra; | ||
568 | info->dateTime=QDateTime( | ||
569 | QDate(info_z.tmu_date.tm_year, info_z.tmu_date.tm_mon+1, info_z.tmu_date.tm_mday), | ||
570 | QTime(info_z.tmu_date.tm_hour, info_z.tmu_date.tm_min, info_z.tmu_date.tm_sec)); | ||
571 | // Add to directory map | ||
572 | p->addCurrentFileToDirectoryMap(info->name); | ||
573 | return true; | ||
574 | } | ||
575 | |||
576 | QString QuaZip::getCurrentFileName()const | ||
577 | { | ||
578 | QuaZip *fakeThis=(QuaZip*)this; // non-const | ||
579 | fakeThis->p->zipError=UNZ_OK; | ||
580 | if(p->mode!=mdUnzip) { | ||
581 | qWarning("QuaZip::getCurrentFileName(): ZIP is not open in mdUnzip mode"); | ||
582 | return QString(); | ||
583 | } | ||
584 | if(!isOpen()||!hasCurrentFile()) return QString(); | ||
585 | QByteArray fileName(MAX_FILE_NAME_LENGTH, 0); | ||
586 | unz_file_info64 file_info; | ||
587 | if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, &file_info, fileName.data(), fileName.size(), | ||
588 | NULL, 0, NULL, 0))!=UNZ_OK) | ||
589 | return QString(); | ||
590 | fileName.resize(file_info.size_filename); | ||
591 | QString result = (file_info.flag & UNZ_ENCODING_UTF8) | ||
592 | ? QString::fromUtf8(fileName) : p->fileNameCodec->toUnicode(fileName); | ||
593 | if (result.isEmpty()) | ||
594 | return result; | ||
595 | // Add to directory map | ||
596 | p->addCurrentFileToDirectoryMap(result); | ||
597 | return result; | ||
598 | } | ||
599 | |||
600 | void QuaZip::setFileNameCodec(QTextCodec *fileNameCodec) | ||
601 | { | ||
602 | p->fileNameCodec=fileNameCodec; | ||
603 | } | ||
604 | |||
605 | void QuaZip::setFileNameCodec(const char *fileNameCodecName) | ||
606 | { | ||
607 | p->fileNameCodec=QTextCodec::codecForName(fileNameCodecName); | ||
608 | } | ||
609 | |||
610 | void QuaZip::setOsCode(uint osCode) | ||
611 | { | ||
612 | p->osCode = osCode; | ||
613 | } | ||
614 | |||
615 | uint QuaZip::getOsCode() const | ||
616 | { | ||
617 | return p->osCode; | ||
618 | } | ||
619 | |||
620 | QTextCodec *QuaZip::getFileNameCodec()const | ||
621 | { | ||
622 | return p->fileNameCodec; | ||
623 | } | ||
624 | |||
625 | void QuaZip::setCommentCodec(QTextCodec *commentCodec) | ||
626 | { | ||
627 | p->commentCodec=commentCodec; | ||
628 | } | ||
629 | |||
630 | void QuaZip::setCommentCodec(const char *commentCodecName) | ||
631 | { | ||
632 | p->commentCodec=QTextCodec::codecForName(commentCodecName); | ||
633 | } | ||
634 | |||
635 | QTextCodec *QuaZip::getCommentCodec()const | ||
636 | { | ||
637 | return p->commentCodec; | ||
638 | } | ||
639 | |||
640 | QString QuaZip::getZipName() const | ||
641 | { | ||
642 | return p->zipName; | ||
643 | } | ||
644 | |||
645 | QIODevice *QuaZip::getIoDevice() const | ||
646 | { | ||
647 | if (!p->zipName.isEmpty()) // opened by name, using an internal QIODevice | ||
648 | return NULL; | ||
649 | return p->ioDevice; | ||
650 | } | ||
651 | |||
652 | QuaZip::Mode QuaZip::getMode()const | ||
653 | { | ||
654 | return p->mode; | ||
655 | } | ||
656 | |||
657 | bool QuaZip::isOpen()const | ||
658 | { | ||
659 | return p->mode!=mdNotOpen; | ||
660 | } | ||
661 | |||
662 | int QuaZip::getZipError() const | ||
663 | { | ||
664 | return p->zipError; | ||
665 | } | ||
666 | |||
667 | void QuaZip::setComment(const QString& comment) | ||
668 | { | ||
669 | p->comment=comment; | ||
670 | } | ||
671 | |||
672 | bool QuaZip::hasCurrentFile()const | ||
673 | { | ||
674 | return p->hasCurrentFile_f; | ||
675 | } | ||
676 | |||
677 | unzFile QuaZip::getUnzFile() | ||
678 | { | ||
679 | return p->unzFile_f; | ||
680 | } | ||
681 | |||
682 | zipFile QuaZip::getZipFile() | ||
683 | { | ||
684 | return p->zipFile_f; | ||
685 | } | ||
686 | |||
687 | void QuaZip::setDataDescriptorWritingEnabled(bool enabled) | ||
688 | { | ||
689 | p->dataDescriptorWritingEnabled = enabled; | ||
690 | } | ||
691 | |||
692 | bool QuaZip::isDataDescriptorWritingEnabled() const | ||
693 | { | ||
694 | return p->dataDescriptorWritingEnabled; | ||
695 | } | ||
696 | |||
697 | template<typename TFileInfo> | ||
698 | TFileInfo QuaZip_getFileInfo(QuaZip *zip, bool *ok); | ||
699 | |||
700 | template<> | ||
701 | QuaZipFileInfo QuaZip_getFileInfo(QuaZip *zip, bool *ok) | ||
702 | { | ||
703 | QuaZipFileInfo info; | ||
704 | *ok = zip->getCurrentFileInfo(&info); | ||
705 | return info; | ||
706 | } | ||
707 | |||
708 | template<> | ||
709 | QuaZipFileInfo64 QuaZip_getFileInfo(QuaZip *zip, bool *ok) | ||
710 | { | ||
711 | QuaZipFileInfo64 info; | ||
712 | *ok = zip->getCurrentFileInfo(&info); | ||
713 | return info; | ||
714 | } | ||
715 | |||
716 | template<> | ||
717 | QString QuaZip_getFileInfo(QuaZip *zip, bool *ok) | ||
718 | { | ||
719 | QString name = zip->getCurrentFileName(); | ||
720 | *ok = !name.isEmpty(); | ||
721 | return name; | ||
722 | } | ||
723 | |||
724 | template<typename TFileInfo> | ||
725 | bool QuaZipPrivate::getFileInfoList(QList<TFileInfo> *result) const | ||
726 | { | ||
727 | QuaZipPrivate *fakeThis=const_cast<QuaZipPrivate*>(this); | ||
728 | fakeThis->zipError=UNZ_OK; | ||
729 | if (mode!=QuaZip::mdUnzip) { | ||
730 | qWarning("QuaZip::getFileNameList/getFileInfoList(): " | ||
731 | "ZIP is not open in mdUnzip mode"); | ||
732 | return false; | ||
733 | } | ||
734 | QString currentFile; | ||
735 | if (q->hasCurrentFile()) { | ||
736 | currentFile = q->getCurrentFileName(); | ||
737 | } | ||
738 | if (q->goToFirstFile()) { | ||
739 | do { | ||
740 | bool ok; | ||
741 | result->append(QuaZip_getFileInfo<TFileInfo>(q, &ok)); | ||
742 | if (!ok) | ||
743 | return false; | ||
744 | } while (q->goToNextFile()); | ||
745 | } | ||
746 | if (zipError != UNZ_OK) | ||
747 | return false; | ||
748 | if (currentFile.isEmpty()) { | ||
749 | if (!q->goToFirstFile()) | ||
750 | return false; | ||
751 | } else { | ||
752 | if (!q->setCurrentFile(currentFile)) | ||
753 | return false; | ||
754 | } | ||
755 | return true; | ||
756 | } | ||
757 | |||
758 | QStringList QuaZip::getFileNameList() const | ||
759 | { | ||
760 | QStringList list; | ||
761 | if (p->getFileInfoList(&list)) | ||
762 | return list; | ||
763 | else | ||
764 | return QStringList(); | ||
765 | } | ||
766 | |||
767 | QList<QuaZipFileInfo> QuaZip::getFileInfoList() const | ||
768 | { | ||
769 | QList<QuaZipFileInfo> list; | ||
770 | if (p->getFileInfoList(&list)) | ||
771 | return list; | ||
772 | else | ||
773 | return QList<QuaZipFileInfo>(); | ||
774 | } | ||
775 | |||
776 | QList<QuaZipFileInfo64> QuaZip::getFileInfoList64() const | ||
777 | { | ||
778 | QList<QuaZipFileInfo64> list; | ||
779 | if (p->getFileInfoList(&list)) | ||
780 | return list; | ||
781 | else | ||
782 | return QList<QuaZipFileInfo64>(); | ||
783 | } | ||
784 | |||
785 | Qt::CaseSensitivity QuaZip::convertCaseSensitivity(QuaZip::CaseSensitivity cs) | ||
786 | { | ||
787 | if (cs == csDefault) { | ||
788 | #ifdef Q_OS_WIN | ||
789 | return Qt::CaseInsensitive; | ||
790 | #else | ||
791 | return Qt::CaseSensitive; | ||
792 | #endif | ||
793 | } else { | ||
794 | return cs == csSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; | ||
795 | } | ||
796 | } | ||
797 | |||
798 | void QuaZip::setDefaultFileNameCodec(QTextCodec *codec) | ||
799 | { | ||
800 | QuaZipPrivate::defaultFileNameCodec = codec; | ||
801 | } | ||
802 | |||
803 | void QuaZip::setDefaultFileNameCodec(const char *codecName) | ||
804 | { | ||
805 | setDefaultFileNameCodec(QTextCodec::codecForName(codecName)); | ||
806 | } | ||
807 | |||
808 | void QuaZip::setDefaultOsCode(uint osCode) | ||
809 | { | ||
810 | QuaZipPrivate::defaultOsCode = osCode; | ||
811 | } | ||
812 | |||
813 | uint QuaZip::getDefaultOsCode() | ||
814 | { | ||
815 | return QuaZipPrivate::defaultOsCode; | ||
816 | } | ||
817 | |||
818 | void QuaZip::setZip64Enabled(bool zip64) | ||
819 | { | ||
820 | p->zip64 = zip64; | ||
821 | } | ||
822 | |||
823 | bool QuaZip::isZip64Enabled() const | ||
824 | { | ||
825 | return p->zip64; | ||
826 | } | ||
827 | |||
828 | void QuaZip::setUtf8Enabled(bool utf8) | ||
829 | { | ||
830 | p->utf8 = utf8; | ||
831 | } | ||
832 | |||
833 | bool QuaZip::isUtf8Enabled() const | ||
834 | { | ||
835 | return p->utf8; | ||
836 | } | ||
837 | |||
838 | bool QuaZip::isAutoClose() const | ||
839 | { | ||
840 | return p->autoClose; | ||
841 | } | ||
842 | |||
843 | void QuaZip::setAutoClose(bool autoClose) const | ||
844 | { | ||
845 | p->autoClose = autoClose; | ||
846 | } | ||