quazipfile.h 20 KB

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