From b230cf3aa24f3883b8b165bd5fd56620a9a95e47 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Sun, 8 Mar 2015 19:07:42 +0100 Subject: Update quazip to release 0.7.1. Update to latest quazip release. Note that quazip is now LGPL and not GPL / LGPL dual licensed anymore. Change-Id: Ie1e975b5b546dd31218eef9df472527493fe81e0 --- rbutil/rbutilqt/quazip/quazipfile.cpp | 385 ++++++++++++++++++++++------------ 1 file changed, 255 insertions(+), 130 deletions(-) (limited to 'rbutil/rbutilqt/quazip/quazipfile.cpp') diff --git a/rbutil/rbutilqt/quazip/quazipfile.cpp b/rbutil/rbutilqt/quazip/quazipfile.cpp index 0399d1dbd0..8d56417698 100644 --- a/rbutil/rbutilqt/quazip/quazipfile.cpp +++ b/rbutil/rbutilqt/quazip/quazipfile.cpp @@ -1,91 +1,165 @@ /* --- A kind of "standard" GPL license statement -- -QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package -Copyright (C) 2005-2007 Sergey A. Tachenov - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2 of the License, or (at your -option) any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - --- A kind of "standard" GPL license statement ends here -- - -See COPYING file for GPL. - -You are also permitted to use QuaZIP under the terms of LGPL (see -COPYING.LGPL). You are free to choose either license, but please note -that QuaZIP makes use of Qt, which is not licensed under LGPL. So if -you are using Open Source edition of Qt, you therefore MUST use GPL for -your code based on QuaZIP, since it would be also based on Qt in this -case. If you are Qt commercial license owner, then you are free to use -QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. +Copyright (C) 2005-2014 Sergey A. Tachenov + +This file is part of QuaZIP. + +QuaZIP is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 of the License, or +(at your option) any later version. + +QuaZIP is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with QuaZIP. If not, see . + +See COPYING file for the full LGPL text. + +Original ZIP package is copyrighted by Gilles Vollant, see +quazip/(un)zip.h files for details, basically it's zlib license. **/ #include "quazipfile.h" using namespace std; +/// The implementation class for QuaZip. +/** +\internal + +This class contains all the private stuff for the QuaZipFile class, thus +allowing to preserve binary compatibility between releases, the +technique known as the Pimpl (private implementation) idiom. +*/ +class QuaZipFilePrivate { + friend class QuaZipFile; + private: + /// The pointer to the associated QuaZipFile instance. + QuaZipFile *q; + /// The QuaZip object to work with. + QuaZip *zip; + /// The file name. + QString fileName; + /// Case sensitivity mode. + QuaZip::CaseSensitivity caseSensitivity; + /// Whether this file is opened in the raw mode. + bool raw; + /// Write position to keep track of. + /** + QIODevice::pos() is broken for non-seekable devices, so we need + our own position. + */ + qint64 writePos; + /// Uncompressed size to write along with a raw file. + quint64 uncompressedSize; + /// CRC to write along with a raw file. + quint32 crc; + /// Whether \ref zip points to an internal QuaZip instance. + /** + This is true if the archive was opened by name, rather than by + supplying an existing QuaZip instance. + */ + bool internal; + /// The last error. + int zipError; + /// Resets \ref zipError. + inline void resetZipError() const {setZipError(UNZ_OK);} + /// Sets the zip error. + /** + This function is marked as const although it changes one field. + This allows to call it from const functions that don't change + anything by themselves. + */ + void setZipError(int zipError) const; + /// The constructor for the corresponding QuaZipFile constructor. + inline QuaZipFilePrivate(QuaZipFile *q): + q(q), zip(NULL), internal(true), zipError(UNZ_OK) {} + /// The constructor for the corresponding QuaZipFile constructor. + inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName): + q(q), internal(true), zipError(UNZ_OK) + { + zip=new QuaZip(zipName); + } + /// The constructor for the corresponding QuaZipFile constructor. + inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName, const QString &fileName, + QuaZip::CaseSensitivity cs): + q(q), internal(true), zipError(UNZ_OK) + { + zip=new QuaZip(zipName); + this->fileName=fileName; + if (this->fileName.startsWith('/')) + this->fileName = this->fileName.mid(1); + this->caseSensitivity=cs; + } + /// The constructor for the QuaZipFile constructor accepting a file name. + inline QuaZipFilePrivate(QuaZipFile *q, QuaZip *zip): + q(q), zip(zip), internal(false), zipError(UNZ_OK) {} + /// The destructor. + inline ~QuaZipFilePrivate() + { + if (internal) + delete zip; + } +}; + QuaZipFile::QuaZipFile(): - zip(NULL), internal(true), zipError(UNZ_OK) + p(new QuaZipFilePrivate(this)) { } QuaZipFile::QuaZipFile(QObject *parent): - QIODevice(parent), zip(NULL), internal(true), zipError(UNZ_OK) + QIODevice(parent), + p(new QuaZipFilePrivate(this)) { } QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent): - QIODevice(parent), internal(true), zipError(UNZ_OK) + QIODevice(parent), + p(new QuaZipFilePrivate(this, zipName)) { - zip=new QuaZip(zipName); - Q_CHECK_PTR(zip); } QuaZipFile::QuaZipFile(const QString& zipName, const QString& fileName, QuaZip::CaseSensitivity cs, QObject *parent): - QIODevice(parent), internal(true), zipError(UNZ_OK) + QIODevice(parent), + p(new QuaZipFilePrivate(this, zipName, fileName, cs)) { - zip=new QuaZip(zipName); - Q_CHECK_PTR(zip); - this->fileName=fileName; - this->caseSensitivity=cs; } QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent): QIODevice(parent), - zip(zip), internal(false), - zipError(UNZ_OK) + p(new QuaZipFilePrivate(this, zip)) { } QuaZipFile::~QuaZipFile() { - if(isOpen()) close(); - if(internal) delete zip; + if (isOpen()) + close(); + delete p; +} + +QString QuaZipFile::getZipName() const +{ + return p->zip==NULL ? QString() : p->zip->getZipName(); } -QString QuaZipFile::getZipName()const +QuaZip *QuaZipFile::getZip() const { - return zip==NULL?QString():zip->getZipName(); + return p->internal ? NULL : p->zip; } QString QuaZipFile::getActualFileName()const { - setZipError(UNZ_OK); - if(zip==NULL||(openMode()&WriteOnly)) return QString(); - QString name=zip->getCurrentFileName(); + p->setZipError(UNZ_OK); + if (p->zip == NULL || (openMode() & WriteOnly)) + return QString(); + QString name=p->zip->getCurrentFileName(); if(name.isNull()) - setZipError(zip->getZipError()); + p->setZipError(p->zip->getZipError()); return name; } @@ -95,10 +169,10 @@ void QuaZipFile::setZipName(const QString& zipName) qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name"); return; } - if(zip!=NULL&&internal) delete zip; - zip=new QuaZip(zipName); - Q_CHECK_PTR(zip); - internal=true; + if(p->zip!=NULL && p->internal) + delete p->zip; + p->zip=new QuaZip(zipName); + p->internal=true; } void QuaZipFile::setZip(QuaZip *zip) @@ -107,19 +181,20 @@ void QuaZipFile::setZip(QuaZip *zip) qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP"); return; } - if(this->zip!=NULL&&internal) delete this->zip; - this->zip=zip; - this->fileName=QString(); - internal=false; + if(p->zip!=NULL && p->internal) + delete p->zip; + p->zip=zip; + p->fileName=QString(); + p->internal=false; } void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs) { - if(zip==NULL) { + if(p->zip==NULL) { qWarning("QuaZipFile::setFileName(): call setZipName() first"); return; } - if(!internal) { + if(!p->internal) { qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip"); return; } @@ -127,18 +202,20 @@ void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs qWarning("QuaZipFile::setFileName(): can not set file name for already opened file"); return; } - this->fileName=fileName; - this->caseSensitivity=cs; + p->fileName=fileName; + if (p->fileName.startsWith('/')) + p->fileName = p->fileName.mid(1); + p->caseSensitivity=cs; } -void QuaZipFile::setZipError(int zipError)const +void QuaZipFilePrivate::setZipError(int zipError) const { - QuaZipFile *fakeThis=(QuaZipFile*)this; // non-const + QuaZipFilePrivate *fakeThis = const_cast(this); // non-const fakeThis->zipError=zipError; if(zipError==UNZ_OK) - fakeThis->setErrorString(QString()); + q->setErrorString(QString()); else - fakeThis->setErrorString(tr("ZIP/UNZIP API error %1").arg(zipError)); + q->setErrorString(QuaZipFile::tr("ZIP/UNZIP API error %1").arg(zipError)); } bool QuaZipFile::open(OpenMode mode) @@ -148,7 +225,7 @@ bool QuaZipFile::open(OpenMode mode) bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password) { - resetZipError(); + p->resetZipError(); if(isOpen()) { qWarning("QuaZipFile::open(): already opened"); return false; @@ -158,35 +235,35 @@ bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const ch return false; } if((mode&ReadOnly)&&!(mode&WriteOnly)) { - if(internal) { - if(!zip->open(QuaZip::mdUnzip)) { - setZipError(zip->getZipError()); + if(p->internal) { + if(!p->zip->open(QuaZip::mdUnzip)) { + p->setZipError(p->zip->getZipError()); return false; } - if(!zip->setCurrentFile(fileName, caseSensitivity)) { - setZipError(zip->getZipError()); - zip->close(); + if(!p->zip->setCurrentFile(p->fileName, p->caseSensitivity)) { + p->setZipError(p->zip->getZipError()); + p->zip->close(); return false; } } else { - if(zip==NULL) { + if(p->zip==NULL) { qWarning("QuaZipFile::open(): zip is NULL"); return false; } - if(zip->getMode()!=QuaZip::mdUnzip) { + if(p->zip->getMode()!=QuaZip::mdUnzip) { qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", - (int)mode, (int)zip->getMode()); + (int)mode, (int)p->zip->getMode()); return false; } - if(!zip->hasCurrentFile()) { + if(!p->zip->hasCurrentFile()) { qWarning("QuaZipFile::open(): zip does not have current file"); return false; } } - setZipError(unzOpenCurrentFile3(zip->getUnzFile(), method, level, (int)raw, password)); - if(zipError==UNZ_OK) { + p->setZipError(unzOpenCurrentFile3(p->zip->getUnzFile(), method, level, (int)raw, password)); + if(p->zipError==UNZ_OK) { setOpenMode(mode); - this->raw=raw; + p->raw=raw; return true; } else return false; @@ -201,23 +278,23 @@ bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info, int windowBits, int memLevel, int strategy) { zip_fileinfo info_z; - resetZipError(); + p->resetZipError(); if(isOpen()) { qWarning("QuaZipFile::open(): already opened"); return false; } if((mode&WriteOnly)&&!(mode&ReadOnly)) { - if(internal) { + if(p->internal) { qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach"); return false; } - if(zip==NULL) { + if(p->zip==NULL) { qWarning("QuaZipFile::open(): zip is NULL"); return false; } - if(zip->getMode()!=QuaZip::mdCreate&&zip->getMode()!=QuaZip::mdAppend&&zip->getMode()!=QuaZip::mdAdd) { + if(p->zip->getMode()!=QuaZip::mdCreate&&p->zip->getMode()!=QuaZip::mdAppend&&p->zip->getMode()!=QuaZip::mdAdd) { qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", - (int)mode, (int)zip->getMode()); + (int)mode, (int)p->zip->getMode()); return false; } info_z.tmz_date.tm_year=info.dateTime.date().year(); @@ -229,21 +306,25 @@ bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info, info_z.dosDate = 0; info_z.internal_fa=(uLong)info.internalAttr; info_z.external_fa=(uLong)info.externalAttr; - setZipError(zipOpenNewFileInZip3(zip->getZipFile(), - zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z, + if (p->zip->isDataDescriptorWritingEnabled()) + zipSetFlags(p->zip->getZipFile(), ZIP_WRITE_DATA_DESCRIPTOR); + else + zipClearFlags(p->zip->getZipFile(), ZIP_WRITE_DATA_DESCRIPTOR); + p->setZipError(zipOpenNewFileInZip3_64(p->zip->getZipFile(), + p->zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z, info.extraLocal.constData(), info.extraLocal.length(), info.extraGlobal.constData(), info.extraGlobal.length(), - zip->getCommentCodec()->fromUnicode(info.comment).constData(), + p->zip->getCommentCodec()->fromUnicode(info.comment).constData(), method, level, (int)raw, windowBits, memLevel, strategy, - password, (uLong)crc)); - if(zipError==UNZ_OK) { - writePos=0; + password, (uLong)crc, p->zip->isZip64Enabled())); + if(p->zipError==UNZ_OK) { + p->writePos=0; setOpenMode(mode); - this->raw=raw; + p->raw=raw; if(raw) { - this->crc=crc; - this->uncompressedSize=info.uncompressedSize; + p->crc=crc; + p->uncompressedSize=info.uncompressedSize; } return true; } else @@ -260,7 +341,7 @@ bool QuaZipFile::isSequential()const qint64 QuaZipFile::pos()const { - if(zip==NULL) { + if(p->zip==NULL) { qWarning("QuaZipFile::pos(): call setZipName() or setZip() first"); return -1; } @@ -269,14 +350,17 @@ qint64 QuaZipFile::pos()const return -1; } if(openMode()&ReadOnly) - return unztell(zip->getUnzFile()); + // QIODevice::pos() is broken for sequential devices, + // but thankfully bytesAvailable() returns the number of + // bytes buffered, so we know how far ahead we are. + return unztell(p->zip->getUnzFile()) - QIODevice::bytesAvailable(); else - return writePos; + return p->writePos; } bool QuaZipFile::atEnd()const { - if(zip==NULL) { + if(p->zip==NULL) { qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first"); return false; } @@ -285,7 +369,9 @@ bool QuaZipFile::atEnd()const return false; } if(openMode()&ReadOnly) - return unzeof(zip->getUnzFile())==1; + // the same problem as with pos() + return QIODevice::bytesAvailable() == 0 + && unzeof(p->zip->getUnzFile())==1; else return true; } @@ -297,81 +383,120 @@ qint64 QuaZipFile::size()const return -1; } if(openMode()&ReadOnly) - return raw?csize():usize(); + return p->raw?csize():usize(); else - return writePos; + return p->writePos; } qint64 QuaZipFile::csize()const { - unz_file_info info_z; - setZipError(UNZ_OK); - if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1; - setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); - if(zipError!=UNZ_OK) + unz_file_info64 info_z; + p->setZipError(UNZ_OK); + if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1; + p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); + if(p->zipError!=UNZ_OK) return -1; return info_z.compressed_size; } qint64 QuaZipFile::usize()const { - unz_file_info info_z; - setZipError(UNZ_OK); - if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1; - setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); - if(zipError!=UNZ_OK) + unz_file_info64 info_z; + p->setZipError(UNZ_OK); + if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1; + p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); + if(p->zipError!=UNZ_OK) return -1; return info_z.uncompressed_size; } bool QuaZipFile::getFileInfo(QuaZipFileInfo *info) { - if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return false; - zip->getCurrentFileInfo(info); - setZipError(zip->getZipError()); - return zipError==UNZ_OK; + QuaZipFileInfo64 info64; + if (getFileInfo(&info64)) { + info64.toQuaZipFileInfo(*info); + return true; + } else { + return false; + } +} + +bool QuaZipFile::getFileInfo(QuaZipFileInfo64 *info) +{ + if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return false; + p->zip->getCurrentFileInfo(info); + p->setZipError(p->zip->getZipError()); + return p->zipError==UNZ_OK; } void QuaZipFile::close() { - resetZipError(); - if(zip==NULL||!zip->isOpen()) return; + p->resetZipError(); + if(p->zip==NULL||!p->zip->isOpen()) return; if(!isOpen()) { qWarning("QuaZipFile::close(): file isn't open"); return; } if(openMode()&ReadOnly) - setZipError(unzCloseCurrentFile(zip->getUnzFile())); + p->setZipError(unzCloseCurrentFile(p->zip->getUnzFile())); else if(openMode()&WriteOnly) - if(isRaw()) setZipError(zipCloseFileInZipRaw(zip->getZipFile(), uncompressedSize, crc)); - else setZipError(zipCloseFileInZip(zip->getZipFile())); + if(isRaw()) p->setZipError(zipCloseFileInZipRaw64(p->zip->getZipFile(), p->uncompressedSize, p->crc)); + else p->setZipError(zipCloseFileInZip(p->zip->getZipFile())); else { qWarning("Wrong open mode: %d", (int)openMode()); return; } - if(zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen); + if(p->zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen); else return; - if(internal) { - zip->close(); - setZipError(zip->getZipError()); + if(p->internal) { + p->zip->close(); + p->setZipError(p->zip->getZipError()); } } qint64 QuaZipFile::readData(char *data, qint64 maxSize) { - setZipError(UNZ_OK); - qint64 bytesRead=unzReadCurrentFile(zip->getUnzFile(), data, (unsigned)maxSize); - if(bytesRead<0) setZipError((int)bytesRead); + p->setZipError(UNZ_OK); + qint64 bytesRead=unzReadCurrentFile(p->zip->getUnzFile(), data, (unsigned)maxSize); + if (bytesRead < 0) { + p->setZipError((int) bytesRead); + return -1; + } return bytesRead; } qint64 QuaZipFile::writeData(const char* data, qint64 maxSize) { - setZipError(ZIP_OK); - setZipError(zipWriteInFileInZip(zip->getZipFile(), data, (uint)maxSize)); - if(zipError!=ZIP_OK) return -1; + p->setZipError(ZIP_OK); + p->setZipError(zipWriteInFileInZip(p->zip->getZipFile(), data, (uint)maxSize)); + if(p->zipError!=ZIP_OK) return -1; else { - writePos+=maxSize; + p->writePos+=maxSize; return maxSize; } } + +QString QuaZipFile::getFileName() const +{ + return p->fileName; +} + +QuaZip::CaseSensitivity QuaZipFile::getCaseSensitivity() const +{ + return p->caseSensitivity; +} + +bool QuaZipFile::isRaw() const +{ + return p->raw; +} + +int QuaZipFile::getZipError() const +{ + return p->zipError; +} + +qint64 QuaZipFile::bytesAvailable() const +{ + return size() - pos(); +} -- cgit v1.2.3