File indexing completed on 2025-02-02 04:36:33

0001 /*
0002 Copyright (C) 2005-2014 Sergey A. Tachenov
0003 
0004 This file is part of QuaZIP.
0005 
0006 QuaZIP is free software: you can redistribute it and/or modify
0007 it under the terms of the GNU Lesser General Public License as published by
0008 the Free Software Foundation, either version 2.1 of the License, or
0009 (at your option) any later version.
0010 
0011 QuaZIP is distributed in the hope that it will be useful,
0012 but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 GNU Lesser General Public License for more details.
0015 
0016 You should have received a copy of the GNU Lesser General Public License
0017 along with QuaZIP.  If not, see <http://www.gnu.org/licenses/>.
0018 
0019 See COPYING file for the full LGPL text.
0020 
0021 Original ZIP package is copyrighted by Gilles Vollant, see
0022 quazip/(un)zip.h files for details, basically it's zlib license.
0023  **/
0024 
0025 #include <QFile>
0026 #include <QFlags>
0027 #include <QHash>
0028 
0029 #include "quazip.h"
0030 
0031 /// All the internal stuff for the QuaZip class.
0032 /**
0033   \internal
0034 
0035   This class keeps all the private stuff for the QuaZip class so it can
0036   be changed without breaking binary compatibility, according to the
0037   Pimpl idiom.
0038   */
0039 class QuaZipPrivate {
0040   friend class QuaZip;
0041   private:
0042     Q_DISABLE_COPY(QuaZipPrivate)
0043     /// The pointer to the corresponding QuaZip instance.
0044     QuaZip *q;
0045     /// The codec for file names.
0046     QTextCodec *fileNameCodec;
0047     /// The codec for comments.
0048     QTextCodec *commentCodec;
0049     /// The archive file name.
0050     QString zipName;
0051     /// The device to access the archive.
0052     QIODevice *ioDevice;
0053     /// The global comment.
0054     QString comment;
0055     /// The open mode.
0056     QuaZip::Mode mode;
0057     union {
0058       /// The internal handle for UNZIP modes.
0059       unzFile unzFile_f;
0060       /// The internal handle for ZIP modes.
0061       zipFile zipFile_f;
0062     };
0063     /// Whether a current file is set.
0064     bool hasCurrentFile_f;
0065     /// The last error.
0066     int zipError;
0067     /// Whether \ref QuaZip::setDataDescriptorWritingEnabled() "the data descriptor writing mode" is enabled.
0068     bool dataDescriptorWritingEnabled;
0069     /// The zip64 mode.
0070     bool zip64;
0071     /// The auto-close flag.
0072     bool autoClose;
0073     inline QTextCodec *getDefaultFileNameCodec()
0074     {
0075         if (defaultFileNameCodec == NULL) {
0076             return QTextCodec::codecForLocale();
0077         } else {
0078             return defaultFileNameCodec;
0079         }
0080     }
0081     /// The constructor for the corresponding QuaZip constructor.
0082     inline QuaZipPrivate(QuaZip *q):
0083       q(q),
0084       fileNameCodec(getDefaultFileNameCodec()),
0085       commentCodec(QTextCodec::codecForLocale()),
0086       ioDevice(NULL),
0087       mode(QuaZip::mdNotOpen),
0088       hasCurrentFile_f(false),
0089       zipError(UNZ_OK),
0090       dataDescriptorWritingEnabled(true),
0091       zip64(false),
0092       autoClose(true)
0093     {
0094         unzFile_f = NULL;
0095         zipFile_f = NULL;
0096         lastMappedDirectoryEntry.num_of_file = 0;
0097         lastMappedDirectoryEntry.pos_in_zip_directory = 0;
0098     }
0099     /// The constructor for the corresponding QuaZip constructor.
0100     inline QuaZipPrivate(QuaZip *q, const QString &zipName):
0101       q(q),
0102       fileNameCodec(getDefaultFileNameCodec()),
0103       commentCodec(QTextCodec::codecForLocale()),
0104       zipName(zipName),
0105       ioDevice(NULL),
0106       mode(QuaZip::mdNotOpen),
0107       hasCurrentFile_f(false),
0108       zipError(UNZ_OK),
0109       dataDescriptorWritingEnabled(true),
0110       zip64(false),
0111       autoClose(true)
0112     {
0113         unzFile_f = NULL;
0114         zipFile_f = NULL;
0115         lastMappedDirectoryEntry.num_of_file = 0;
0116         lastMappedDirectoryEntry.pos_in_zip_directory = 0;
0117     }
0118     /// The constructor for the corresponding QuaZip constructor.
0119     inline QuaZipPrivate(QuaZip *q, QIODevice *ioDevice):
0120         q(q),
0121       fileNameCodec(getDefaultFileNameCodec()),
0122       commentCodec(QTextCodec::codecForLocale()),
0123       ioDevice(ioDevice),
0124       mode(QuaZip::mdNotOpen),
0125       hasCurrentFile_f(false),
0126       zipError(UNZ_OK),
0127       dataDescriptorWritingEnabled(true),
0128       zip64(false),
0129       autoClose(true)
0130     {
0131         unzFile_f = NULL;
0132         zipFile_f = NULL;
0133         lastMappedDirectoryEntry.num_of_file = 0;
0134         lastMappedDirectoryEntry.pos_in_zip_directory = 0;
0135     }
0136     /// Returns either a list of file names or a list of QuaZipFileInfo.
0137     template<typename TFileInfo>
0138         bool getFileInfoList(QList<TFileInfo> *result) const;
0139 
0140     /// Stores map of filenames and file locations for unzipping
0141       inline void clearDirectoryMap();
0142       inline void addCurrentFileToDirectoryMap(const QString &fileName);
0143       bool goToFirstUnmappedFile();
0144       QHash<QString, unz64_file_pos> directoryCaseSensitive;
0145       QHash<QString, unz64_file_pos> directoryCaseInsensitive;
0146       unz64_file_pos lastMappedDirectoryEntry;
0147       static QTextCodec *defaultFileNameCodec;
0148 };
0149 
0150 QTextCodec *QuaZipPrivate::defaultFileNameCodec = NULL;
0151 
0152 void QuaZipPrivate::clearDirectoryMap()
0153 {
0154     directoryCaseInsensitive.clear();
0155     directoryCaseSensitive.clear();
0156     lastMappedDirectoryEntry.num_of_file = 0;
0157     lastMappedDirectoryEntry.pos_in_zip_directory = 0;
0158 }
0159 
0160 void QuaZipPrivate::addCurrentFileToDirectoryMap(const QString &fileName)
0161 {
0162     if (!hasCurrentFile_f || fileName.isEmpty()) {
0163         return;
0164     }
0165     // Adds current file to filename map as fileName
0166     unz64_file_pos fileDirectoryPos;
0167     unzGetFilePos64(unzFile_f, &fileDirectoryPos);
0168     directoryCaseSensitive.insert(fileName, fileDirectoryPos);
0169     // Only add lowercase to directory map if not already there
0170     // ensures only map the first one seen
0171     QString lower = fileName.toLower();
0172     if (!directoryCaseInsensitive.contains(lower))
0173         directoryCaseInsensitive.insert(lower, fileDirectoryPos);
0174     // Mark last one
0175     if (fileDirectoryPos.pos_in_zip_directory > lastMappedDirectoryEntry.pos_in_zip_directory)
0176         lastMappedDirectoryEntry = fileDirectoryPos;
0177 }
0178 
0179 bool QuaZipPrivate::goToFirstUnmappedFile()
0180 {
0181     zipError = UNZ_OK;
0182     if (mode != QuaZip::mdUnzip) {
0183         qWarning("QuaZipPrivate::goToNextUnmappedFile(): ZIP is not open in mdUnzip mode");
0184         return false;
0185     }
0186     // If not mapped anything, go to beginning
0187     if (lastMappedDirectoryEntry.pos_in_zip_directory == 0) {
0188         unzGoToFirstFile(unzFile_f);
0189     } else {
0190         // Goto the last one mapped, plus one
0191         unzGoToFilePos64(unzFile_f, &lastMappedDirectoryEntry);
0192         unzGoToNextFile(unzFile_f);
0193     }
0194     hasCurrentFile_f=zipError==UNZ_OK;
0195     if(zipError==UNZ_END_OF_LIST_OF_FILE)
0196       zipError=UNZ_OK;
0197     return hasCurrentFile_f;
0198 }
0199 
0200 QuaZip::QuaZip():
0201   p(new QuaZipPrivate(this))
0202 {
0203 }
0204 
0205 QuaZip::QuaZip(const QString& zipName):
0206   p(new QuaZipPrivate(this, zipName))
0207 {
0208 }
0209 
0210 QuaZip::QuaZip(QIODevice *ioDevice):
0211   p(new QuaZipPrivate(this, ioDevice))
0212 {
0213 }
0214 
0215 QuaZip::~QuaZip()
0216 {
0217   if(isOpen())
0218     close();
0219   delete p;
0220 }
0221 
0222 bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi)
0223 {
0224   p->zipError=UNZ_OK;
0225   if(isOpen()) {
0226     qWarning("QuaZip::open(): ZIP already opened");
0227     return false;
0228   }
0229   QIODevice *ioDevice = p->ioDevice;
0230   if (ioDevice == NULL) {
0231     if (p->zipName.isEmpty()) {
0232       qWarning("QuaZip::open(): set either ZIP file name or IO device first");
0233       return false;
0234     } else {
0235       ioDevice = new QFile(p->zipName);
0236     }
0237   }
0238   unsigned flags = 0;
0239   switch(mode) {
0240     case mdUnzip:
0241       if (ioApi == NULL) {
0242           if (p->autoClose)
0243               flags |= UNZ_AUTO_CLOSE;
0244           p->unzFile_f=unzOpenInternal(ioDevice, NULL, 1, flags);
0245       } else {
0246           // QuaZIP pre-zip64 compatibility mode
0247           p->unzFile_f=unzOpen2(ioDevice, ioApi);
0248           if (p->unzFile_f != NULL) {
0249               if (p->autoClose) {
0250                   unzSetFlags(p->unzFile_f, UNZ_AUTO_CLOSE);
0251               } else {
0252                   unzClearFlags(p->unzFile_f, UNZ_AUTO_CLOSE);
0253               }
0254           }
0255       }
0256       if(p->unzFile_f!=NULL) {
0257         if (ioDevice->isSequential()) {
0258             unzClose(p->unzFile_f);
0259             if (!p->zipName.isEmpty())
0260                 delete ioDevice;
0261             qWarning("QuaZip::open(): "
0262                      "only mdCreate can be used with "
0263                      "sequential devices");
0264             return false;
0265         }
0266         p->mode=mode;
0267         p->ioDevice = ioDevice;
0268         return true;
0269       } else {
0270         p->zipError=UNZ_OPENERROR;
0271         if (!p->zipName.isEmpty())
0272           delete ioDevice;
0273         return false;
0274       }
0275     case mdCreate:
0276     case mdAppend:
0277     case mdAdd:
0278       if (ioApi == NULL) {
0279           if (p->autoClose)
0280               flags |= ZIP_AUTO_CLOSE;
0281           if (p->dataDescriptorWritingEnabled)
0282               flags |= ZIP_WRITE_DATA_DESCRIPTOR;
0283           p->zipFile_f=zipOpen3(ioDevice,
0284               mode==mdCreate?APPEND_STATUS_CREATE:
0285               mode==mdAppend?APPEND_STATUS_CREATEAFTER:
0286               APPEND_STATUS_ADDINZIP,
0287               NULL, NULL, flags);
0288       } else {
0289           // QuaZIP pre-zip64 compatibility mode
0290           p->zipFile_f=zipOpen2(ioDevice,
0291               mode==mdCreate?APPEND_STATUS_CREATE:
0292               mode==mdAppend?APPEND_STATUS_CREATEAFTER:
0293               APPEND_STATUS_ADDINZIP,
0294               NULL,
0295               ioApi);
0296           if (p->zipFile_f != NULL) {
0297               zipSetFlags(p->zipFile_f, flags);
0298           }
0299       }
0300       if(p->zipFile_f!=NULL) {
0301         if (ioDevice->isSequential()) {
0302             if (mode != mdCreate) {
0303                 zipClose(p->zipFile_f, NULL);
0304                 qWarning("QuaZip::open(): "
0305                         "only mdCreate can be used with "
0306                          "sequential devices");
0307                 if (!p->zipName.isEmpty())
0308                     delete ioDevice;
0309                 return false;
0310             }
0311             zipSetFlags(p->zipFile_f, ZIP_SEQUENTIAL);
0312         }
0313         p->mode=mode;
0314         p->ioDevice = ioDevice;
0315         return true;
0316       } else {
0317         p->zipError=UNZ_OPENERROR;
0318         if (!p->zipName.isEmpty())
0319           delete ioDevice;
0320         return false;
0321       }
0322     default:
0323       qWarning("QuaZip::open(): unknown mode: %d", (int)mode);
0324       if (!p->zipName.isEmpty())
0325         delete ioDevice;
0326       return false;
0327       break;
0328   }
0329 }
0330 
0331 void QuaZip::close()
0332 {
0333   p->zipError=UNZ_OK;
0334   switch(p->mode) {
0335     case mdNotOpen:
0336       qWarning("QuaZip::close(): ZIP is not open");
0337       return;
0338     case mdUnzip:
0339       p->zipError=unzClose(p->unzFile_f);
0340       break;
0341     case mdCreate:
0342     case mdAppend:
0343     case mdAdd:
0344       p->zipError=zipClose(p->zipFile_f, 
0345           p->comment.isNull() ? NULL
0346           : p->commentCodec->fromUnicode(p->comment).constData());
0347       break;
0348     default:
0349       qWarning("QuaZip::close(): unknown mode: %d", (int)p->mode);
0350       return;
0351   }
0352   // opened by name, need to delete the internal IO device
0353   if (!p->zipName.isEmpty()) {
0354       delete p->ioDevice;
0355       p->ioDevice = NULL;
0356   }
0357   p->clearDirectoryMap();
0358   if(p->zipError==UNZ_OK)
0359     p->mode=mdNotOpen;
0360 }
0361 
0362 void QuaZip::setZipName(const QString& zipName)
0363 {
0364   if(isOpen()) {
0365     qWarning("QuaZip::setZipName(): ZIP is already open!");
0366     return;
0367   }
0368   p->zipName=zipName;
0369   p->ioDevice = NULL;
0370 }
0371 
0372 void QuaZip::setIoDevice(QIODevice *ioDevice)
0373 {
0374   if(isOpen()) {
0375     qWarning("QuaZip::setIoDevice(): ZIP is already open!");
0376     return;
0377   }
0378   p->ioDevice = ioDevice;
0379   p->zipName = QString();
0380 }
0381 
0382 int QuaZip::getEntriesCount()const
0383 {
0384   QuaZip *fakeThis=(QuaZip*)this; // non-const
0385   fakeThis->p->zipError=UNZ_OK;
0386   if(p->mode!=mdUnzip) {
0387     qWarning("QuaZip::getEntriesCount(): ZIP is not open in mdUnzip mode");
0388     return -1;
0389   }
0390   unz_global_info64 globalInfo;
0391   if((fakeThis->p->zipError=unzGetGlobalInfo64(p->unzFile_f, &globalInfo))!=UNZ_OK)
0392     return p->zipError;
0393   return (int)globalInfo.number_entry;
0394 }
0395 
0396 QString QuaZip::getComment()const
0397 {
0398   QuaZip *fakeThis=(QuaZip*)this; // non-const
0399   fakeThis->p->zipError=UNZ_OK;
0400   if(p->mode!=mdUnzip) {
0401     qWarning("QuaZip::getComment(): ZIP is not open in mdUnzip mode");
0402     return QString();
0403   }
0404   unz_global_info64 globalInfo;
0405   QByteArray comment;
0406   if((fakeThis->p->zipError=unzGetGlobalInfo64(p->unzFile_f, &globalInfo))!=UNZ_OK)
0407     return QString();
0408   comment.resize(globalInfo.size_comment);
0409   if((fakeThis->p->zipError=unzGetGlobalComment(p->unzFile_f, comment.data(), comment.size())) < 0)
0410     return QString();
0411   fakeThis->p->zipError = UNZ_OK;
0412   return p->commentCodec->toUnicode(comment);
0413 }
0414 
0415 bool QuaZip::setCurrentFile(const QString& fileName, CaseSensitivity cs)
0416 {
0417   p->zipError=UNZ_OK;
0418   if(p->mode!=mdUnzip) {
0419     qWarning("QuaZip::setCurrentFile(): ZIP is not open in mdUnzip mode");
0420     return false;
0421   }
0422   if(fileName.isEmpty()) {
0423     p->hasCurrentFile_f=false;
0424     return true;
0425   }
0426   // Unicode-aware reimplementation of the unzLocateFile function
0427   if(p->unzFile_f==NULL) {
0428     p->zipError=UNZ_PARAMERROR;
0429     return false;
0430   }
0431   if(fileName.length()>MAX_FILE_NAME_LENGTH) {
0432     p->zipError=UNZ_PARAMERROR;
0433     return false;
0434   }
0435   // Find the file by name
0436   bool sens = convertCaseSensitivity(cs) == Qt::CaseSensitive;
0437   QString lower, current;
0438   if(!sens) lower=fileName.toLower();
0439   p->hasCurrentFile_f=false;
0440 
0441   // Check the appropriate Map
0442   unz64_file_pos fileDirPos;
0443   fileDirPos.pos_in_zip_directory = 0;
0444   if (sens) {
0445       if (p->directoryCaseSensitive.contains(fileName))
0446           fileDirPos = p->directoryCaseSensitive.value(fileName);
0447   } else {
0448       if (p->directoryCaseInsensitive.contains(lower))
0449           fileDirPos = p->directoryCaseInsensitive.value(lower);
0450   }
0451 
0452   if (fileDirPos.pos_in_zip_directory != 0) {
0453       p->zipError = unzGoToFilePos64(p->unzFile_f, &fileDirPos);
0454       p->hasCurrentFile_f = p->zipError == UNZ_OK;
0455   }
0456 
0457   if (p->hasCurrentFile_f)
0458       return p->hasCurrentFile_f;
0459 
0460   // Not mapped yet, start from where we have got to so far
0461   for(bool more=p->goToFirstUnmappedFile(); more; more=goToNextFile()) {
0462     current=getCurrentFileName();
0463     if(current.isEmpty()) return false;
0464     if(sens) {
0465       if(current==fileName) break;
0466     } else {
0467       if(current.toLower()==lower) break;
0468     }
0469   }
0470   return p->hasCurrentFile_f;
0471 }
0472 
0473 bool QuaZip::goToFirstFile()
0474 {
0475   p->zipError=UNZ_OK;
0476   if(p->mode!=mdUnzip) {
0477     qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode");
0478     return false;
0479   }
0480   p->zipError=unzGoToFirstFile(p->unzFile_f);
0481   p->hasCurrentFile_f=p->zipError==UNZ_OK;
0482   return p->hasCurrentFile_f;
0483 }
0484 
0485 bool QuaZip::goToNextFile()
0486 {
0487   p->zipError=UNZ_OK;
0488   if(p->mode!=mdUnzip) {
0489     qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode");
0490     return false;
0491   }
0492   p->zipError=unzGoToNextFile(p->unzFile_f);
0493   p->hasCurrentFile_f=p->zipError==UNZ_OK;
0494   if(p->zipError==UNZ_END_OF_LIST_OF_FILE)
0495     p->zipError=UNZ_OK;
0496   return p->hasCurrentFile_f;
0497 }
0498 
0499 bool QuaZip::getCurrentFileInfo(QuaZipFileInfo *info)const
0500 {
0501     QuaZipFileInfo64 info64;
0502     if (info == NULL) { // Very unlikely because of the overloads
0503         return false;
0504     }
0505     if (getCurrentFileInfo(&info64)) {
0506         info64.toQuaZipFileInfo(*info);
0507         return true;
0508     } else {
0509         return false;
0510     }
0511 }
0512 
0513 bool QuaZip::getCurrentFileInfo(QuaZipFileInfo64 *info)const
0514 {
0515   QuaZip *fakeThis=(QuaZip*)this; // non-const
0516   fakeThis->p->zipError=UNZ_OK;
0517   if(p->mode!=mdUnzip) {
0518     qWarning("QuaZip::getCurrentFileInfo(): ZIP is not open in mdUnzip mode");
0519     return false;
0520   }
0521   unz_file_info64 info_z;
0522   QByteArray fileName;
0523   QByteArray extra;
0524   QByteArray comment;
0525   if(info==NULL) return false;
0526   if(!isOpen()||!hasCurrentFile()) return false;
0527   if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, &info_z, NULL, 0, NULL, 0, NULL, 0))!=UNZ_OK)
0528     return false;
0529   fileName.resize(info_z.size_filename);
0530   extra.resize(info_z.size_file_extra);
0531   comment.resize(info_z.size_file_comment);
0532   if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, NULL,
0533       fileName.data(), fileName.size(),
0534       extra.data(), extra.size(),
0535       comment.data(), comment.size()))!=UNZ_OK)
0536     return false;
0537   info->versionCreated=info_z.version;
0538   info->versionNeeded=info_z.version_needed;
0539   info->flags=info_z.flag;
0540   info->method=info_z.compression_method;
0541   info->crc=info_z.crc;
0542   info->compressedSize=info_z.compressed_size;
0543   info->uncompressedSize=info_z.uncompressed_size;
0544   info->diskNumberStart=info_z.disk_num_start;
0545   info->internalAttr=info_z.internal_fa;
0546   info->externalAttr=info_z.external_fa;
0547   info->name=p->fileNameCodec->toUnicode(fileName);
0548   info->comment=p->commentCodec->toUnicode(comment);
0549   info->extra=extra;
0550   info->dateTime=QDateTime(
0551       QDate(info_z.tmu_date.tm_year, info_z.tmu_date.tm_mon+1, info_z.tmu_date.tm_mday),
0552       QTime(info_z.tmu_date.tm_hour, info_z.tmu_date.tm_min, info_z.tmu_date.tm_sec));
0553   // Add to directory map
0554   p->addCurrentFileToDirectoryMap(info->name);
0555   return true;
0556 }
0557 
0558 QString QuaZip::getCurrentFileName()const
0559 {
0560   QuaZip *fakeThis=(QuaZip*)this; // non-const
0561   fakeThis->p->zipError=UNZ_OK;
0562   if(p->mode!=mdUnzip) {
0563     qWarning("QuaZip::getCurrentFileName(): ZIP is not open in mdUnzip mode");
0564     return QString();
0565   }
0566   if(!isOpen()||!hasCurrentFile()) return QString();
0567   QByteArray fileName(MAX_FILE_NAME_LENGTH, 0);
0568   if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, NULL, fileName.data(), fileName.size(),
0569       NULL, 0, NULL, 0))!=UNZ_OK)
0570     return QString();
0571   QString result = p->fileNameCodec->toUnicode(fileName.constData());
0572   if (result.isEmpty())
0573       return result;
0574   // Add to directory map
0575   p->addCurrentFileToDirectoryMap(result);
0576   return result;
0577 }
0578 
0579 void QuaZip::setFileNameCodec(QTextCodec *fileNameCodec)
0580 {
0581   p->fileNameCodec=fileNameCodec;
0582 }
0583 
0584 void QuaZip::setFileNameCodec(const char *fileNameCodecName)
0585 {
0586   p->fileNameCodec=QTextCodec::codecForName(fileNameCodecName);
0587 }
0588 
0589 QTextCodec *QuaZip::getFileNameCodec()const
0590 {
0591   return p->fileNameCodec;
0592 }
0593 
0594 void QuaZip::setCommentCodec(QTextCodec *commentCodec)
0595 {
0596   p->commentCodec=commentCodec;
0597 }
0598 
0599 void QuaZip::setCommentCodec(const char *commentCodecName)
0600 {
0601   p->commentCodec=QTextCodec::codecForName(commentCodecName);
0602 }
0603 
0604 QTextCodec *QuaZip::getCommentCodec()const
0605 {
0606   return p->commentCodec;
0607 }
0608 
0609 QString QuaZip::getZipName() const
0610 {
0611   return p->zipName;
0612 }
0613 
0614 QIODevice *QuaZip::getIoDevice() const
0615 {
0616   if (!p->zipName.isEmpty()) // opened by name, using an internal QIODevice
0617     return NULL;
0618   return p->ioDevice;
0619 }
0620 
0621 QuaZip::Mode QuaZip::getMode()const
0622 {
0623   return p->mode;
0624 }
0625 
0626 bool QuaZip::isOpen()const
0627 {
0628   return p->mode!=mdNotOpen;
0629 }
0630 
0631 int QuaZip::getZipError() const
0632 {
0633   return p->zipError;
0634 }
0635 
0636 void QuaZip::setComment(const QString& comment)
0637 {
0638   p->comment=comment;
0639 }
0640 
0641 bool QuaZip::hasCurrentFile()const
0642 {
0643   return p->hasCurrentFile_f;
0644 }
0645 
0646 unzFile QuaZip::getUnzFile()
0647 {
0648   return p->unzFile_f;
0649 }
0650 
0651 zipFile QuaZip::getZipFile()
0652 {
0653   return p->zipFile_f;
0654 }
0655 
0656 void QuaZip::setDataDescriptorWritingEnabled(bool enabled)
0657 {
0658     p->dataDescriptorWritingEnabled = enabled;
0659 }
0660 
0661 bool QuaZip::isDataDescriptorWritingEnabled() const
0662 {
0663     return p->dataDescriptorWritingEnabled;
0664 }
0665 
0666 template<typename TFileInfo>
0667 TFileInfo QuaZip_getFileInfo(QuaZip *zip, bool *ok);
0668 
0669 template<>
0670 QuaZipFileInfo QuaZip_getFileInfo(QuaZip *zip, bool *ok)
0671 {
0672     QuaZipFileInfo info;
0673     *ok = zip->getCurrentFileInfo(&info);
0674     return info;
0675 }
0676 
0677 template<>
0678 QuaZipFileInfo64 QuaZip_getFileInfo(QuaZip *zip, bool *ok)
0679 {
0680     QuaZipFileInfo64 info;
0681     *ok = zip->getCurrentFileInfo(&info);
0682     return info;
0683 }
0684 
0685 template<>
0686 QString QuaZip_getFileInfo(QuaZip *zip, bool *ok)
0687 {
0688     QString name = zip->getCurrentFileName();
0689     *ok = !name.isEmpty();
0690     return name;
0691 }
0692 
0693 template<typename TFileInfo>
0694 bool QuaZipPrivate::getFileInfoList(QList<TFileInfo> *result) const
0695 {
0696   QuaZipPrivate *fakeThis=const_cast<QuaZipPrivate*>(this);
0697   fakeThis->zipError=UNZ_OK;
0698   if (mode!=QuaZip::mdUnzip) {
0699     qWarning("QuaZip::getFileNameList/getFileInfoList(): "
0700             "ZIP is not open in mdUnzip mode");
0701     return false;
0702   }
0703   QString currentFile;
0704   if (q->hasCurrentFile()) {
0705       currentFile = q->getCurrentFileName();
0706   }
0707   if (q->goToFirstFile()) {
0708       do {
0709           bool ok;
0710           result->append(QuaZip_getFileInfo<TFileInfo>(q, &ok));
0711           if (!ok)
0712               return false;
0713       } while (q->goToNextFile());
0714   }
0715   if (zipError != UNZ_OK)
0716       return false;
0717   if (currentFile.isEmpty()) {
0718       if (!q->goToFirstFile())
0719           return false;
0720   } else {
0721       if (!q->setCurrentFile(currentFile))
0722           return false;
0723   }
0724   return true;
0725 }
0726 
0727 QStringList QuaZip::getFileNameList() const
0728 {
0729     QStringList list;
0730     if (p->getFileInfoList(&list))
0731         return list;
0732     else
0733         return QStringList();
0734 }
0735 
0736 QList<QuaZipFileInfo> QuaZip::getFileInfoList() const
0737 {
0738     QList<QuaZipFileInfo> list;
0739     if (p->getFileInfoList(&list))
0740         return list;
0741     else
0742         return QList<QuaZipFileInfo>();
0743 }
0744 
0745 QList<QuaZipFileInfo64> QuaZip::getFileInfoList64() const
0746 {
0747     QList<QuaZipFileInfo64> list;
0748     if (p->getFileInfoList(&list))
0749         return list;
0750     else
0751         return QList<QuaZipFileInfo64>();
0752 }
0753 
0754 Qt::CaseSensitivity QuaZip::convertCaseSensitivity(QuaZip::CaseSensitivity cs)
0755 {
0756   if (cs == csDefault) {
0757 #ifdef Q_OS_WIN
0758       return Qt::CaseInsensitive;
0759 #else
0760       return Qt::CaseSensitive;
0761 #endif
0762   } else {
0763       return cs == csSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
0764   }
0765 }
0766 
0767 void QuaZip::setDefaultFileNameCodec(QTextCodec *codec)
0768 {
0769     QuaZipPrivate::defaultFileNameCodec = codec;
0770 }
0771 
0772 void QuaZip::setDefaultFileNameCodec(const char *codecName)
0773 {
0774     setDefaultFileNameCodec(QTextCodec::codecForName(codecName));
0775 }
0776 
0777 void QuaZip::setZip64Enabled(bool zip64)
0778 {
0779     p->zip64 = zip64;
0780 }
0781 
0782 bool QuaZip::isZip64Enabled() const
0783 {
0784     return p->zip64;
0785 }
0786 
0787 bool QuaZip::isAutoClose() const
0788 {
0789     return p->autoClose;
0790 }
0791 
0792 void QuaZip::setAutoClose(bool autoClose) const
0793 {
0794     p->autoClose = autoClose;
0795 }