ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/s10k/CommonLibs/quazip-0.7.2/quazip/quazipfile.cpp
Revision: 1096
Committed: Sat Dec 30 14:40:33 2017 UTC (7 years, 9 months ago) by s10k
Content type: text/x-c++src
File size: 15223 byte(s)
Log Message:
Added zlib, quazip, basicxmlsyntaxhighlighter, conditionalsemaphore and linenumberdisplay libraries. zlib and quazip are pre-compiled, but you can compile them yourself, just delete the dll files (or equivalent binary files to your OS)

File Contents

# Content
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 "quazipfile.h"
26
27 using namespace std;
28
29 /// The implementation class for QuaZip.
30 /**
31 \internal
32
33 This class contains all the private stuff for the QuaZipFile class, thus
34 allowing to preserve binary compatibility between releases, the
35 technique known as the Pimpl (private implementation) idiom.
36 */
37 class QuaZipFilePrivate {
38 friend class QuaZipFile;
39 private:
40 Q_DISABLE_COPY(QuaZipFilePrivate)
41 /// The pointer to the associated QuaZipFile instance.
42 QuaZipFile *q;
43 /// The QuaZip object to work with.
44 QuaZip *zip;
45 /// The file name.
46 QString fileName;
47 /// Case sensitivity mode.
48 QuaZip::CaseSensitivity caseSensitivity;
49 /// Whether this file is opened in the raw mode.
50 bool raw;
51 /// Write position to keep track of.
52 /**
53 QIODevice::pos() is broken for non-seekable devices, so we need
54 our own position.
55 */
56 qint64 writePos;
57 /// Uncompressed size to write along with a raw file.
58 quint64 uncompressedSize;
59 /// CRC to write along with a raw file.
60 quint32 crc;
61 /// Whether \ref zip points to an internal QuaZip instance.
62 /**
63 This is true if the archive was opened by name, rather than by
64 supplying an existing QuaZip instance.
65 */
66 bool internal;
67 /// The last error.
68 int zipError;
69 /// Resets \ref zipError.
70 inline void resetZipError() const {setZipError(UNZ_OK);}
71 /// Sets the zip error.
72 /**
73 This function is marked as const although it changes one field.
74 This allows to call it from const functions that don't change
75 anything by themselves.
76 */
77 void setZipError(int zipError) const;
78 /// The constructor for the corresponding QuaZipFile constructor.
79 inline QuaZipFilePrivate(QuaZipFile *q):
80 q(q),
81 zip(NULL),
82 caseSensitivity(QuaZip::csDefault),
83 raw(false),
84 writePos(0),
85 uncompressedSize(0),
86 crc(0),
87 internal(true),
88 zipError(UNZ_OK) {}
89 /// The constructor for the corresponding QuaZipFile constructor.
90 inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName):
91 q(q),
92 caseSensitivity(QuaZip::csDefault),
93 raw(false),
94 writePos(0),
95 uncompressedSize(0),
96 crc(0),
97 internal(true),
98 zipError(UNZ_OK)
99 {
100 zip=new QuaZip(zipName);
101 }
102 /// The constructor for the corresponding QuaZipFile constructor.
103 inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName, const QString &fileName,
104 QuaZip::CaseSensitivity cs):
105 q(q),
106 raw(false),
107 writePos(0),
108 uncompressedSize(0),
109 crc(0),
110 internal(true),
111 zipError(UNZ_OK)
112 {
113 zip=new QuaZip(zipName);
114 this->fileName=fileName;
115 if (this->fileName.startsWith('/'))
116 this->fileName = this->fileName.mid(1);
117 this->caseSensitivity=cs;
118 }
119 /// The constructor for the QuaZipFile constructor accepting a file name.
120 inline QuaZipFilePrivate(QuaZipFile *q, QuaZip *zip):
121 q(q),
122 zip(zip),
123 raw(false),
124 writePos(0),
125 uncompressedSize(0),
126 crc(0),
127 internal(false),
128 zipError(UNZ_OK) {}
129 /// The destructor.
130 inline ~QuaZipFilePrivate()
131 {
132 if (internal)
133 delete zip;
134 }
135 };
136
137 QuaZipFile::QuaZipFile():
138 p(new QuaZipFilePrivate(this))
139 {
140 }
141
142 QuaZipFile::QuaZipFile(QObject *parent):
143 QIODevice(parent),
144 p(new QuaZipFilePrivate(this))
145 {
146 }
147
148 QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent):
149 QIODevice(parent),
150 p(new QuaZipFilePrivate(this, zipName))
151 {
152 }
153
154 QuaZipFile::QuaZipFile(const QString& zipName, const QString& fileName,
155 QuaZip::CaseSensitivity cs, QObject *parent):
156 QIODevice(parent),
157 p(new QuaZipFilePrivate(this, zipName, fileName, cs))
158 {
159 }
160
161 QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent):
162 QIODevice(parent),
163 p(new QuaZipFilePrivate(this, zip))
164 {
165 }
166
167 QuaZipFile::~QuaZipFile()
168 {
169 if (isOpen())
170 close();
171 delete p;
172 }
173
174 QString QuaZipFile::getZipName() const
175 {
176 return p->zip==NULL ? QString() : p->zip->getZipName();
177 }
178
179 QuaZip *QuaZipFile::getZip() const
180 {
181 return p->internal ? NULL : p->zip;
182 }
183
184 QString QuaZipFile::getActualFileName()const
185 {
186 p->setZipError(UNZ_OK);
187 if (p->zip == NULL || (openMode() & WriteOnly))
188 return QString();
189 QString name=p->zip->getCurrentFileName();
190 if(name.isNull())
191 p->setZipError(p->zip->getZipError());
192 return name;
193 }
194
195 void QuaZipFile::setZipName(const QString& zipName)
196 {
197 if(isOpen()) {
198 qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name");
199 return;
200 }
201 if(p->zip!=NULL && p->internal)
202 delete p->zip;
203 p->zip=new QuaZip(zipName);
204 p->internal=true;
205 }
206
207 void QuaZipFile::setZip(QuaZip *zip)
208 {
209 if(isOpen()) {
210 qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP");
211 return;
212 }
213 if(p->zip!=NULL && p->internal)
214 delete p->zip;
215 p->zip=zip;
216 p->fileName=QString();
217 p->internal=false;
218 }
219
220 void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs)
221 {
222 if(p->zip==NULL) {
223 qWarning("QuaZipFile::setFileName(): call setZipName() first");
224 return;
225 }
226 if(!p->internal) {
227 qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip");
228 return;
229 }
230 if(isOpen()) {
231 qWarning("QuaZipFile::setFileName(): can not set file name for already opened file");
232 return;
233 }
234 p->fileName=fileName;
235 if (p->fileName.startsWith('/'))
236 p->fileName = p->fileName.mid(1);
237 p->caseSensitivity=cs;
238 }
239
240 void QuaZipFilePrivate::setZipError(int zipError) const
241 {
242 QuaZipFilePrivate *fakeThis = const_cast<QuaZipFilePrivate*>(this); // non-const
243 fakeThis->zipError=zipError;
244 if(zipError==UNZ_OK)
245 q->setErrorString(QString());
246 else
247 q->setErrorString(QuaZipFile::tr("ZIP/UNZIP API error %1").arg(zipError));
248 }
249
250 bool QuaZipFile::open(OpenMode mode)
251 {
252 return open(mode, NULL);
253 }
254
255 bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password)
256 {
257 p->resetZipError();
258 if(isOpen()) {
259 qWarning("QuaZipFile::open(): already opened");
260 return false;
261 }
262 if(mode&Unbuffered) {
263 qWarning("QuaZipFile::open(): Unbuffered mode is not supported");
264 return false;
265 }
266 if((mode&ReadOnly)&&!(mode&WriteOnly)) {
267 if(p->internal) {
268 if(!p->zip->open(QuaZip::mdUnzip)) {
269 p->setZipError(p->zip->getZipError());
270 return false;
271 }
272 if(!p->zip->setCurrentFile(p->fileName, p->caseSensitivity)) {
273 p->setZipError(p->zip->getZipError());
274 p->zip->close();
275 return false;
276 }
277 } else {
278 if(p->zip==NULL) {
279 qWarning("QuaZipFile::open(): zip is NULL");
280 return false;
281 }
282 if(p->zip->getMode()!=QuaZip::mdUnzip) {
283 qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d",
284 (int)mode, (int)p->zip->getMode());
285 return false;
286 }
287 if(!p->zip->hasCurrentFile()) {
288 qWarning("QuaZipFile::open(): zip does not have current file");
289 return false;
290 }
291 }
292 p->setZipError(unzOpenCurrentFile3(p->zip->getUnzFile(), method, level, (int)raw, password));
293 if(p->zipError==UNZ_OK) {
294 setOpenMode(mode);
295 p->raw=raw;
296 return true;
297 } else
298 return false;
299 }
300 qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode);
301 return false;
302 }
303
304 bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info,
305 const char *password, quint32 crc,
306 int method, int level, bool raw,
307 int windowBits, int memLevel, int strategy)
308 {
309 zip_fileinfo info_z;
310 p->resetZipError();
311 if(isOpen()) {
312 qWarning("QuaZipFile::open(): already opened");
313 return false;
314 }
315 if((mode&WriteOnly)&&!(mode&ReadOnly)) {
316 if(p->internal) {
317 qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach");
318 return false;
319 }
320 if(p->zip==NULL) {
321 qWarning("QuaZipFile::open(): zip is NULL");
322 return false;
323 }
324 if(p->zip->getMode()!=QuaZip::mdCreate&&p->zip->getMode()!=QuaZip::mdAppend&&p->zip->getMode()!=QuaZip::mdAdd) {
325 qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d",
326 (int)mode, (int)p->zip->getMode());
327 return false;
328 }
329 info_z.tmz_date.tm_year=info.dateTime.date().year();
330 info_z.tmz_date.tm_mon=info.dateTime.date().month() - 1;
331 info_z.tmz_date.tm_mday=info.dateTime.date().day();
332 info_z.tmz_date.tm_hour=info.dateTime.time().hour();
333 info_z.tmz_date.tm_min=info.dateTime.time().minute();
334 info_z.tmz_date.tm_sec=info.dateTime.time().second();
335 info_z.dosDate = 0;
336 info_z.internal_fa=(uLong)info.internalAttr;
337 info_z.external_fa=(uLong)info.externalAttr;
338 if (p->zip->isDataDescriptorWritingEnabled())
339 zipSetFlags(p->zip->getZipFile(), ZIP_WRITE_DATA_DESCRIPTOR);
340 else
341 zipClearFlags(p->zip->getZipFile(), ZIP_WRITE_DATA_DESCRIPTOR);
342 p->setZipError(zipOpenNewFileInZip3_64(p->zip->getZipFile(),
343 p->zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z,
344 info.extraLocal.constData(), info.extraLocal.length(),
345 info.extraGlobal.constData(), info.extraGlobal.length(),
346 p->zip->getCommentCodec()->fromUnicode(info.comment).constData(),
347 method, level, (int)raw,
348 windowBits, memLevel, strategy,
349 password, (uLong)crc, p->zip->isZip64Enabled()));
350 if(p->zipError==UNZ_OK) {
351 p->writePos=0;
352 setOpenMode(mode);
353 p->raw=raw;
354 if(raw) {
355 p->crc=crc;
356 p->uncompressedSize=info.uncompressedSize;
357 }
358 return true;
359 } else
360 return false;
361 }
362 qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode);
363 return false;
364 }
365
366 bool QuaZipFile::isSequential()const
367 {
368 return true;
369 }
370
371 qint64 QuaZipFile::pos()const
372 {
373 if(p->zip==NULL) {
374 qWarning("QuaZipFile::pos(): call setZipName() or setZip() first");
375 return -1;
376 }
377 if(!isOpen()) {
378 qWarning("QuaZipFile::pos(): file is not open");
379 return -1;
380 }
381 if(openMode()&ReadOnly)
382 // QIODevice::pos() is broken for sequential devices,
383 // but thankfully bytesAvailable() returns the number of
384 // bytes buffered, so we know how far ahead we are.
385 return unztell(p->zip->getUnzFile()) - QIODevice::bytesAvailable();
386 else
387 return p->writePos;
388 }
389
390 bool QuaZipFile::atEnd()const
391 {
392 if(p->zip==NULL) {
393 qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first");
394 return false;
395 }
396 if(!isOpen()) {
397 qWarning("QuaZipFile::atEnd(): file is not open");
398 return false;
399 }
400 if(openMode()&ReadOnly)
401 // the same problem as with pos()
402 return QIODevice::bytesAvailable() == 0
403 && unzeof(p->zip->getUnzFile())==1;
404 else
405 return true;
406 }
407
408 qint64 QuaZipFile::size()const
409 {
410 if(!isOpen()) {
411 qWarning("QuaZipFile::atEnd(): file is not open");
412 return -1;
413 }
414 if(openMode()&ReadOnly)
415 return p->raw?csize():usize();
416 else
417 return p->writePos;
418 }
419
420 qint64 QuaZipFile::csize()const
421 {
422 unz_file_info64 info_z;
423 p->setZipError(UNZ_OK);
424 if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1;
425 p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0));
426 if(p->zipError!=UNZ_OK)
427 return -1;
428 return info_z.compressed_size;
429 }
430
431 qint64 QuaZipFile::usize()const
432 {
433 unz_file_info64 info_z;
434 p->setZipError(UNZ_OK);
435 if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1;
436 p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0));
437 if(p->zipError!=UNZ_OK)
438 return -1;
439 return info_z.uncompressed_size;
440 }
441
442 bool QuaZipFile::getFileInfo(QuaZipFileInfo *info)
443 {
444 QuaZipFileInfo64 info64;
445 if (getFileInfo(&info64)) {
446 info64.toQuaZipFileInfo(*info);
447 return true;
448 } else {
449 return false;
450 }
451 }
452
453 bool QuaZipFile::getFileInfo(QuaZipFileInfo64 *info)
454 {
455 if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return false;
456 p->zip->getCurrentFileInfo(info);
457 p->setZipError(p->zip->getZipError());
458 return p->zipError==UNZ_OK;
459 }
460
461 void QuaZipFile::close()
462 {
463 p->resetZipError();
464 if(p->zip==NULL||!p->zip->isOpen()) return;
465 if(!isOpen()) {
466 qWarning("QuaZipFile::close(): file isn't open");
467 return;
468 }
469 if(openMode()&ReadOnly)
470 p->setZipError(unzCloseCurrentFile(p->zip->getUnzFile()));
471 else if(openMode()&WriteOnly)
472 if(isRaw()) p->setZipError(zipCloseFileInZipRaw64(p->zip->getZipFile(), p->uncompressedSize, p->crc));
473 else p->setZipError(zipCloseFileInZip(p->zip->getZipFile()));
474 else {
475 qWarning("Wrong open mode: %d", (int)openMode());
476 return;
477 }
478 if(p->zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen);
479 else return;
480 if(p->internal) {
481 p->zip->close();
482 p->setZipError(p->zip->getZipError());
483 }
484 }
485
486 qint64 QuaZipFile::readData(char *data, qint64 maxSize)
487 {
488 p->setZipError(UNZ_OK);
489 qint64 bytesRead=unzReadCurrentFile(p->zip->getUnzFile(), data, (unsigned)maxSize);
490 if (bytesRead < 0) {
491 p->setZipError((int) bytesRead);
492 return -1;
493 }
494 return bytesRead;
495 }
496
497 qint64 QuaZipFile::writeData(const char* data, qint64 maxSize)
498 {
499 p->setZipError(ZIP_OK);
500 p->setZipError(zipWriteInFileInZip(p->zip->getZipFile(), data, (uint)maxSize));
501 if(p->zipError!=ZIP_OK) return -1;
502 else {
503 p->writePos+=maxSize;
504 return maxSize;
505 }
506 }
507
508 QString QuaZipFile::getFileName() const
509 {
510 return p->fileName;
511 }
512
513 QuaZip::CaseSensitivity QuaZipFile::getCaseSensitivity() const
514 {
515 return p->caseSensitivity;
516 }
517
518 bool QuaZipFile::isRaw() const
519 {
520 return p->raw;
521 }
522
523 int QuaZipFile::getZipError() const
524 {
525 return p->zipError;
526 }
527
528 qint64 QuaZipFile::bytesAvailable() const
529 {
530 return size() - pos();
531 }