5752
|
1 |
#ifndef QUA_ZIP_H
|
|
2 |
#define QUA_ZIP_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 <QString>
|
|
28 |
#include <QTextCodec>
|
|
29 |
|
|
30 |
#include "zip.h"
|
|
31 |
#include "unzip.h"
|
|
32 |
|
|
33 |
#include "quazip_global.h"
|
|
34 |
#include "quazipfileinfo.h"
|
|
35 |
|
|
36 |
// just in case it will be defined in the later versions of the ZIP/UNZIP
|
|
37 |
#ifndef UNZ_OPENERROR
|
|
38 |
// define additional error code
|
|
39 |
#define UNZ_OPENERROR -1000
|
|
40 |
#endif
|
|
41 |
|
|
42 |
class QuaZipPrivate;
|
|
43 |
|
|
44 |
/// ZIP archive.
|
|
45 |
/** \class QuaZip quazip.h <quazip/quazip.h>
|
|
46 |
* This class implements basic interface to the ZIP archive. It can be
|
|
47 |
* used to read table contents of the ZIP archive and retreiving
|
|
48 |
* information about the files inside it.
|
|
49 |
*
|
|
50 |
* You can also use this class to open files inside archive by passing
|
|
51 |
* pointer to the instance of this class to the constructor of the
|
|
52 |
* QuaZipFile class. But see QuaZipFile::QuaZipFile(QuaZip*, QObject*)
|
|
53 |
* for the possible pitfalls.
|
|
54 |
*
|
|
55 |
* This class is indended to provide interface to the ZIP subpackage of
|
|
56 |
* the ZIP/UNZIP package as well as to the UNZIP subpackage. But
|
|
57 |
* currently it supports only UNZIP.
|
|
58 |
*
|
|
59 |
* The use of this class is simple - just create instance using
|
|
60 |
* constructor, then set ZIP archive file name using setFile() function
|
|
61 |
* (if you did not passed the name to the constructor), then open() and
|
|
62 |
* then use different functions to work with it! Well, if you are
|
|
63 |
* paranoid, you may also wish to call close before destructing the
|
|
64 |
* instance, to check for errors on close.
|
|
65 |
*
|
|
66 |
* You may also use getUnzFile() and getZipFile() functions to get the
|
|
67 |
* ZIP archive handle and use it with ZIP/UNZIP package API directly.
|
|
68 |
*
|
|
69 |
* This class supports localized file names inside ZIP archive, but you
|
|
70 |
* have to set up proper codec with setCodec() function. By default,
|
|
71 |
* locale codec will be used, which is probably ok for UNIX systems, but
|
|
72 |
* will almost certainly fail with ZIP archives created in Windows. This
|
|
73 |
* is because Windows ZIP programs have strange habit of using DOS
|
|
74 |
* encoding for file names in ZIP archives. For example, ZIP archive
|
|
75 |
* with cyrillic names created in Windows will have file names in \c
|
|
76 |
* IBM866 encoding instead of \c WINDOWS-1251. I think that calling one
|
|
77 |
* function is not much trouble, but for true platform independency it
|
|
78 |
* would be nice to have some mechanism for file name encoding auto
|
|
79 |
* detection using locale information. Does anyone know a good way to do
|
|
80 |
* it?
|
|
81 |
**/
|
|
82 |
class QUAZIP_EXPORT QuaZip {
|
|
83 |
friend class QuaZipPrivate;
|
|
84 |
public:
|
|
85 |
/// Useful constants.
|
|
86 |
enum Constants {
|
|
87 |
MAX_FILE_NAME_LENGTH=256 /**< Maximum file name length. Taken from
|
|
88 |
\c UNZ_MAXFILENAMEINZIP constant in
|
|
89 |
unzip.c. */
|
|
90 |
};
|
|
91 |
/// Open mode of the ZIP file.
|
|
92 |
enum Mode {
|
|
93 |
mdNotOpen, ///< ZIP file is not open. This is the initial mode.
|
|
94 |
mdUnzip, ///< ZIP file is open for reading files inside it.
|
|
95 |
mdCreate, ///< ZIP file was created with open() call.
|
|
96 |
mdAppend, /**< ZIP file was opened in append mode. This refers to
|
|
97 |
* \c APPEND_STATUS_CREATEAFTER mode in ZIP/UNZIP package
|
|
98 |
* and means that zip is appended to some existing file
|
|
99 |
* what is useful when that file contains
|
|
100 |
* self-extractor code. This is obviously \em not what
|
|
101 |
* you whant to use to add files to the existing ZIP
|
|
102 |
* archive.
|
|
103 |
**/
|
|
104 |
mdAdd ///< ZIP file was opened for adding files in the archive.
|
|
105 |
};
|
|
106 |
/// Case sensitivity for the file names.
|
|
107 |
/** This is what you specify when accessing files in the archive.
|
|
108 |
* Works perfectly fine with any characters thanks to Qt's great
|
|
109 |
* unicode support. This is different from ZIP/UNZIP API, where
|
|
110 |
* only US-ASCII characters was supported.
|
|
111 |
**/
|
|
112 |
enum CaseSensitivity {
|
|
113 |
csDefault=0, ///< Default for platform. Case sensitive for UNIX, not for Windows.
|
|
114 |
csSensitive=1, ///< Case sensitive.
|
|
115 |
csInsensitive=2 ///< Case insensitive.
|
|
116 |
};
|
|
117 |
private:
|
|
118 |
QuaZipPrivate *p;
|
|
119 |
// not (and will not be) implemented
|
|
120 |
QuaZip(const QuaZip& that);
|
|
121 |
// not (and will not be) implemented
|
|
122 |
QuaZip& operator=(const QuaZip& that);
|
|
123 |
public:
|
|
124 |
/// Constructs QuaZip object.
|
|
125 |
/** Call setName() before opening constructed object. */
|
|
126 |
QuaZip();
|
|
127 |
/// Constructs QuaZip object associated with ZIP file \a zipName.
|
|
128 |
QuaZip(const QString& zipName);
|
|
129 |
/// Constructs QuaZip object associated with ZIP file represented by \a ioDevice.
|
|
130 |
/** The IO device must be seekable, otherwise an error will occur when opening. */
|
|
131 |
QuaZip(QIODevice *ioDevice);
|
|
132 |
/// Destroys QuaZip object.
|
|
133 |
/** Calls close() if necessary. */
|
|
134 |
~QuaZip();
|
|
135 |
/// Opens ZIP file.
|
|
136 |
/**
|
|
137 |
* Argument \a mode specifies open mode of the ZIP archive. See Mode
|
|
138 |
* for details. Note that there is zipOpen2() function in the
|
|
139 |
* ZIP/UNZIP API which accepts \a globalcomment argument, but it
|
|
140 |
* does not use it anywhere, so this open() function does not have this
|
|
141 |
* argument. See setComment() if you need to set global comment.
|
|
142 |
*
|
|
143 |
* If the ZIP file is accessed via explicitly set QIODevice, then
|
|
144 |
* this device is opened in the necessary mode. If the device was
|
|
145 |
* already opened by some other means, then the behaviour is defined by
|
|
146 |
* the device implementation, but generally it is not a very good
|
|
147 |
* idea. For example, QFile will at least issue a warning.
|
|
148 |
*
|
|
149 |
* \return \c true if successful, \c false otherwise.
|
|
150 |
*
|
|
151 |
* \note ZIP/UNZIP API open calls do not return error code - they
|
|
152 |
* just return \c NULL indicating an error. But to make things
|
|
153 |
* easier, quazip.h header defines additional error code \c
|
|
154 |
* UNZ_ERROROPEN and getZipError() will return it if the open call
|
|
155 |
* of the ZIP/UNZIP API returns \c NULL.
|
|
156 |
*
|
|
157 |
* Argument \a ioApi specifies IO function set for ZIP/UNZIP
|
|
158 |
* package to use. See unzip.h, zip.h and ioapi.h for details. Note
|
|
159 |
* that IO API for QuaZip is different from the original package.
|
|
160 |
* The file path argument was changed to be of type \c voidpf, and
|
|
161 |
* QuaZip passes a QIODevice pointer there. This QIODevice is either
|
|
162 |
* set explicitly via setIoDevice() or the QuaZip(QIODevice*)
|
|
163 |
* constructor, or it is created internally when opening the archive
|
|
164 |
* by its file name. The default API (qioapi.cpp) just delegates
|
|
165 |
* everything to the QIODevice API. Not only this allows to use a
|
|
166 |
* QIODevice instead of file name, but also has a nice side effect
|
|
167 |
* of raising the file size limit from 2G to 4G.
|
|
168 |
*
|
|
169 |
* In short: just forget about the \a ioApi argument and you'll be
|
|
170 |
* fine.
|
|
171 |
**/
|
|
172 |
bool open(Mode mode, zlib_filefunc_def *ioApi =NULL);
|
|
173 |
/// Closes ZIP file.
|
|
174 |
/** Call getZipError() to determine if the close was successful. The
|
|
175 |
* underlying QIODevice is also closed, regardless of whether it was
|
|
176 |
* set explicitly or not. */
|
|
177 |
void close();
|
|
178 |
/// Sets the codec used to encode/decode file names inside archive.
|
|
179 |
/** This is necessary to access files in the ZIP archive created
|
|
180 |
* under Windows with non-latin characters in file names. For
|
|
181 |
* example, file names with cyrillic letters will be in \c IBM866
|
|
182 |
* encoding.
|
|
183 |
**/
|
|
184 |
void setFileNameCodec(QTextCodec *fileNameCodec);
|
|
185 |
/// Sets the codec used to encode/decode file names inside archive.
|
|
186 |
/** \overload
|
|
187 |
* Equivalent to calling setFileNameCodec(QTextCodec::codecForName(codecName));
|
|
188 |
**/
|
|
189 |
void setFileNameCodec(const char *fileNameCodecName);
|
|
190 |
/// Returns the codec used to encode/decode comments inside archive.
|
|
191 |
QTextCodec* getFileNameCodec() const;
|
|
192 |
/// Sets the codec used to encode/decode comments inside archive.
|
|
193 |
/** This codec defaults to locale codec, which is probably ok.
|
|
194 |
**/
|
|
195 |
void setCommentCodec(QTextCodec *commentCodec);
|
|
196 |
/// Sets the codec used to encode/decode comments inside archive.
|
|
197 |
/** \overload
|
|
198 |
* Equivalent to calling setCommentCodec(QTextCodec::codecForName(codecName));
|
|
199 |
**/
|
|
200 |
void setCommentCodec(const char *commentCodecName);
|
|
201 |
/// Returns the codec used to encode/decode comments inside archive.
|
|
202 |
QTextCodec* getCommentCodec() const;
|
|
203 |
/// Returns the name of the ZIP file.
|
|
204 |
/** Returns null string if no ZIP file name has been set, for
|
|
205 |
* example when the QuaZip instance is set up to use a QIODevice
|
|
206 |
* instead.
|
|
207 |
* \sa setZipName(), setIoDevice(), getIoDevice()
|
|
208 |
**/
|
|
209 |
QString getZipName() const;
|
|
210 |
/// Sets the name of the ZIP file.
|
|
211 |
/** Does nothing if the ZIP file is open.
|
|
212 |
*
|
|
213 |
* Does not reset error code returned by getZipError().
|
|
214 |
* \sa setIoDevice(), getIoDevice(), getZipName()
|
|
215 |
**/
|
|
216 |
void setZipName(const QString& zipName);
|
|
217 |
/// Returns the device representing this ZIP file.
|
|
218 |
/** Returns null string if no device has been set explicitly, for
|
|
219 |
* example when opening a ZIP file by name.
|
|
220 |
* \sa setIoDevice(), getZipName(), setZipName()
|
|
221 |
**/
|
|
222 |
QIODevice *getIoDevice() const;
|
|
223 |
/// Sets the device representing the ZIP file.
|
|
224 |
/** Does nothing if the ZIP file is open.
|
|
225 |
*
|
|
226 |
* Does not reset error code returned by getZipError().
|
|
227 |
* \sa getIoDevice(), getZipName(), setZipName()
|
|
228 |
**/
|
|
229 |
void setIoDevice(QIODevice *ioDevice);
|
|
230 |
/// Returns the mode in which ZIP file was opened.
|
|
231 |
Mode getMode() const;
|
|
232 |
/// Returns \c true if ZIP file is open, \c false otherwise.
|
|
233 |
bool isOpen() const;
|
|
234 |
/// Returns the error code of the last operation.
|
|
235 |
/** Returns \c UNZ_OK if the last operation was successful.
|
|
236 |
*
|
|
237 |
* Error code resets to \c UNZ_OK every time you call any function
|
|
238 |
* that accesses something inside ZIP archive, even if it is \c
|
|
239 |
* const (like getEntriesCount()). open() and close() calls reset
|
|
240 |
* error code too. See documentation for the specific functions for
|
|
241 |
* details on error detection.
|
|
242 |
**/
|
|
243 |
int getZipError() const;
|
|
244 |
/// Returns number of the entries in the ZIP central directory.
|
|
245 |
/** Returns negative error code in the case of error. The same error
|
|
246 |
* code will be returned by subsequent getZipError() call.
|
|
247 |
**/
|
|
248 |
int getEntriesCount() const;
|
|
249 |
/// Returns global comment in the ZIP file.
|
|
250 |
QString getComment() const;
|
|
251 |
/// Sets global comment in the ZIP file.
|
|
252 |
/** Comment will be written to the archive on close operation.
|
|
253 |
*
|
|
254 |
* \sa open()
|
|
255 |
**/
|
|
256 |
void setComment(const QString& comment);
|
|
257 |
/// Sets the current file to the first file in the archive.
|
|
258 |
/** Returns \c true on success, \c false otherwise. Call
|
|
259 |
* getZipError() to get the error code.
|
|
260 |
**/
|
|
261 |
bool goToFirstFile();
|
|
262 |
/// Sets the current file to the next file in the archive.
|
|
263 |
/** Returns \c true on success, \c false otherwise. Call
|
|
264 |
* getZipError() to determine if there was an error.
|
|
265 |
*
|
|
266 |
* Should be used only in QuaZip::mdUnzip mode.
|
|
267 |
*
|
|
268 |
* \note If the end of file was reached, getZipError() will return
|
|
269 |
* \c UNZ_OK instead of \c UNZ_END_OF_LIST_OF_FILE. This is to make
|
|
270 |
* things like this easier:
|
|
271 |
* \code
|
|
272 |
* for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) {
|
|
273 |
* // do something
|
|
274 |
* }
|
|
275 |
* if(zip.getZipError()==UNZ_OK) {
|
|
276 |
* // ok, there was no error
|
|
277 |
* }
|
|
278 |
* \endcode
|
|
279 |
**/
|
|
280 |
bool goToNextFile();
|
|
281 |
/// Sets current file by its name.
|
|
282 |
/** Returns \c true if successful, \c false otherwise. Argument \a
|
|
283 |
* cs specifies case sensitivity of the file name. Call
|
|
284 |
* getZipError() in the case of a failure to get error code.
|
|
285 |
*
|
|
286 |
* This is not a wrapper to unzLocateFile() function. That is
|
|
287 |
* because I had to implement locale-specific case-insensitive
|
|
288 |
* comparison.
|
|
289 |
*
|
|
290 |
* Here are the differences from the original implementation:
|
|
291 |
*
|
|
292 |
* - If the file was not found, error code is \c UNZ_OK, not \c
|
|
293 |
* UNZ_END_OF_LIST_OF_FILE (see also goToNextFile()).
|
|
294 |
* - If this function fails, it unsets the current file rather than
|
|
295 |
* resetting it back to what it was before the call.
|
|
296 |
*
|
|
297 |
* If \a fileName is null string then this function unsets the
|
|
298 |
* current file and return \c true. Note that you should close the
|
|
299 |
* file first if it is open! See
|
|
300 |
* QuaZipFile::QuaZipFile(QuaZip*,QObject*) for the details.
|
|
301 |
*
|
|
302 |
* Should be used only in QuaZip::mdUnzip mode.
|
|
303 |
*
|
|
304 |
* \sa setFileNameCodec(), CaseSensitivity
|
|
305 |
**/
|
|
306 |
bool setCurrentFile(const QString& fileName, CaseSensitivity cs =csDefault);
|
|
307 |
/// Returns \c true if the current file has been set.
|
|
308 |
bool hasCurrentFile() const;
|
|
309 |
/// Retrieves information about the current file.
|
|
310 |
/** Fills the structure pointed by \a info. Returns \c true on
|
|
311 |
* success, \c false otherwise. In the latter case structure pointed
|
|
312 |
* by \a info remains untouched. If there was an error,
|
|
313 |
* getZipError() returns error code.
|
|
314 |
*
|
|
315 |
* Should be used only in QuaZip::mdUnzip mode.
|
|
316 |
*
|
|
317 |
* Does nothing and returns \c false in any of the following cases.
|
|
318 |
* - ZIP is not open;
|
|
319 |
* - ZIP does not have current file;
|
|
320 |
* - \a info is \c NULL;
|
|
321 |
*
|
|
322 |
* In all these cases getZipError() returns \c UNZ_OK since there
|
|
323 |
* is no ZIP/UNZIP API call.
|
|
324 |
**/
|
|
325 |
bool getCurrentFileInfo(QuaZipFileInfo* info)const;
|
|
326 |
/// Returns the current file name.
|
|
327 |
/** Equivalent to calling getCurrentFileInfo() and then getting \c
|
|
328 |
* name field of the QuaZipFileInfo structure, but faster and more
|
|
329 |
* convenient.
|
|
330 |
*
|
|
331 |
* Should be used only in QuaZip::mdUnzip mode.
|
|
332 |
**/
|
|
333 |
QString getCurrentFileName()const;
|
|
334 |
/// Returns \c unzFile handle.
|
|
335 |
/** You can use this handle to directly call UNZIP part of the
|
|
336 |
* ZIP/UNZIP package functions (see unzip.h).
|
|
337 |
*
|
|
338 |
* \warning When using the handle returned by this function, please
|
|
339 |
* keep in mind that QuaZip class is unable to detect any changes
|
|
340 |
* you make in the ZIP file state (e. g. changing current file, or
|
|
341 |
* closing the handle). So please do not do anything with this
|
|
342 |
* handle that is possible to do with the functions of this class.
|
|
343 |
* Or at least return the handle in the original state before
|
|
344 |
* calling some another function of this class (including implicit
|
|
345 |
* destructor calls and calls from the QuaZipFile objects that refer
|
|
346 |
* to this QuaZip instance!). So if you have changed the current
|
|
347 |
* file in the ZIP archive - then change it back or you may
|
|
348 |
* experience some strange behavior or even crashes.
|
|
349 |
**/
|
|
350 |
unzFile getUnzFile();
|
|
351 |
/// Returns \c zipFile handle.
|
|
352 |
/** You can use this handle to directly call ZIP part of the
|
|
353 |
* ZIP/UNZIP package functions (see zip.h). Warnings about the
|
|
354 |
* getUnzFile() function also apply to this function.
|
|
355 |
**/
|
|
356 |
zipFile getZipFile();
|
|
357 |
};
|
|
358 |
|
|
359 |
#endif
|