misc/quazip/quazipfile.h
changeset 8058 bcebfc477459
parent 8054 39f8ea1a441f
parent 8057 93e16240f178
child 8059 07661fb20586
equal deleted inserted replaced
8054:39f8ea1a441f 8058:bcebfc477459
     1 #ifndef QUA_ZIPFILE_H
       
     2 #define QUA_ZIPFILE_H
       
     3 
       
     4 /*
       
     5 Copyright (C) 2005-2011 Sergey A. Tachenov
       
     6 
       
     7 This program is free software; you can redistribute it and/or modify it
       
     8 under the terms of the GNU Lesser General Public License as published by
       
     9 the Free Software Foundation; either version 2 of the License, or (at
       
    10 your option) any later version.
       
    11 
       
    12 This program is distributed in the hope that it will be useful, but
       
    13 WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
       
    15 General Public License for more details.
       
    16 
       
    17 You should have received a copy of the GNU Lesser General Public License
       
    18 along with this program; if not, write to the Free Software Foundation,
       
    19 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
       
    20 
       
    21 See COPYING file for the full LGPL text.
       
    22 
       
    23 Original ZIP package is copyrighted by Gilles Vollant, see
       
    24 quazip/(un)zip.h files for details, basically it's zlib license.
       
    25  **/
       
    26 
       
    27 #include <QIODevice>
       
    28 
       
    29 #include "quazip_global.h"
       
    30 #include "quazip.h"
       
    31 #include "quazipnewinfo.h"
       
    32 
       
    33 class QuaZipFilePrivate;
       
    34 
       
    35 /// A file inside ZIP archive.
       
    36 /** \class QuaZipFile quazipfile.h <quazip/quazipfile.h>
       
    37  * This is the most interesting class. Not only it provides C++
       
    38  * interface to the ZIP/UNZIP package, but also integrates it with Qt by
       
    39  * subclassing QIODevice. This makes possible to access files inside ZIP
       
    40  * archive using QTextStream or QDataStream, for example. Actually, this
       
    41  * is the main purpose of the whole QuaZIP library.
       
    42  *
       
    43  * You can either use existing QuaZip instance to create instance of
       
    44  * this class or pass ZIP archive file name to this class, in which case
       
    45  * it will create internal QuaZip object. See constructors' descriptions
       
    46  * for details. Writing is only possible with the existing instance.
       
    47  *
       
    48  * Note that due to the underlying library's limitation it is not
       
    49  * possible to use multiple QuaZipFile instances to open several files
       
    50  * in the same archive at the same time. If you need to write to
       
    51  * multiple files in parallel, then you should write to temporary files
       
    52  * first, then pack them all at once when you have finished writing. If
       
    53  * you need to read multiple files inside the same archive in parallel,
       
    54  * you should extract them all into a temporary directory first.
       
    55  *
       
    56  * \section quazipfile-sequential Sequential or random-access?
       
    57  *
       
    58  * At the first thought, QuaZipFile has fixed size, the start and the
       
    59  * end and should be therefore considered random-access device. But
       
    60  * there is one major obstacle to making it random-access: ZIP/UNZIP API
       
    61  * does not support seek() operation and the only way to implement it is
       
    62  * through reopening the file and re-reading to the required position,
       
    63  * but this is prohibitively slow.
       
    64  *
       
    65  * Therefore, QuaZipFile is considered to be a sequential device. This
       
    66  * has advantage of availability of the ungetChar() operation (QIODevice
       
    67  * does not implement it properly for non-sequential devices unless they
       
    68  * support seek()). Disadvantage is a somewhat strange behaviour of the
       
    69  * size() and pos() functions. This should be kept in mind while using
       
    70  * this class.
       
    71  *
       
    72  **/
       
    73 class QUAZIP_EXPORT QuaZipFile: public QIODevice {
       
    74   friend class QuaZipFilePrivate;
       
    75   Q_OBJECT
       
    76   private:
       
    77     QuaZipFilePrivate *p;
       
    78     // these are not supported nor implemented
       
    79     QuaZipFile(const QuaZipFile& that);
       
    80     QuaZipFile& operator=(const QuaZipFile& that);
       
    81   protected:
       
    82     /// Implementation of the QIODevice::readData().
       
    83     qint64 readData(char *data, qint64 maxSize);
       
    84     /// Implementation of the QIODevice::writeData().
       
    85     qint64 writeData(const char *data, qint64 maxSize);
       
    86   public:
       
    87     /// Constructs a QuaZipFile instance.
       
    88     /** You should use setZipName() and setFileName() or setZip() before
       
    89      * trying to call open() on the constructed object.
       
    90      **/
       
    91     QuaZipFile();
       
    92     /// Constructs a QuaZipFile instance.
       
    93     /** \a parent argument specifies this object's parent object.
       
    94      *
       
    95      * You should use setZipName() and setFileName() or setZip() before
       
    96      * trying to call open() on the constructed object.
       
    97      **/
       
    98     QuaZipFile(QObject *parent);
       
    99     /// Constructs a QuaZipFile instance.
       
   100     /** \a parent argument specifies this object's parent object and \a
       
   101      * zipName specifies ZIP archive file name.
       
   102      *
       
   103      * You should use setFileName() before trying to call open() on the
       
   104      * constructed object.
       
   105      *
       
   106      * QuaZipFile constructed by this constructor can be used for read
       
   107      * only access. Use QuaZipFile(QuaZip*,QObject*) for writing.
       
   108      **/
       
   109     QuaZipFile(const QString& zipName, QObject *parent =NULL);
       
   110     /// Constructs a QuaZipFile instance.
       
   111     /** \a parent argument specifies this object's parent object, \a
       
   112      * zipName specifies ZIP archive file name and \a fileName and \a cs
       
   113      * specify a name of the file to open inside archive.
       
   114      *
       
   115      * QuaZipFile constructed by this constructor can be used for read
       
   116      * only access. Use QuaZipFile(QuaZip*,QObject*) for writing.
       
   117      *
       
   118      * \sa QuaZip::setCurrentFile()
       
   119      **/
       
   120     QuaZipFile(const QString& zipName, const QString& fileName,
       
   121         QuaZip::CaseSensitivity cs =QuaZip::csDefault, QObject *parent =NULL);
       
   122     /// Constructs a QuaZipFile instance.
       
   123     /** \a parent argument specifies this object's parent object.
       
   124      *
       
   125      * \a zip is the pointer to the existing QuaZip object. This
       
   126      * QuaZipFile object then can be used to read current file in the
       
   127      * \a zip or to write to the file inside it.
       
   128      *
       
   129      * \warning Using this constructor for reading current file can be
       
   130      * tricky. Let's take the following example:
       
   131      * \code
       
   132      * QuaZip zip("archive.zip");
       
   133      * zip.open(QuaZip::mdUnzip);
       
   134      * zip.setCurrentFile("file-in-archive");
       
   135      * QuaZipFile file(&zip);
       
   136      * file.open(QIODevice::ReadOnly);
       
   137      * // ok, now we can read from the file
       
   138      * file.read(somewhere, some);
       
   139      * zip.setCurrentFile("another-file-in-archive"); // oops...
       
   140      * QuaZipFile anotherFile(&zip);
       
   141      * anotherFile.open(QIODevice::ReadOnly);
       
   142      * anotherFile.read(somewhere, some); // this is still ok...
       
   143      * file.read(somewhere, some); // and this is NOT
       
   144      * \endcode
       
   145      * So, what exactly happens here? When we change current file in the
       
   146      * \c zip archive, \c file that references it becomes invalid
       
   147      * (actually, as far as I understand ZIP/UNZIP sources, it becomes
       
   148      * closed, but QuaZipFile has no means to detect it).
       
   149      *
       
   150      * Summary: do not close \c zip object or change its current file as
       
   151      * long as QuaZipFile is open. Even better - use another constructors
       
   152      * which create internal QuaZip instances, one per object, and
       
   153      * therefore do not cause unnecessary trouble. This constructor may
       
   154      * be useful, though, if you already have a QuaZip instance and do
       
   155      * not want to access several files at once. Good example:
       
   156      * \code
       
   157      * QuaZip zip("archive.zip");
       
   158      * zip.open(QuaZip::mdUnzip);
       
   159      * // first, we need some information about archive itself
       
   160      * QByteArray comment=zip.getComment();
       
   161      * // and now we are going to access files inside it
       
   162      * QuaZipFile file(&zip);
       
   163      * for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) {
       
   164      *   file.open(QIODevice::ReadOnly);
       
   165      *   // do something cool with file here
       
   166      *   file.close(); // do not forget to close!
       
   167      * }
       
   168      * zip.close();
       
   169      * \endcode
       
   170      **/
       
   171     QuaZipFile(QuaZip *zip, QObject *parent =NULL);
       
   172     /// Destroys a QuaZipFile instance.
       
   173     /** Closes file if open, destructs internal QuaZip object (if it
       
   174      * exists and \em is internal, of course).
       
   175      **/
       
   176     virtual ~QuaZipFile();
       
   177     /// Returns the ZIP archive file name.
       
   178     /** If this object was created by passing QuaZip pointer to the
       
   179      * constructor, this function will return that QuaZip's file name
       
   180      * (or null string if that object does not have file name yet).
       
   181      *
       
   182      * Otherwise, returns associated ZIP archive file name or null
       
   183      * string if there are no name set yet.
       
   184      *
       
   185      * \sa setZipName() getFileName()
       
   186      **/
       
   187     QString getZipName()const;
       
   188     /// Returns a pointer to the associated QuaZip object.
       
   189     /** Returns \c NULL if there is no associated QuaZip or it is
       
   190      * internal (so you will not mess with it).
       
   191      **/
       
   192     QuaZip* getZip()const;
       
   193     /// Returns file name.
       
   194     /** This function returns file name you passed to this object either
       
   195      * by using
       
   196      * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*)
       
   197      * or by calling setFileName(). Real name of the file may differ in
       
   198      * case if you used case-insensitivity.
       
   199      *
       
   200      * Returns null string if there is no file name set yet. This is the
       
   201      * case when this QuaZipFile operates on the existing QuaZip object
       
   202      * (constructor QuaZipFile(QuaZip*,QObject*) or setZip() was used).
       
   203      * 
       
   204      * \sa getActualFileName
       
   205      **/
       
   206     QString getFileName() const;
       
   207     /// Returns case sensitivity of the file name.
       
   208     /** This function returns case sensitivity argument you passed to
       
   209      * this object either by using
       
   210      * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*)
       
   211      * or by calling setFileName().
       
   212      *
       
   213      * Returns unpredictable value if getFileName() returns null string
       
   214      * (this is the case when you did not used setFileName() or
       
   215      * constructor above).
       
   216      *
       
   217      * \sa getFileName
       
   218      **/
       
   219     QuaZip::CaseSensitivity getCaseSensitivity() const;
       
   220     /// Returns the actual file name in the archive.
       
   221     /** This is \em not a ZIP archive file name, but a name of file inside
       
   222      * archive. It is not necessary the same name that you have passed
       
   223      * to the
       
   224      * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*),
       
   225      * setFileName() or QuaZip::setCurrentFile() - this is the real file
       
   226      * name inside archive, so it may differ in case if the file name
       
   227      * search was case-insensitive.
       
   228      *
       
   229      * Equivalent to calling getCurrentFileName() on the associated
       
   230      * QuaZip object. Returns null string if there is no associated
       
   231      * QuaZip object or if it does not have a current file yet. And this
       
   232      * is the case if you called setFileName() but did not open the
       
   233      * file yet. So this is perfectly fine:
       
   234      * \code
       
   235      * QuaZipFile file("somezip.zip");
       
   236      * file.setFileName("somefile");
       
   237      * QString name=file.getName(); // name=="somefile"
       
   238      * QString actual=file.getActualFileName(); // actual is null string
       
   239      * file.open(QIODevice::ReadOnly);
       
   240      * QString actual=file.getActualFileName(); // actual can be "SoMeFiLe" on Windows
       
   241      * \endcode
       
   242      *
       
   243      * \sa getZipName(), getFileName(), QuaZip::CaseSensitivity
       
   244      **/
       
   245     QString getActualFileName()const;
       
   246     /// Sets the ZIP archive file name.
       
   247     /** Automatically creates internal QuaZip object and destroys
       
   248      * previously created internal QuaZip object, if any.
       
   249      *
       
   250      * Will do nothing if this file is already open. You must close() it
       
   251      * first.
       
   252      **/
       
   253     void setZipName(const QString& zipName);
       
   254     /// Returns \c true if the file was opened in raw mode.
       
   255     /** If the file is not open, the returned value is undefined.
       
   256      *
       
   257      * \sa open(OpenMode,int*,int*,bool,const char*)
       
   258      **/
       
   259     bool isRaw() const;
       
   260     /// Binds to the existing QuaZip instance.
       
   261     /** This function destroys internal QuaZip object, if any, and makes
       
   262      * this QuaZipFile to use current file in the \a zip object for any
       
   263      * further operations. See QuaZipFile(QuaZip*,QObject*) for the
       
   264      * possible pitfalls.
       
   265      *
       
   266      * Will do nothing if the file is currently open. You must close()
       
   267      * it first.
       
   268      **/
       
   269     void setZip(QuaZip *zip);
       
   270     /// Sets the file name.
       
   271     /** Will do nothing if at least one of the following conditions is
       
   272      * met:
       
   273      * - ZIP name has not been set yet (getZipName() returns null
       
   274      *   string).
       
   275      * - This QuaZipFile is associated with external QuaZip. In this
       
   276      *   case you should call that QuaZip's setCurrentFile() function
       
   277      *   instead!
       
   278      * - File is already open so setting the name is meaningless.
       
   279      *
       
   280      * \sa QuaZip::setCurrentFile
       
   281      **/
       
   282     void setFileName(const QString& fileName, QuaZip::CaseSensitivity cs =QuaZip::csDefault);
       
   283     /// Opens a file for reading.
       
   284     /** Returns \c true on success, \c false otherwise.
       
   285      * Call getZipError() to get error code.
       
   286      *
       
   287      * \note Since ZIP/UNZIP API provides buffered reading only,
       
   288      * QuaZipFile does not support unbuffered reading. So do not pass
       
   289      * QIODevice::Unbuffered flag in \a mode, or open will fail.
       
   290      **/
       
   291     virtual bool open(OpenMode mode);
       
   292     /// Opens a file for reading.
       
   293     /** \overload
       
   294      * Argument \a password specifies a password to decrypt the file. If
       
   295      * it is NULL then this function behaves just like open(OpenMode).
       
   296      **/
       
   297     inline bool open(OpenMode mode, const char *password)
       
   298     {return open(mode, NULL, NULL, false, password);}
       
   299     /// Opens a file for reading.
       
   300     /** \overload
       
   301      * Argument \a password specifies a password to decrypt the file.
       
   302      *
       
   303      * An integers pointed by \a method and \a level will receive codes
       
   304      * of the compression method and level used. See unzip.h.
       
   305      *
       
   306      * If raw is \c true then no decompression is performed.
       
   307      *
       
   308      * \a method should not be \c NULL. \a level can be \c NULL if you
       
   309      * don't want to know the compression level.
       
   310      **/
       
   311     bool open(OpenMode mode, int *method, int *level, bool raw, const char *password =NULL);
       
   312     /// Opens a file for writing.
       
   313     /** \a info argument specifies information about file. It should at
       
   314      * least specify a correct file name. Also, it is a good idea to
       
   315      * specify correct timestamp (by default, current time will be
       
   316      * used). See QuaZipNewInfo.
       
   317      *
       
   318      * Arguments \a password and \a crc provide necessary information
       
   319      * for crypting. Note that you should specify both of them if you
       
   320      * need crypting. If you do not, pass \c NULL as password, but you
       
   321      * still need to specify \a crc if you are going to use raw mode
       
   322      * (see below).
       
   323      *
       
   324      * Arguments \a method and \a level specify compression method and
       
   325      * level.
       
   326      *
       
   327      * If \a raw is \c true, no compression is performed. In this case,
       
   328      * \a crc and uncompressedSize field of the \a info are required.
       
   329      *
       
   330      * Arguments \a windowBits, \a memLevel, \a strategy provide zlib
       
   331      * algorithms tuning. See deflateInit2() in zlib.
       
   332      **/
       
   333     bool open(OpenMode mode, const QuaZipNewInfo& info,
       
   334         const char *password =NULL, quint32 crc =0,
       
   335         int method =Z_DEFLATED, int level =Z_DEFAULT_COMPRESSION, bool raw =false,
       
   336         int windowBits =-MAX_WBITS, int memLevel =DEF_MEM_LEVEL, int strategy =Z_DEFAULT_STRATEGY);
       
   337     /// Returns \c true, but \ref quazipfile-sequential "beware"!
       
   338     virtual bool isSequential()const;
       
   339     /// Returns current position in the file.
       
   340     /** Implementation of the QIODevice::pos(). When reading, this
       
   341      * function is a wrapper to the ZIP/UNZIP unztell(), therefore it is
       
   342      * unable to keep track of the ungetChar() calls (which is
       
   343      * non-virtual and therefore is dangerous to reimplement). So if you
       
   344      * are using ungetChar() feature of the QIODevice, this function
       
   345      * reports incorrect value until you get back characters which you
       
   346      * ungot.
       
   347      *
       
   348      * When writing, pos() returns number of bytes already written
       
   349      * (uncompressed unless you use raw mode).
       
   350      *
       
   351      * \note Although
       
   352      * \ref quazipfile-sequential "QuaZipFile is a sequential device"
       
   353      * and therefore pos() should always return zero, it does not,
       
   354      * because it would be misguiding. Keep this in mind.
       
   355      *
       
   356      * This function returns -1 if the file or archive is not open.
       
   357      *
       
   358      * Error code returned by getZipError() is not affected by this
       
   359      * function call.
       
   360      **/
       
   361     virtual qint64 pos()const;
       
   362     /// Returns \c true if the end of file was reached.
       
   363     /** This function returns \c false in the case of error. This means
       
   364      * that you called this function on either not open file, or a file
       
   365      * in the not open archive or even on a QuaZipFile instance that
       
   366      * does not even have QuaZip instance associated. Do not do that
       
   367      * because there is no means to determine whether \c false is
       
   368      * returned because of error or because end of file was reached.
       
   369      * Well, on the other side you may interpret \c false return value
       
   370      * as "there is no file open to check for end of file and there is
       
   371      * no end of file therefore".
       
   372      *
       
   373      * When writing, this function always returns \c true (because you
       
   374      * are always writing to the end of file).
       
   375      *
       
   376      * Error code returned by getZipError() is not affected by this
       
   377      * function call.
       
   378      **/
       
   379     virtual bool atEnd()const;
       
   380     /// Returns file size.
       
   381     /** This function returns csize() if the file is open for reading in
       
   382      * raw mode, usize() if it is open for reading in normal mode and
       
   383      * pos() if it is open for writing.
       
   384      *
       
   385      * Returns -1 on error, call getZipError() to get error code.
       
   386      *
       
   387      * \note This function returns file size despite that
       
   388      * \ref quazipfile-sequential "QuaZipFile is considered to be sequential device",
       
   389      * for which size() should return bytesAvailable() instead. But its
       
   390      * name would be very misguiding otherwise, so just keep in mind
       
   391      * this inconsistence.
       
   392      **/
       
   393     virtual qint64 size()const;
       
   394     /// Returns compressed file size.
       
   395     /** Equivalent to calling getFileInfo() and then getting
       
   396      * compressedSize field, but more convenient and faster.
       
   397      *
       
   398      * File must be open for reading before calling this function.
       
   399      *
       
   400      * Returns -1 on error, call getZipError() to get error code.
       
   401      **/
       
   402     qint64 csize()const;
       
   403     /// Returns uncompressed file size.
       
   404     /** Equivalent to calling getFileInfo() and then getting
       
   405      * uncompressedSize field, but more convenient and faster. See
       
   406      * getFileInfo() for a warning.
       
   407      *
       
   408      * File must be open for reading before calling this function.
       
   409      *
       
   410      * Returns -1 on error, call getZipError() to get error code.
       
   411      **/
       
   412     qint64 usize()const;
       
   413     /// Gets information about current file.
       
   414     /** This function does the same thing as calling
       
   415      * QuaZip::getCurrentFileInfo() on the associated QuaZip object,
       
   416      * but you can not call getCurrentFileInfo() if the associated
       
   417      * QuaZip is internal (because you do not have access to it), while
       
   418      * you still can call this function in that case.
       
   419      *
       
   420      * File must be open for reading before calling this function.
       
   421      *
       
   422      * Returns \c false in the case of an error.
       
   423      **/
       
   424     bool getFileInfo(QuaZipFileInfo *info);
       
   425     /// Closes the file.
       
   426     /** Call getZipError() to determine if the close was successful.
       
   427      **/
       
   428     virtual void close();
       
   429     /// Returns the error code returned by the last ZIP/UNZIP API call.
       
   430     int getZipError() const;
       
   431 };
       
   432 
       
   433 #endif