/src/libtomahawk/thirdparty/quazip/quazip/quazipfile.h

http://github.com/tomahawk-player/tomahawk · C Header · 433 lines · 53 code · 6 blank · 374 comment · 0 complexity · 37241a053413d47bd5a226ee27e033c8 MD5 · raw file

  1. #ifndef QUA_ZIPFILE_H
  2. #define QUA_ZIPFILE_H
  3. /*
  4. Copyright (C) 2005-2011 Sergey A. Tachenov
  5. This program is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or (at
  8. your option) any later version.
  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. You should have received a copy of the GNU Lesser General Public License
  14. along with this program; if not, write to the Free Software Foundation,
  15. Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  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. * Arguments \a password and \a crc provide necessary information
  309. * for crypting. Note that you should specify both of them if you
  310. * need crypting. If you do not, pass \c NULL as password, but you
  311. * still need to specify \a crc if you are going to use raw mode
  312. * (see below).
  313. *
  314. * Arguments \a method and \a level specify compression method and
  315. * level.
  316. *
  317. * If \a raw is \c true, no compression is performed. In this case,
  318. * \a crc and uncompressedSize field of the \a info are required.
  319. *
  320. * Arguments \a windowBits, \a memLevel, \a strategy provide zlib
  321. * algorithms tuning. See deflateInit2() in zlib.
  322. **/
  323. bool open(OpenMode mode, const QuaZipNewInfo& info,
  324. const char *password =NULL, quint32 crc =0,
  325. int method =Z_DEFLATED, int level =Z_DEFAULT_COMPRESSION, bool raw =false,
  326. int windowBits =-MAX_WBITS, int memLevel =DEF_MEM_LEVEL, int strategy =Z_DEFAULT_STRATEGY);
  327. /// Returns \c true, but \ref quazipfile-sequential "beware"!
  328. virtual bool isSequential()const;
  329. /// Returns current position in the file.
  330. /** Implementation of the QIODevice::pos(). When reading, this
  331. * function is a wrapper to the ZIP/UNZIP unztell(), therefore it is
  332. * unable to keep track of the ungetChar() calls (which is
  333. * non-virtual and therefore is dangerous to reimplement). So if you
  334. * are using ungetChar() feature of the QIODevice, this function
  335. * reports incorrect value until you get back characters which you
  336. * ungot.
  337. *
  338. * When writing, pos() returns number of bytes already written
  339. * (uncompressed unless you use raw mode).
  340. *
  341. * \note Although
  342. * \ref quazipfile-sequential "QuaZipFile is a sequential device"
  343. * and therefore pos() should always return zero, it does not,
  344. * because it would be misguiding. Keep this in mind.
  345. *
  346. * This function returns -1 if the file or archive is not open.
  347. *
  348. * Error code returned by getZipError() is not affected by this
  349. * function call.
  350. **/
  351. virtual qint64 pos()const;
  352. /// Returns \c true if the end of file was reached.
  353. /** This function returns \c false in the case of error. This means
  354. * that you called this function on either not open file, or a file
  355. * in the not open archive or even on a QuaZipFile instance that
  356. * does not even have QuaZip instance associated. Do not do that
  357. * because there is no means to determine whether \c false is
  358. * returned because of error or because end of file was reached.
  359. * Well, on the other side you may interpret \c false return value
  360. * as "there is no file open to check for end of file and there is
  361. * no end of file therefore".
  362. *
  363. * When writing, this function always returns \c true (because you
  364. * are always writing to the end of file).
  365. *
  366. * Error code returned by getZipError() is not affected by this
  367. * function call.
  368. **/
  369. virtual bool atEnd()const;
  370. /// Returns file size.
  371. /** This function returns csize() if the file is open for reading in
  372. * raw mode, usize() if it is open for reading in normal mode and
  373. * pos() if it is open for writing.
  374. *
  375. * Returns -1 on error, call getZipError() to get error code.
  376. *
  377. * \note This function returns file size despite that
  378. * \ref quazipfile-sequential "QuaZipFile is considered to be sequential device",
  379. * for which size() should return bytesAvailable() instead. But its
  380. * name would be very misguiding otherwise, so just keep in mind
  381. * this inconsistence.
  382. **/
  383. virtual qint64 size()const;
  384. /// Returns compressed file size.
  385. /** Equivalent to calling getFileInfo() and then getting
  386. * compressedSize field, but more convenient and faster.
  387. *
  388. * File must be open for reading before calling this function.
  389. *
  390. * Returns -1 on error, call getZipError() to get error code.
  391. **/
  392. qint64 csize()const;
  393. /// Returns uncompressed file size.
  394. /** Equivalent to calling getFileInfo() and then getting
  395. * uncompressedSize field, but more convenient and faster. See
  396. * getFileInfo() for a warning.
  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 usize()const;
  403. /// Gets information about current file.
  404. /** This function does the same thing as calling
  405. * QuaZip::getCurrentFileInfo() on the associated QuaZip object,
  406. * but you can not call getCurrentFileInfo() if the associated
  407. * QuaZip is internal (because you do not have access to it), while
  408. * you still can call this function in that case.
  409. *
  410. * File must be open for reading before calling this function.
  411. *
  412. * Returns \c false in the case of an error.
  413. **/
  414. bool getFileInfo(QuaZipFileInfo *info);
  415. /// Closes the file.
  416. /** Call getZipError() to determine if the close was successful.
  417. **/
  418. virtual void close();
  419. /// Returns the error code returned by the last ZIP/UNZIP API call.
  420. int getZipError() const;
  421. };
  422. #endif