/* * 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 **/ #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 -1; } 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; } }