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