ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
quazipfile.cpp
Go to the documentation of this file.
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 
30 
37 class QuaZipFilePrivate {
38  friend class QuaZipFile;
39 
40 private:
41  Q_DISABLE_COPY(QuaZipFilePrivate)
43  QuaZipFile *q;
45  QuaZip *zip;
47  QString fileName;
49  QuaZip::CaseSensitivity caseSensitivity;
51  bool raw;
53 
57  qint64 writePos;
59  quint64 uncompressedSize;
61  quint32 crc;
63 
67  bool internal;
69  int zipError;
71  inline void resetZipError() const { setZipError(UNZ_OK); }
73 
78  void setZipError(int zipError) const;
80  inline QuaZipFilePrivate(QuaZipFile *q)
81  : q(q),
82  zip(NULL),
83  caseSensitivity(QuaZip::csDefault),
84  raw(false),
85  writePos(0),
86  uncompressedSize(0),
87  crc(0),
88  internal(true),
89  zipError(UNZ_OK) {}
91  inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName)
92  : q(q),
93  caseSensitivity(QuaZip::csDefault),
94  raw(false),
95  writePos(0),
96  uncompressedSize(0),
97  crc(0),
98  internal(true),
99  zipError(UNZ_OK) {
100  zip = new QuaZip(zipName);
101  }
103  inline QuaZipFilePrivate(QuaZipFile *q,
104  const QString &zipName,
105  const QString &fileName,
107  : q(q),
108  raw(false),
109  writePos(0),
110  uncompressedSize(0),
111  crc(0),
112  internal(true),
113  zipError(UNZ_OK) {
114  zip = new QuaZip(zipName);
115  this->fileName = fileName;
116  if (this->fileName.startsWith('/'))
117  this->fileName = this->fileName.mid(1);
118  this->caseSensitivity = cs;
119  }
121  inline QuaZipFilePrivate(QuaZipFile *q, QuaZip *zip)
122  : q(q),
123  zip(zip),
124  raw(false),
125  writePos(0),
126  uncompressedSize(0),
127  crc(0),
128  internal(false),
129  zipError(UNZ_OK) {}
131  inline ~QuaZipFilePrivate() {
132  if (internal) delete zip;
133  }
134 };
135 
136 QuaZipFile::QuaZipFile() : p(new QuaZipFilePrivate(this)) {}
137 
138 QuaZipFile::QuaZipFile(QObject *parent)
139  : QIODevice(parent), p(new QuaZipFilePrivate(this)) {}
140 
141 QuaZipFile::QuaZipFile(const QString &zipName, QObject *parent)
142  : QIODevice(parent), p(new QuaZipFilePrivate(this, zipName)) {}
143 
144 QuaZipFile::QuaZipFile(const QString &zipName,
145  const QString &fileName,
147  QObject *parent)
148  : QIODevice(parent),
149  p(new QuaZipFilePrivate(this, zipName, fileName, cs)) {}
150 
151 QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent)
152  : QIODevice(parent), p(new QuaZipFilePrivate(this, zip)) {}
153 
155  if (isOpen()) close();
156  delete p;
157 }
158 
159 QString QuaZipFile::getZipName() const {
160  return p->zip == NULL ? QString() : p->zip->getZipName();
161 }
162 
163 QuaZip *QuaZipFile::getZip() const { return p->internal ? NULL : p->zip; }
164 
166  p->setZipError(UNZ_OK);
167  if (p->zip == NULL || (openMode() & WriteOnly)) return QString();
168  QString name = p->zip->getCurrentFileName();
169  if (name.isNull()) p->setZipError(p->zip->getZipError());
170  return name;
171 }
172 
173 void QuaZipFile::setZipName(const QString &zipName) {
174  if (isOpen()) {
175  qWarning(
176  "QuaZipFile::setZipName(): file is already open - can not set "
177  "ZIP name");
178  return;
179  }
180  if (p->zip != NULL && p->internal) delete p->zip;
181  p->zip = new QuaZip(zipName);
182  p->internal = true;
183 }
184 
186  if (isOpen()) {
187  qWarning(
188  "QuaZipFile::setZip(): file is already open - can not set ZIP");
189  return;
190  }
191  if (p->zip != NULL && p->internal) delete p->zip;
192  p->zip = zip;
193  p->fileName = QString();
194  p->internal = false;
195 }
196 
197 void QuaZipFile::setFileName(const QString &fileName,
199  if (p->zip == NULL) {
200  qWarning("QuaZipFile::setFileName(): call setZipName() first");
201  return;
202  }
203  if (!p->internal) {
204  qWarning(
205  "QuaZipFile::setFileName(): should not be used when not using "
206  "internal QuaZip");
207  return;
208  }
209  if (isOpen()) {
210  qWarning(
211  "QuaZipFile::setFileName(): can not set file name for already "
212  "opened file");
213  return;
214  }
215  p->fileName = fileName;
216  if (p->fileName.startsWith('/')) p->fileName = p->fileName.mid(1);
217  p->caseSensitivity = cs;
218 }
219 
220 void QuaZipFilePrivate::setZipError(int zipError) const {
221  QuaZipFilePrivate *fakeThis =
222  const_cast<QuaZipFilePrivate *>(this); // non-const
223  fakeThis->zipError = zipError;
224  if (zipError == UNZ_OK)
225  q->setErrorString(QString());
226  else
227  q->setErrorString(
228  QuaZipFile::tr("ZIP/UNZIP API error %1").arg(zipError));
229 }
230 
231 bool QuaZipFile::open(OpenMode mode) { return open(mode, NULL); }
232 
233 bool QuaZipFile::open(OpenMode mode,
234  int *method,
235  int *level,
236  bool raw,
237  const char *password) {
238  p->resetZipError();
239  if (isOpen()) {
240  qWarning("QuaZipFile::open(): already opened");
241  return false;
242  }
243  if (mode & Unbuffered) {
244  qWarning("QuaZipFile::open(): Unbuffered mode is not supported");
245  return false;
246  }
247  if ((mode & ReadOnly) && !(mode & WriteOnly)) {
248  if (p->internal) {
249  if (!p->zip->open(QuaZip::mdUnzip)) {
250  p->setZipError(p->zip->getZipError());
251  return false;
252  }
253  if (!p->zip->setCurrentFile(p->fileName, p->caseSensitivity)) {
254  p->setZipError(p->zip->getZipError());
255  p->zip->close();
256  return false;
257  }
258  } else {
259  if (p->zip == NULL) {
260  qWarning("QuaZipFile::open(): zip is NULL");
261  return false;
262  }
263  if (p->zip->getMode() != QuaZip::mdUnzip) {
264  qWarning(
265  "QuaZipFile::open(): file open mode %d incompatible "
266  "with ZIP open mode %d",
267  (int)mode, (int)p->zip->getMode());
268  return false;
269  }
270  if (!p->zip->hasCurrentFile()) {
271  qWarning("QuaZipFile::open(): zip does not have current file");
272  return false;
273  }
274  }
275  p->setZipError(unzOpenCurrentFile3(p->zip->getUnzFile(), method, level,
276  (int)raw, password));
277  if (p->zipError == UNZ_OK) {
278  setOpenMode(mode);
279  p->raw = raw;
280  return true;
281  } else
282  return false;
283  }
284  qWarning("QuaZipFile::open(): open mode %d not supported by this function",
285  (int)mode);
286  return false;
287 }
288 
289 bool QuaZipFile::open(OpenMode mode,
290  const QuaZipNewInfo &info,
291  const char *password,
292  quint32 crc,
293  int method,
294  int level,
295  bool raw,
296  int windowBits,
297  int memLevel,
298  int strategy) {
299  zip_fileinfo info_z;
300  p->resetZipError();
301  if (isOpen()) {
302  qWarning("QuaZipFile::open(): already opened");
303  return false;
304  }
305  if ((mode & WriteOnly) && !(mode & ReadOnly)) {
306  if (p->internal) {
307  qWarning(
308  "QuaZipFile::open(): write mode is incompatible with "
309  "internal QuaZip approach");
310  return false;
311  }
312  if (p->zip == NULL) {
313  qWarning("QuaZipFile::open(): zip is NULL");
314  return false;
315  }
316  if (p->zip->getMode() != QuaZip::mdCreate &&
317  p->zip->getMode() != QuaZip::mdAppend &&
318  p->zip->getMode() != QuaZip::mdAdd) {
319  qWarning(
320  "QuaZipFile::open(): file open mode %d incompatible with "
321  "ZIP open mode %d",
322  (int)mode, (int)p->zip->getMode());
323  return false;
324  }
325  info_z.tmz_date.tm_year = info.dateTime.date().year();
326  info_z.tmz_date.tm_mon = info.dateTime.date().month() - 1;
327  info_z.tmz_date.tm_mday = info.dateTime.date().day();
328  info_z.tmz_date.tm_hour = info.dateTime.time().hour();
329  info_z.tmz_date.tm_min = info.dateTime.time().minute();
330  info_z.tmz_date.tm_sec = info.dateTime.time().second();
331  info_z.dosDate = 0;
332  info_z.internal_fa = (uLong)info.internalAttr;
333  info_z.external_fa = (uLong)info.externalAttr;
334  if (p->zip->isDataDescriptorWritingEnabled())
335  zipSetFlags(p->zip->getZipFile(), ZIP_WRITE_DATA_DESCRIPTOR);
336  else
337  zipClearFlags(p->zip->getZipFile(), ZIP_WRITE_DATA_DESCRIPTOR);
338  p->setZipError(zipOpenNewFileInZip3_64(
339  p->zip->getZipFile(),
340  p->zip->getFileNameCodec()->fromUnicode(info.name).constData(),
341  &info_z, info.extraLocal.constData(), info.extraLocal.length(),
342  info.extraGlobal.constData(), info.extraGlobal.length(),
343  p->zip->getCommentCodec()
344  ->fromUnicode(info.comment)
345  .constData(),
346  method, level, (int)raw, windowBits, memLevel, strategy,
347  password, (uLong)crc, p->zip->isZip64Enabled()));
348  if (p->zipError == UNZ_OK) {
349  p->writePos = 0;
350  setOpenMode(mode);
351  p->raw = raw;
352  if (raw) {
353  p->crc = crc;
354  p->uncompressedSize = info.uncompressedSize;
355  }
356  return true;
357  } else
358  return false;
359  }
360  qWarning("QuaZipFile::open(): open mode %d not supported by this function",
361  (int)mode);
362  return false;
363 }
364 
365 bool QuaZipFile::isSequential() const { return true; }
366 
367 qint64 QuaZipFile::pos() const {
368  if (p->zip == NULL) {
369  qWarning("QuaZipFile::pos(): call setZipName() or setZip() first");
370  return -1;
371  }
372  if (!isOpen()) {
373  qWarning("QuaZipFile::pos(): file is not open");
374  return -1;
375  }
376  if (openMode() & ReadOnly)
377  // QIODevice::pos() is broken for sequential devices,
378  // but thankfully bytesAvailable() returns the number of
379  // bytes buffered, so we know how far ahead we are.
380  return unztell64(p->zip->getUnzFile()) - QIODevice::bytesAvailable();
381  else
382  return p->writePos;
383 }
384 
385 bool QuaZipFile::atEnd() const {
386  if (p->zip == NULL) {
387  qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first");
388  return false;
389  }
390  if (!isOpen()) {
391  qWarning("QuaZipFile::atEnd(): file is not open");
392  return false;
393  }
394  if (openMode() & ReadOnly)
395  // the same problem as with pos()
396  return QIODevice::bytesAvailable() == 0 &&
397  unzeof(p->zip->getUnzFile()) == 1;
398  else
399  return true;
400 }
401 
402 qint64 QuaZipFile::size() const {
403  if (!isOpen()) {
404  qWarning("QuaZipFile::atEnd(): file is not open");
405  return -1;
406  }
407  if (openMode() & ReadOnly)
408  return p->raw ? csize() : usize();
409  else
410  return p->writePos;
411 }
412 
413 qint64 QuaZipFile::csize() const {
414  unz_file_info64 info_z;
415  p->setZipError(UNZ_OK);
416  if (p->zip == NULL || p->zip->getMode() != QuaZip::mdUnzip) return -1;
417  p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL,
418  0, NULL, 0, NULL, 0));
419  if (p->zipError != UNZ_OK) return -1;
420  return info_z.compressed_size;
421 }
422 
423 qint64 QuaZipFile::usize() const {
424  unz_file_info64 info_z;
425  p->setZipError(UNZ_OK);
426  if (p->zip == NULL || p->zip->getMode() != QuaZip::mdUnzip) return -1;
427  p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL,
428  0, NULL, 0, NULL, 0));
429  if (p->zipError != UNZ_OK) return -1;
430  return info_z.uncompressed_size;
431 }
432 
434  QuaZipFileInfo64 info64;
435  if (getFileInfo(&info64)) {
436  info64.toQuaZipFileInfo(*info);
437  return true;
438  } else {
439  return false;
440  }
441 }
442 
444  if (p->zip == NULL || p->zip->getMode() != QuaZip::mdUnzip) return false;
445  p->zip->getCurrentFileInfo(info);
446  p->setZipError(p->zip->getZipError());
447  return p->zipError == UNZ_OK;
448 }
449 
451  p->resetZipError();
452  if (p->zip == NULL || !p->zip->isOpen()) return;
453  if (!isOpen()) {
454  qWarning("QuaZipFile::close(): file isn't open");
455  return;
456  }
457  if (openMode() & ReadOnly)
458  p->setZipError(unzCloseCurrentFile(p->zip->getUnzFile()));
459  else if (openMode() & WriteOnly)
460  if (isRaw())
461  p->setZipError(zipCloseFileInZipRaw64(p->zip->getZipFile(),
462  p->uncompressedSize, p->crc));
463  else
464  p->setZipError(zipCloseFileInZip(p->zip->getZipFile()));
465  else {
466  qWarning("Wrong open mode: %d", (int)openMode());
467  return;
468  }
469  if (p->zipError == UNZ_OK)
470  setOpenMode(QIODevice::NotOpen);
471  else
472  return;
473  if (p->internal) {
474  p->zip->close();
475  p->setZipError(p->zip->getZipError());
476  }
477 }
478 
479 qint64 QuaZipFile::readData(char *data, qint64 maxSize) {
480  p->setZipError(UNZ_OK);
481  qint64 bytesRead =
482  unzReadCurrentFile(p->zip->getUnzFile(), data, (unsigned)maxSize);
483  if (bytesRead < 0) {
484  p->setZipError((int)bytesRead);
485  return -1;
486  }
487  return bytesRead;
488 }
489 
490 qint64 QuaZipFile::writeData(const char *data, qint64 maxSize) {
491  p->setZipError(ZIP_OK);
492  p->setZipError(
493  zipWriteInFileInZip(p->zip->getZipFile(), data, (uint)maxSize));
494  if (p->zipError != ZIP_OK)
495  return -1;
496  else {
497  p->writePos += maxSize;
498  return maxSize;
499  }
500 }
501 
502 QString QuaZipFile::getFileName() const { return p->fileName; }
503 
505  return p->caseSensitivity;
506 }
507 
508 bool QuaZipFile::isRaw() const { return p->raw; }
509 
510 int QuaZipFile::getZipError() const { return p->zipError; }
511 
512 qint64 QuaZipFile::bytesAvailable() const { return size() - pos(); }
std::string name
#define NULL
A file inside ZIP archive.
Definition: quazipfile.h:74
bool isRaw() const
Returns true if the file was opened in raw mode.
Definition: quazipfile.cpp:508
void setFileName(const QString &fileName, QuaZip::CaseSensitivity cs=QuaZip::csDefault)
Sets the file name.
Definition: quazipfile.cpp:197
virtual void close()
Closes the file.
Definition: quazipfile.cpp:450
virtual bool open(OpenMode mode)
Opens a file for reading.
Definition: quazipfile.cpp:231
QString getActualFileName() const
Returns the actual file name in the archive.
Definition: quazipfile.cpp:165
virtual bool isSequential() const
Returns true, but beware!
Definition: quazipfile.cpp:365
int getZipError() const
Returns the error code returned by the last ZIP/UNZIP API call.
Definition: quazipfile.cpp:510
QString getZipName() const
Returns the ZIP archive file name.
Definition: quazipfile.cpp:159
virtual qint64 size() const
Returns file size.
Definition: quazipfile.cpp:402
qint64 csize() const
Returns compressed file size.
Definition: quazipfile.cpp:413
virtual ~QuaZipFile()
Destroys a QuaZipFile instance.
Definition: quazipfile.cpp:154
qint64 readData(char *data, qint64 maxSize)
Implementation of the QIODevice::readData().
Definition: quazipfile.cpp:479
virtual bool atEnd() const
Returns true if the end of file was reached.
Definition: quazipfile.cpp:385
virtual qint64 bytesAvailable() const
Returns the number of bytes available for reading.
Definition: quazipfile.cpp:512
void setZip(QuaZip *zip)
Binds to the existing QuaZip instance.
Definition: quazipfile.cpp:185
qint64 writeData(const char *data, qint64 maxSize)
Implementation of the QIODevice::writeData().
Definition: quazipfile.cpp:490
QuaZip * getZip() const
Returns a pointer to the associated QuaZip object.
Definition: quazipfile.cpp:163
void setZipName(const QString &zipName)
Sets the ZIP archive file name.
Definition: quazipfile.cpp:173
virtual qint64 pos() const
Returns current position in the file.
Definition: quazipfile.cpp:367
QuaZipFile()
Constructs a QuaZipFile instance.
Definition: quazipfile.cpp:136
bool getFileInfo(QuaZipFileInfo *info)
Gets information about current file.
Definition: quazipfile.cpp:433
QString getFileName() const
Returns file name.
Definition: quazipfile.cpp:502
qint64 usize() const
Returns uncompressed file size.
Definition: quazipfile.cpp:423
QuaZip::CaseSensitivity getCaseSensitivity() const
Returns case sensitivity of the file name.
Definition: quazipfile.cpp:504
ZIP archive.
Definition: quazip.h:128
@ mdAdd
ZIP file was opened for adding files in the archive.
Definition: quazip.h:151
@ mdCreate
ZIP file was created with open() call.
Definition: quazip.h:142
@ mdUnzip
ZIP file is open for reading files inside it.
Definition: quazip.h:141
@ mdAppend
Definition: quazip.h:143
CaseSensitivity
Case sensitivity for the file names.
Definition: quazip.h:159
unsigned int uint
Definition: cutil_math.h:28
Definition: Eigen.h:85
#define isOpen(pFd)
Definition: sqlite3.c:52420
Information about a file inside archive (with zip64 support).
bool toQuaZipFileInfo(QuaZipFileInfo &info) const
Converts to QuaZipFileInfo.
Information about a file inside archive.
Information about a file to be created.
Definition: quazipnewinfo.h:49
ulong uncompressedSize
Uncompressed file size.
Definition: quazipnewinfo.h:83
QString name
File name.
Definition: quazipnewinfo.h:54
quint16 internalAttr
File internal attributes.
Definition: quazipnewinfo.h:63
QByteArray extraLocal
File local extra field.
Definition: quazipnewinfo.h:76
QByteArray extraGlobal
File global extra field.
Definition: quazipnewinfo.h:78
QString comment
File comment.
Definition: quazipnewinfo.h:74
QDateTime dateTime
File timestamp.
Definition: quazipnewinfo.h:61
quint32 externalAttr
File external attributes.
Definition: quazipnewinfo.h:70
uInt tm_hour
Definition: zip.h:108
uInt tm_min
Definition: zip.h:107
uInt tm_year
Definition: zip.h:111
uInt tm_sec
Definition: zip.h:106
uInt tm_mon
Definition: zip.h:110
uInt tm_mday
Definition: zip.h:109
ZPOS64_T uncompressed_size
Definition: unzip.h:128
ZPOS64_T compressed_size
Definition: unzip.h:127
uLong dosDate
Definition: zip.h:116
uLong internal_fa
Definition: zip.h:120
uLong external_fa
Definition: zip.h:121
tm_zip tmz_date
Definition: zip.h:115
ZPOS64_T ZEXPORT unztell64(unzFile file)
Definition: unzip.c:1904
int ZEXPORT unzGetCurrentFileInfo64(unzFile file, unz_file_info64 *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)
Definition: unzip.c:1134
int ZEXPORT unzeof(unzFile file)
Definition: unzip.c:1924
int ZEXPORT unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password)
Definition: unzip.c:1480
int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len)
Definition: unzip.c:1692
int ZEXPORT unzCloseCurrentFile(unzFile file)
Definition: unzip.c:2004
#define UNZ_OK
Definition: unzip.h:83
int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32)
Definition: zip.c:1548
int ZEXPORT zipSetFlags(zipFile file, unsigned flags)
Definition: zip.c:2071
int ZEXPORT zipWriteInFileInZip(zipFile file, const void *buf, unsigned int len)
Definition: zip.c:1442
int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, uInt size_extrafield_global, const char *comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char *password, uLong crcForCrypting, int zip64)
Definition: zip.c:1336
int ZEXPORT zipCloseFileInZip(zipFile file)
Definition: zip.c:1804
int ZEXPORT zipClearFlags(zipFile file, unsigned flags)
Definition: zip.c:2085
#define ZIP_OK
Definition: zip.h:83
#define ZIP_WRITE_DATA_DESCRIPTOR
Definition: zip.h:90