summaryrefslogtreecommitdiffstats
path: root/rbutil/rbutilqt/quazip/quazipfile.cpp
diff options
context:
space:
mode:
authorDominik Riebeling <Dominik.Riebeling@gmail.com>2015-03-08 19:07:42 +0100
committerDominik Riebeling <Dominik.Riebeling@gmail.com>2015-05-02 16:52:14 +0200
commitb230cf3aa24f3883b8b165bd5fd56620a9a95e47 (patch)
tree19e46e3697c98c3e51f7f4e91e3879f95bd0bc43 /rbutil/rbutilqt/quazip/quazipfile.cpp
parentd4fee369712f006785fd3a8904a5e2b5c529598b (diff)
downloadrockbox-b230cf3aa24f3883b8b165bd5fd56620a9a95e47.tar.gz
rockbox-b230cf3aa24f3883b8b165bd5fd56620a9a95e47.zip
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
Diffstat (limited to 'rbutil/rbutilqt/quazip/quazipfile.cpp')
-rw-r--r--rbutil/rbutilqt/quazip/quazipfile.cpp385
1 files changed, 255 insertions, 130 deletions
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 <http://www.gnu.org/licenses/>.
+
+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<QuaZipFilePrivate*>(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();
+}