5752
+ − 1
/*
+ − 2
Copyright (C) 2005-2011 Sergey A. Tachenov
+ − 3
+ − 4
This program is free software; you can redistribute it and/or modify it
+ − 5
under the terms of the GNU Lesser General Public License as published by
+ − 6
the Free Software Foundation; either version 2 of the License, or (at
+ − 7
your option) any later version.
+ − 8
+ − 9
This program is distributed in the hope that it will be useful, but
+ − 10
WITHOUT ANY WARRANTY; without even the implied warranty of
+ − 11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ − 12
General Public License for more details.
+ − 13
+ − 14
You should have received a copy of the GNU Lesser General Public License
+ − 15
along with this program; if not, write to the Free Software Foundation,
+ − 16
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ − 17
+ − 18
See COPYING file for the full LGPL text.
+ − 19
+ − 20
Original ZIP package is copyrighted by Gilles Vollant, see
+ − 21
quazip/(un)zip.h files for details, basically it's zlib license.
+ − 22
**/
+ − 23
+ − 24
#include "quazipfile.h"
+ − 25
+ − 26
using namespace std;
+ − 27
+ − 28
class QuaZipFilePrivate {
+ − 29
friend class QuaZipFile;
+ − 30
private:
+ − 31
QuaZipFile *q;
+ − 32
QuaZip *zip;
+ − 33
QString fileName;
+ − 34
QuaZip::CaseSensitivity caseSensitivity;
+ − 35
bool raw;
+ − 36
qint64 writePos;
+ − 37
// these two are for writing raw files
+ − 38
ulong uncompressedSize;
+ − 39
quint32 crc;
+ − 40
bool internal;
+ − 41
int zipError;
+ − 42
inline void resetZipError() const {setZipError(UNZ_OK);}
+ − 43
// const, but sets zipError!
+ − 44
void setZipError(int zipError) const;
+ − 45
inline QuaZipFilePrivate(QuaZipFile *q):
+ − 46
q(q), zip(NULL), internal(true), zipError(UNZ_OK) {}
+ − 47
inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName):
+ − 48
q(q), internal(true), zipError(UNZ_OK)
+ − 49
{
+ − 50
zip=new QuaZip(zipName);
+ − 51
}
+ − 52
inline QuaZipFilePrivate(QuaZipFile *q, const QString &zipName, const QString &fileName,
+ − 53
QuaZip::CaseSensitivity cs):
+ − 54
q(q), internal(true), zipError(UNZ_OK)
+ − 55
{
+ − 56
zip=new QuaZip(zipName);
+ − 57
this->fileName=fileName;
+ − 58
this->caseSensitivity=cs;
+ − 59
}
+ − 60
inline QuaZipFilePrivate(QuaZipFile *q, QuaZip *zip):
+ − 61
q(q), zip(zip), internal(false), zipError(UNZ_OK) {}
+ − 62
inline ~QuaZipFilePrivate()
+ − 63
{
+ − 64
if (internal)
+ − 65
delete zip;
+ − 66
}
+ − 67
};
+ − 68
+ − 69
QuaZipFile::QuaZipFile():
+ − 70
p(new QuaZipFilePrivate(this))
+ − 71
{
+ − 72
}
+ − 73
+ − 74
QuaZipFile::QuaZipFile(QObject *parent):
+ − 75
QIODevice(parent),
+ − 76
p(new QuaZipFilePrivate(this))
+ − 77
{
+ − 78
}
+ − 79
+ − 80
QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent):
+ − 81
QIODevice(parent),
+ − 82
p(new QuaZipFilePrivate(this, zipName))
+ − 83
{
+ − 84
}
+ − 85
+ − 86
QuaZipFile::QuaZipFile(const QString& zipName, const QString& fileName,
+ − 87
QuaZip::CaseSensitivity cs, QObject *parent):
+ − 88
QIODevice(parent),
+ − 89
p(new QuaZipFilePrivate(this, zipName, fileName, cs))
+ − 90
{
+ − 91
}
+ − 92
+ − 93
QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent):
+ − 94
QIODevice(parent),
+ − 95
p(new QuaZipFilePrivate(this, zip))
+ − 96
{
+ − 97
}
+ − 98
+ − 99
QuaZipFile::~QuaZipFile()
+ − 100
{
+ − 101
if (isOpen())
+ − 102
close();
+ − 103
delete p;
+ − 104
}
+ − 105
+ − 106
QString QuaZipFile::getZipName() const
+ − 107
{
+ − 108
return p->zip==NULL ? QString() : p->zip->getZipName();
+ − 109
}
+ − 110
+ − 111
QString QuaZipFile::getActualFileName()const
+ − 112
{
+ − 113
p->setZipError(UNZ_OK);
+ − 114
if (p->zip == NULL || (openMode() & WriteOnly))
+ − 115
return QString();
+ − 116
QString name=p->zip->getCurrentFileName();
+ − 117
if(name.isNull())
+ − 118
p->setZipError(p->zip->getZipError());
+ − 119
return name;
+ − 120
}
+ − 121
+ − 122
void QuaZipFile::setZipName(const QString& zipName)
+ − 123
{
+ − 124
if(isOpen()) {
+ − 125
qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name");
+ − 126
return;
+ − 127
}
+ − 128
if(p->zip!=NULL && p->internal)
+ − 129
delete p->zip;
+ − 130
p->zip=new QuaZip(zipName);
+ − 131
p->internal=true;
+ − 132
}
+ − 133
+ − 134
void QuaZipFile::setZip(QuaZip *zip)
+ − 135
{
+ − 136
if(isOpen()) {
+ − 137
qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP");
+ − 138
return;
+ − 139
}
+ − 140
if(p->zip!=NULL && p->internal)
+ − 141
delete p->zip;
+ − 142
p->zip=zip;
+ − 143
p->fileName=QString();
+ − 144
p->internal=false;
+ − 145
}
+ − 146
+ − 147
void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs)
+ − 148
{
+ − 149
if(p->zip==NULL) {
+ − 150
qWarning("QuaZipFile::setFileName(): call setZipName() first");
+ − 151
return;
+ − 152
}
+ − 153
if(!p->internal) {
+ − 154
qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip");
+ − 155
return;
+ − 156
}
+ − 157
if(isOpen()) {
+ − 158
qWarning("QuaZipFile::setFileName(): can not set file name for already opened file");
+ − 159
return;
+ − 160
}
+ − 161
p->fileName=fileName;
+ − 162
p->caseSensitivity=cs;
+ − 163
}
+ − 164
+ − 165
void QuaZipFilePrivate::setZipError(int zipError) const
+ − 166
{
+ − 167
QuaZipFilePrivate *fakeThis = const_cast<QuaZipFilePrivate*>(this); // non-const
+ − 168
fakeThis->zipError=zipError;
+ − 169
if(zipError==UNZ_OK)
+ − 170
q->setErrorString(QString());
+ − 171
else
+ − 172
q->setErrorString(q->tr("ZIP/UNZIP API error %1").arg(zipError));
+ − 173
}
+ − 174
+ − 175
bool QuaZipFile::open(OpenMode mode)
+ − 176
{
+ − 177
return open(mode, NULL);
+ − 178
}
+ − 179
+ − 180
bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password)
+ − 181
{
+ − 182
p->resetZipError();
+ − 183
if(isOpen()) {
+ − 184
qWarning("QuaZipFile::open(): already opened");
+ − 185
return false;
+ − 186
}
+ − 187
if(mode&Unbuffered) {
+ − 188
qWarning("QuaZipFile::open(): Unbuffered mode is not supported");
+ − 189
return false;
+ − 190
}
+ − 191
if((mode&ReadOnly)&&!(mode&WriteOnly)) {
+ − 192
if(p->internal) {
+ − 193
if(!p->zip->open(QuaZip::mdUnzip)) {
+ − 194
p->setZipError(p->zip->getZipError());
+ − 195
return false;
+ − 196
}
+ − 197
if(!p->zip->setCurrentFile(p->fileName, p->caseSensitivity)) {
+ − 198
p->setZipError(p->zip->getZipError());
+ − 199
p->zip->close();
+ − 200
return false;
+ − 201
}
+ − 202
} else {
+ − 203
if(p->zip==NULL) {
+ − 204
qWarning("QuaZipFile::open(): zip is NULL");
+ − 205
return false;
+ − 206
}
+ − 207
if(p->zip->getMode()!=QuaZip::mdUnzip) {
+ − 208
qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d",
+ − 209
(int)mode, (int)p->zip->getMode());
+ − 210
return false;
+ − 211
}
+ − 212
if(!p->zip->hasCurrentFile()) {
+ − 213
qWarning("QuaZipFile::open(): zip does not have current file");
+ − 214
return false;
+ − 215
}
+ − 216
}
+ − 217
p->setZipError(unzOpenCurrentFile3(p->zip->getUnzFile(), method, level, (int)raw, password));
+ − 218
if(p->zipError==UNZ_OK) {
+ − 219
setOpenMode(mode);
+ − 220
p->raw=raw;
+ − 221
return true;
+ − 222
} else
+ − 223
return false;
+ − 224
}
+ − 225
qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode);
+ − 226
return false;
+ − 227
}
+ − 228
+ − 229
bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info,
+ − 230
const char *password, quint32 crc,
+ − 231
int method, int level, bool raw,
+ − 232
int windowBits, int memLevel, int strategy)
+ − 233
{
+ − 234
zip_fileinfo info_z;
+ − 235
p->resetZipError();
+ − 236
if(isOpen()) {
+ − 237
qWarning("QuaZipFile::open(): already opened");
+ − 238
return false;
+ − 239
}
+ − 240
if((mode&WriteOnly)&&!(mode&ReadOnly)) {
+ − 241
if(p->internal) {
+ − 242
qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach");
+ − 243
return false;
+ − 244
}
+ − 245
if(p->zip==NULL) {
+ − 246
qWarning("QuaZipFile::open(): zip is NULL");
+ − 247
return false;
+ − 248
}
+ − 249
if(p->zip->getMode()!=QuaZip::mdCreate&&p->zip->getMode()!=QuaZip::mdAppend&&p->zip->getMode()!=QuaZip::mdAdd) {
+ − 250
qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d",
+ − 251
(int)mode, (int)p->zip->getMode());
+ − 252
return false;
+ − 253
}
+ − 254
info_z.tmz_date.tm_year=info.dateTime.date().year();
+ − 255
info_z.tmz_date.tm_mon=info.dateTime.date().month() - 1;
+ − 256
info_z.tmz_date.tm_mday=info.dateTime.date().day();
+ − 257
info_z.tmz_date.tm_hour=info.dateTime.time().hour();
+ − 258
info_z.tmz_date.tm_min=info.dateTime.time().minute();
+ − 259
info_z.tmz_date.tm_sec=info.dateTime.time().second();
+ − 260
info_z.dosDate = 0;
+ − 261
info_z.internal_fa=(uLong)info.internalAttr;
+ − 262
info_z.external_fa=(uLong)info.externalAttr;
+ − 263
p->setZipError(zipOpenNewFileInZip3(p->zip->getZipFile(),
+ − 264
p->zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z,
+ − 265
info.extraLocal.constData(), info.extraLocal.length(),
+ − 266
info.extraGlobal.constData(), info.extraGlobal.length(),
+ − 267
p->zip->getCommentCodec()->fromUnicode(info.comment).constData(),
+ − 268
method, level, (int)raw,
+ − 269
windowBits, memLevel, strategy,
+ − 270
password, (uLong)crc));
+ − 271
if(p->zipError==UNZ_OK) {
+ − 272
p->writePos=0;
+ − 273
setOpenMode(mode);
+ − 274
p->raw=raw;
+ − 275
if(raw) {
+ − 276
p->crc=crc;
+ − 277
p->uncompressedSize=info.uncompressedSize;
+ − 278
}
+ − 279
return true;
+ − 280
} else
+ − 281
return false;
+ − 282
}
+ − 283
qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode);
+ − 284
return false;
+ − 285
}
+ − 286
+ − 287
bool QuaZipFile::isSequential()const
+ − 288
{
+ − 289
return true;
+ − 290
}
+ − 291
+ − 292
qint64 QuaZipFile::pos()const
+ − 293
{
+ − 294
if(p->zip==NULL) {
+ − 295
qWarning("QuaZipFile::pos(): call setZipName() or setZip() first");
+ − 296
return -1;
+ − 297
}
+ − 298
if(!isOpen()) {
+ − 299
qWarning("QuaZipFile::pos(): file is not open");
+ − 300
return -1;
+ − 301
}
+ − 302
if(openMode()&ReadOnly)
+ − 303
return unztell(p->zip->getUnzFile());
+ − 304
else
+ − 305
return p->writePos;
+ − 306
}
+ − 307
+ − 308
bool QuaZipFile::atEnd()const
+ − 309
{
+ − 310
if(p->zip==NULL) {
+ − 311
qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first");
+ − 312
return false;
+ − 313
}
+ − 314
if(!isOpen()) {
+ − 315
qWarning("QuaZipFile::atEnd(): file is not open");
+ − 316
return false;
+ − 317
}
+ − 318
if(openMode()&ReadOnly)
+ − 319
return unzeof(p->zip->getUnzFile())==1;
+ − 320
else
+ − 321
return true;
+ − 322
}
+ − 323
+ − 324
qint64 QuaZipFile::size()const
+ − 325
{
+ − 326
if(!isOpen()) {
+ − 327
qWarning("QuaZipFile::atEnd(): file is not open");
+ − 328
return -1;
+ − 329
}
+ − 330
if(openMode()&ReadOnly)
+ − 331
return p->raw?csize():usize();
+ − 332
else
+ − 333
return p->writePos;
+ − 334
}
+ − 335
+ − 336
qint64 QuaZipFile::csize()const
+ − 337
{
+ − 338
unz_file_info info_z;
+ − 339
p->setZipError(UNZ_OK);
+ − 340
if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1;
+ − 341
p->setZipError(unzGetCurrentFileInfo(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0));
+ − 342
if(p->zipError!=UNZ_OK)
+ − 343
return -1;
+ − 344
return info_z.compressed_size;
+ − 345
}
+ − 346
+ − 347
qint64 QuaZipFile::usize()const
+ − 348
{
+ − 349
unz_file_info info_z;
+ − 350
p->setZipError(UNZ_OK);
+ − 351
if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1;
+ − 352
p->setZipError(unzGetCurrentFileInfo(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0));
+ − 353
if(p->zipError!=UNZ_OK)
+ − 354
return -1;
+ − 355
return info_z.uncompressed_size;
+ − 356
}
+ − 357
+ − 358
bool QuaZipFile::getFileInfo(QuaZipFileInfo *info)
+ − 359
{
+ − 360
if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return false;
+ − 361
p->zip->getCurrentFileInfo(info);
+ − 362
p->setZipError(p->zip->getZipError());
+ − 363
return p->zipError==UNZ_OK;
+ − 364
}
+ − 365
+ − 366
void QuaZipFile::close()
+ − 367
{
+ − 368
p->resetZipError();
+ − 369
if(p->zip==NULL||!p->zip->isOpen()) return;
+ − 370
if(!isOpen()) {
+ − 371
qWarning("QuaZipFile::close(): file isn't open");
+ − 372
return;
+ − 373
}
+ − 374
if(openMode()&ReadOnly)
+ − 375
p->setZipError(unzCloseCurrentFile(p->zip->getUnzFile()));
+ − 376
else if(openMode()&WriteOnly)
+ − 377
if(isRaw()) p->setZipError(zipCloseFileInZipRaw(p->zip->getZipFile(), p->uncompressedSize, p->crc));
+ − 378
else p->setZipError(zipCloseFileInZip(p->zip->getZipFile()));
+ − 379
else {
+ − 380
qWarning("Wrong open mode: %d", (int)openMode());
+ − 381
return;
+ − 382
}
+ − 383
if(p->zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen);
+ − 384
else return;
+ − 385
if(p->internal) {
+ − 386
p->zip->close();
+ − 387
p->setZipError(p->zip->getZipError());
+ − 388
}
+ − 389
}
+ − 390
+ − 391
qint64 QuaZipFile::readData(char *data, qint64 maxSize)
+ − 392
{
+ − 393
p->setZipError(UNZ_OK);
+ − 394
qint64 bytesRead=unzReadCurrentFile(p->zip->getUnzFile(), data, (unsigned)maxSize);
+ − 395
if(bytesRead<0) p->setZipError((int)bytesRead);
+ − 396
return bytesRead;
+ − 397
}
+ − 398
+ − 399
qint64 QuaZipFile::writeData(const char* data, qint64 maxSize)
+ − 400
{
+ − 401
p->setZipError(ZIP_OK);
+ − 402
p->setZipError(zipWriteInFileInZip(p->zip->getZipFile(), data, (uint)maxSize));
+ − 403
if(p->zipError!=ZIP_OK) return -1;
+ − 404
else {
+ − 405
p->writePos+=maxSize;
+ − 406
return maxSize;
+ − 407
}
+ − 408
}
+ − 409
+ − 410
QString QuaZipFile::getFileName() const
+ − 411
{
+ − 412
return p->fileName;
+ − 413
}
+ − 414
+ − 415
QuaZip::CaseSensitivity QuaZipFile::getCaseSensitivity() const
+ − 416
{
+ − 417
return p->caseSensitivity;
+ − 418
}
+ − 419
+ − 420
bool QuaZipFile::isRaw() const
+ − 421
{
+ − 422
return p->raw;
+ − 423
}
+ − 424
+ − 425
int QuaZipFile::getZipError() const
+ − 426
{
+ − 427
return p->zipError;
+ − 428
}