Don't underflow the buffer in format_track_path() if it consists of whitespaces
[maemo-rb.git] / utils / themeeditor / quazip / quazipfile.cpp
blob0399d1dbd02044f9614bb209d7dbadd8cc2cc9fa
1 /*
2 -- A kind of "standard" GPL license statement --
3 QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package
4 Copyright (C) 2005-2007 Sergey A. Tachenov
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2 of the License, or (at your
9 option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 -- A kind of "standard" GPL license statement ends here --
22 See COPYING file for GPL.
24 You are also permitted to use QuaZIP under the terms of LGPL (see
25 COPYING.LGPL). You are free to choose either license, but please note
26 that QuaZIP makes use of Qt, which is not licensed under LGPL. So if
27 you are using Open Source edition of Qt, you therefore MUST use GPL for
28 your code based on QuaZIP, since it would be also based on Qt in this
29 case. If you are Qt commercial license owner, then you are free to use
30 QuaZIP as long as you respect either GPL or LGPL for QuaZIP code.
31 **/
33 #include "quazipfile.h"
35 using namespace std;
37 QuaZipFile::QuaZipFile():
38 zip(NULL), internal(true), zipError(UNZ_OK)
42 QuaZipFile::QuaZipFile(QObject *parent):
43 QIODevice(parent), zip(NULL), internal(true), zipError(UNZ_OK)
47 QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent):
48 QIODevice(parent), internal(true), zipError(UNZ_OK)
50 zip=new QuaZip(zipName);
51 Q_CHECK_PTR(zip);
54 QuaZipFile::QuaZipFile(const QString& zipName, const QString& fileName,
55 QuaZip::CaseSensitivity cs, QObject *parent):
56 QIODevice(parent), internal(true), zipError(UNZ_OK)
58 zip=new QuaZip(zipName);
59 Q_CHECK_PTR(zip);
60 this->fileName=fileName;
61 this->caseSensitivity=cs;
64 QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent):
65 QIODevice(parent),
66 zip(zip), internal(false),
67 zipError(UNZ_OK)
71 QuaZipFile::~QuaZipFile()
73 if(isOpen()) close();
74 if(internal) delete zip;
77 QString QuaZipFile::getZipName()const
79 return zip==NULL?QString():zip->getZipName();
82 QString QuaZipFile::getActualFileName()const
84 setZipError(UNZ_OK);
85 if(zip==NULL||(openMode()&WriteOnly)) return QString();
86 QString name=zip->getCurrentFileName();
87 if(name.isNull())
88 setZipError(zip->getZipError());
89 return name;
92 void QuaZipFile::setZipName(const QString& zipName)
94 if(isOpen()) {
95 qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name");
96 return;
98 if(zip!=NULL&&internal) delete zip;
99 zip=new QuaZip(zipName);
100 Q_CHECK_PTR(zip);
101 internal=true;
104 void QuaZipFile::setZip(QuaZip *zip)
106 if(isOpen()) {
107 qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP");
108 return;
110 if(this->zip!=NULL&&internal) delete this->zip;
111 this->zip=zip;
112 this->fileName=QString();
113 internal=false;
116 void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs)
118 if(zip==NULL) {
119 qWarning("QuaZipFile::setFileName(): call setZipName() first");
120 return;
122 if(!internal) {
123 qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip");
124 return;
126 if(isOpen()) {
127 qWarning("QuaZipFile::setFileName(): can not set file name for already opened file");
128 return;
130 this->fileName=fileName;
131 this->caseSensitivity=cs;
134 void QuaZipFile::setZipError(int zipError)const
136 QuaZipFile *fakeThis=(QuaZipFile*)this; // non-const
137 fakeThis->zipError=zipError;
138 if(zipError==UNZ_OK)
139 fakeThis->setErrorString(QString());
140 else
141 fakeThis->setErrorString(tr("ZIP/UNZIP API error %1").arg(zipError));
144 bool QuaZipFile::open(OpenMode mode)
146 return open(mode, NULL);
149 bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password)
151 resetZipError();
152 if(isOpen()) {
153 qWarning("QuaZipFile::open(): already opened");
154 return false;
156 if(mode&Unbuffered) {
157 qWarning("QuaZipFile::open(): Unbuffered mode is not supported");
158 return false;
160 if((mode&ReadOnly)&&!(mode&WriteOnly)) {
161 if(internal) {
162 if(!zip->open(QuaZip::mdUnzip)) {
163 setZipError(zip->getZipError());
164 return false;
166 if(!zip->setCurrentFile(fileName, caseSensitivity)) {
167 setZipError(zip->getZipError());
168 zip->close();
169 return false;
171 } else {
172 if(zip==NULL) {
173 qWarning("QuaZipFile::open(): zip is NULL");
174 return false;
176 if(zip->getMode()!=QuaZip::mdUnzip) {
177 qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d",
178 (int)mode, (int)zip->getMode());
179 return false;
181 if(!zip->hasCurrentFile()) {
182 qWarning("QuaZipFile::open(): zip does not have current file");
183 return false;
186 setZipError(unzOpenCurrentFile3(zip->getUnzFile(), method, level, (int)raw, password));
187 if(zipError==UNZ_OK) {
188 setOpenMode(mode);
189 this->raw=raw;
190 return true;
191 } else
192 return false;
194 qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode);
195 return false;
198 bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info,
199 const char *password, quint32 crc,
200 int method, int level, bool raw,
201 int windowBits, int memLevel, int strategy)
203 zip_fileinfo info_z;
204 resetZipError();
205 if(isOpen()) {
206 qWarning("QuaZipFile::open(): already opened");
207 return false;
209 if((mode&WriteOnly)&&!(mode&ReadOnly)) {
210 if(internal) {
211 qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach");
212 return false;
214 if(zip==NULL) {
215 qWarning("QuaZipFile::open(): zip is NULL");
216 return false;
218 if(zip->getMode()!=QuaZip::mdCreate&&zip->getMode()!=QuaZip::mdAppend&&zip->getMode()!=QuaZip::mdAdd) {
219 qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d",
220 (int)mode, (int)zip->getMode());
221 return false;
223 info_z.tmz_date.tm_year=info.dateTime.date().year();
224 info_z.tmz_date.tm_mon=info.dateTime.date().month() - 1;
225 info_z.tmz_date.tm_mday=info.dateTime.date().day();
226 info_z.tmz_date.tm_hour=info.dateTime.time().hour();
227 info_z.tmz_date.tm_min=info.dateTime.time().minute();
228 info_z.tmz_date.tm_sec=info.dateTime.time().second();
229 info_z.dosDate = 0;
230 info_z.internal_fa=(uLong)info.internalAttr;
231 info_z.external_fa=(uLong)info.externalAttr;
232 setZipError(zipOpenNewFileInZip3(zip->getZipFile(),
233 zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z,
234 info.extraLocal.constData(), info.extraLocal.length(),
235 info.extraGlobal.constData(), info.extraGlobal.length(),
236 zip->getCommentCodec()->fromUnicode(info.comment).constData(),
237 method, level, (int)raw,
238 windowBits, memLevel, strategy,
239 password, (uLong)crc));
240 if(zipError==UNZ_OK) {
241 writePos=0;
242 setOpenMode(mode);
243 this->raw=raw;
244 if(raw) {
245 this->crc=crc;
246 this->uncompressedSize=info.uncompressedSize;
248 return true;
249 } else
250 return false;
252 qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode);
253 return false;
256 bool QuaZipFile::isSequential()const
258 return true;
261 qint64 QuaZipFile::pos()const
263 if(zip==NULL) {
264 qWarning("QuaZipFile::pos(): call setZipName() or setZip() first");
265 return -1;
267 if(!isOpen()) {
268 qWarning("QuaZipFile::pos(): file is not open");
269 return -1;
271 if(openMode()&ReadOnly)
272 return unztell(zip->getUnzFile());
273 else
274 return writePos;
277 bool QuaZipFile::atEnd()const
279 if(zip==NULL) {
280 qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first");
281 return false;
283 if(!isOpen()) {
284 qWarning("QuaZipFile::atEnd(): file is not open");
285 return false;
287 if(openMode()&ReadOnly)
288 return unzeof(zip->getUnzFile())==1;
289 else
290 return true;
293 qint64 QuaZipFile::size()const
295 if(!isOpen()) {
296 qWarning("QuaZipFile::atEnd(): file is not open");
297 return -1;
299 if(openMode()&ReadOnly)
300 return raw?csize():usize();
301 else
302 return writePos;
305 qint64 QuaZipFile::csize()const
307 unz_file_info info_z;
308 setZipError(UNZ_OK);
309 if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1;
310 setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0));
311 if(zipError!=UNZ_OK)
312 return -1;
313 return info_z.compressed_size;
316 qint64 QuaZipFile::usize()const
318 unz_file_info info_z;
319 setZipError(UNZ_OK);
320 if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1;
321 setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0));
322 if(zipError!=UNZ_OK)
323 return -1;
324 return info_z.uncompressed_size;
327 bool QuaZipFile::getFileInfo(QuaZipFileInfo *info)
329 if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return false;
330 zip->getCurrentFileInfo(info);
331 setZipError(zip->getZipError());
332 return zipError==UNZ_OK;
335 void QuaZipFile::close()
337 resetZipError();
338 if(zip==NULL||!zip->isOpen()) return;
339 if(!isOpen()) {
340 qWarning("QuaZipFile::close(): file isn't open");
341 return;
343 if(openMode()&ReadOnly)
344 setZipError(unzCloseCurrentFile(zip->getUnzFile()));
345 else if(openMode()&WriteOnly)
346 if(isRaw()) setZipError(zipCloseFileInZipRaw(zip->getZipFile(), uncompressedSize, crc));
347 else setZipError(zipCloseFileInZip(zip->getZipFile()));
348 else {
349 qWarning("Wrong open mode: %d", (int)openMode());
350 return;
352 if(zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen);
353 else return;
354 if(internal) {
355 zip->close();
356 setZipError(zip->getZipError());
360 qint64 QuaZipFile::readData(char *data, qint64 maxSize)
362 setZipError(UNZ_OK);
363 qint64 bytesRead=unzReadCurrentFile(zip->getUnzFile(), data, (unsigned)maxSize);
364 if(bytesRead<0) setZipError((int)bytesRead);
365 return bytesRead;
368 qint64 QuaZipFile::writeData(const char* data, qint64 maxSize)
370 setZipError(ZIP_OK);
371 setZipError(zipWriteInFileInZip(zip->getZipFile(), data, (uint)maxSize));
372 if(zipError!=ZIP_OK) return -1;
373 else {
374 writePos+=maxSize;
375 return maxSize;