| /* |
| -- 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. |
| **/ |
| |
| #include "quazipfile.h" |
| |
| using namespace std; |
| |
| QuaZipFile::QuaZipFile(): |
| zip(NULL), internal(true), zipError(UNZ_OK) |
| { |
| } |
| |
| QuaZipFile::QuaZipFile(QObject *parent): |
| QIODevice(parent), zip(NULL), internal(true), zipError(UNZ_OK) |
| { |
| } |
| |
| QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent): |
| QIODevice(parent), internal(true), zipError(UNZ_OK) |
| { |
| 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) |
| { |
| 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) |
| { |
| } |
| |
| QuaZipFile::~QuaZipFile() |
| { |
| if(isOpen()) close(); |
| if(internal) delete zip; |
| } |
| |
| QString QuaZipFile::getZipName()const |
| { |
| return zip==NULL?QString():zip->getZipName(); |
| } |
| |
| QString QuaZipFile::getActualFileName()const |
| { |
| setZipError(UNZ_OK); |
| if(zip==NULL||(openMode()&WriteOnly)) return QString(); |
| QString name=zip->getCurrentFileName(); |
| if(name.isNull()) |
| setZipError(zip->getZipError()); |
| return name; |
| } |
| |
| void QuaZipFile::setZipName(const QString& zipName) |
| { |
| if(isOpen()) { |
| 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; |
| } |
| |
| void QuaZipFile::setZip(QuaZip *zip) |
| { |
| if(isOpen()) { |
| 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; |
| } |
| |
| void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs) |
| { |
| if(zip==NULL) { |
| qWarning("QuaZipFile::setFileName(): call setZipName() first"); |
| return; |
| } |
| if(!internal) { |
| qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip"); |
| return; |
| } |
| if(isOpen()) { |
| qWarning("QuaZipFile::setFileName(): can not set file name for already opened file"); |
| return; |
| } |
| this->fileName=fileName; |
| this->caseSensitivity=cs; |
| } |
| |
| void QuaZipFile::setZipError(int zipError)const |
| { |
| QuaZipFile *fakeThis=(QuaZipFile*)this; // non-const |
| fakeThis->zipError=zipError; |
| if(zipError==UNZ_OK) |
| fakeThis->setErrorString(QString()); |
| else |
| fakeThis->setErrorString(tr("ZIP/UNZIP API error %1").arg(zipError)); |
| } |
| |
| bool QuaZipFile::open(OpenMode mode) |
| { |
| return open(mode, NULL); |
| } |
| |
| bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password) |
| { |
| resetZipError(); |
| if(isOpen()) { |
| qWarning("QuaZipFile::open(): already opened"); |
| return false; |
| } |
| if(mode&Unbuffered) { |
| qWarning("QuaZipFile::open(): Unbuffered mode is not supported"); |
| return false; |
| } |
| if((mode&ReadOnly)&&!(mode&WriteOnly)) { |
| if(internal) { |
| if(!zip->open(QuaZip::mdUnzip)) { |
| setZipError(zip->getZipError()); |
| return false; |
| } |
| if(!zip->setCurrentFile(fileName, caseSensitivity)) { |
| setZipError(zip->getZipError()); |
| zip->close(); |
| return false; |
| } |
| } else { |
| if(zip==NULL) { |
| qWarning("QuaZipFile::open(): zip is NULL"); |
| return false; |
| } |
| if(zip->getMode()!=QuaZip::mdUnzip) { |
| qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", |
| (int)mode, (int)zip->getMode()); |
| return false; |
| } |
| if(!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) { |
| setOpenMode(mode); |
| this->raw=raw; |
| return true; |
| } else |
| return false; |
| } |
| qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode); |
| return false; |
| } |
| |
| bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info, |
| const char *password, quint32 crc, |
| int method, int level, bool raw, |
| int windowBits, int memLevel, int strategy) |
| { |
| zip_fileinfo info_z; |
| resetZipError(); |
| if(isOpen()) { |
| qWarning("QuaZipFile::open(): already opened"); |
| return false; |
| } |
| if((mode&WriteOnly)&&!(mode&ReadOnly)) { |
| if(internal) { |
| qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach"); |
| return false; |
| } |
| if(zip==NULL) { |
| qWarning("QuaZipFile::open(): zip is NULL"); |
| return false; |
| } |
| if(zip->getMode()!=QuaZip::mdCreate&&zip->getMode()!=QuaZip::mdAppend&&zip->getMode()!=QuaZip::mdAdd) { |
| qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", |
| (int)mode, (int)zip->getMode()); |
| return false; |
| } |
| info_z.tmz_date.tm_year=info.dateTime.date().year(); |
| info_z.tmz_date.tm_mon=info.dateTime.date().month() - 1; |
| info_z.tmz_date.tm_mday=info.dateTime.date().day(); |
| info_z.tmz_date.tm_hour=info.dateTime.time().hour(); |
| info_z.tmz_date.tm_min=info.dateTime.time().minute(); |
| info_z.tmz_date.tm_sec=info.dateTime.time().second(); |
| 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, |
| info.extraLocal.constData(), info.extraLocal.length(), |
| info.extraGlobal.constData(), info.extraGlobal.length(), |
| zip->getCommentCodec()->fromUnicode(info.comment).constData(), |
| method, level, (int)raw, |
| windowBits, memLevel, strategy, |
| password, (uLong)crc)); |
| if(zipError==UNZ_OK) { |
| writePos=0; |
| setOpenMode(mode); |
| this->raw=raw; |
| if(raw) { |
| this->crc=crc; |
| this->uncompressedSize=info.uncompressedSize; |
| } |
| return true; |
| } else |
| return false; |
| } |
| qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode); |
| return false; |
| } |
| |
| bool QuaZipFile::isSequential()const |
| { |
| return true; |
| } |
| |
| qint64 QuaZipFile::pos()const |
| { |
| if(zip==NULL) { |
| qWarning("QuaZipFile::pos(): call setZipName() or setZip() first"); |
| return -1; |
| } |
| if(!isOpen()) { |
| qWarning("QuaZipFile::pos(): file is not open"); |
| return -1; |
| } |
| if(openMode()&ReadOnly) |
| return unztell(zip->getUnzFile()); |
| else |
| return writePos; |
| } |
| |
| bool QuaZipFile::atEnd()const |
| { |
| if(zip==NULL) { |
| qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first"); |
| return false; |
| } |
| if(!isOpen()) { |
| qWarning("QuaZipFile::atEnd(): file is not open"); |
| return false; |
| } |
| if(openMode()&ReadOnly) |
| return unzeof(zip->getUnzFile())==1; |
| else |
| return true; |
| } |
| |
| qint64 QuaZipFile::size()const |
| { |
| if(!isOpen()) { |
| qWarning("QuaZipFile::atEnd(): file is not open"); |
| return -1; |
| } |
| if(openMode()&ReadOnly) |
| return raw?csize():usize(); |
| else |
| return 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) |
| 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) |
| 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; |
| } |
| |
| void QuaZipFile::close() |
| { |
| resetZipError(); |
| if(zip==NULL||!zip->isOpen()) return; |
| if(!isOpen()) { |
| qWarning("QuaZipFile::close(): file isn't open"); |
| return; |
| } |
| if(openMode()&ReadOnly) |
| setZipError(unzCloseCurrentFile(zip->getUnzFile())); |
| else if(openMode()&WriteOnly) |
| if(isRaw()) setZipError(zipCloseFileInZipRaw(zip->getZipFile(), uncompressedSize, crc)); |
| else setZipError(zipCloseFileInZip(zip->getZipFile())); |
| else { |
| qWarning("Wrong open mode: %d", (int)openMode()); |
| return; |
| } |
| if(zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen); |
| else return; |
| if(internal) { |
| zip->close(); |
| setZipError(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); |
| 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; |
| else { |
| writePos+=maxSize; |
| return maxSize; |
| } |
| } |