summaryrefslogtreecommitdiff
path: root/rbutil/rbutilqt/zip
diff options
context:
space:
mode:
authorNicolas Pennequin <nicolas.pennequin@free.fr>2008-05-11 17:21:14 +0000
committerNicolas Pennequin <nicolas.pennequin@free.fr>2008-05-11 17:21:14 +0000
commit9c54187678281077b8700c1c107f54a0b40d7050 (patch)
treeb07061b11477bfbdfddaa52bee43f4993167dbc0 /rbutil/rbutilqt/zip
parent850c4f98baecf3d3c28e916927d15d3bbd0cd502 (diff)
downloadrockbox-9c54187678281077b8700c1c107f54a0b40d7050.tar.gz
rockbox-9c54187678281077b8700c1c107f54a0b40d7050.zip
Set svn:eol-style on files from the rbutil directory and its subdirectories.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17462 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'rbutil/rbutilqt/zip')
-rw-r--r--rbutil/rbutilqt/zip/unzip.cpp2720
-rw-r--r--rbutil/rbutilqt/zip/unzip.h288
-rw-r--r--rbutil/rbutilqt/zip/unzip_p.h224
-rw-r--r--rbutil/rbutilqt/zip/zip.cpp2442
-rw-r--r--rbutil/rbutilqt/zip/zip.h230
-rw-r--r--rbutil/rbutilqt/zip/zip_p.h186
-rw-r--r--rbutil/rbutilqt/zip/zipentry_p.h156
7 files changed, 3123 insertions, 3123 deletions
diff --git a/rbutil/rbutilqt/zip/unzip.cpp b/rbutil/rbutilqt/zip/unzip.cpp
index 3cc385ab36..d49529bad9 100644
--- a/rbutil/rbutilqt/zip/unzip.cpp
+++ b/rbutil/rbutilqt/zip/unzip.cpp
@@ -1,1360 +1,1360 @@
1/**************************************************************************** 1/****************************************************************************
2** Filename: unzip.cpp 2** Filename: unzip.cpp
3** Last updated [dd/mm/yyyy]: 28/01/2007 3** Last updated [dd/mm/yyyy]: 28/01/2007
4** 4**
5** pkzip 2.0 decompression. 5** pkzip 2.0 decompression.
6** 6**
7** Some of the code has been inspired by other open source projects, 7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip). 8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library. 9** Compression and decompression actually uses the zlib library.
10** 10**
11** Copyright (C) 2007 Angius Fabrizio. All rights reserved. 11** Copyright (C) 2007 Angius Fabrizio. All rights reserved.
12** 12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/). 13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14** 14**
15** This file may be distributed and/or modified under the terms of the 15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software 16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the 17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file. 18** packaging of this file.
19** 19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22** 22**
23** See the file LICENSE.GPL that came with this software distribution or 23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information. 24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25** 25**
26**********************************************************************/ 26**********************************************************************/
27 27
28#include "unzip.h" 28#include "unzip.h"
29#include "unzip_p.h" 29#include "unzip_p.h"
30#include "zipentry_p.h" 30#include "zipentry_p.h"
31 31
32#include <QString> 32#include <QString>
33#include <QStringList> 33#include <QStringList>
34#include <QDir> 34#include <QDir>
35#include <QFile> 35#include <QFile>
36#include <QCoreApplication> 36#include <QCoreApplication>
37 37
38// You can remove this #include if you replace the qDebug() statements. 38// You can remove this #include if you replace the qDebug() statements.
39#include <QtDebug> 39#include <QtDebug>
40 40
41/*! 41/*!
42 \class UnZip unzip.h 42 \class UnZip unzip.h
43 43
44 \brief PKZip 2.0 file decompression. 44 \brief PKZip 2.0 file decompression.
45 Compatibility with later versions is not ensured as they may use 45 Compatibility with later versions is not ensured as they may use
46 unsupported compression algorithms. 46 unsupported compression algorithms.
47 Versions after 2.7 may have an incompatible header format and thus be 47 Versions after 2.7 may have an incompatible header format and thus be
48 completely incompatible. 48 completely incompatible.
49*/ 49*/
50 50
51/*! \enum UnZip::ErrorCode The result of a decompression operation. 51/*! \enum UnZip::ErrorCode The result of a decompression operation.
52 \value UnZip::Ok No error occurred. 52 \value UnZip::Ok No error occurred.
53 \value UnZip::ZlibInit Failed to init or load the zlib library. 53 \value UnZip::ZlibInit Failed to init or load the zlib library.
54 \value UnZip::ZlibError The zlib library returned some error. 54 \value UnZip::ZlibError The zlib library returned some error.
55 \value UnZip::OpenFailed Unable to create or open a device. 55 \value UnZip::OpenFailed Unable to create or open a device.
56 \value UnZip::PartiallyCorrupted Corrupted zip archive - some files could be extracted. 56 \value UnZip::PartiallyCorrupted Corrupted zip archive - some files could be extracted.
57 \value UnZip::Corrupted Corrupted or invalid zip archive. 57 \value UnZip::Corrupted Corrupted or invalid zip archive.
58 \value UnZip::WrongPassword Unable to decrypt a password protected file. 58 \value UnZip::WrongPassword Unable to decrypt a password protected file.
59 \value UnZip::NoOpenArchive No archive has been opened yet. 59 \value UnZip::NoOpenArchive No archive has been opened yet.
60 \value UnZip::FileNotFound Unable to find the requested file in the archive. 60 \value UnZip::FileNotFound Unable to find the requested file in the archive.
61 \value UnZip::ReadFailed Reading of a file failed. 61 \value UnZip::ReadFailed Reading of a file failed.
62 \value UnZip::WriteFailed Writing of a file failed. 62 \value UnZip::WriteFailed Writing of a file failed.
63 \value UnZip::SeekFailed Seek failed. 63 \value UnZip::SeekFailed Seek failed.
64 \value UnZip::CreateDirFailed Could not create a directory. 64 \value UnZip::CreateDirFailed Could not create a directory.
65 \value UnZip::InvalidDevice A null device has been passed as parameter. 65 \value UnZip::InvalidDevice A null device has been passed as parameter.
66 \value UnZip::InvalidArchive This is not a valid (or supported) ZIP archive. 66 \value UnZip::InvalidArchive This is not a valid (or supported) ZIP archive.
67 \value UnZip::HeaderConsistencyError Local header record info does not match with the central directory record info. The archive may be corrupted. 67 \value UnZip::HeaderConsistencyError Local header record info does not match with the central directory record info. The archive may be corrupted.
68 68
69 \value UnZip::Skip Internal use only. 69 \value UnZip::Skip Internal use only.
70 \value UnZip::SkipAll Internal use only. 70 \value UnZip::SkipAll Internal use only.
71*/ 71*/
72 72
73/*! \enum UnZip::ExtractionOptions Some options for the file extraction methods. 73/*! \enum UnZip::ExtractionOptions Some options for the file extraction methods.
74 \value UnZip::ExtractPaths Default. Does not ignore the path of the zipped files. 74 \value UnZip::ExtractPaths Default. Does not ignore the path of the zipped files.
75 \value UnZip::SkipPaths Default. Ignores the path of the zipped files and extracts them all to the same root directory. 75 \value UnZip::SkipPaths Default. Ignores the path of the zipped files and extracts them all to the same root directory.
76*/ 76*/
77 77
78//! Local header size (excluding signature, excluding variable length fields) 78//! Local header size (excluding signature, excluding variable length fields)
79#define UNZIP_LOCAL_HEADER_SIZE 26 79#define UNZIP_LOCAL_HEADER_SIZE 26
80//! Central Directory file entry size (excluding signature, excluding variable length fields) 80//! Central Directory file entry size (excluding signature, excluding variable length fields)
81#define UNZIP_CD_ENTRY_SIZE_NS 42 81#define UNZIP_CD_ENTRY_SIZE_NS 42
82//! Data descriptor size (excluding signature) 82//! Data descriptor size (excluding signature)
83#define UNZIP_DD_SIZE 12 83#define UNZIP_DD_SIZE 12
84//! End Of Central Directory size (including signature, excluding variable length fields) 84//! End Of Central Directory size (including signature, excluding variable length fields)
85#define UNZIP_EOCD_SIZE 22 85#define UNZIP_EOCD_SIZE 22
86//! Local header entry encryption header size 86//! Local header entry encryption header size
87#define UNZIP_LOCAL_ENC_HEADER_SIZE 12 87#define UNZIP_LOCAL_ENC_HEADER_SIZE 12
88 88
89// Some offsets inside a CD record (excluding signature) 89// Some offsets inside a CD record (excluding signature)
90#define UNZIP_CD_OFF_VERSION 0 90#define UNZIP_CD_OFF_VERSION 0
91#define UNZIP_CD_OFF_GPFLAG 4 91#define UNZIP_CD_OFF_GPFLAG 4
92#define UNZIP_CD_OFF_CMETHOD 6 92#define UNZIP_CD_OFF_CMETHOD 6
93#define UNZIP_CD_OFF_MODT 8 93#define UNZIP_CD_OFF_MODT 8
94#define UNZIP_CD_OFF_MODD 10 94#define UNZIP_CD_OFF_MODD 10
95#define UNZIP_CD_OFF_CRC32 12 95#define UNZIP_CD_OFF_CRC32 12
96#define UNZIP_CD_OFF_CSIZE 16 96#define UNZIP_CD_OFF_CSIZE 16
97#define UNZIP_CD_OFF_USIZE 20 97#define UNZIP_CD_OFF_USIZE 20
98#define UNZIP_CD_OFF_NAMELEN 24 98#define UNZIP_CD_OFF_NAMELEN 24
99#define UNZIP_CD_OFF_XLEN 26 99#define UNZIP_CD_OFF_XLEN 26
100#define UNZIP_CD_OFF_COMMLEN 28 100#define UNZIP_CD_OFF_COMMLEN 28
101#define UNZIP_CD_OFF_LHOFFSET 38 101#define UNZIP_CD_OFF_LHOFFSET 38
102 102
103// Some offsets inside a local header record (excluding signature) 103// Some offsets inside a local header record (excluding signature)
104#define UNZIP_LH_OFF_VERSION 0 104#define UNZIP_LH_OFF_VERSION 0
105#define UNZIP_LH_OFF_GPFLAG 2 105#define UNZIP_LH_OFF_GPFLAG 2
106#define UNZIP_LH_OFF_CMETHOD 4 106#define UNZIP_LH_OFF_CMETHOD 4
107#define UNZIP_LH_OFF_MODT 6 107#define UNZIP_LH_OFF_MODT 6
108#define UNZIP_LH_OFF_MODD 8 108#define UNZIP_LH_OFF_MODD 8
109#define UNZIP_LH_OFF_CRC32 10 109#define UNZIP_LH_OFF_CRC32 10
110#define UNZIP_LH_OFF_CSIZE 14 110#define UNZIP_LH_OFF_CSIZE 14
111#define UNZIP_LH_OFF_USIZE 18 111#define UNZIP_LH_OFF_USIZE 18
112#define UNZIP_LH_OFF_NAMELEN 22 112#define UNZIP_LH_OFF_NAMELEN 22
113#define UNZIP_LH_OFF_XLEN 24 113#define UNZIP_LH_OFF_XLEN 24
114 114
115// Some offsets inside a data descriptor record (excluding signature) 115// Some offsets inside a data descriptor record (excluding signature)
116#define UNZIP_DD_OFF_CRC32 0 116#define UNZIP_DD_OFF_CRC32 0
117#define UNZIP_DD_OFF_CSIZE 4 117#define UNZIP_DD_OFF_CSIZE 4
118#define UNZIP_DD_OFF_USIZE 8 118#define UNZIP_DD_OFF_USIZE 8
119 119
120// Some offsets inside a EOCD record 120// Some offsets inside a EOCD record
121#define UNZIP_EOCD_OFF_ENTRIES 6 121#define UNZIP_EOCD_OFF_ENTRIES 6
122#define UNZIP_EOCD_OFF_CDOFF 12 122#define UNZIP_EOCD_OFF_CDOFF 12
123#define UNZIP_EOCD_OFF_COMMLEN 16 123#define UNZIP_EOCD_OFF_COMMLEN 16
124 124
125/*! 125/*!
126 Max version handled by this API. 126 Max version handled by this API.
127 0x1B = 2.7 --> full compatibility only up to version 2.0 (0x14) 127 0x1B = 2.7 --> full compatibility only up to version 2.0 (0x14)
128 versions from 2.1 to 2.7 may use unsupported compression methods 128 versions from 2.1 to 2.7 may use unsupported compression methods
129 versions after 2.7 may have an incompatible header format 129 versions after 2.7 may have an incompatible header format
130*/ 130*/
131#define UNZIP_VERSION 0x1B 131#define UNZIP_VERSION 0x1B
132//! Full compatibility granted until this version 132//! Full compatibility granted until this version
133#define UNZIP_VERSION_STRICT 0x14 133#define UNZIP_VERSION_STRICT 0x14
134 134
135//! CRC32 routine 135//! CRC32 routine
136#define CRC32(c, b) crcTable[((int)c^b) & 0xff] ^ (c >> 8) 136#define CRC32(c, b) crcTable[((int)c^b) & 0xff] ^ (c >> 8)
137 137
138//! Checks if some file has been already extracted. 138//! Checks if some file has been already extracted.
139#define UNZIP_CHECK_FOR_VALID_DATA \ 139#define UNZIP_CHECK_FOR_VALID_DATA \
140 {\ 140 {\
141 if (headers != 0)\ 141 if (headers != 0)\
142 {\ 142 {\
143 qDebug() << "Corrupted zip archive. Some files might be extracted.";\ 143 qDebug() << "Corrupted zip archive. Some files might be extracted.";\
144 ec = headers->size() != 0 ? UnZip::PartiallyCorrupted : UnZip::Corrupted;\ 144 ec = headers->size() != 0 ? UnZip::PartiallyCorrupted : UnZip::Corrupted;\
145 break;\ 145 break;\
146 }\ 146 }\
147 else\ 147 else\
148 {\ 148 {\
149 delete device;\ 149 delete device;\
150 device = 0;\ 150 device = 0;\
151 qDebug() << "Corrupted or invalid zip archive";\ 151 qDebug() << "Corrupted or invalid zip archive";\
152 ec = UnZip::Corrupted;\ 152 ec = UnZip::Corrupted;\
153 break;\ 153 break;\
154 }\ 154 }\
155 } 155 }
156 156
157 157
158/************************************************************************ 158/************************************************************************
159 Public interface 159 Public interface
160*************************************************************************/ 160*************************************************************************/
161 161
162/*! 162/*!
163 Creates a new Zip file decompressor. 163 Creates a new Zip file decompressor.
164*/ 164*/
165UnZip::UnZip() 165UnZip::UnZip()
166{ 166{
167 d = new UnzipPrivate; 167 d = new UnzipPrivate;
168} 168}
169 169
170/*! 170/*!
171 Closes any open archive and releases used resources. 171 Closes any open archive and releases used resources.
172*/ 172*/
173UnZip::~UnZip() 173UnZip::~UnZip()
174{ 174{
175 closeArchive(); 175 closeArchive();
176 delete d; 176 delete d;
177} 177}
178 178
179/*! 179/*!
180 Returns true if there is an open archive. 180 Returns true if there is an open archive.
181*/ 181*/
182bool UnZip::isOpen() const 182bool UnZip::isOpen() const
183{ 183{
184 return d->device != 0; 184 return d->device != 0;
185} 185}
186 186
187/*! 187/*!
188 Opens a zip archive and reads the files list. Closes any previously opened archive. 188 Opens a zip archive and reads the files list. Closes any previously opened archive.
189*/ 189*/
190UnZip::ErrorCode UnZip::openArchive(const QString& filename) 190UnZip::ErrorCode UnZip::openArchive(const QString& filename)
191{ 191{
192 QFile* file = new QFile(filename); 192 QFile* file = new QFile(filename);
193 193
194 if (!file->exists()) { 194 if (!file->exists()) {
195 delete file; 195 delete file;
196 return UnZip::FileNotFound; 196 return UnZip::FileNotFound;
197 } 197 }
198 198
199 if (!file->open(QIODevice::ReadOnly)) { 199 if (!file->open(QIODevice::ReadOnly)) {
200 delete file; 200 delete file;
201 return UnZip::OpenFailed; 201 return UnZip::OpenFailed;
202 } 202 }
203 203
204 return openArchive(file); 204 return openArchive(file);
205} 205}
206 206
207/*! 207/*!
208 Opens a zip archive and reads the entries list. 208 Opens a zip archive and reads the entries list.
209 Closes any previously opened archive. 209 Closes any previously opened archive.
210 \warning The class takes ownership of the device so don't delete it! 210 \warning The class takes ownership of the device so don't delete it!
211*/ 211*/
212UnZip::ErrorCode UnZip::openArchive(QIODevice* device) 212UnZip::ErrorCode UnZip::openArchive(QIODevice* device)
213{ 213{
214 if (device == 0) 214 if (device == 0)
215 { 215 {
216 qDebug() << "Invalid device."; 216 qDebug() << "Invalid device.";
217 return UnZip::InvalidDevice; 217 return UnZip::InvalidDevice;
218 } 218 }
219 219
220 return d->openArchive(device); 220 return d->openArchive(device);
221} 221}
222 222
223/*! 223/*!
224 Closes the archive and releases all the used resources (like cached passwords). 224 Closes the archive and releases all the used resources (like cached passwords).
225*/ 225*/
226void UnZip::closeArchive() 226void UnZip::closeArchive()
227{ 227{
228 d->closeArchive(); 228 d->closeArchive();
229} 229}
230 230
231QString UnZip::archiveComment() const 231QString UnZip::archiveComment() const
232{ 232{
233 if (d->device == 0) 233 if (d->device == 0)
234 return QString(); 234 return QString();
235 return d->comment; 235 return d->comment;
236} 236}
237 237
238/*! 238/*!
239 Returns a locale translated error string for a given error code. 239 Returns a locale translated error string for a given error code.
240*/ 240*/
241QString UnZip::formatError(UnZip::ErrorCode c) const 241QString UnZip::formatError(UnZip::ErrorCode c) const
242{ 242{
243 switch (c) 243 switch (c)
244 { 244 {
245 case Ok: return QCoreApplication::translate("UnZip", "ZIP operation completed successfully."); break; 245 case Ok: return QCoreApplication::translate("UnZip", "ZIP operation completed successfully."); break;
246 case ZlibInit: return QCoreApplication::translate("UnZip", "Failed to initialize or load zlib library."); break; 246 case ZlibInit: return QCoreApplication::translate("UnZip", "Failed to initialize or load zlib library."); break;
247 case ZlibError: return QCoreApplication::translate("UnZip", "zlib library error."); break; 247 case ZlibError: return QCoreApplication::translate("UnZip", "zlib library error."); break;
248 case OpenFailed: return QCoreApplication::translate("UnZip", "Unable to create or open file."); break; 248 case OpenFailed: return QCoreApplication::translate("UnZip", "Unable to create or open file."); break;
249 case PartiallyCorrupted: return QCoreApplication::translate("UnZip", "Partially corrupted archive. Some files might be extracted."); break; 249 case PartiallyCorrupted: return QCoreApplication::translate("UnZip", "Partially corrupted archive. Some files might be extracted."); break;
250 case Corrupted: return QCoreApplication::translate("UnZip", "Corrupted archive."); break; 250 case Corrupted: return QCoreApplication::translate("UnZip", "Corrupted archive."); break;
251 case WrongPassword: return QCoreApplication::translate("UnZip", "Wrong password."); break; 251 case WrongPassword: return QCoreApplication::translate("UnZip", "Wrong password."); break;
252 case NoOpenArchive: return QCoreApplication::translate("UnZip", "No archive has been created yet."); break; 252 case NoOpenArchive: return QCoreApplication::translate("UnZip", "No archive has been created yet."); break;
253 case FileNotFound: return QCoreApplication::translate("UnZip", "File or directory does not exist."); break; 253 case FileNotFound: return QCoreApplication::translate("UnZip", "File or directory does not exist."); break;
254 case ReadFailed: return QCoreApplication::translate("UnZip", "File read error."); break; 254 case ReadFailed: return QCoreApplication::translate("UnZip", "File read error."); break;
255 case WriteFailed: return QCoreApplication::translate("UnZip", "File write error."); break; 255 case WriteFailed: return QCoreApplication::translate("UnZip", "File write error."); break;
256 case SeekFailed: return QCoreApplication::translate("UnZip", "File seek error."); break; 256 case SeekFailed: return QCoreApplication::translate("UnZip", "File seek error."); break;
257 case CreateDirFailed: return QCoreApplication::translate("UnZip", "Unable to create a directory."); break; 257 case CreateDirFailed: return QCoreApplication::translate("UnZip", "Unable to create a directory."); break;
258 case InvalidDevice: return QCoreApplication::translate("UnZip", "Invalid device."); break; 258 case InvalidDevice: return QCoreApplication::translate("UnZip", "Invalid device."); break;
259 case InvalidArchive: return QCoreApplication::translate("UnZip", "Invalid or incompatible zip archive."); break; 259 case InvalidArchive: return QCoreApplication::translate("UnZip", "Invalid or incompatible zip archive."); break;
260 case HeaderConsistencyError: return QCoreApplication::translate("UnZip", "Inconsistent headers. Archive might be corrupted."); break; 260 case HeaderConsistencyError: return QCoreApplication::translate("UnZip", "Inconsistent headers. Archive might be corrupted."); break;
261 default: ; 261 default: ;
262 } 262 }
263 263
264 return QCoreApplication::translate("UnZip", "Unknown error."); 264 return QCoreApplication::translate("UnZip", "Unknown error.");
265} 265}
266 266
267/*! 267/*!
268 Returns true if the archive contains a file with the given path and name. 268 Returns true if the archive contains a file with the given path and name.
269*/ 269*/
270bool UnZip::contains(const QString& file) const 270bool UnZip::contains(const QString& file) const
271{ 271{
272 if (d->headers == 0) 272 if (d->headers == 0)
273 return false; 273 return false;
274 274
275 return d->headers->contains(file); 275 return d->headers->contains(file);
276} 276}
277 277
278/*! 278/*!
279 Returns complete paths of files and directories in this archive. 279 Returns complete paths of files and directories in this archive.
280*/ 280*/
281QStringList UnZip::fileList() const 281QStringList UnZip::fileList() const
282{ 282{
283 return d->headers == 0 ? QStringList() : d->headers->keys(); 283 return d->headers == 0 ? QStringList() : d->headers->keys();
284} 284}
285 285
286/*! 286/*!
287 Returns information for each (correctly parsed) entry of this archive. 287 Returns information for each (correctly parsed) entry of this archive.
288*/ 288*/
289QList<UnZip::ZipEntry> UnZip::entryList() const 289QList<UnZip::ZipEntry> UnZip::entryList() const
290{ 290{
291 QList<UnZip::ZipEntry> list; 291 QList<UnZip::ZipEntry> list;
292 292
293 if (d->headers != 0) 293 if (d->headers != 0)
294 { 294 {
295 for (QMap<QString,ZipEntryP*>::ConstIterator it = d->headers->constBegin(); it != d->headers->constEnd(); ++it) 295 for (QMap<QString,ZipEntryP*>::ConstIterator it = d->headers->constBegin(); it != d->headers->constEnd(); ++it)
296 { 296 {
297 const ZipEntryP* entry = it.value(); 297 const ZipEntryP* entry = it.value();
298 Q_ASSERT(entry != 0); 298 Q_ASSERT(entry != 0);
299 299
300 ZipEntry z; 300 ZipEntry z;
301 301
302 z.filename = it.key(); 302 z.filename = it.key();
303 if (!entry->comment.isEmpty()) 303 if (!entry->comment.isEmpty())
304 z.comment = entry->comment; 304 z.comment = entry->comment;
305 z.compressedSize = entry->szComp; 305 z.compressedSize = entry->szComp;
306 z.uncompressedSize = entry->szUncomp; 306 z.uncompressedSize = entry->szUncomp;
307 z.crc32 = entry->crc; 307 z.crc32 = entry->crc;
308 z.lastModified = d->convertDateTime(entry->modDate, entry->modTime); 308 z.lastModified = d->convertDateTime(entry->modDate, entry->modTime);
309 309
310 z.compression = entry->compMethod == 0 ? NoCompression : entry->compMethod == 8 ? Deflated : UnknownCompression; 310 z.compression = entry->compMethod == 0 ? NoCompression : entry->compMethod == 8 ? Deflated : UnknownCompression;
311 z.type = z.filename.endsWith("/") ? Directory : File; 311 z.type = z.filename.endsWith("/") ? Directory : File;
312 312
313 z.encrypted = entry->isEncrypted(); 313 z.encrypted = entry->isEncrypted();
314 314
315 list.append(z); 315 list.append(z);
316 } 316 }
317 } 317 }
318 318
319 return list; 319 return list;
320} 320}
321 321
322/*! 322/*!
323 Extracts the whole archive to a directory. 323 Extracts the whole archive to a directory.
324*/ 324*/
325UnZip::ErrorCode UnZip::extractAll(const QString& dirname, ExtractionOptions options) 325UnZip::ErrorCode UnZip::extractAll(const QString& dirname, ExtractionOptions options)
326{ 326{
327 return extractAll(QDir(dirname), options); 327 return extractAll(QDir(dirname), options);
328} 328}
329 329
330/*! 330/*!
331 Extracts the whole archive to a directory. 331 Extracts the whole archive to a directory.
332*/ 332*/
333UnZip::ErrorCode UnZip::extractAll(const QDir& dir, ExtractionOptions options) 333UnZip::ErrorCode UnZip::extractAll(const QDir& dir, ExtractionOptions options)
334{ 334{
335 // this should only happen if we didn't call openArchive() yet 335 // this should only happen if we didn't call openArchive() yet
336 if (d->device == 0) 336 if (d->device == 0)
337 return NoOpenArchive; 337 return NoOpenArchive;
338 338
339 if (d->headers == 0) 339 if (d->headers == 0)
340 return Ok; 340 return Ok;
341 341
342 bool end = false; 342 bool end = false;
343 for (QMap<QString,ZipEntryP*>::Iterator itr = d->headers->begin(); itr != d->headers->end(); ++itr) 343 for (QMap<QString,ZipEntryP*>::Iterator itr = d->headers->begin(); itr != d->headers->end(); ++itr)
344 { 344 {
345 ZipEntryP* entry = itr.value(); 345 ZipEntryP* entry = itr.value();
346 Q_ASSERT(entry != 0); 346 Q_ASSERT(entry != 0);
347 347
348 if ((entry->isEncrypted()) && d->skipAllEncrypted) 348 if ((entry->isEncrypted()) && d->skipAllEncrypted)
349 continue; 349 continue;
350 350
351 switch (d->extractFile(itr.key(), *entry, dir, options)) 351 switch (d->extractFile(itr.key(), *entry, dir, options))
352 { 352 {
353 case Corrupted: 353 case Corrupted:
354 qDebug() << "Removing corrupted entry" << itr.key(); 354 qDebug() << "Removing corrupted entry" << itr.key();
355 d->headers->erase(itr++); 355 d->headers->erase(itr++);
356 if (itr == d->headers->end()) 356 if (itr == d->headers->end())
357 end = true; 357 end = true;
358 break; 358 break;
359 case CreateDirFailed: 359 case CreateDirFailed:
360 break; 360 break;
361 case Skip: 361 case Skip:
362 break; 362 break;
363 case SkipAll: 363 case SkipAll:
364 d->skipAllEncrypted = true; 364 d->skipAllEncrypted = true;
365 break; 365 break;
366 default: 366 default:
367 ; 367 ;
368 } 368 }
369 369
370 if (end) 370 if (end)
371 break; 371 break;
372 } 372 }
373 373
374 return Ok; 374 return Ok;
375} 375}
376 376
377/*! 377/*!
378 Extracts a single file to a directory. 378 Extracts a single file to a directory.
379*/ 379*/
380UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QString& dirname, ExtractionOptions options) 380UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QString& dirname, ExtractionOptions options)
381{ 381{
382 return extractFile(filename, QDir(dirname), options); 382 return extractFile(filename, QDir(dirname), options);
383} 383}
384 384
385/*! 385/*!
386 Extracts a single file to a directory. 386 Extracts a single file to a directory.
387*/ 387*/
388UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QDir& dir, ExtractionOptions options) 388UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QDir& dir, ExtractionOptions options)
389{ 389{
390 QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename); 390 QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename);
391 if (itr != d->headers->end()) 391 if (itr != d->headers->end())
392 { 392 {
393 ZipEntryP* entry = itr.value(); 393 ZipEntryP* entry = itr.value();
394 Q_ASSERT(entry != 0); 394 Q_ASSERT(entry != 0);
395 return d->extractFile(itr.key(), *entry, dir, options); 395 return d->extractFile(itr.key(), *entry, dir, options);
396 } 396 }
397 397
398 return FileNotFound; 398 return FileNotFound;
399} 399}
400 400
401/*! 401/*!
402 Extracts a single file to a directory. 402 Extracts a single file to a directory.
403*/ 403*/
404UnZip::ErrorCode UnZip::extractFile(const QString& filename, QIODevice* dev, ExtractionOptions options) 404UnZip::ErrorCode UnZip::extractFile(const QString& filename, QIODevice* dev, ExtractionOptions options)
405{ 405{
406 if (dev == 0) 406 if (dev == 0)
407 return InvalidDevice; 407 return InvalidDevice;
408 408
409 QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename); 409 QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename);
410 if (itr != d->headers->end()) { 410 if (itr != d->headers->end()) {
411 ZipEntryP* entry = itr.value(); 411 ZipEntryP* entry = itr.value();
412 Q_ASSERT(entry != 0); 412 Q_ASSERT(entry != 0);
413 return d->extractFile(itr.key(), *entry, dev, options); 413 return d->extractFile(itr.key(), *entry, dev, options);
414 } 414 }
415 415
416 return FileNotFound; 416 return FileNotFound;
417} 417}
418 418
419/*! 419/*!
420 Extracts a list of files. 420 Extracts a list of files.
421 Stops extraction at the first error (but continues if a file does not exist in the archive). 421 Stops extraction at the first error (but continues if a file does not exist in the archive).
422 */ 422 */
423UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options) 423UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options)
424{ 424{
425 QDir dir(dirname); 425 QDir dir(dirname);
426 ErrorCode ec; 426 ErrorCode ec;
427 427
428 for (QStringList::ConstIterator itr = filenames.constBegin(); itr != filenames.constEnd(); ++itr) 428 for (QStringList::ConstIterator itr = filenames.constBegin(); itr != filenames.constEnd(); ++itr)
429 { 429 {
430 ec = extractFile(*itr, dir, options); 430 ec = extractFile(*itr, dir, options);
431 if (ec == FileNotFound) 431 if (ec == FileNotFound)
432 continue; 432 continue;
433 if (ec != Ok) 433 if (ec != Ok)
434 return ec; 434 return ec;
435 } 435 }
436 436
437 return Ok; 437 return Ok;
438} 438}
439 439
440/*! 440/*!
441 Extracts a list of files. 441 Extracts a list of files.
442 Stops extraction at the first error (but continues if a file does not exist in the archive). 442 Stops extraction at the first error (but continues if a file does not exist in the archive).
443 */ 443 */
444UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options) 444UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options)
445{ 445{
446 ErrorCode ec; 446 ErrorCode ec;
447 447
448 for (QStringList::ConstIterator itr = filenames.constBegin(); itr != filenames.constEnd(); ++itr) 448 for (QStringList::ConstIterator itr = filenames.constBegin(); itr != filenames.constEnd(); ++itr)
449 { 449 {
450 ec = extractFile(*itr, dir, options); 450 ec = extractFile(*itr, dir, options);
451 if (ec == FileNotFound) 451 if (ec == FileNotFound)
452 continue; 452 continue;
453 if (ec != Ok) 453 if (ec != Ok)
454 return ec; 454 return ec;
455 } 455 }
456 456
457 return Ok; 457 return Ok;
458} 458}
459 459
460/*! 460/*!
461 Remove/replace this method to add your own password retrieval routine. 461 Remove/replace this method to add your own password retrieval routine.
462*/ 462*/
463void UnZip::setPassword(const QString& pwd) 463void UnZip::setPassword(const QString& pwd)
464{ 464{
465 d->password = pwd; 465 d->password = pwd;
466} 466}
467 467
468/*! 468/*!
469 ZipEntry constructor - initialize data. Type is set to File. 469 ZipEntry constructor - initialize data. Type is set to File.
470*/ 470*/
471UnZip::ZipEntry::ZipEntry() 471UnZip::ZipEntry::ZipEntry()
472{ 472{
473 compressedSize = uncompressedSize = crc32 = 0; 473 compressedSize = uncompressedSize = crc32 = 0;
474 compression = NoCompression; 474 compression = NoCompression;
475 type = File; 475 type = File;
476 encrypted = false; 476 encrypted = false;
477} 477}
478 478
479 479
480/************************************************************************ 480/************************************************************************
481 Private interface 481 Private interface
482*************************************************************************/ 482*************************************************************************/
483 483
484//! \internal 484//! \internal
485UnzipPrivate::UnzipPrivate() 485UnzipPrivate::UnzipPrivate()
486{ 486{
487 skipAllEncrypted = false; 487 skipAllEncrypted = false;
488 headers = 0; 488 headers = 0;
489 device = 0; 489 device = 0;
490 490
491 uBuffer = (unsigned char*) buffer1; 491 uBuffer = (unsigned char*) buffer1;
492 crcTable = (quint32*) get_crc_table(); 492 crcTable = (quint32*) get_crc_table();
493 493
494 cdOffset = eocdOffset = 0; 494 cdOffset = eocdOffset = 0;
495 cdEntryCount = 0; 495 cdEntryCount = 0;
496 unsupportedEntryCount = 0; 496 unsupportedEntryCount = 0;
497} 497}
498 498
499//! \internal Parses a Zip archive. 499//! \internal Parses a Zip archive.
500UnZip::ErrorCode UnzipPrivate::openArchive(QIODevice* dev) 500UnZip::ErrorCode UnzipPrivate::openArchive(QIODevice* dev)
501{ 501{
502 Q_ASSERT(dev != 0); 502 Q_ASSERT(dev != 0);
503 503
504 if (device != 0) 504 if (device != 0)
505 closeArchive(); 505 closeArchive();
506 506
507 device = dev; 507 device = dev;
508 508
509 if (!(device->isOpen() || device->open(QIODevice::ReadOnly))) 509 if (!(device->isOpen() || device->open(QIODevice::ReadOnly)))
510 { 510 {
511 delete device; 511 delete device;
512 device = 0; 512 device = 0;
513 513
514 qDebug() << "Unable to open device for reading"; 514 qDebug() << "Unable to open device for reading";
515 return UnZip::OpenFailed; 515 return UnZip::OpenFailed;
516 } 516 }
517 517
518 UnZip::ErrorCode ec; 518 UnZip::ErrorCode ec;
519 519
520 ec = seekToCentralDirectory(); 520 ec = seekToCentralDirectory();
521 if (ec != UnZip::Ok) 521 if (ec != UnZip::Ok)
522 { 522 {
523 closeArchive(); 523 closeArchive();
524 return ec; 524 return ec;
525 } 525 }
526 526
527 //! \todo Ignore CD entry count? CD may be corrupted. 527 //! \todo Ignore CD entry count? CD may be corrupted.
528 if (cdEntryCount == 0) 528 if (cdEntryCount == 0)
529 { 529 {
530 return UnZip::Ok; 530 return UnZip::Ok;
531 } 531 }
532 532
533 bool continueParsing = true; 533 bool continueParsing = true;
534 534
535 while (continueParsing) 535 while (continueParsing)
536 { 536 {
537 if (device->read(buffer1, 4) != 4) 537 if (device->read(buffer1, 4) != 4)
538 UNZIP_CHECK_FOR_VALID_DATA 538 UNZIP_CHECK_FOR_VALID_DATA
539 539
540 if (! (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x01 && buffer1[3] == 0x02) ) 540 if (! (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x01 && buffer1[3] == 0x02) )
541 break; 541 break;
542 542
543 if ( (ec = parseCentralDirectoryRecord()) != UnZip::Ok ) 543 if ( (ec = parseCentralDirectoryRecord()) != UnZip::Ok )
544 break; 544 break;
545 } 545 }
546 546
547 if (ec != UnZip::Ok) 547 if (ec != UnZip::Ok)
548 closeArchive(); 548 closeArchive();
549 549
550 return ec; 550 return ec;
551} 551}
552 552
553/* 553/*
554 \internal Parses a local header record and makes some consistency check 554 \internal Parses a local header record and makes some consistency check
555 with the information stored in the Central Directory record for this entry 555 with the information stored in the Central Directory record for this entry
556 that has been previously parsed. 556 that has been previously parsed.
557 \todo Optional consistency check (as a ExtractionOptions flag) 557 \todo Optional consistency check (as a ExtractionOptions flag)
558 558
559 local file header signature 4 bytes (0x04034b50) 559 local file header signature 4 bytes (0x04034b50)
560 version needed to extract 2 bytes 560 version needed to extract 2 bytes
561 general purpose bit flag 2 bytes 561 general purpose bit flag 2 bytes
562 compression method 2 bytes 562 compression method 2 bytes
563 last mod file time 2 bytes 563 last mod file time 2 bytes
564 last mod file date 2 bytes 564 last mod file date 2 bytes
565 crc-32 4 bytes 565 crc-32 4 bytes
566 compressed size 4 bytes 566 compressed size 4 bytes
567 uncompressed size 4 bytes 567 uncompressed size 4 bytes
568 file name length 2 bytes 568 file name length 2 bytes
569 extra field length 2 bytes 569 extra field length 2 bytes
570 570
571 file name (variable size) 571 file name (variable size)
572 extra field (variable size) 572 extra field (variable size)
573*/ 573*/
574UnZip::ErrorCode UnzipPrivate::parseLocalHeaderRecord(const QString& path, ZipEntryP& entry) 574UnZip::ErrorCode UnzipPrivate::parseLocalHeaderRecord(const QString& path, ZipEntryP& entry)
575{ 575{
576 if (!device->seek(entry.lhOffset)) 576 if (!device->seek(entry.lhOffset))
577 return UnZip::SeekFailed; 577 return UnZip::SeekFailed;
578 578
579 // Test signature 579 // Test signature
580 if (device->read(buffer1, 4) != 4) 580 if (device->read(buffer1, 4) != 4)
581 return UnZip::ReadFailed; 581 return UnZip::ReadFailed;
582 582
583 if ((buffer1[0] != 'P') || (buffer1[1] != 'K') || (buffer1[2] != 0x03) || (buffer1[3] != 0x04)) 583 if ((buffer1[0] != 'P') || (buffer1[1] != 'K') || (buffer1[2] != 0x03) || (buffer1[3] != 0x04))
584 return UnZip::InvalidArchive; 584 return UnZip::InvalidArchive;
585 585
586 if (device->read(buffer1, UNZIP_LOCAL_HEADER_SIZE) != UNZIP_LOCAL_HEADER_SIZE) 586 if (device->read(buffer1, UNZIP_LOCAL_HEADER_SIZE) != UNZIP_LOCAL_HEADER_SIZE)
587 return UnZip::ReadFailed; 587 return UnZip::ReadFailed;
588 588
589 /* 589 /*
590 Check 3rd general purpose bit flag. 590 Check 3rd general purpose bit flag.
591 591
592 "bit 3: If this bit is set, the fields crc-32, compressed size 592 "bit 3: If this bit is set, the fields crc-32, compressed size
593 and uncompressed size are set to zero in the local 593 and uncompressed size are set to zero in the local
594 header. The correct values are put in the data descriptor 594 header. The correct values are put in the data descriptor
595 immediately following the compressed data." 595 immediately following the compressed data."
596 */ 596 */
597 bool hasDataDescriptor = entry.hasDataDescriptor(); 597 bool hasDataDescriptor = entry.hasDataDescriptor();
598 598
599 bool checkFailed = false; 599 bool checkFailed = false;
600 600
601 if (!checkFailed) 601 if (!checkFailed)
602 checkFailed = entry.compMethod != getUShort(uBuffer, UNZIP_LH_OFF_CMETHOD); 602 checkFailed = entry.compMethod != getUShort(uBuffer, UNZIP_LH_OFF_CMETHOD);
603 if (!checkFailed) 603 if (!checkFailed)
604 checkFailed = entry.gpFlag[0] != uBuffer[UNZIP_LH_OFF_GPFLAG]; 604 checkFailed = entry.gpFlag[0] != uBuffer[UNZIP_LH_OFF_GPFLAG];
605 if (!checkFailed) 605 if (!checkFailed)
606 checkFailed = entry.gpFlag[1] != uBuffer[UNZIP_LH_OFF_GPFLAG + 1]; 606 checkFailed = entry.gpFlag[1] != uBuffer[UNZIP_LH_OFF_GPFLAG + 1];
607 if (!checkFailed) 607 if (!checkFailed)
608 checkFailed = entry.modTime[0] != uBuffer[UNZIP_LH_OFF_MODT]; 608 checkFailed = entry.modTime[0] != uBuffer[UNZIP_LH_OFF_MODT];
609 if (!checkFailed) 609 if (!checkFailed)
610 checkFailed = entry.modTime[1] != uBuffer[UNZIP_LH_OFF_MODT + 1]; 610 checkFailed = entry.modTime[1] != uBuffer[UNZIP_LH_OFF_MODT + 1];
611 if (!checkFailed) 611 if (!checkFailed)
612 checkFailed = entry.modDate[0] != uBuffer[UNZIP_LH_OFF_MODD]; 612 checkFailed = entry.modDate[0] != uBuffer[UNZIP_LH_OFF_MODD];
613 if (!checkFailed) 613 if (!checkFailed)
614 checkFailed = entry.modDate[1] != uBuffer[UNZIP_LH_OFF_MODD + 1]; 614 checkFailed = entry.modDate[1] != uBuffer[UNZIP_LH_OFF_MODD + 1];
615 if (!hasDataDescriptor) 615 if (!hasDataDescriptor)
616 { 616 {
617 if (!checkFailed) 617 if (!checkFailed)
618 checkFailed = entry.crc != getULong(uBuffer, UNZIP_LH_OFF_CRC32); 618 checkFailed = entry.crc != getULong(uBuffer, UNZIP_LH_OFF_CRC32);
619 if (!checkFailed) 619 if (!checkFailed)
620 checkFailed = entry.szComp != getULong(uBuffer, UNZIP_LH_OFF_CSIZE); 620 checkFailed = entry.szComp != getULong(uBuffer, UNZIP_LH_OFF_CSIZE);
621 if (!checkFailed) 621 if (!checkFailed)
622 checkFailed = entry.szUncomp != getULong(uBuffer, UNZIP_LH_OFF_USIZE); 622 checkFailed = entry.szUncomp != getULong(uBuffer, UNZIP_LH_OFF_USIZE);
623 } 623 }
624 624
625 if (checkFailed) 625 if (checkFailed)
626 return UnZip::HeaderConsistencyError; 626 return UnZip::HeaderConsistencyError;
627 627
628 // Check filename 628 // Check filename
629 quint16 szName = getUShort(uBuffer, UNZIP_LH_OFF_NAMELEN); 629 quint16 szName = getUShort(uBuffer, UNZIP_LH_OFF_NAMELEN);
630 if (szName == 0) 630 if (szName == 0)
631 return UnZip::HeaderConsistencyError; 631 return UnZip::HeaderConsistencyError;
632 632
633 if (device->read(buffer2, szName) != szName) 633 if (device->read(buffer2, szName) != szName)
634 return UnZip::ReadFailed; 634 return UnZip::ReadFailed;
635 635
636 QString filename = QString::fromAscii(buffer2, szName); 636 QString filename = QString::fromAscii(buffer2, szName);
637 if (filename != path) 637 if (filename != path)
638 { 638 {
639 qDebug() << "Filename in local header mismatches."; 639 qDebug() << "Filename in local header mismatches.";
640 return UnZip::HeaderConsistencyError; 640 return UnZip::HeaderConsistencyError;
641 } 641 }
642 642
643 // Skip extra field 643 // Skip extra field
644 quint16 szExtra = getUShort(uBuffer, UNZIP_LH_OFF_XLEN); 644 quint16 szExtra = getUShort(uBuffer, UNZIP_LH_OFF_XLEN);
645 if (szExtra != 0) 645 if (szExtra != 0)
646 { 646 {
647 if (!device->seek(device->pos() + szExtra)) 647 if (!device->seek(device->pos() + szExtra))
648 return UnZip::SeekFailed; 648 return UnZip::SeekFailed;
649 } 649 }
650 650
651 entry.dataOffset = device->pos(); 651 entry.dataOffset = device->pos();
652 652
653 if (hasDataDescriptor) 653 if (hasDataDescriptor)
654 { 654 {
655 /* 655 /*
656 The data descriptor has this OPTIONAL signature: PK\7\8 656 The data descriptor has this OPTIONAL signature: PK\7\8
657 We try to skip the compressed data relying on the size set in the 657 We try to skip the compressed data relying on the size set in the
658 Central Directory record. 658 Central Directory record.
659 */ 659 */
660 if (!device->seek(device->pos() + entry.szComp)) 660 if (!device->seek(device->pos() + entry.szComp))
661 return UnZip::SeekFailed; 661 return UnZip::SeekFailed;
662 662
663 // Read 4 bytes and check if there is a data descriptor signature 663 // Read 4 bytes and check if there is a data descriptor signature
664 if (device->read(buffer2, 4) != 4) 664 if (device->read(buffer2, 4) != 4)
665 return UnZip::ReadFailed; 665 return UnZip::ReadFailed;
666 666
667 bool hasSignature = buffer2[0] == 'P' && buffer2[1] == 'K' && buffer2[2] == 0x07 && buffer2[3] == 0x08; 667 bool hasSignature = buffer2[0] == 'P' && buffer2[1] == 'K' && buffer2[2] == 0x07 && buffer2[3] == 0x08;
668 if (hasSignature) 668 if (hasSignature)
669 { 669 {
670 if (device->read(buffer2, UNZIP_DD_SIZE) != UNZIP_DD_SIZE) 670 if (device->read(buffer2, UNZIP_DD_SIZE) != UNZIP_DD_SIZE)
671 return UnZip::ReadFailed; 671 return UnZip::ReadFailed;
672 } 672 }
673 else 673 else
674 { 674 {
675 if (device->read(buffer2 + 4, UNZIP_DD_SIZE - 4) != UNZIP_DD_SIZE - 4) 675 if (device->read(buffer2 + 4, UNZIP_DD_SIZE - 4) != UNZIP_DD_SIZE - 4)
676 return UnZip::ReadFailed; 676 return UnZip::ReadFailed;
677 } 677 }
678 678
679 // DD: crc, compressed size, uncompressed size 679 // DD: crc, compressed size, uncompressed size
680 if ( 680 if (
681 entry.crc != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CRC32) || 681 entry.crc != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CRC32) ||
682 entry.szComp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CSIZE) || 682 entry.szComp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CSIZE) ||
683 entry.szUncomp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_USIZE) 683 entry.szUncomp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_USIZE)
684 ) 684 )
685 return UnZip::HeaderConsistencyError; 685 return UnZip::HeaderConsistencyError;
686 } 686 }
687 687
688 return UnZip::Ok; 688 return UnZip::Ok;
689} 689}
690 690
691/*! \internal Attempts to find the start of the central directory record. 691/*! \internal Attempts to find the start of the central directory record.
692 692
693 We seek the file back until we reach the "End Of Central Directory" 693 We seek the file back until we reach the "End Of Central Directory"
694 signature PK\5\6. 694 signature PK\5\6.
695 695
696 end of central dir signature 4 bytes (0x06054b50) 696 end of central dir signature 4 bytes (0x06054b50)
697 number of this disk 2 bytes 697 number of this disk 2 bytes
698 number of the disk with the 698 number of the disk with the
699 start of the central directory 2 bytes 699 start of the central directory 2 bytes
700 total number of entries in the 700 total number of entries in the
701 central directory on this disk 2 bytes 701 central directory on this disk 2 bytes
702 total number of entries in 702 total number of entries in
703 the central directory 2 bytes 703 the central directory 2 bytes
704 size of the central directory 4 bytes 704 size of the central directory 4 bytes
705 offset of start of central 705 offset of start of central
706 directory with respect to 706 directory with respect to
707 the starting disk number 4 bytes 707 the starting disk number 4 bytes
708 .ZIP file comment length 2 bytes 708 .ZIP file comment length 2 bytes
709 --- SIZE UNTIL HERE: UNZIP_EOCD_SIZE --- 709 --- SIZE UNTIL HERE: UNZIP_EOCD_SIZE ---
710 .ZIP file comment (variable size) 710 .ZIP file comment (variable size)
711*/ 711*/
712UnZip::ErrorCode UnzipPrivate::seekToCentralDirectory() 712UnZip::ErrorCode UnzipPrivate::seekToCentralDirectory()
713{ 713{
714 qint64 length = device->size(); 714 qint64 length = device->size();
715 qint64 offset = length - UNZIP_EOCD_SIZE; 715 qint64 offset = length - UNZIP_EOCD_SIZE;
716 716
717 if (length < UNZIP_EOCD_SIZE) 717 if (length < UNZIP_EOCD_SIZE)
718 return UnZip::InvalidArchive; 718 return UnZip::InvalidArchive;
719 719
720 if (!device->seek( offset )) 720 if (!device->seek( offset ))
721 return UnZip::SeekFailed; 721 return UnZip::SeekFailed;
722 722
723 if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE) 723 if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
724 return UnZip::ReadFailed; 724 return UnZip::ReadFailed;
725 725
726 bool eocdFound = (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x05 && buffer1[3] == 0x06); 726 bool eocdFound = (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x05 && buffer1[3] == 0x06);
727 727
728 if (eocdFound) 728 if (eocdFound)
729 { 729 {
730 // Zip file has no comment (the only variable length field in the EOCD record) 730 // Zip file has no comment (the only variable length field in the EOCD record)
731 eocdOffset = offset; 731 eocdOffset = offset;
732 } 732 }
733 else 733 else
734 { 734 {
735 qint64 read; 735 qint64 read;
736 char* p = 0; 736 char* p = 0;
737 737
738 offset -= UNZIP_EOCD_SIZE; 738 offset -= UNZIP_EOCD_SIZE;
739 739
740 if (offset <= 0) 740 if (offset <= 0)
741 return UnZip::InvalidArchive; 741 return UnZip::InvalidArchive;
742 742
743 if (!device->seek( offset )) 743 if (!device->seek( offset ))
744 return UnZip::SeekFailed; 744 return UnZip::SeekFailed;
745 745
746 while ((read = device->read(buffer1, UNZIP_EOCD_SIZE)) >= 0) 746 while ((read = device->read(buffer1, UNZIP_EOCD_SIZE)) >= 0)
747 { 747 {
748 if ( (p = strstr(buffer1, "PK\5\6")) != 0) 748 if ( (p = strstr(buffer1, "PK\5\6")) != 0)
749 { 749 {
750 // Seek to the start of the EOCD record so we can read it fully 750 // Seek to the start of the EOCD record so we can read it fully
751 // Yes... we could simply read the missing bytes and append them to the buffer 751 // Yes... we could simply read the missing bytes and append them to the buffer
752 // but this is far easier so heck it! 752 // but this is far easier so heck it!
753 device->seek( offset + (p - buffer1) ); 753 device->seek( offset + (p - buffer1) );
754 eocdFound = true; 754 eocdFound = true;
755 eocdOffset = offset + (p - buffer1); 755 eocdOffset = offset + (p - buffer1);
756 756
757 // Read EOCD record 757 // Read EOCD record
758 if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE) 758 if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
759 return UnZip::ReadFailed; 759 return UnZip::ReadFailed;
760 760
761 break; 761 break;
762 } 762 }
763 763
764 offset -= UNZIP_EOCD_SIZE; 764 offset -= UNZIP_EOCD_SIZE;
765 if (offset <= 0) 765 if (offset <= 0)
766 return UnZip::InvalidArchive; 766 return UnZip::InvalidArchive;
767 767
768 if (!device->seek( offset )) 768 if (!device->seek( offset ))
769 return UnZip::SeekFailed; 769 return UnZip::SeekFailed;
770 } 770 }
771 } 771 }
772 772
773 if (!eocdFound) 773 if (!eocdFound)
774 return UnZip::InvalidArchive; 774 return UnZip::InvalidArchive;
775 775
776 // Parse EOCD to locate CD offset 776 // Parse EOCD to locate CD offset
777 offset = getULong((const unsigned char*)buffer1, UNZIP_EOCD_OFF_CDOFF + 4); 777 offset = getULong((const unsigned char*)buffer1, UNZIP_EOCD_OFF_CDOFF + 4);
778 778
779 cdOffset = offset; 779 cdOffset = offset;
780 780
781 cdEntryCount = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_ENTRIES + 4); 781 cdEntryCount = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_ENTRIES + 4);
782 782
783 quint16 commentLength = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_COMMLEN + 4); 783 quint16 commentLength = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_COMMLEN + 4);
784 if (commentLength != 0) 784 if (commentLength != 0)
785 { 785 {
786 QByteArray c = device->read(commentLength); 786 QByteArray c = device->read(commentLength);
787 if (c.count() != commentLength) 787 if (c.count() != commentLength)
788 return UnZip::ReadFailed; 788 return UnZip::ReadFailed;
789 789
790 comment = c; 790 comment = c;
791 } 791 }
792 792
793 // Seek to the start of the CD record 793 // Seek to the start of the CD record
794 if (!device->seek( cdOffset )) 794 if (!device->seek( cdOffset ))
795 return UnZip::SeekFailed; 795 return UnZip::SeekFailed;
796 796
797 return UnZip::Ok; 797 return UnZip::Ok;
798} 798}
799 799
800/*! 800/*!
801 \internal Parses a central directory record. 801 \internal Parses a central directory record.
802 802
803 Central Directory record structure: 803 Central Directory record structure:
804 804
805 [file header 1] 805 [file header 1]
806 . 806 .
807 . 807 .
808 . 808 .
809 [file header n] 809 [file header n]
810 [digital signature] // PKZip 6.2 or later only 810 [digital signature] // PKZip 6.2 or later only
811 811
812 File header: 812 File header:
813 813
814 central file header signature 4 bytes (0x02014b50) 814 central file header signature 4 bytes (0x02014b50)
815 version made by 2 bytes 815 version made by 2 bytes
816 version needed to extract 2 bytes 816 version needed to extract 2 bytes
817 general purpose bit flag 2 bytes 817 general purpose bit flag 2 bytes
818 compression method 2 bytes 818 compression method 2 bytes
819 last mod file time 2 bytes 819 last mod file time 2 bytes
820 last mod file date 2 bytes 820 last mod file date 2 bytes
821 crc-32 4 bytes 821 crc-32 4 bytes
822 compressed size 4 bytes 822 compressed size 4 bytes
823 uncompressed size 4 bytes 823 uncompressed size 4 bytes
824 file name length 2 bytes 824 file name length 2 bytes
825 extra field length 2 bytes 825 extra field length 2 bytes
826 file comment length 2 bytes 826 file comment length 2 bytes
827 disk number start 2 bytes 827 disk number start 2 bytes
828 internal file attributes 2 bytes 828 internal file attributes 2 bytes
829 external file attributes 4 bytes 829 external file attributes 4 bytes
830 relative offset of local header 4 bytes 830 relative offset of local header 4 bytes
831 831
832 file name (variable size) 832 file name (variable size)
833 extra field (variable size) 833 extra field (variable size)
834 file comment (variable size) 834 file comment (variable size)
835*/ 835*/
836UnZip::ErrorCode UnzipPrivate::parseCentralDirectoryRecord() 836UnZip::ErrorCode UnzipPrivate::parseCentralDirectoryRecord()
837{ 837{
838 // Read CD record 838 // Read CD record
839 if (device->read(buffer1, UNZIP_CD_ENTRY_SIZE_NS) != UNZIP_CD_ENTRY_SIZE_NS) 839 if (device->read(buffer1, UNZIP_CD_ENTRY_SIZE_NS) != UNZIP_CD_ENTRY_SIZE_NS)
840 return UnZip::ReadFailed; 840 return UnZip::ReadFailed;
841 841
842 bool skipEntry = false; 842 bool skipEntry = false;
843 843
844 // Get compression type so we can skip non compatible algorithms 844 // Get compression type so we can skip non compatible algorithms
845 quint16 compMethod = getUShort(uBuffer, UNZIP_CD_OFF_CMETHOD); 845 quint16 compMethod = getUShort(uBuffer, UNZIP_CD_OFF_CMETHOD);
846 846
847 // Get variable size fields length so we can skip the whole record 847 // Get variable size fields length so we can skip the whole record
848 // if necessary 848 // if necessary
849 quint16 szName = getUShort(uBuffer, UNZIP_CD_OFF_NAMELEN); 849 quint16 szName = getUShort(uBuffer, UNZIP_CD_OFF_NAMELEN);
850 quint16 szExtra = getUShort(uBuffer, UNZIP_CD_OFF_XLEN); 850 quint16 szExtra = getUShort(uBuffer, UNZIP_CD_OFF_XLEN);
851 quint16 szComment = getUShort(uBuffer, UNZIP_CD_OFF_COMMLEN); 851 quint16 szComment = getUShort(uBuffer, UNZIP_CD_OFF_COMMLEN);
852 852
853 quint32 skipLength = szName + szExtra + szComment; 853 quint32 skipLength = szName + szExtra + szComment;
854 854
855 UnZip::ErrorCode ec = UnZip::Ok; 855 UnZip::ErrorCode ec = UnZip::Ok;
856 856
857 if ((compMethod != 0) && (compMethod != 8)) 857 if ((compMethod != 0) && (compMethod != 8))
858 { 858 {
859 qDebug() << "Unsupported compression method. Skipping file."; 859 qDebug() << "Unsupported compression method. Skipping file.";
860 skipEntry = true; 860 skipEntry = true;
861 } 861 }
862 862
863 // Header parsing may be a problem if version is bigger than UNZIP_VERSION 863 // Header parsing may be a problem if version is bigger than UNZIP_VERSION
864 if (!skipEntry && buffer1[UNZIP_CD_OFF_VERSION] > UNZIP_VERSION) 864 if (!skipEntry && buffer1[UNZIP_CD_OFF_VERSION] > UNZIP_VERSION)
865 { 865 {
866 qDebug() << "Unsupported PKZip version. Skipping file."; 866 qDebug() << "Unsupported PKZip version. Skipping file.";
867 skipEntry = true; 867 skipEntry = true;
868 } 868 }
869 869
870 if (!skipEntry && szName == 0) 870 if (!skipEntry && szName == 0)
871 { 871 {
872 qDebug() << "Skipping file with no name."; 872 qDebug() << "Skipping file with no name.";
873 skipEntry = true; 873 skipEntry = true;
874 } 874 }
875 875
876 if (!skipEntry && device->read(buffer2, szName) != szName) 876 if (!skipEntry && device->read(buffer2, szName) != szName)
877 { 877 {
878 ec = UnZip::ReadFailed; 878 ec = UnZip::ReadFailed;
879 skipEntry = true; 879 skipEntry = true;
880 } 880 }
881 881
882 if (skipEntry) 882 if (skipEntry)
883 { 883 {
884 if (ec == UnZip::Ok) 884 if (ec == UnZip::Ok)
885 { 885 {
886 if (!device->seek( device->pos() + skipLength )) 886 if (!device->seek( device->pos() + skipLength ))
887 ec = UnZip::SeekFailed; 887 ec = UnZip::SeekFailed;
888 888
889 unsupportedEntryCount++; 889 unsupportedEntryCount++;
890 } 890 }
891 891
892 return ec; 892 return ec;
893 } 893 }
894 894
895 QString filename = QString::fromAscii(buffer2, szName); 895 QString filename = QString::fromAscii(buffer2, szName);
896 896
897 ZipEntryP* h = new ZipEntryP; 897 ZipEntryP* h = new ZipEntryP;
898 h->compMethod = compMethod; 898 h->compMethod = compMethod;
899 899
900 h->gpFlag[0] = buffer1[UNZIP_CD_OFF_GPFLAG]; 900 h->gpFlag[0] = buffer1[UNZIP_CD_OFF_GPFLAG];
901 h->gpFlag[1] = buffer1[UNZIP_CD_OFF_GPFLAG + 1]; 901 h->gpFlag[1] = buffer1[UNZIP_CD_OFF_GPFLAG + 1];
902 902
903 h->modTime[0] = buffer1[UNZIP_CD_OFF_MODT]; 903 h->modTime[0] = buffer1[UNZIP_CD_OFF_MODT];
904 h->modTime[1] = buffer1[UNZIP_CD_OFF_MODT + 1]; 904 h->modTime[1] = buffer1[UNZIP_CD_OFF_MODT + 1];
905 905
906 h->modDate[0] = buffer1[UNZIP_CD_OFF_MODD]; 906 h->modDate[0] = buffer1[UNZIP_CD_OFF_MODD];
907 h->modDate[1] = buffer1[UNZIP_CD_OFF_MODD + 1]; 907 h->modDate[1] = buffer1[UNZIP_CD_OFF_MODD + 1];
908 908
909 h->crc = getULong(uBuffer, UNZIP_CD_OFF_CRC32); 909 h->crc = getULong(uBuffer, UNZIP_CD_OFF_CRC32);
910 h->szComp = getULong(uBuffer, UNZIP_CD_OFF_CSIZE); 910 h->szComp = getULong(uBuffer, UNZIP_CD_OFF_CSIZE);
911 h->szUncomp = getULong(uBuffer, UNZIP_CD_OFF_USIZE); 911 h->szUncomp = getULong(uBuffer, UNZIP_CD_OFF_USIZE);
912 912
913 // Skip extra field (if any) 913 // Skip extra field (if any)
914 if (szExtra != 0) 914 if (szExtra != 0)
915 { 915 {
916 if (!device->seek( device->pos() + szExtra )) 916 if (!device->seek( device->pos() + szExtra ))
917 { 917 {
918 delete h; 918 delete h;
919 return UnZip::SeekFailed; 919 return UnZip::SeekFailed;
920 } 920 }
921 } 921 }
922 922
923 // Read comment field (if any) 923 // Read comment field (if any)
924 if (szComment != 0) 924 if (szComment != 0)
925 { 925 {
926 if (device->read(buffer2, szComment) != szComment) 926 if (device->read(buffer2, szComment) != szComment)
927 { 927 {
928 delete h; 928 delete h;
929 return UnZip::ReadFailed; 929 return UnZip::ReadFailed;
930 } 930 }
931 931
932 h->comment = QString::fromAscii(buffer2, szComment); 932 h->comment = QString::fromAscii(buffer2, szComment);
933 } 933 }
934 934
935 h->lhOffset = getULong(uBuffer, UNZIP_CD_OFF_LHOFFSET); 935 h->lhOffset = getULong(uBuffer, UNZIP_CD_OFF_LHOFFSET);
936 936
937 if (headers == 0) 937 if (headers == 0)
938 headers = new QMap<QString, ZipEntryP*>(); 938 headers = new QMap<QString, ZipEntryP*>();
939 headers->insert(filename, h); 939 headers->insert(filename, h);
940 940
941 return UnZip::Ok; 941 return UnZip::Ok;
942} 942}
943 943
944//! \internal Closes the archive and resets the internal status. 944//! \internal Closes the archive and resets the internal status.
945void UnzipPrivate::closeArchive() 945void UnzipPrivate::closeArchive()
946{ 946{
947 if (device == 0) 947 if (device == 0)
948 return; 948 return;
949 949
950 skipAllEncrypted = false; 950 skipAllEncrypted = false;
951 951
952 if (headers != 0) 952 if (headers != 0)
953 { 953 {
954 qDeleteAll(*headers); 954 qDeleteAll(*headers);
955 delete headers; 955 delete headers;
956 headers = 0; 956 headers = 0;
957 } 957 }
958 958
959 delete device; device = 0; 959 delete device; device = 0;
960 960
961 cdOffset = eocdOffset = 0; 961 cdOffset = eocdOffset = 0;
962 cdEntryCount = 0; 962 cdEntryCount = 0;
963 unsupportedEntryCount = 0; 963 unsupportedEntryCount = 0;
964 964
965 comment.clear(); 965 comment.clear();
966} 966}
967 967
968//! \internal 968//! \internal
969UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options) 969UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options)
970{ 970{
971 QString name(path); 971 QString name(path);
972 QString dirname; 972 QString dirname;
973 QString directory; 973 QString directory;
974 974
975 int pos = name.lastIndexOf('/'); 975 int pos = name.lastIndexOf('/');
976 976
977 // This entry is for a directory 977 // This entry is for a directory
978 if (pos == name.length() - 1) 978 if (pos == name.length() - 1)
979 { 979 {
980 if (options.testFlag(UnZip::SkipPaths)) 980 if (options.testFlag(UnZip::SkipPaths))
981 return UnZip::Ok; 981 return UnZip::Ok;
982 982
983 directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(name)); 983 directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(name));
984 if (!createDirectory(directory)) 984 if (!createDirectory(directory))
985 { 985 {
986 qDebug() << QString("Unable to create directory: %1").arg(directory); 986 qDebug() << QString("Unable to create directory: %1").arg(directory);
987 return UnZip::CreateDirFailed; 987 return UnZip::CreateDirFailed;
988 } 988 }
989 989
990 return UnZip::Ok; 990 return UnZip::Ok;
991 } 991 }
992 992
993 // Extract path from entry 993 // Extract path from entry
994 if (pos > 0) 994 if (pos > 0)
995 { 995 {
996 // get directory part 996 // get directory part
997 dirname = name.left(pos); 997 dirname = name.left(pos);
998 if (options.testFlag(UnZip::SkipPaths)) 998 if (options.testFlag(UnZip::SkipPaths))
999 { 999 {
1000 directory = dir.absolutePath(); 1000 directory = dir.absolutePath();
1001 } 1001 }
1002 else 1002 else
1003 { 1003 {
1004 directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(dirname)); 1004 directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(dirname));
1005 if (!createDirectory(directory)) 1005 if (!createDirectory(directory))
1006 { 1006 {
1007 qDebug() << QString("Unable to create directory: %1").arg(directory); 1007 qDebug() << QString("Unable to create directory: %1").arg(directory);
1008 return UnZip::CreateDirFailed; 1008 return UnZip::CreateDirFailed;
1009 } 1009 }
1010 } 1010 }
1011 name = name.right(name.length() - pos - 1); 1011 name = name.right(name.length() - pos - 1);
1012 } else directory = dir.absolutePath(); 1012 } else directory = dir.absolutePath();
1013 1013
1014 name = QString("%1/%2").arg(directory).arg(name); 1014 name = QString("%1/%2").arg(directory).arg(name);
1015 1015
1016 QFile outFile(name); 1016 QFile outFile(name);
1017 1017
1018 if (!outFile.open(QIODevice::WriteOnly)) 1018 if (!outFile.open(QIODevice::WriteOnly))
1019 { 1019 {
1020 qDebug() << QString("Unable to open %1 for writing").arg(name); 1020 qDebug() << QString("Unable to open %1 for writing").arg(name);
1021 return UnZip::OpenFailed; 1021 return UnZip::OpenFailed;
1022 } 1022 }
1023 1023
1024 //! \todo Set creation/last_modified date/time 1024 //! \todo Set creation/last_modified date/time
1025 1025
1026 UnZip::ErrorCode ec = extractFile(path, entry, &outFile, options); 1026 UnZip::ErrorCode ec = extractFile(path, entry, &outFile, options);
1027 1027
1028 outFile.close(); 1028 outFile.close();
1029 1029
1030 if (ec != UnZip::Ok) 1030 if (ec != UnZip::Ok)
1031 { 1031 {
1032 if (!outFile.remove()) 1032 if (!outFile.remove())
1033 qDebug() << QString("Unable to remove corrupted file: %1").arg(name); 1033 qDebug() << QString("Unable to remove corrupted file: %1").arg(name);
1034 } 1034 }
1035 1035
1036 return ec; 1036 return ec;
1037} 1037}
1038 1038
1039//! \internal 1039//! \internal
1040UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, QIODevice* dev, UnZip::ExtractionOptions options) 1040UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, QIODevice* dev, UnZip::ExtractionOptions options)
1041{ 1041{
1042 Q_UNUSED(options); 1042 Q_UNUSED(options);
1043 Q_ASSERT(dev != 0); 1043 Q_ASSERT(dev != 0);
1044 1044
1045 if (!entry.lhEntryChecked) 1045 if (!entry.lhEntryChecked)
1046 { 1046 {
1047 UnZip::ErrorCode ec = parseLocalHeaderRecord(path, entry); 1047 UnZip::ErrorCode ec = parseLocalHeaderRecord(path, entry);
1048 entry.lhEntryChecked = true; 1048 entry.lhEntryChecked = true;
1049 1049
1050 if (ec != UnZip::Ok) 1050 if (ec != UnZip::Ok)
1051 return ec; 1051 return ec;
1052 } 1052 }
1053 1053
1054 if (!device->seek(entry.dataOffset)) 1054 if (!device->seek(entry.dataOffset))
1055 return UnZip::SeekFailed; 1055 return UnZip::SeekFailed;
1056 1056
1057 // Encryption keys 1057 // Encryption keys
1058 quint32 keys[3]; 1058 quint32 keys[3];
1059 1059
1060 if (entry.isEncrypted()) 1060 if (entry.isEncrypted())
1061 { 1061 {
1062 UnZip::ErrorCode e = testPassword(keys, path, entry); 1062 UnZip::ErrorCode e = testPassword(keys, path, entry);
1063 if (e != UnZip::Ok) 1063 if (e != UnZip::Ok)
1064 { 1064 {
1065 qDebug() << QString("Unable to decrypt %1").arg(path); 1065 qDebug() << QString("Unable to decrypt %1").arg(path);
1066 return e; 1066 return e;
1067 }//! Encryption header size 1067 }//! Encryption header size
1068 entry.szComp -= UNZIP_LOCAL_ENC_HEADER_SIZE; // remove encryption header size 1068 entry.szComp -= UNZIP_LOCAL_ENC_HEADER_SIZE; // remove encryption header size
1069 } 1069 }
1070 1070
1071 if (entry.szComp == 0) 1071 if (entry.szComp == 0)
1072 { 1072 {
1073 if (entry.crc != 0) 1073 if (entry.crc != 0)
1074 return UnZip::Corrupted; 1074 return UnZip::Corrupted;
1075 1075
1076 return UnZip::Ok; 1076 return UnZip::Ok;
1077 } 1077 }
1078 1078
1079 uInt rep = entry.szComp / UNZIP_READ_BUFFER; 1079 uInt rep = entry.szComp / UNZIP_READ_BUFFER;
1080 uInt rem = entry.szComp % UNZIP_READ_BUFFER; 1080 uInt rem = entry.szComp % UNZIP_READ_BUFFER;
1081 uInt cur = 0; 1081 uInt cur = 0;
1082 1082
1083 // extract data 1083 // extract data
1084 qint64 read; 1084 qint64 read;
1085 quint64 tot = 0; 1085 quint64 tot = 0;
1086 1086
1087 quint32 myCRC = crc32(0L, Z_NULL, 0); 1087 quint32 myCRC = crc32(0L, Z_NULL, 0);
1088 1088
1089 if (entry.compMethod == 0) 1089 if (entry.compMethod == 0)
1090 { 1090 {
1091 while ( (read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem)) > 0 ) 1091 while ( (read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem)) > 0 )
1092 { 1092 {
1093 if (entry.isEncrypted()) 1093 if (entry.isEncrypted())
1094 decryptBytes(keys, buffer1, read); 1094 decryptBytes(keys, buffer1, read);
1095 1095
1096 myCRC = crc32(myCRC, uBuffer, read); 1096 myCRC = crc32(myCRC, uBuffer, read);
1097 1097
1098 if (dev->write(buffer1, read) != read) 1098 if (dev->write(buffer1, read) != read)
1099 return UnZip::WriteFailed; 1099 return UnZip::WriteFailed;
1100 1100
1101 cur++; 1101 cur++;
1102 tot += read; 1102 tot += read;
1103 1103
1104 if (tot == entry.szComp) 1104 if (tot == entry.szComp)
1105 break; 1105 break;
1106 } 1106 }
1107 1107
1108 if (read < 0) 1108 if (read < 0)
1109 return UnZip::ReadFailed; 1109 return UnZip::ReadFailed;
1110 } 1110 }
1111 else if (entry.compMethod == 8) 1111 else if (entry.compMethod == 8)
1112 { 1112 {
1113 /* Allocate inflate state */ 1113 /* Allocate inflate state */
1114 z_stream zstr; 1114 z_stream zstr;
1115 zstr.zalloc = Z_NULL; 1115 zstr.zalloc = Z_NULL;
1116 zstr.zfree = Z_NULL; 1116 zstr.zfree = Z_NULL;
1117 zstr.opaque = Z_NULL; 1117 zstr.opaque = Z_NULL;
1118 zstr.next_in = Z_NULL; 1118 zstr.next_in = Z_NULL;
1119 zstr.avail_in = 0; 1119 zstr.avail_in = 0;
1120 1120
1121 int zret; 1121 int zret;
1122 1122
1123 // Use inflateInit2 with negative windowBits to get raw decompression 1123 // Use inflateInit2 with negative windowBits to get raw decompression
1124 if ( (zret = inflateInit2_(&zstr, -MAX_WBITS, ZLIB_VERSION, sizeof(z_stream))) != Z_OK ) 1124 if ( (zret = inflateInit2_(&zstr, -MAX_WBITS, ZLIB_VERSION, sizeof(z_stream))) != Z_OK )
1125 return UnZip::ZlibError; 1125 return UnZip::ZlibError;
1126 1126
1127 int szDecomp; 1127 int szDecomp;
1128 1128
1129 // Decompress until deflate stream ends or end of file 1129 // Decompress until deflate stream ends or end of file
1130 do 1130 do
1131 { 1131 {
1132 read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem); 1132 read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem);
1133 if (read == 0) 1133 if (read == 0)
1134 break; 1134 break;
1135 if (read < 0) 1135 if (read < 0)
1136 { 1136 {
1137 (void)inflateEnd(&zstr); 1137 (void)inflateEnd(&zstr);
1138 return UnZip::ReadFailed; 1138 return UnZip::ReadFailed;
1139 } 1139 }
1140 1140
1141 if (entry.isEncrypted()) 1141 if (entry.isEncrypted())
1142 decryptBytes(keys, buffer1, read); 1142 decryptBytes(keys, buffer1, read);
1143 1143
1144 cur++; 1144 cur++;
1145 tot += read; 1145 tot += read;
1146 1146
1147 zstr.avail_in = (uInt) read; 1147 zstr.avail_in = (uInt) read;
1148 zstr.next_in = (Bytef*) buffer1; 1148 zstr.next_in = (Bytef*) buffer1;
1149 1149
1150 1150
1151 // Run inflate() on input until output buffer not full 1151 // Run inflate() on input until output buffer not full
1152 do { 1152 do {
1153 zstr.avail_out = UNZIP_READ_BUFFER; 1153 zstr.avail_out = UNZIP_READ_BUFFER;
1154 zstr.next_out = (Bytef*) buffer2;; 1154 zstr.next_out = (Bytef*) buffer2;;
1155 1155
1156 zret = inflate(&zstr, Z_NO_FLUSH); 1156 zret = inflate(&zstr, Z_NO_FLUSH);
1157 1157
1158 switch (zret) { 1158 switch (zret) {
1159 case Z_NEED_DICT: 1159 case Z_NEED_DICT:
1160 case Z_DATA_ERROR: 1160 case Z_DATA_ERROR:
1161 case Z_MEM_ERROR: 1161 case Z_MEM_ERROR:
1162 inflateEnd(&zstr); 1162 inflateEnd(&zstr);
1163 return UnZip::WriteFailed; 1163 return UnZip::WriteFailed;
1164 default: 1164 default:
1165 ; 1165 ;
1166 } 1166 }
1167 1167
1168 szDecomp = UNZIP_READ_BUFFER - zstr.avail_out; 1168 szDecomp = UNZIP_READ_BUFFER - zstr.avail_out;
1169 if (dev->write(buffer2, szDecomp) != szDecomp) 1169 if (dev->write(buffer2, szDecomp) != szDecomp)
1170 { 1170 {
1171 inflateEnd(&zstr); 1171 inflateEnd(&zstr);
1172 return UnZip::ZlibError; 1172 return UnZip::ZlibError;
1173 } 1173 }
1174 1174
1175 myCRC = crc32(myCRC, (const Bytef*) buffer2, szDecomp); 1175 myCRC = crc32(myCRC, (const Bytef*) buffer2, szDecomp);
1176 1176
1177 } while (zstr.avail_out == 0); 1177 } while (zstr.avail_out == 0);
1178 1178
1179 } 1179 }
1180 while (zret != Z_STREAM_END); 1180 while (zret != Z_STREAM_END);
1181 1181
1182 inflateEnd(&zstr); 1182 inflateEnd(&zstr);
1183 } 1183 }
1184 1184
1185 if (myCRC != entry.crc) 1185 if (myCRC != entry.crc)
1186 return UnZip::Corrupted; 1186 return UnZip::Corrupted;
1187 1187
1188 return UnZip::Ok; 1188 return UnZip::Ok;
1189} 1189}
1190 1190
1191//! \internal Creates a new directory and all the needed parent directories. 1191//! \internal Creates a new directory and all the needed parent directories.
1192bool UnzipPrivate::createDirectory(const QString& path) 1192bool UnzipPrivate::createDirectory(const QString& path)
1193{ 1193{
1194 QDir d(path); 1194 QDir d(path);
1195 if (!d.exists()) 1195 if (!d.exists())
1196 { 1196 {
1197 int sep = path.lastIndexOf("/"); 1197 int sep = path.lastIndexOf("/");
1198 if (sep <= 0) return true; 1198 if (sep <= 0) return true;
1199 1199
1200 if (!createDirectory(path.left(sep))) 1200 if (!createDirectory(path.left(sep)))
1201 return false; 1201 return false;
1202 1202
1203 if (!d.mkdir(path)) 1203 if (!d.mkdir(path))
1204 { 1204 {
1205 qDebug() << QString("Unable to create directory: %1").arg(path); 1205 qDebug() << QString("Unable to create directory: %1").arg(path);
1206 return false; 1206 return false;
1207 } 1207 }
1208 } 1208 }
1209 1209
1210 return true; 1210 return true;
1211} 1211}
1212 1212
1213/*! 1213/*!
1214 \internal Reads an quint32 (4 bytes) from a byte array starting at given offset. 1214 \internal Reads an quint32 (4 bytes) from a byte array starting at given offset.
1215*/ 1215*/
1216quint32 UnzipPrivate::getULong(const unsigned char* data, quint32 offset) const 1216quint32 UnzipPrivate::getULong(const unsigned char* data, quint32 offset) const
1217{ 1217{
1218 quint32 res = (quint32) data[offset]; 1218 quint32 res = (quint32) data[offset];
1219 res |= (((quint32)data[offset+1]) << 8); 1219 res |= (((quint32)data[offset+1]) << 8);
1220 res |= (((quint32)data[offset+2]) << 16); 1220 res |= (((quint32)data[offset+2]) << 16);
1221 res |= (((quint32)data[offset+3]) << 24); 1221 res |= (((quint32)data[offset+3]) << 24);
1222 1222
1223 return res; 1223 return res;
1224} 1224}
1225 1225
1226/*! 1226/*!
1227 \internal Reads an quint64 (8 bytes) from a byte array starting at given offset. 1227 \internal Reads an quint64 (8 bytes) from a byte array starting at given offset.
1228*/ 1228*/
1229quint64 UnzipPrivate::getULLong(const unsigned char* data, quint32 offset) const 1229quint64 UnzipPrivate::getULLong(const unsigned char* data, quint32 offset) const
1230{ 1230{
1231 quint64 res = (quint64) data[offset]; 1231 quint64 res = (quint64) data[offset];
1232 res |= (((quint64)data[offset+1]) << 8); 1232 res |= (((quint64)data[offset+1]) << 8);
1233 res |= (((quint64)data[offset+2]) << 16); 1233 res |= (((quint64)data[offset+2]) << 16);
1234 res |= (((quint64)data[offset+3]) << 24); 1234 res |= (((quint64)data[offset+3]) << 24);
1235 res |= (((quint64)data[offset+1]) << 32); 1235 res |= (((quint64)data[offset+1]) << 32);
1236 res |= (((quint64)data[offset+2]) << 40); 1236 res |= (((quint64)data[offset+2]) << 40);
1237 res |= (((quint64)data[offset+3]) << 48); 1237 res |= (((quint64)data[offset+3]) << 48);
1238 res |= (((quint64)data[offset+3]) << 56); 1238 res |= (((quint64)data[offset+3]) << 56);
1239 1239
1240 return res; 1240 return res;
1241} 1241}
1242 1242
1243/*! 1243/*!
1244 \internal Reads an quint16 (2 bytes) from a byte array starting at given offset. 1244 \internal Reads an quint16 (2 bytes) from a byte array starting at given offset.
1245*/ 1245*/
1246quint16 UnzipPrivate::getUShort(const unsigned char* data, quint32 offset) const 1246quint16 UnzipPrivate::getUShort(const unsigned char* data, quint32 offset) const
1247{ 1247{
1248 return (quint16) data[offset] | (((quint16)data[offset+1]) << 8); 1248 return (quint16) data[offset] | (((quint16)data[offset+1]) << 8);
1249} 1249}
1250 1250
1251/*! 1251/*!
1252 \internal Return the next byte in the pseudo-random sequence 1252 \internal Return the next byte in the pseudo-random sequence
1253 */ 1253 */
1254int UnzipPrivate::decryptByte(quint32 key2) const 1254int UnzipPrivate::decryptByte(quint32 key2) const
1255{ 1255{
1256 quint16 temp = ((quint16)(key2) & 0xffff) | 2; 1256 quint16 temp = ((quint16)(key2) & 0xffff) | 2;
1257 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); 1257 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
1258} 1258}
1259 1259
1260/*! 1260/*!
1261 \internal Update the encryption keys with the next byte of plain text 1261 \internal Update the encryption keys with the next byte of plain text
1262 */ 1262 */
1263void UnzipPrivate::updateKeys(quint32* keys, int c) const 1263void UnzipPrivate::updateKeys(quint32* keys, int c) const
1264{ 1264{
1265 keys[0] = CRC32(keys[0], c); 1265 keys[0] = CRC32(keys[0], c);
1266 keys[1] += keys[0] & 0xff; 1266 keys[1] += keys[0] & 0xff;
1267 keys[1] = keys[1] * 134775813L + 1; 1267 keys[1] = keys[1] * 134775813L + 1;
1268 keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24); 1268 keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24);
1269} 1269}
1270 1270
1271/*! 1271/*!
1272 \internal Initialize the encryption keys and the random header according to 1272 \internal Initialize the encryption keys and the random header according to
1273 the given password. 1273 the given password.
1274 */ 1274 */
1275void UnzipPrivate::initKeys(const QString& pwd, quint32* keys) const 1275void UnzipPrivate::initKeys(const QString& pwd, quint32* keys) const
1276{ 1276{
1277 keys[0] = 305419896L; 1277 keys[0] = 305419896L;
1278 keys[1] = 591751049L; 1278 keys[1] = 591751049L;
1279 keys[2] = 878082192L; 1279 keys[2] = 878082192L;
1280 1280
1281 QByteArray pwdBytes = pwd.toAscii(); 1281 QByteArray pwdBytes = pwd.toAscii();
1282 int sz = pwdBytes.size(); 1282 int sz = pwdBytes.size();
1283 const char* ascii = pwdBytes.data(); 1283 const char* ascii = pwdBytes.data();
1284 1284
1285 for (int i=0; i<sz; ++i) 1285 for (int i=0; i<sz; ++i)
1286 updateKeys(keys, (int)ascii[i]); 1286 updateKeys(keys, (int)ascii[i]);
1287} 1287}
1288 1288
1289/*! 1289/*!
1290 \internal Attempts to test a password without actually extracting a file. 1290 \internal Attempts to test a password without actually extracting a file.
1291 The \p file parameter can be used in the user interface or for debugging purposes 1291 The \p file parameter can be used in the user interface or for debugging purposes
1292 as it is the name of the encrypted file for wich the password is being tested. 1292 as it is the name of the encrypted file for wich the password is being tested.
1293*/ 1293*/
1294UnZip::ErrorCode UnzipPrivate::testPassword(quint32* keys, const QString& file, const ZipEntryP& header) 1294UnZip::ErrorCode UnzipPrivate::testPassword(quint32* keys, const QString& file, const ZipEntryP& header)
1295{ 1295{
1296 Q_UNUSED(file); 1296 Q_UNUSED(file);
1297 1297
1298 // read encryption keys 1298 // read encryption keys
1299 if (device->read(buffer1, 12) != 12) 1299 if (device->read(buffer1, 12) != 12)
1300 return UnZip::Corrupted; 1300 return UnZip::Corrupted;
1301 1301
1302 // Replace this code if you want to i.e. call some dialog and ask the user for a password 1302 // Replace this code if you want to i.e. call some dialog and ask the user for a password
1303 initKeys(password, keys); 1303 initKeys(password, keys);
1304 if (testKeys(header, keys)) 1304 if (testKeys(header, keys))
1305 return UnZip::Ok; 1305 return UnZip::Ok;
1306 1306
1307 return UnZip::Skip; 1307 return UnZip::Skip;
1308} 1308}
1309 1309
1310/*! 1310/*!
1311 \internal Tests a set of keys on the encryption header. 1311 \internal Tests a set of keys on the encryption header.
1312*/ 1312*/
1313bool UnzipPrivate::testKeys(const ZipEntryP& header, quint32* keys) 1313bool UnzipPrivate::testKeys(const ZipEntryP& header, quint32* keys)
1314{ 1314{
1315 char lastByte; 1315 char lastByte;
1316 1316
1317 // decrypt encryption header 1317 // decrypt encryption header
1318 for (int i=0; i<11; ++i) 1318 for (int i=0; i<11; ++i)
1319 updateKeys(keys, lastByte = buffer1[i] ^ decryptByte(keys[2])); 1319 updateKeys(keys, lastByte = buffer1[i] ^ decryptByte(keys[2]));
1320 updateKeys(keys, lastByte = buffer1[11] ^ decryptByte(keys[2])); 1320 updateKeys(keys, lastByte = buffer1[11] ^ decryptByte(keys[2]));
1321 1321
1322 // if there is an extended header (bit in the gp flag) buffer[11] is a byte from the file time 1322 // if there is an extended header (bit in the gp flag) buffer[11] is a byte from the file time
1323 // with no extended header we have to check the crc high-order byte 1323 // with no extended header we have to check the crc high-order byte
1324 char c = ((header.gpFlag[0] & 0x08) == 8) ? header.modTime[1] : header.crc >> 24; 1324 char c = ((header.gpFlag[0] & 0x08) == 8) ? header.modTime[1] : header.crc >> 24;
1325 1325
1326 return (lastByte == c); 1326 return (lastByte == c);
1327} 1327}
1328 1328
1329/*! 1329/*!
1330 \internal Decrypts an array of bytes long \p read. 1330 \internal Decrypts an array of bytes long \p read.
1331*/ 1331*/
1332void UnzipPrivate::decryptBytes(quint32* keys, char* buffer, qint64 read) 1332void UnzipPrivate::decryptBytes(quint32* keys, char* buffer, qint64 read)
1333{ 1333{
1334 for (int i=0; i<(int)read; ++i) 1334 for (int i=0; i<(int)read; ++i)
1335 updateKeys(keys, buffer[i] ^= decryptByte(keys[2])); 1335 updateKeys(keys, buffer[i] ^= decryptByte(keys[2]));
1336} 1336}
1337 1337
1338/*! 1338/*!
1339 \internal Converts date and time values from ZIP format to a QDateTime object. 1339 \internal Converts date and time values from ZIP format to a QDateTime object.
1340*/ 1340*/
1341QDateTime UnzipPrivate::convertDateTime(const unsigned char date[2], const unsigned char time[2]) const 1341QDateTime UnzipPrivate::convertDateTime(const unsigned char date[2], const unsigned char time[2]) const
1342{ 1342{
1343 QDateTime dt; 1343 QDateTime dt;
1344 1344
1345 // Usual PKZip low-byte to high-byte order 1345 // Usual PKZip low-byte to high-byte order
1346 1346
1347 // Date: 7 bits = years from 1980, 4 bits = month, 5 bits = day 1347 // Date: 7 bits = years from 1980, 4 bits = month, 5 bits = day
1348 quint16 year = (date[1] >> 1) & 127; 1348 quint16 year = (date[1] >> 1) & 127;
1349 quint16 month = ((date[1] << 3) & 14) | ((date[0] >> 5) & 7); 1349 quint16 month = ((date[1] << 3) & 14) | ((date[0] >> 5) & 7);
1350 quint16 day = date[0] & 31; 1350 quint16 day = date[0] & 31;
1351 1351
1352 // Time: 5 bits hour, 6 bits minutes, 5 bits seconds with a 2sec precision 1352 // Time: 5 bits hour, 6 bits minutes, 5 bits seconds with a 2sec precision
1353 quint16 hour = (time[1] >> 3) & 31; 1353 quint16 hour = (time[1] >> 3) & 31;
1354 quint16 minutes = ((time[1] << 3) & 56) | ((time[0] >> 5) & 7); 1354 quint16 minutes = ((time[1] << 3) & 56) | ((time[0] >> 5) & 7);
1355 quint16 seconds = (time[0] & 31) * 2; 1355 quint16 seconds = (time[0] & 31) * 2;
1356 1356
1357 dt.setDate(QDate(1980 + year, month, day)); 1357 dt.setDate(QDate(1980 + year, month, day));
1358 dt.setTime(QTime(hour, minutes, seconds)); 1358 dt.setTime(QTime(hour, minutes, seconds));
1359 return dt; 1359 return dt;
1360} 1360}
diff --git a/rbutil/rbutilqt/zip/unzip.h b/rbutil/rbutilqt/zip/unzip.h
index a48fbe8724..e480541716 100644
--- a/rbutil/rbutilqt/zip/unzip.h
+++ b/rbutil/rbutilqt/zip/unzip.h
@@ -1,144 +1,144 @@
1/**************************************************************************** 1/****************************************************************************
2** Filename: unzip.h 2** Filename: unzip.h
3** Last updated [dd/mm/yyyy]: 28/01/2007 3** Last updated [dd/mm/yyyy]: 28/01/2007
4** 4**
5** pkzip 2.0 decompression. 5** pkzip 2.0 decompression.
6** 6**
7** Some of the code has been inspired by other open source projects, 7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip). 8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library. 9** Compression and decompression actually uses the zlib library.
10** 10**
11** Copyright (C) 2007 Angius Fabrizio. All rights reserved. 11** Copyright (C) 2007 Angius Fabrizio. All rights reserved.
12** 12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/). 13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14** 14**
15** This file may be distributed and/or modified under the terms of the 15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software 16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the 17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file. 18** packaging of this file.
19** 19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22** 22**
23** See the file LICENSE.GPL that came with this software distribution or 23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information. 24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25** 25**
26**********************************************************************/ 26**********************************************************************/
27 27
28#ifndef OSDAB_UNZIP__H 28#ifndef OSDAB_UNZIP__H
29#define OSDAB_UNZIP__H 29#define OSDAB_UNZIP__H
30 30
31#include <QtGlobal> 31#include <QtGlobal>
32#include <QMap> 32#include <QMap>
33#include <QDateTime> 33#include <QDateTime>
34 34
35#include <zlib/zlib.h> 35#include <zlib/zlib.h>
36 36
37class UnzipPrivate; 37class UnzipPrivate;
38class QIODevice; 38class QIODevice;
39class QFile; 39class QFile;
40class QDir; 40class QDir;
41class QStringList; 41class QStringList;
42class QString; 42class QString;
43 43
44 44
45class UnZip 45class UnZip
46{ 46{
47public: 47public:
48 enum ErrorCode 48 enum ErrorCode
49 { 49 {
50 Ok, 50 Ok,
51 ZlibInit, 51 ZlibInit,
52 ZlibError, 52 ZlibError,
53 OpenFailed, 53 OpenFailed,
54 PartiallyCorrupted, 54 PartiallyCorrupted,
55 Corrupted, 55 Corrupted,
56 WrongPassword, 56 WrongPassword,
57 NoOpenArchive, 57 NoOpenArchive,
58 FileNotFound, 58 FileNotFound,
59 ReadFailed, 59 ReadFailed,
60 WriteFailed, 60 WriteFailed,
61 SeekFailed, 61 SeekFailed,
62 CreateDirFailed, 62 CreateDirFailed,
63 InvalidDevice, 63 InvalidDevice,
64 InvalidArchive, 64 InvalidArchive,
65 HeaderConsistencyError, 65 HeaderConsistencyError,
66 66
67 Skip, SkipAll // internal use only 67 Skip, SkipAll // internal use only
68 }; 68 };
69 69
70 enum ExtractionOption 70 enum ExtractionOption
71 { 71 {
72 //! Extracts paths (default) 72 //! Extracts paths (default)
73 ExtractPaths = 0x0001, 73 ExtractPaths = 0x0001,
74 //! Ignores paths and extracts all the files to the same directory 74 //! Ignores paths and extracts all the files to the same directory
75 SkipPaths = 0x0002 75 SkipPaths = 0x0002
76 }; 76 };
77 Q_DECLARE_FLAGS(ExtractionOptions, ExtractionOption) 77 Q_DECLARE_FLAGS(ExtractionOptions, ExtractionOption)
78 78
79 enum CompressionMethod 79 enum CompressionMethod
80 { 80 {
81 NoCompression, Deflated, UnknownCompression 81 NoCompression, Deflated, UnknownCompression
82 }; 82 };
83 83
84 enum FileType 84 enum FileType
85 { 85 {
86 File, Directory 86 File, Directory
87 }; 87 };
88 88
89 typedef struct ZipEntry 89 typedef struct ZipEntry
90 { 90 {
91 ZipEntry(); 91 ZipEntry();
92 92
93 QString filename; 93 QString filename;
94 QString comment; 94 QString comment;
95 95
96 quint32 compressedSize; 96 quint32 compressedSize;
97 quint32 uncompressedSize; 97 quint32 uncompressedSize;
98 quint32 crc32; 98 quint32 crc32;
99 99
100 QDateTime lastModified; 100 QDateTime lastModified;
101 101
102 CompressionMethod compression; 102 CompressionMethod compression;
103 FileType type; 103 FileType type;
104 104
105 bool encrypted; 105 bool encrypted;
106 }; 106 };
107 107
108 UnZip(); 108 UnZip();
109 virtual ~UnZip(); 109 virtual ~UnZip();
110 110
111 bool isOpen() const; 111 bool isOpen() const;
112 112
113 ErrorCode openArchive(const QString& filename); 113 ErrorCode openArchive(const QString& filename);
114 ErrorCode openArchive(QIODevice* device); 114 ErrorCode openArchive(QIODevice* device);
115 void closeArchive(); 115 void closeArchive();
116 116
117 QString archiveComment() const; 117 QString archiveComment() const;
118 118
119 QString formatError(UnZip::ErrorCode c) const; 119 QString formatError(UnZip::ErrorCode c) const;
120 120
121 bool contains(const QString& file) const; 121 bool contains(const QString& file) const;
122 122
123 QStringList fileList() const; 123 QStringList fileList() const;
124 QList<ZipEntry> entryList() const; 124 QList<ZipEntry> entryList() const;
125 125
126 ErrorCode extractAll(const QString& dirname, ExtractionOptions options = ExtractPaths); 126 ErrorCode extractAll(const QString& dirname, ExtractionOptions options = ExtractPaths);
127 ErrorCode extractAll(const QDir& dir, ExtractionOptions options = ExtractPaths); 127 ErrorCode extractAll(const QDir& dir, ExtractionOptions options = ExtractPaths);
128 128
129 ErrorCode extractFile(const QString& filename, const QString& dirname, ExtractionOptions options = ExtractPaths); 129 ErrorCode extractFile(const QString& filename, const QString& dirname, ExtractionOptions options = ExtractPaths);
130 ErrorCode extractFile(const QString& filename, const QDir& dir, ExtractionOptions options = ExtractPaths); 130 ErrorCode extractFile(const QString& filename, const QDir& dir, ExtractionOptions options = ExtractPaths);
131 ErrorCode extractFile(const QString& filename, QIODevice* device, ExtractionOptions options = ExtractPaths); 131 ErrorCode extractFile(const QString& filename, QIODevice* device, ExtractionOptions options = ExtractPaths);
132 132
133 ErrorCode extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options = ExtractPaths); 133 ErrorCode extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options = ExtractPaths);
134 ErrorCode extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options = ExtractPaths); 134 ErrorCode extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options = ExtractPaths);
135 135
136 void setPassword(const QString& pwd); 136 void setPassword(const QString& pwd);
137 137
138private: 138private:
139 UnzipPrivate* d; 139 UnzipPrivate* d;
140}; 140};
141 141
142Q_DECLARE_OPERATORS_FOR_FLAGS(UnZip::ExtractionOptions) 142Q_DECLARE_OPERATORS_FOR_FLAGS(UnZip::ExtractionOptions)
143 143
144#endif // OSDAB_UNZIP__H 144#endif // OSDAB_UNZIP__H
diff --git a/rbutil/rbutilqt/zip/unzip_p.h b/rbutil/rbutilqt/zip/unzip_p.h
index c05ac67b47..c0ea11b7bf 100644
--- a/rbutil/rbutilqt/zip/unzip_p.h
+++ b/rbutil/rbutilqt/zip/unzip_p.h
@@ -1,112 +1,112 @@
1/**************************************************************************** 1/****************************************************************************
2** Filename: unzip_p.h 2** Filename: unzip_p.h
3** Last updated [dd/mm/yyyy]: 28/01/2007 3** Last updated [dd/mm/yyyy]: 28/01/2007
4** 4**
5** pkzip 2.0 decompression. 5** pkzip 2.0 decompression.
6** 6**
7** Some of the code has been inspired by other open source projects, 7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip). 8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library. 9** Compression and decompression actually uses the zlib library.
10** 10**
11** Copyright (C) 2007 Angius Fabrizio. All rights reserved. 11** Copyright (C) 2007 Angius Fabrizio. All rights reserved.
12** 12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/). 13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14** 14**
15** This file may be distributed and/or modified under the terms of the 15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software 16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the 17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file. 18** packaging of this file.
19** 19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22** 22**
23** See the file LICENSE.GPL that came with this software distribution or 23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information. 24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25** 25**
26**********************************************************************/ 26**********************************************************************/
27 27
28// 28//
29// W A R N I N G 29// W A R N I N G
30// ------------- 30// -------------
31// 31//
32// This file is not part of the Zip/UnZip API. It exists purely as an 32// This file is not part of the Zip/UnZip API. It exists purely as an
33// implementation detail. This header file may change from version to 33// implementation detail. This header file may change from version to
34// version without notice, or even be removed. 34// version without notice, or even be removed.
35// 35//
36// We mean it. 36// We mean it.
37// 37//
38 38
39#ifndef OSDAB_UNZIP_P__H 39#ifndef OSDAB_UNZIP_P__H
40#define OSDAB_UNZIP_P__H 40#define OSDAB_UNZIP_P__H
41 41
42#include "unzip.h" 42#include "unzip.h"
43#include "zipentry_p.h" 43#include "zipentry_p.h"
44 44
45#include <QtGlobal> 45#include <QtGlobal>
46 46
47// zLib authors suggest using larger buffers (128K or 256K) for (de)compression (especially for inflate()) 47// zLib authors suggest using larger buffers (128K or 256K) for (de)compression (especially for inflate())
48// we use a 256K buffer here - if you want to use this code on a pre-iceage mainframe please change it ;) 48// we use a 256K buffer here - if you want to use this code on a pre-iceage mainframe please change it ;)
49#define UNZIP_READ_BUFFER (256*1024) 49#define UNZIP_READ_BUFFER (256*1024)
50 50
51class UnzipPrivate 51class UnzipPrivate
52{ 52{
53public: 53public:
54 UnzipPrivate(); 54 UnzipPrivate();
55 55
56 // Replace this with whatever else you use to store/retrieve the password. 56 // Replace this with whatever else you use to store/retrieve the password.
57 QString password; 57 QString password;
58 58
59 bool skipAllEncrypted; 59 bool skipAllEncrypted;
60 60
61 QMap<QString,ZipEntryP*>* headers; 61 QMap<QString,ZipEntryP*>* headers;
62 62
63 QIODevice* device; 63 QIODevice* device;
64 64
65 char buffer1[UNZIP_READ_BUFFER]; 65 char buffer1[UNZIP_READ_BUFFER];
66 char buffer2[UNZIP_READ_BUFFER]; 66 char buffer2[UNZIP_READ_BUFFER];
67 67
68 unsigned char* uBuffer; 68 unsigned char* uBuffer;
69 const quint32* crcTable; 69 const quint32* crcTable;
70 70
71 // Central Directory (CD) offset 71 // Central Directory (CD) offset
72 quint32 cdOffset; 72 quint32 cdOffset;
73 // End of Central Directory (EOCD) offset 73 // End of Central Directory (EOCD) offset
74 quint32 eocdOffset; 74 quint32 eocdOffset;
75 75
76 // Number of entries in the Central Directory (as to the EOCD record) 76 // Number of entries in the Central Directory (as to the EOCD record)
77 quint16 cdEntryCount; 77 quint16 cdEntryCount;
78 78
79 // The number of detected entries that have been skipped because of a non compatible format 79 // The number of detected entries that have been skipped because of a non compatible format
80 quint16 unsupportedEntryCount; 80 quint16 unsupportedEntryCount;
81 81
82 QString comment; 82 QString comment;
83 83
84 UnZip::ErrorCode openArchive(QIODevice* device); 84 UnZip::ErrorCode openArchive(QIODevice* device);
85 85
86 UnZip::ErrorCode seekToCentralDirectory(); 86 UnZip::ErrorCode seekToCentralDirectory();
87 UnZip::ErrorCode parseCentralDirectoryRecord(); 87 UnZip::ErrorCode parseCentralDirectoryRecord();
88 UnZip::ErrorCode parseLocalHeaderRecord(const QString& path, ZipEntryP& entry); 88 UnZip::ErrorCode parseLocalHeaderRecord(const QString& path, ZipEntryP& entry);
89 89
90 void closeArchive(); 90 void closeArchive();
91 91
92 UnZip::ErrorCode extractFile(const QString& path, ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options); 92 UnZip::ErrorCode extractFile(const QString& path, ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options);
93 UnZip::ErrorCode extractFile(const QString& path, ZipEntryP& entry, QIODevice* device, UnZip::ExtractionOptions options); 93 UnZip::ErrorCode extractFile(const QString& path, ZipEntryP& entry, QIODevice* device, UnZip::ExtractionOptions options);
94 94
95 UnZip::ErrorCode testPassword(quint32* keys, const QString& file, const ZipEntryP& header); 95 UnZip::ErrorCode testPassword(quint32* keys, const QString& file, const ZipEntryP& header);
96 bool testKeys(const ZipEntryP& header, quint32* keys); 96 bool testKeys(const ZipEntryP& header, quint32* keys);
97 97
98 bool createDirectory(const QString& path); 98 bool createDirectory(const QString& path);
99 99
100 inline void decryptBytes(quint32* keys, char* buffer, qint64 read); 100 inline void decryptBytes(quint32* keys, char* buffer, qint64 read);
101 101
102 inline quint32 getULong(const unsigned char* data, quint32 offset) const; 102 inline quint32 getULong(const unsigned char* data, quint32 offset) const;
103 inline quint64 getULLong(const unsigned char* data, quint32 offset) const; 103 inline quint64 getULLong(const unsigned char* data, quint32 offset) const;
104 inline quint16 getUShort(const unsigned char* data, quint32 offset) const; 104 inline quint16 getUShort(const unsigned char* data, quint32 offset) const;
105 inline int decryptByte(quint32 key2) const; 105 inline int decryptByte(quint32 key2) const;
106 inline void updateKeys(quint32* keys, int c) const; 106 inline void updateKeys(quint32* keys, int c) const;
107 inline void initKeys(const QString& pwd, quint32* keys) const; 107 inline void initKeys(const QString& pwd, quint32* keys) const;
108 108
109 inline QDateTime convertDateTime(const unsigned char date[2], const unsigned char time[2]) const; 109 inline QDateTime convertDateTime(const unsigned char date[2], const unsigned char time[2]) const;
110}; 110};
111 111
112#endif // OSDAB_UNZIP_P__H 112#endif // OSDAB_UNZIP_P__H
diff --git a/rbutil/rbutilqt/zip/zip.cpp b/rbutil/rbutilqt/zip/zip.cpp
index ac1eaaea0b..6732278fe6 100644
--- a/rbutil/rbutilqt/zip/zip.cpp
+++ b/rbutil/rbutilqt/zip/zip.cpp
@@ -1,1221 +1,1221 @@
1/**************************************************************************** 1/****************************************************************************
2** Filename: zip.cpp 2** Filename: zip.cpp
3** Last updated [dd/mm/yyyy]: 01/02/2007 3** Last updated [dd/mm/yyyy]: 01/02/2007
4** 4**
5** pkzip 2.0 file compression. 5** pkzip 2.0 file compression.
6** 6**
7** Some of the code has been inspired by other open source projects, 7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip). 8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library. 9** Compression and decompression actually uses the zlib library.
10** 10**
11** Copyright (C) 2007 Angius Fabrizio. All rights reserved. 11** Copyright (C) 2007 Angius Fabrizio. All rights reserved.
12** 12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/). 13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14** 14**
15** This file may be distributed and/or modified under the terms of the 15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software 16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the 17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file. 18** packaging of this file.
19** 19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22** 22**
23** See the file LICENSE.GPL that came with this software distribution or 23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information. 24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25** 25**
26**********************************************************************/ 26**********************************************************************/
27 27
28#include "zip.h" 28#include "zip.h"
29#include "zip_p.h" 29#include "zip_p.h"
30#include "zipentry_p.h" 30#include "zipentry_p.h"
31 31
32// we only use this to seed the random number generator 32// we only use this to seed the random number generator
33#include <time.h> 33#include <time.h>
34 34
35#include <QMap> 35#include <QMap>
36#include <QString> 36#include <QString>
37#include <QStringList> 37#include <QStringList>
38#include <QDir> 38#include <QDir>
39#include <QFile> 39#include <QFile>
40#include <QDateTime> 40#include <QDateTime>
41#include <QCoreApplication> 41#include <QCoreApplication>
42 42
43// You can remove this #include if you replace the qDebug() statements. 43// You can remove this #include if you replace the qDebug() statements.
44#include <QtDebug> 44#include <QtDebug>
45 45
46//! Local header size (including signature, excluding variable length fields) 46//! Local header size (including signature, excluding variable length fields)
47#define ZIP_LOCAL_HEADER_SIZE 30 47#define ZIP_LOCAL_HEADER_SIZE 30
48//! Encryption header size 48//! Encryption header size
49#define ZIP_LOCAL_ENC_HEADER_SIZE 12 49#define ZIP_LOCAL_ENC_HEADER_SIZE 12
50//! Data descriptor size (signature included) 50//! Data descriptor size (signature included)
51#define ZIP_DD_SIZE_WS 16 51#define ZIP_DD_SIZE_WS 16
52//! Central Directory record size (signature included) 52//! Central Directory record size (signature included)
53#define ZIP_CD_SIZE 46 53#define ZIP_CD_SIZE 46
54//! End of Central Directory record size (signature included) 54//! End of Central Directory record size (signature included)
55#define ZIP_EOCD_SIZE 22 55#define ZIP_EOCD_SIZE 22
56 56
57// Some offsets inside a local header record (signature included) 57// Some offsets inside a local header record (signature included)
58#define ZIP_LH_OFF_VERS 4 58#define ZIP_LH_OFF_VERS 4
59#define ZIP_LH_OFF_GPFLAG 6 59#define ZIP_LH_OFF_GPFLAG 6
60#define ZIP_LH_OFF_CMET 8 60#define ZIP_LH_OFF_CMET 8
61#define ZIP_LH_OFF_MODT 10 61#define ZIP_LH_OFF_MODT 10
62#define ZIP_LH_OFF_MODD 12 62#define ZIP_LH_OFF_MODD 12
63#define ZIP_LH_OFF_CRC 14 63#define ZIP_LH_OFF_CRC 14
64#define ZIP_LH_OFF_CSIZE 18 64#define ZIP_LH_OFF_CSIZE 18
65#define ZIP_LH_OFF_USIZE 22 65#define ZIP_LH_OFF_USIZE 22
66#define ZIP_LH_OFF_NAMELEN 26 66#define ZIP_LH_OFF_NAMELEN 26
67#define ZIP_LH_OFF_XLEN 28 67#define ZIP_LH_OFF_XLEN 28
68 68
69// Some offsets inside a data descriptor record (including signature) 69// Some offsets inside a data descriptor record (including signature)
70#define ZIP_DD_OFF_CRC32 4 70#define ZIP_DD_OFF_CRC32 4
71#define ZIP_DD_OFF_CSIZE 8 71#define ZIP_DD_OFF_CSIZE 8
72#define ZIP_DD_OFF_USIZE 12 72#define ZIP_DD_OFF_USIZE 12
73 73
74// Some offsets inside a Central Directory record (including signature) 74// Some offsets inside a Central Directory record (including signature)
75#define ZIP_CD_OFF_MADEBY 4 75#define ZIP_CD_OFF_MADEBY 4
76#define ZIP_CD_OFF_VERSION 6 76#define ZIP_CD_OFF_VERSION 6
77#define ZIP_CD_OFF_GPFLAG 8 77#define ZIP_CD_OFF_GPFLAG 8
78#define ZIP_CD_OFF_CMET 10 78#define ZIP_CD_OFF_CMET 10
79#define ZIP_CD_OFF_MODT 12 79#define ZIP_CD_OFF_MODT 12
80#define ZIP_CD_OFF_MODD 14 80#define ZIP_CD_OFF_MODD 14
81#define ZIP_CD_OFF_CRC 16 81#define ZIP_CD_OFF_CRC 16
82#define ZIP_CD_OFF_CSIZE 20 82#define ZIP_CD_OFF_CSIZE 20
83#define ZIP_CD_OFF_USIZE 24 83#define ZIP_CD_OFF_USIZE 24
84#define ZIP_CD_OFF_NAMELEN 28 84#define ZIP_CD_OFF_NAMELEN 28
85#define ZIP_CD_OFF_XLEN 30 85#define ZIP_CD_OFF_XLEN 30
86#define ZIP_CD_OFF_COMMLEN 32 86#define ZIP_CD_OFF_COMMLEN 32
87#define ZIP_CD_OFF_DISKSTART 34 87#define ZIP_CD_OFF_DISKSTART 34
88#define ZIP_CD_OFF_IATTR 36 88#define ZIP_CD_OFF_IATTR 36
89#define ZIP_CD_OFF_EATTR 38 89#define ZIP_CD_OFF_EATTR 38
90#define ZIP_CD_OFF_LHOFF 42 90#define ZIP_CD_OFF_LHOFF 42
91 91
92// Some offsets inside a EOCD record (including signature) 92// Some offsets inside a EOCD record (including signature)
93#define ZIP_EOCD_OFF_DISKNUM 4 93#define ZIP_EOCD_OFF_DISKNUM 4
94#define ZIP_EOCD_OFF_CDDISKNUM 6 94#define ZIP_EOCD_OFF_CDDISKNUM 6
95#define ZIP_EOCD_OFF_ENTRIES 8 95#define ZIP_EOCD_OFF_ENTRIES 8
96#define ZIP_EOCD_OFF_CDENTRIES 10 96#define ZIP_EOCD_OFF_CDENTRIES 10
97#define ZIP_EOCD_OFF_CDSIZE 12 97#define ZIP_EOCD_OFF_CDSIZE 12
98#define ZIP_EOCD_OFF_CDOFF 16 98#define ZIP_EOCD_OFF_CDOFF 16
99#define ZIP_EOCD_OFF_COMMLEN 20 99#define ZIP_EOCD_OFF_COMMLEN 20
100 100
101//! PKZip version for archives created by this API 101//! PKZip version for archives created by this API
102#define ZIP_VERSION 0x14 102#define ZIP_VERSION 0x14
103 103
104//! Do not store very small files as the compression headers overhead would be to big 104//! Do not store very small files as the compression headers overhead would be to big
105#define ZIP_COMPRESSION_THRESHOLD 60 105#define ZIP_COMPRESSION_THRESHOLD 60
106 106
107//! This macro updates a one-char-only CRC; it's the Info-Zip macro re-adapted 107//! This macro updates a one-char-only CRC; it's the Info-Zip macro re-adapted
108#define CRC32(c, b) crcTable[((int)c^b) & 0xff] ^ (c >> 8) 108#define CRC32(c, b) crcTable[((int)c^b) & 0xff] ^ (c >> 8)
109 109
110/*! 110/*!
111 \class Zip zip.h 111 \class Zip zip.h
112 112
113 \brief Zip file compression. 113 \brief Zip file compression.
114 114
115 Some quick usage examples. 115 Some quick usage examples.
116 116
117 \verbatim 117 \verbatim
118 Suppose you have this directory structure: 118 Suppose you have this directory structure:
119 119
120 /root/dir1/ 120 /root/dir1/
121 /root/dir1/file1.1 121 /root/dir1/file1.1
122 /root/dir1/file1.2 122 /root/dir1/file1.2
123 /root/dir1/dir1.1/ 123 /root/dir1/dir1.1/
124 /root/dir1/dir1.2/file1.2.1 124 /root/dir1/dir1.2/file1.2.1
125 125
126 EXAMPLE 1: 126 EXAMPLE 1:
127 myZipInstance.addDirectory("/root/dir1"); 127 myZipInstance.addDirectory("/root/dir1");
128 128
129 RESULT: 129 RESULT:
130 Beheaves like any common zip software and creates a zip file with this structure: 130 Beheaves like any common zip software and creates a zip file with this structure:
131 131
132 dir1/ 132 dir1/
133 dir1/file1.1 133 dir1/file1.1
134 dir1/file1.2 134 dir1/file1.2
135 dir1/dir1.1/ 135 dir1/dir1.1/
136 dir1/dir1.2/file1.2.1 136 dir1/dir1.2/file1.2.1
137 137
138 EXAMPLE 2: 138 EXAMPLE 2:
139 myZipInstance.addDirectory("/root/dir1", "myRoot/myFolder"); 139 myZipInstance.addDirectory("/root/dir1", "myRoot/myFolder");
140 140
141 RESULT: 141 RESULT:
142 Adds a custom root to the paths and creates a zip file with this structure: 142 Adds a custom root to the paths and creates a zip file with this structure:
143 143
144 myRoot/myFolder/dir1/ 144 myRoot/myFolder/dir1/
145 myRoot/myFolder/dir1/file1.1 145 myRoot/myFolder/dir1/file1.1
146 myRoot/myFolder/dir1/file1.2 146 myRoot/myFolder/dir1/file1.2
147 myRoot/myFolder/dir1/dir1.1/ 147 myRoot/myFolder/dir1/dir1.1/
148 myRoot/myFolder/dir1/dir1.2/file1.2.1 148 myRoot/myFolder/dir1/dir1.2/file1.2.1
149 149
150 EXAMPLE 3: 150 EXAMPLE 3:
151 myZipInstance.addDirectory("/root/dir1", Zip::AbsolutePaths); 151 myZipInstance.addDirectory("/root/dir1", Zip::AbsolutePaths);
152 152
153 NOTE: 153 NOTE:
154 Same as calling addDirectory(SOME_PATH, PARENT_PATH_of_SOME_PATH). 154 Same as calling addDirectory(SOME_PATH, PARENT_PATH_of_SOME_PATH).
155 155
156 RESULT: 156 RESULT:
157 Preserves absolute paths and creates a zip file with this structure: 157 Preserves absolute paths and creates a zip file with this structure:
158 158
159 /root/dir1/ 159 /root/dir1/
160 /root/dir1/file1.1 160 /root/dir1/file1.1
161 /root/dir1/file1.2 161 /root/dir1/file1.2
162 /root/dir1/dir1.1/ 162 /root/dir1/dir1.1/
163 /root/dir1/dir1.2/file1.2.1 163 /root/dir1/dir1.2/file1.2.1
164 164
165 EXAMPLE 4: 165 EXAMPLE 4:
166 myZipInstance.setPassword("hellopass"); 166 myZipInstance.setPassword("hellopass");
167 myZipInstance.addDirectory("/root/dir1", "/"); 167 myZipInstance.addDirectory("/root/dir1", "/");
168 168
169 RESULT: 169 RESULT:
170 Adds and encrypts the files in /root/dir1, creating the following zip structure: 170 Adds and encrypts the files in /root/dir1, creating the following zip structure:
171 171
172 /dir1/ 172 /dir1/
173 /dir1/file1.1 173 /dir1/file1.1
174 /dir1/file1.2 174 /dir1/file1.2
175 /dir1/dir1.1/ 175 /dir1/dir1.1/
176 /dir1/dir1.2/file1.2.1 176 /dir1/dir1.2/file1.2.1
177 177
178 \endverbatim 178 \endverbatim
179*/ 179*/
180 180
181/*! \enum Zip::ErrorCode The result of a compression operation. 181/*! \enum Zip::ErrorCode The result of a compression operation.
182 \value Zip::Ok No error occurred. 182 \value Zip::Ok No error occurred.
183 \value Zip::ZlibInit Failed to init or load the zlib library. 183 \value Zip::ZlibInit Failed to init or load the zlib library.
184 \value Zip::ZlibError The zlib library returned some error. 184 \value Zip::ZlibError The zlib library returned some error.
185 \value Zip::FileExists The file already exists and will not be overwritten. 185 \value Zip::FileExists The file already exists and will not be overwritten.
186 \value Zip::OpenFailed Unable to create or open a device. 186 \value Zip::OpenFailed Unable to create or open a device.
187 \value Zip::NoOpenArchive CreateArchive() has not been called yet. 187 \value Zip::NoOpenArchive CreateArchive() has not been called yet.
188 \value Zip::FileNotFound File or directory does not exist. 188 \value Zip::FileNotFound File or directory does not exist.
189 \value Zip::ReadFailed Reading of a file failed. 189 \value Zip::ReadFailed Reading of a file failed.
190 \value Zip::WriteFailed Writing of a file failed. 190 \value Zip::WriteFailed Writing of a file failed.
191 \value Zip::SeekFailed Seek failed. 191 \value Zip::SeekFailed Seek failed.
192*/ 192*/
193 193
194/*! \enum Zip::CompressionLevel Returns the result of a decompression operation. 194/*! \enum Zip::CompressionLevel Returns the result of a decompression operation.
195 \value Zip::Store No compression. 195 \value Zip::Store No compression.
196 \value Zip::Deflate1 Deflate compression level 1(lowest compression). 196 \value Zip::Deflate1 Deflate compression level 1(lowest compression).
197 \value Zip::Deflate1 Deflate compression level 2. 197 \value Zip::Deflate1 Deflate compression level 2.
198 \value Zip::Deflate1 Deflate compression level 3. 198 \value Zip::Deflate1 Deflate compression level 3.
199 \value Zip::Deflate1 Deflate compression level 4. 199 \value Zip::Deflate1 Deflate compression level 4.
200 \value Zip::Deflate1 Deflate compression level 5. 200 \value Zip::Deflate1 Deflate compression level 5.
201 \value Zip::Deflate1 Deflate compression level 6. 201 \value Zip::Deflate1 Deflate compression level 6.
202 \value Zip::Deflate1 Deflate compression level 7. 202 \value Zip::Deflate1 Deflate compression level 7.
203 \value Zip::Deflate1 Deflate compression level 8. 203 \value Zip::Deflate1 Deflate compression level 8.
204 \value Zip::Deflate1 Deflate compression level 9 (maximum compression). 204 \value Zip::Deflate1 Deflate compression level 9 (maximum compression).
205 \value Zip::AutoCPU Adapt compression level to CPU speed (faster CPU => better compression). 205 \value Zip::AutoCPU Adapt compression level to CPU speed (faster CPU => better compression).
206 \value Zip::AutoMIME Adapt compression level to MIME type of the file being compressed. 206 \value Zip::AutoMIME Adapt compression level to MIME type of the file being compressed.
207 \value Zip::AutoFull Use both CPU and MIME type detection. 207 \value Zip::AutoFull Use both CPU and MIME type detection.
208*/ 208*/
209 209
210 210
211/************************************************************************ 211/************************************************************************
212 Public interface 212 Public interface
213*************************************************************************/ 213*************************************************************************/
214 214
215/*! 215/*!
216 Creates a new Zip file compressor. 216 Creates a new Zip file compressor.
217*/ 217*/
218Zip::Zip() 218Zip::Zip()
219{ 219{
220 d = new ZipPrivate; 220 d = new ZipPrivate;
221} 221}
222 222
223/*! 223/*!
224 Closes any open archive and releases used resources. 224 Closes any open archive and releases used resources.
225*/ 225*/
226Zip::~Zip() 226Zip::~Zip()
227{ 227{
228 closeArchive(); 228 closeArchive();
229 delete d; 229 delete d;
230} 230}
231 231
232/*! 232/*!
233 Returns true if there is an open archive. 233 Returns true if there is an open archive.
234*/ 234*/
235bool Zip::isOpen() const 235bool Zip::isOpen() const
236{ 236{
237 return d->device != 0; 237 return d->device != 0;
238} 238}
239 239
240/*! 240/*!
241 Sets the password to be used for the next files being added! 241 Sets the password to be used for the next files being added!
242 Files added before calling this method will use the previously 242 Files added before calling this method will use the previously
243 set password (if any). 243 set password (if any).
244 Closing the archive won't clear the password! 244 Closing the archive won't clear the password!
245*/ 245*/
246void Zip::setPassword(const QString& pwd) 246void Zip::setPassword(const QString& pwd)
247{ 247{
248 d->password = pwd; 248 d->password = pwd;
249} 249}
250 250
251//! Convenience method, clears the current password. 251//! Convenience method, clears the current password.
252void Zip::clearPassword() 252void Zip::clearPassword()
253{ 253{
254 d->password.clear(); 254 d->password.clear();
255} 255}
256 256
257//! Returns the currently used password. 257//! Returns the currently used password.
258QString Zip::password() const 258QString Zip::password() const
259{ 259{
260 return d->password; 260 return d->password;
261} 261}
262 262
263/*! 263/*!
264 Attempts to create a new Zip archive. If \p overwrite is true and the file 264 Attempts to create a new Zip archive. If \p overwrite is true and the file
265 already exist it will be overwritten. 265 already exist it will be overwritten.
266 Any open archive will be closed. 266 Any open archive will be closed.
267 */ 267 */
268Zip::ErrorCode Zip::createArchive(const QString& filename, bool overwrite) 268Zip::ErrorCode Zip::createArchive(const QString& filename, bool overwrite)
269{ 269{
270 QFile* file = new QFile(filename); 270 QFile* file = new QFile(filename);
271 271
272 if (file->exists() && !overwrite) { 272 if (file->exists() && !overwrite) {
273 delete file; 273 delete file;
274 return Zip::FileExists; 274 return Zip::FileExists;
275 } 275 }
276 276
277 if (!file->open(QIODevice::WriteOnly)) { 277 if (!file->open(QIODevice::WriteOnly)) {
278 delete file; 278 delete file;
279 return Zip::OpenFailed; 279 return Zip::OpenFailed;
280 } 280 }
281 281
282 Zip::ErrorCode ec = createArchive(file); 282 Zip::ErrorCode ec = createArchive(file);
283 if (ec != Zip::Ok) { 283 if (ec != Zip::Ok) {
284 file->remove(); 284 file->remove();
285 } 285 }
286 286
287 return ec; 287 return ec;
288} 288}
289 289
290/*! 290/*!
291 Attempts to create a new Zip archive. If there is another open archive this will be closed. 291 Attempts to create a new Zip archive. If there is another open archive this will be closed.
292 \warning The class takes ownership of the device! 292 \warning The class takes ownership of the device!
293 */ 293 */
294Zip::ErrorCode Zip::createArchive(QIODevice* device) 294Zip::ErrorCode Zip::createArchive(QIODevice* device)
295{ 295{
296 if (device == 0) 296 if (device == 0)
297 { 297 {
298 qDebug() << "Invalid device."; 298 qDebug() << "Invalid device.";
299 return Zip::OpenFailed; 299 return Zip::OpenFailed;
300 } 300 }
301 301
302 return d->createArchive(device); 302 return d->createArchive(device);
303} 303}
304 304
305/*! 305/*!
306 Returns the current archive comment. 306 Returns the current archive comment.
307*/ 307*/
308QString Zip::archiveComment() const 308QString Zip::archiveComment() const
309{ 309{
310 return d->comment; 310 return d->comment;
311} 311}
312 312
313/*! 313/*!
314 Sets the comment for this archive. Note: createArchive() should have been 314 Sets the comment for this archive. Note: createArchive() should have been
315 called before. 315 called before.
316*/ 316*/
317void Zip::setArchiveComment(const QString& comment) 317void Zip::setArchiveComment(const QString& comment)
318{ 318{
319 if (d->device != 0) 319 if (d->device != 0)
320 d->comment = comment; 320 d->comment = comment;
321} 321}
322 322
323/*! 323/*!
324 Convenience method, same as calling 324 Convenience method, same as calling
325 Zip::addDirectory(const QString&,const QString&,CompressionLevel) 325 Zip::addDirectory(const QString&,const QString&,CompressionLevel)
326 with an empty \p root parameter (or with the parent directory of \p path if the 326 with an empty \p root parameter (or with the parent directory of \p path if the
327 AbsolutePaths options is set). 327 AbsolutePaths options is set).
328 328
329 The ExtractionOptions are checked in the order they are defined in the zip.h heaser file. 329 The ExtractionOptions are checked in the order they are defined in the zip.h heaser file.
330 This means that the last one overwrites the previous one (if some conflict occurs), i.e. 330 This means that the last one overwrites the previous one (if some conflict occurs), i.e.
331 Zip::IgnorePaths | Zip::AbsolutePaths would be interpreted as Zip::IgnorePaths. 331 Zip::IgnorePaths | Zip::AbsolutePaths would be interpreted as Zip::IgnorePaths.
332 */ 332 */
333Zip::ErrorCode Zip::addDirectory(const QString& path, CompressionOptions options, CompressionLevel level) 333Zip::ErrorCode Zip::addDirectory(const QString& path, CompressionOptions options, CompressionLevel level)
334{ 334{
335 return addDirectory(path, QString(), options, level); 335 return addDirectory(path, QString(), options, level);
336} 336}
337 337
338/*! 338/*!
339 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel) 339 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
340 with the Zip::RelativePaths flag as compression option. 340 with the Zip::RelativePaths flag as compression option.
341 */ 341 */
342Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root, CompressionLevel level) 342Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root, CompressionLevel level)
343{ 343{
344 return addDirectory(path, root, Zip::RelativePaths, level); 344 return addDirectory(path, root, Zip::RelativePaths, level);
345} 345}
346 346
347/*! 347/*!
348 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel) 348 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
349 with the Zip::IgnorePaths flag as compression option and an empty \p root parameter. 349 with the Zip::IgnorePaths flag as compression option and an empty \p root parameter.
350*/ 350*/
351Zip::ErrorCode Zip::addDirectoryContents(const QString& path, CompressionLevel level) 351Zip::ErrorCode Zip::addDirectoryContents(const QString& path, CompressionLevel level)
352{ 352{
353 return addDirectory(path, QString(), IgnorePaths, level); 353 return addDirectory(path, QString(), IgnorePaths, level);
354} 354}
355 355
356/*! 356/*!
357 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel) 357 Convenience method, same as calling Zip::addDirectory(const QString&,const QString&,CompressionOptions,CompressionLevel)
358 with the Zip::IgnorePaths flag as compression option. 358 with the Zip::IgnorePaths flag as compression option.
359*/ 359*/
360Zip::ErrorCode Zip::addDirectoryContents(const QString& path, const QString& root, CompressionLevel level) 360Zip::ErrorCode Zip::addDirectoryContents(const QString& path, const QString& root, CompressionLevel level)
361{ 361{
362 return addDirectory(path, root, IgnorePaths, level); 362 return addDirectory(path, root, IgnorePaths, level);
363} 363}
364 364
365/*! 365/*!
366 Recursively adds files contained in \p dir to the archive, using \p root as name for the root folder. 366 Recursively adds files contained in \p dir to the archive, using \p root as name for the root folder.
367 Stops adding files if some error occurs. 367 Stops adding files if some error occurs.
368 368
369 The ExtractionOptions are checked in the order they are defined in the zip.h heaser file. 369 The ExtractionOptions are checked in the order they are defined in the zip.h heaser file.
370 This means that the last one overwrites the previous one (if some conflict occurs), i.e. 370 This means that the last one overwrites the previous one (if some conflict occurs), i.e.
371 Zip::IgnorePaths | Zip::AbsolutePaths would be interpreted as Zip::IgnorePaths. 371 Zip::IgnorePaths | Zip::AbsolutePaths would be interpreted as Zip::IgnorePaths.
372 372
373 The \p root parameter is ignored with the Zip::IgnorePaths parameter and used as path prefix (a trailing / 373 The \p root parameter is ignored with the Zip::IgnorePaths parameter and used as path prefix (a trailing /
374 is always added as directory separator!) otherwise (even with Zip::AbsolutePaths set!). 374 is always added as directory separator!) otherwise (even with Zip::AbsolutePaths set!).
375*/ 375*/
376Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root, CompressionOptions options, CompressionLevel level) 376Zip::ErrorCode Zip::addDirectory(const QString& path, const QString& root, CompressionOptions options, CompressionLevel level)
377{ 377{
378 // qDebug() << QString("addDir(path=%1, root=%2)").arg(path, root); 378 // qDebug() << QString("addDir(path=%1, root=%2)").arg(path, root);
379 379
380 // Bad boy didn't call createArchive() yet :) 380 // Bad boy didn't call createArchive() yet :)
381 if (d->device == 0) 381 if (d->device == 0)
382 return Zip::NoOpenArchive; 382 return Zip::NoOpenArchive;
383 383
384 QDir dir(path); 384 QDir dir(path);
385 if (!dir.exists()) 385 if (!dir.exists())
386 return Zip::FileNotFound; 386 return Zip::FileNotFound;
387 387
388 // Remove any trailing separator 388 // Remove any trailing separator
389 QString actualRoot = root.trimmed(); 389 QString actualRoot = root.trimmed();
390 390
391 // Preserve Unix root 391 // Preserve Unix root
392 if (actualRoot != "/") 392 if (actualRoot != "/")
393 { 393 {
394 while (actualRoot.endsWith("/") || actualRoot.endsWith("\\")) 394 while (actualRoot.endsWith("/") || actualRoot.endsWith("\\"))
395 actualRoot.truncate(actualRoot.length() - 1); 395 actualRoot.truncate(actualRoot.length() - 1);
396 } 396 }
397 397
398 // QDir::cleanPath() fixes some issues with QDir::dirName() 398 // QDir::cleanPath() fixes some issues with QDir::dirName()
399 QFileInfo current(QDir::cleanPath(path)); 399 QFileInfo current(QDir::cleanPath(path));
400 400
401 if (!actualRoot.isEmpty() && actualRoot != "/") 401 if (!actualRoot.isEmpty() && actualRoot != "/")
402 actualRoot.append("/"); 402 actualRoot.append("/");
403 403
404 /* This part is quite confusing and needs some test or check */ 404 /* This part is quite confusing and needs some test or check */
405 /* An attempt to compress the / root directory evtl. using a root prefix should be a good test */ 405 /* An attempt to compress the / root directory evtl. using a root prefix should be a good test */
406 if (options.testFlag(AbsolutePaths) && !options.testFlag(IgnorePaths)) 406 if (options.testFlag(AbsolutePaths) && !options.testFlag(IgnorePaths))
407 { 407 {
408 QString absolutePath = d->extractRoot(path); 408 QString absolutePath = d->extractRoot(path);
409 if (!absolutePath.isEmpty() && absolutePath != "/") 409 if (!absolutePath.isEmpty() && absolutePath != "/")
410 absolutePath.append("/"); 410 absolutePath.append("/");
411 actualRoot.append(absolutePath); 411 actualRoot.append(absolutePath);
412 } 412 }
413 413
414 if (!options.testFlag(IgnorePaths)) 414 if (!options.testFlag(IgnorePaths))
415 { 415 {
416 actualRoot = actualRoot.append(QDir(current.absoluteFilePath()).dirName()); 416 actualRoot = actualRoot.append(QDir(current.absoluteFilePath()).dirName());
417 actualRoot.append("/"); 417 actualRoot.append("/");
418 } 418 }
419 419
420 // actualRoot now contains the path of the file relative to the zip archive 420 // actualRoot now contains the path of the file relative to the zip archive
421 // with a trailing / 421 // with a trailing /
422 422
423 QFileInfoList list = dir.entryInfoList( 423 QFileInfoList list = dir.entryInfoList(
424 QDir::Files | 424 QDir::Files |
425 QDir::Dirs | 425 QDir::Dirs |
426 QDir::NoDotAndDotDot | 426 QDir::NoDotAndDotDot |
427 QDir::NoSymLinks); 427 QDir::NoSymLinks);
428 428
429 ErrorCode ec = Zip::Ok; 429 ErrorCode ec = Zip::Ok;
430 bool filesAdded = false; 430 bool filesAdded = false;
431 431
432 CompressionOptions recursionOptions; 432 CompressionOptions recursionOptions;
433 if (options.testFlag(IgnorePaths)) 433 if (options.testFlag(IgnorePaths))
434 recursionOptions |= IgnorePaths; 434 recursionOptions |= IgnorePaths;
435 else recursionOptions |= RelativePaths; 435 else recursionOptions |= RelativePaths;
436 436
437 for (int i = 0; i < list.size() && ec == Zip::Ok; ++i) 437 for (int i = 0; i < list.size() && ec == Zip::Ok; ++i)
438 { 438 {
439 QFileInfo info = list.at(i); 439 QFileInfo info = list.at(i);
440 440
441 if (info.isDir()) 441 if (info.isDir())
442 { 442 {
443 // Recursion :) 443 // Recursion :)
444 progress(); 444 progress();
445 ec = addDirectory(info.absoluteFilePath(), actualRoot, recursionOptions, level); 445 ec = addDirectory(info.absoluteFilePath(), actualRoot, recursionOptions, level);
446 } 446 }
447 else 447 else
448 { 448 {
449 progress(); 449 progress();
450 ec = d->createEntry(info, actualRoot, level); 450 ec = d->createEntry(info, actualRoot, level);
451 filesAdded = true; 451 filesAdded = true;
452 } 452 }
453 } 453 }
454 454
455 455
456 // We need an explicit record for this dir 456 // We need an explicit record for this dir
457 // Non-empty directories don't need it because they have a path component in the filename 457 // Non-empty directories don't need it because they have a path component in the filename
458 if (!filesAdded && !options.testFlag(IgnorePaths)) 458 if (!filesAdded && !options.testFlag(IgnorePaths))
459 ec = d->createEntry(current, actualRoot, level); 459 ec = d->createEntry(current, actualRoot, level);
460 460
461 return ec; 461 return ec;
462} 462}
463 463
464/*! 464/*!
465 Closes the archive and writes any pending data. 465 Closes the archive and writes any pending data.
466*/ 466*/
467Zip::ErrorCode Zip::closeArchive() 467Zip::ErrorCode Zip::closeArchive()
468{ 468{
469 Zip::ErrorCode ec = d->closeArchive(); 469 Zip::ErrorCode ec = d->closeArchive();
470 d->reset(); 470 d->reset();
471 return ec; 471 return ec;
472} 472}
473 473
474/*! 474/*!
475 Returns a locale translated error string for a given error code. 475 Returns a locale translated error string for a given error code.
476*/ 476*/
477QString Zip::formatError(Zip::ErrorCode c) const 477QString Zip::formatError(Zip::ErrorCode c) const
478{ 478{
479 switch (c) 479 switch (c)
480 { 480 {
481 case Ok: return QCoreApplication::translate("Zip", "ZIP operation completed successfully."); break; 481 case Ok: return QCoreApplication::translate("Zip", "ZIP operation completed successfully."); break;
482 case ZlibInit: return QCoreApplication::translate("Zip", "Failed to initialize or load zlib library."); break; 482 case ZlibInit: return QCoreApplication::translate("Zip", "Failed to initialize or load zlib library."); break;
483 case ZlibError: return QCoreApplication::translate("Zip", "zlib library error."); break; 483 case ZlibError: return QCoreApplication::translate("Zip", "zlib library error."); break;
484 case OpenFailed: return QCoreApplication::translate("Zip", "Unable to create or open file."); break; 484 case OpenFailed: return QCoreApplication::translate("Zip", "Unable to create or open file."); break;
485 case NoOpenArchive: return QCoreApplication::translate("Zip", "No archive has been created yet."); break; 485 case NoOpenArchive: return QCoreApplication::translate("Zip", "No archive has been created yet."); break;
486 case FileNotFound: return QCoreApplication::translate("Zip", "File or directory does not exist."); break; 486 case FileNotFound: return QCoreApplication::translate("Zip", "File or directory does not exist."); break;
487 case ReadFailed: return QCoreApplication::translate("Zip", "File read error."); break; 487 case ReadFailed: return QCoreApplication::translate("Zip", "File read error."); break;
488 case WriteFailed: return QCoreApplication::translate("Zip", "File write error."); break; 488 case WriteFailed: return QCoreApplication::translate("Zip", "File write error."); break;
489 case SeekFailed: return QCoreApplication::translate("Zip", "File seek error."); break; 489 case SeekFailed: return QCoreApplication::translate("Zip", "File seek error."); break;
490 default: ; 490 default: ;
491 } 491 }
492 492
493 return QCoreApplication::translate("Zip", "Unknown error."); 493 return QCoreApplication::translate("Zip", "Unknown error.");
494} 494}
495 495
496 496
497/************************************************************************ 497/************************************************************************
498 Private interface 498 Private interface
499*************************************************************************/ 499*************************************************************************/
500 500
501//! \internal 501//! \internal
502ZipPrivate::ZipPrivate() 502ZipPrivate::ZipPrivate()
503{ 503{
504 headers = 0; 504 headers = 0;
505 device = 0; 505 device = 0;
506 506
507 // keep an unsigned pointer so we avoid to over bloat the code with casts 507 // keep an unsigned pointer so we avoid to over bloat the code with casts
508 uBuffer = (unsigned char*) buffer1; 508 uBuffer = (unsigned char*) buffer1;
509 crcTable = (quint32*) get_crc_table(); 509 crcTable = (quint32*) get_crc_table();
510} 510}
511 511
512//! \internal 512//! \internal
513ZipPrivate::~ZipPrivate() 513ZipPrivate::~ZipPrivate()
514{ 514{
515 closeArchive(); 515 closeArchive();
516} 516}
517 517
518//! \internal 518//! \internal
519Zip::ErrorCode ZipPrivate::createArchive(QIODevice* dev) 519Zip::ErrorCode ZipPrivate::createArchive(QIODevice* dev)
520{ 520{
521 Q_ASSERT(dev != 0); 521 Q_ASSERT(dev != 0);
522 522
523 if (device != 0) 523 if (device != 0)
524 closeArchive(); 524 closeArchive();
525 525
526 device = dev; 526 device = dev;
527 527
528 if (!device->isOpen()) 528 if (!device->isOpen())
529 { 529 {
530 if (!device->open(QIODevice::ReadOnly)) { 530 if (!device->open(QIODevice::ReadOnly)) {
531 delete device; 531 delete device;
532 device = 0; 532 device = 0;
533 qDebug() << "Unable to open device for writing."; 533 qDebug() << "Unable to open device for writing.";
534 return Zip::OpenFailed; 534 return Zip::OpenFailed;
535 } 535 }
536 } 536 }
537 537
538 headers = new QMap<QString,ZipEntryP*>; 538 headers = new QMap<QString,ZipEntryP*>;
539 return Zip::Ok; 539 return Zip::Ok;
540} 540}
541 541
542//! \internal Writes a new entry in the zip file. 542//! \internal Writes a new entry in the zip file.
543Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& root, Zip::CompressionLevel level) 543Zip::ErrorCode ZipPrivate::createEntry(const QFileInfo& file, const QString& root, Zip::CompressionLevel level)
544{ 544{
545 //! \todo Automatic level detection (cpu, extension & file size) 545 //! \todo Automatic level detection (cpu, extension & file size)
546 546
547 // Directories and very small files are always stored 547 // Directories and very small files are always stored
548 // (small files would get bigger due to the compression headers overhead) 548 // (small files would get bigger due to the compression headers overhead)
549 549
550 // Need this for zlib 550 // Need this for zlib
551 bool isPNGFile = false; 551 bool isPNGFile = false;
552 bool dirOnly = file.isDir(); 552 bool dirOnly = file.isDir();
553 553
554 QString entryName = root; 554 QString entryName = root;
555 555
556 // Directory entry 556 // Directory entry
557 if (dirOnly) 557 if (dirOnly)
558 level = Zip::Store; 558 level = Zip::Store;
559 else 559 else
560 { 560 {
561 entryName.append(file.fileName()); 561 entryName.append(file.fileName());
562 562
563 QString ext = file.completeSuffix().toLower(); 563 QString ext = file.completeSuffix().toLower();
564 isPNGFile = ext == "png"; 564 isPNGFile = ext == "png";
565 565
566 if (file.size() < ZIP_COMPRESSION_THRESHOLD) 566 if (file.size() < ZIP_COMPRESSION_THRESHOLD)
567 level = Zip::Store; 567 level = Zip::Store;
568 else 568 else
569 switch (level) 569 switch (level)
570 { 570 {
571 case Zip::AutoCPU: 571 case Zip::AutoCPU:
572 level = Zip::Deflate5; 572 level = Zip::Deflate5;
573 break; 573 break;
574 case Zip::AutoMIME: 574 case Zip::AutoMIME:
575 level = detectCompressionByMime(ext); 575 level = detectCompressionByMime(ext);
576 break; 576 break;
577 case Zip::AutoFull: 577 case Zip::AutoFull:
578 level = detectCompressionByMime(ext); 578 level = detectCompressionByMime(ext);
579 break; 579 break;
580 default: 580 default:
581 ; 581 ;
582 } 582 }
583 } 583 }
584 584
585 // entryName contains the path as it should be written 585 // entryName contains the path as it should be written
586 // in the zip file records 586 // in the zip file records
587 // qDebug() << QString("addDir(file=%1, root=%2, entry=%3)").arg(file.absoluteFilePath(), root, entryName); 587 // qDebug() << QString("addDir(file=%1, root=%2, entry=%3)").arg(file.absoluteFilePath(), root, entryName);
588 588
589 // create header and store it to write a central directory later 589 // create header and store it to write a central directory later
590 ZipEntryP* h = new ZipEntryP; 590 ZipEntryP* h = new ZipEntryP;
591 591
592 h->compMethod = (level == Zip::Store) ? 0 : 0x0008; 592 h->compMethod = (level == Zip::Store) ? 0 : 0x0008;
593 593
594 // Set encryption bit and set the data descriptor bit 594 // Set encryption bit and set the data descriptor bit
595 // so we can use mod time instead of crc for password check 595 // so we can use mod time instead of crc for password check
596 bool encrypt = !dirOnly && !password.isEmpty(); 596 bool encrypt = !dirOnly && !password.isEmpty();
597 if (encrypt) 597 if (encrypt)
598 h->gpFlag[0] |= 9; 598 h->gpFlag[0] |= 9;
599 599
600 QDateTime dt = file.lastModified(); 600 QDateTime dt = file.lastModified();
601 QDate d = dt.date(); 601 QDate d = dt.date();
602 h->modDate[1] = ((d.year() - 1980) << 1) & 254; 602 h->modDate[1] = ((d.year() - 1980) << 1) & 254;
603 h->modDate[1] |= ((d.month() >> 3) & 1); 603 h->modDate[1] |= ((d.month() >> 3) & 1);
604 h->modDate[0] = ((d.month() & 7) << 5) & 224; 604 h->modDate[0] = ((d.month() & 7) << 5) & 224;
605 h->modDate[0] |= d.day(); 605 h->modDate[0] |= d.day();
606 606
607 QTime t = dt.time(); 607 QTime t = dt.time();
608 h->modTime[1] = (t.hour() << 3) & 248; 608 h->modTime[1] = (t.hour() << 3) & 248;
609 h->modTime[1] |= ((t.minute() >> 3) & 7); 609 h->modTime[1] |= ((t.minute() >> 3) & 7);
610 h->modTime[0] = ((t.minute() & 7) << 5) & 224; 610 h->modTime[0] = ((t.minute() & 7) << 5) & 224;
611 h->modTime[0] |= t.second() / 2; 611 h->modTime[0] |= t.second() / 2;
612 612
613 h->szUncomp = dirOnly ? 0 : file.size(); 613 h->szUncomp = dirOnly ? 0 : file.size();
614 614
615 // **** Write local file header **** 615 // **** Write local file header ****
616 616
617 // signature 617 // signature
618 buffer1[0] = 'P'; buffer1[1] = 'K'; 618 buffer1[0] = 'P'; buffer1[1] = 'K';
619 buffer1[2] = 0x3; buffer1[3] = 0x4; 619 buffer1[2] = 0x3; buffer1[3] = 0x4;
620 620
621 // version needed to extract 621 // version needed to extract
622 buffer1[ZIP_LH_OFF_VERS] = ZIP_VERSION; 622 buffer1[ZIP_LH_OFF_VERS] = ZIP_VERSION;
623 buffer1[ZIP_LH_OFF_VERS + 1] = 0; 623 buffer1[ZIP_LH_OFF_VERS + 1] = 0;
624 624
625 // general purpose flag 625 // general purpose flag
626 buffer1[ZIP_LH_OFF_GPFLAG] = h->gpFlag[0]; 626 buffer1[ZIP_LH_OFF_GPFLAG] = h->gpFlag[0];
627 buffer1[ZIP_LH_OFF_GPFLAG + 1] = h->gpFlag[1]; 627 buffer1[ZIP_LH_OFF_GPFLAG + 1] = h->gpFlag[1];
628 628
629 // compression method 629 // compression method
630 buffer1[ZIP_LH_OFF_CMET] = h->compMethod & 0xFF; 630 buffer1[ZIP_LH_OFF_CMET] = h->compMethod & 0xFF;
631 buffer1[ZIP_LH_OFF_CMET + 1] = (h->compMethod>>8) & 0xFF; 631 buffer1[ZIP_LH_OFF_CMET + 1] = (h->compMethod>>8) & 0xFF;
632 632
633 // last mod file time 633 // last mod file time
634 buffer1[ZIP_LH_OFF_MODT] = h->modTime[0]; 634 buffer1[ZIP_LH_OFF_MODT] = h->modTime[0];
635 buffer1[ZIP_LH_OFF_MODT + 1] = h->modTime[1]; 635 buffer1[ZIP_LH_OFF_MODT + 1] = h->modTime[1];
636 636
637 // last mod file date 637 // last mod file date
638 buffer1[ZIP_LH_OFF_MODD] = h->modDate[0]; 638 buffer1[ZIP_LH_OFF_MODD] = h->modDate[0];
639 buffer1[ZIP_LH_OFF_MODD + 1] = h->modDate[1]; 639 buffer1[ZIP_LH_OFF_MODD + 1] = h->modDate[1];
640 640
641 // skip crc (4bytes) [14,15,16,17] 641 // skip crc (4bytes) [14,15,16,17]
642 642
643 // skip compressed size but include evtl. encryption header (4bytes: [18,19,20,21]) 643 // skip compressed size but include evtl. encryption header (4bytes: [18,19,20,21])
644 buffer1[ZIP_LH_OFF_CSIZE] = 644 buffer1[ZIP_LH_OFF_CSIZE] =
645 buffer1[ZIP_LH_OFF_CSIZE + 1] = 645 buffer1[ZIP_LH_OFF_CSIZE + 1] =
646 buffer1[ZIP_LH_OFF_CSIZE + 2] = 646 buffer1[ZIP_LH_OFF_CSIZE + 2] =
647 buffer1[ZIP_LH_OFF_CSIZE + 3] = 0; 647 buffer1[ZIP_LH_OFF_CSIZE + 3] = 0;
648 648
649 h->szComp = encrypt ? ZIP_LOCAL_ENC_HEADER_SIZE : 0; 649 h->szComp = encrypt ? ZIP_LOCAL_ENC_HEADER_SIZE : 0;
650 650
651 // uncompressed size [22,23,24,25] 651 // uncompressed size [22,23,24,25]
652 setULong(h->szUncomp, buffer1, ZIP_LH_OFF_USIZE); 652 setULong(h->szUncomp, buffer1, ZIP_LH_OFF_USIZE);
653 653
654 // filename length 654 // filename length
655 QByteArray entryNameBytes = entryName.toAscii(); 655 QByteArray entryNameBytes = entryName.toAscii();
656 int sz = entryNameBytes.size(); 656 int sz = entryNameBytes.size();
657 657
658 buffer1[ZIP_LH_OFF_NAMELEN] = sz & 0xFF; 658 buffer1[ZIP_LH_OFF_NAMELEN] = sz & 0xFF;
659 buffer1[ZIP_LH_OFF_NAMELEN + 1] = (sz >> 8) & 0xFF; 659 buffer1[ZIP_LH_OFF_NAMELEN + 1] = (sz >> 8) & 0xFF;
660 660
661 // extra field length 661 // extra field length
662 buffer1[ZIP_LH_OFF_XLEN] = buffer1[ZIP_LH_OFF_XLEN + 1] = 0; 662 buffer1[ZIP_LH_OFF_XLEN] = buffer1[ZIP_LH_OFF_XLEN + 1] = 0;
663 663
664 // Store offset to write crc and compressed size 664 // Store offset to write crc and compressed size
665 h->lhOffset = device->pos(); 665 h->lhOffset = device->pos();
666 quint32 crcOffset = h->lhOffset + ZIP_LH_OFF_CRC; 666 quint32 crcOffset = h->lhOffset + ZIP_LH_OFF_CRC;
667 667
668 if (device->write(buffer1, ZIP_LOCAL_HEADER_SIZE) != ZIP_LOCAL_HEADER_SIZE) 668 if (device->write(buffer1, ZIP_LOCAL_HEADER_SIZE) != ZIP_LOCAL_HEADER_SIZE)
669 { 669 {
670 delete h; 670 delete h;
671 return Zip::WriteFailed; 671 return Zip::WriteFailed;
672 } 672 }
673 673
674 // Write out filename 674 // Write out filename
675 if (device->write(entryNameBytes) != sz) 675 if (device->write(entryNameBytes) != sz)
676 { 676 {
677 delete h; 677 delete h;
678 return Zip::WriteFailed; 678 return Zip::WriteFailed;
679 } 679 }
680 680
681 // Encryption keys 681 // Encryption keys
682 quint32 keys[3] = { 0, 0, 0 }; 682 quint32 keys[3] = { 0, 0, 0 };
683 683
684 if (encrypt) 684 if (encrypt)
685 { 685 {
686 // **** encryption header **** 686 // **** encryption header ****
687 687
688 // XOR with PI to ensure better random numbers 688 // XOR with PI to ensure better random numbers
689 // with poorly implemented rand() as suggested by Info-Zip 689 // with poorly implemented rand() as suggested by Info-Zip
690 srand(time(NULL) ^ 3141592654UL); 690 srand(time(NULL) ^ 3141592654UL);
691 int randByte; 691 int randByte;
692 692
693 initKeys(keys); 693 initKeys(keys);
694 for (int i=0; i<10; ++i) 694 for (int i=0; i<10; ++i)
695 { 695 {
696 randByte = (rand() >> 7) & 0xff; 696 randByte = (rand() >> 7) & 0xff;
697 buffer1[i] = decryptByte(keys[2]) ^ randByte; 697 buffer1[i] = decryptByte(keys[2]) ^ randByte;
698 updateKeys(keys, randByte); 698 updateKeys(keys, randByte);
699 } 699 }
700 700
701 // Encrypt encryption header 701 // Encrypt encryption header
702 initKeys(keys); 702 initKeys(keys);
703 for (int i=0; i<10; ++i) 703 for (int i=0; i<10; ++i)
704 { 704 {
705 randByte = decryptByte(keys[2]); 705 randByte = decryptByte(keys[2]);
706 updateKeys(keys, buffer1[i]); 706 updateKeys(keys, buffer1[i]);
707 buffer1[i] ^= randByte; 707 buffer1[i] ^= randByte;
708 } 708 }
709 709
710 // We don't know the CRC at this time, so we use the modification time 710 // We don't know the CRC at this time, so we use the modification time
711 // as the last two bytes 711 // as the last two bytes
712 randByte = decryptByte(keys[2]); 712 randByte = decryptByte(keys[2]);
713 updateKeys(keys, h->modTime[0]); 713 updateKeys(keys, h->modTime[0]);
714 buffer1[10] ^= randByte; 714 buffer1[10] ^= randByte;
715 715
716 randByte = decryptByte(keys[2]); 716 randByte = decryptByte(keys[2]);
717 updateKeys(keys, h->modTime[1]); 717 updateKeys(keys, h->modTime[1]);
718 buffer1[11] ^= randByte; 718 buffer1[11] ^= randByte;
719 719
720 // Write out encryption header 720 // Write out encryption header
721 if (device->write(buffer1, ZIP_LOCAL_ENC_HEADER_SIZE) != ZIP_LOCAL_ENC_HEADER_SIZE) 721 if (device->write(buffer1, ZIP_LOCAL_ENC_HEADER_SIZE) != ZIP_LOCAL_ENC_HEADER_SIZE)
722 { 722 {
723 delete h; 723 delete h;
724 return Zip::WriteFailed; 724 return Zip::WriteFailed;
725 } 725 }
726 } 726 }
727 727
728 qint64 written = 0; 728 qint64 written = 0;
729 quint32 crc = crc32(0L, Z_NULL, 0); 729 quint32 crc = crc32(0L, Z_NULL, 0);
730 730
731 if (!dirOnly) 731 if (!dirOnly)
732 { 732 {
733 QFile actualFile(file.absoluteFilePath()); 733 QFile actualFile(file.absoluteFilePath());
734 if (!actualFile.open(QIODevice::ReadOnly)) 734 if (!actualFile.open(QIODevice::ReadOnly))
735 { 735 {
736 qDebug() << QString("An error occurred while opening %1").arg(file.absoluteFilePath()); 736 qDebug() << QString("An error occurred while opening %1").arg(file.absoluteFilePath());
737 return Zip::OpenFailed; 737 return Zip::OpenFailed;
738 } 738 }
739 739
740 // Write file data 740 // Write file data
741 qint64 read = 0; 741 qint64 read = 0;
742 qint64 totRead = 0; 742 qint64 totRead = 0;
743 qint64 toRead = actualFile.size(); 743 qint64 toRead = actualFile.size();
744 744
745 if (level == Zip::Store) 745 if (level == Zip::Store)
746 { 746 {
747 while ( (read = actualFile.read(buffer1, ZIP_READ_BUFFER)) > 0 ) 747 while ( (read = actualFile.read(buffer1, ZIP_READ_BUFFER)) > 0 )
748 { 748 {
749 crc = crc32(crc, uBuffer, read); 749 crc = crc32(crc, uBuffer, read);
750 750
751 if (password != 0) 751 if (password != 0)
752 encryptBytes(keys, buffer1, read); 752 encryptBytes(keys, buffer1, read);
753 753
754 if ( (written = device->write(buffer1, read)) != read ) 754 if ( (written = device->write(buffer1, read)) != read )
755 { 755 {
756 actualFile.close(); 756 actualFile.close();
757 delete h; 757 delete h;
758 return Zip::WriteFailed; 758 return Zip::WriteFailed;
759 } 759 }
760 } 760 }
761 } 761 }
762 else 762 else
763 { 763 {
764 z_stream zstr; 764 z_stream zstr;
765 765
766 // Initialize zalloc, zfree and opaque before calling the init function 766 // Initialize zalloc, zfree and opaque before calling the init function
767 zstr.zalloc = Z_NULL; 767 zstr.zalloc = Z_NULL;
768 zstr.zfree = Z_NULL; 768 zstr.zfree = Z_NULL;
769 zstr.opaque = Z_NULL; 769 zstr.opaque = Z_NULL;
770 770
771 int zret; 771 int zret;
772 772
773 // Use deflateInit2 with negative windowBits to get raw compression 773 // Use deflateInit2 with negative windowBits to get raw compression
774 if ((zret = deflateInit2_( 774 if ((zret = deflateInit2_(
775 &zstr, 775 &zstr,
776 (int)level, 776 (int)level,
777 Z_DEFLATED, 777 Z_DEFLATED,
778 -MAX_WBITS, 778 -MAX_WBITS,
779 8, 779 8,
780 isPNGFile ? Z_RLE : Z_DEFAULT_STRATEGY, 780 isPNGFile ? Z_RLE : Z_DEFAULT_STRATEGY,
781 ZLIB_VERSION, 781 ZLIB_VERSION,
782 sizeof(z_stream) 782 sizeof(z_stream)
783 )) != Z_OK ) 783 )) != Z_OK )
784 { 784 {
785 actualFile.close(); 785 actualFile.close();
786 qDebug() << "Could not initialize zlib for compression"; 786 qDebug() << "Could not initialize zlib for compression";
787 delete h; 787 delete h;
788 return Zip::ZlibError; 788 return Zip::ZlibError;
789 } 789 }
790 790
791 qint64 compressed; 791 qint64 compressed;
792 792
793 int flush = Z_NO_FLUSH; 793 int flush = Z_NO_FLUSH;
794 794
795 do 795 do
796 { 796 {
797 read = actualFile.read(buffer1, ZIP_READ_BUFFER); 797 read = actualFile.read(buffer1, ZIP_READ_BUFFER);
798 totRead += read; 798 totRead += read;
799 799
800 if (read == 0) 800 if (read == 0)
801 break; 801 break;
802 if (read < 0) 802 if (read < 0)
803 { 803 {
804 actualFile.close(); 804 actualFile.close();
805 deflateEnd(&zstr); 805 deflateEnd(&zstr);
806 qDebug() << QString("Error while reading %1").arg(file.absoluteFilePath()); 806 qDebug() << QString("Error while reading %1").arg(file.absoluteFilePath());
807 delete h; 807 delete h;
808 return Zip::ReadFailed; 808 return Zip::ReadFailed;
809 } 809 }
810 810
811 crc = crc32(crc, uBuffer, read); 811 crc = crc32(crc, uBuffer, read);
812 812
813 zstr.next_in = (Bytef*) buffer1; 813 zstr.next_in = (Bytef*) buffer1;
814 zstr.avail_in = (uInt)read; 814 zstr.avail_in = (uInt)read;
815 815
816 // Tell zlib if this is the last chunk we want to encode 816 // Tell zlib if this is the last chunk we want to encode
817 // by setting the flush parameter to Z_FINISH 817 // by setting the flush parameter to Z_FINISH
818 flush = (totRead == toRead) ? Z_FINISH : Z_NO_FLUSH; 818 flush = (totRead == toRead) ? Z_FINISH : Z_NO_FLUSH;
819 819
820 // Run deflate() on input until output buffer not full 820 // Run deflate() on input until output buffer not full
821 // finish compression if all of source has been read in 821 // finish compression if all of source has been read in
822 do 822 do
823 { 823 {
824 zstr.next_out = (Bytef*) buffer2; 824 zstr.next_out = (Bytef*) buffer2;
825 zstr.avail_out = ZIP_READ_BUFFER; 825 zstr.avail_out = ZIP_READ_BUFFER;
826 826
827 zret = deflate(&zstr, flush); 827 zret = deflate(&zstr, flush);
828 // State not clobbered 828 // State not clobbered
829 Q_ASSERT(zret != Z_STREAM_ERROR); 829 Q_ASSERT(zret != Z_STREAM_ERROR);
830 830
831 // Write compressed data to file and empty buffer 831 // Write compressed data to file and empty buffer
832 compressed = ZIP_READ_BUFFER - zstr.avail_out; 832 compressed = ZIP_READ_BUFFER - zstr.avail_out;
833 833
834 if (password != 0) 834 if (password != 0)
835 encryptBytes(keys, buffer2, compressed); 835 encryptBytes(keys, buffer2, compressed);
836 836
837 if (device->write(buffer2, compressed) != compressed) 837 if (device->write(buffer2, compressed) != compressed)
838 { 838 {
839 deflateEnd(&zstr); 839 deflateEnd(&zstr);
840 actualFile.close(); 840 actualFile.close();
841 qDebug() << QString("Error while writing %1").arg(file.absoluteFilePath()); 841 qDebug() << QString("Error while writing %1").arg(file.absoluteFilePath());
842 delete h; 842 delete h;
843 return Zip::WriteFailed; 843 return Zip::WriteFailed;
844 } 844 }
845 845
846 written += compressed; 846 written += compressed;
847 847
848 } while (zstr.avail_out == 0); 848 } while (zstr.avail_out == 0);
849 849
850 // All input will be used 850 // All input will be used
851 Q_ASSERT(zstr.avail_in == 0); 851 Q_ASSERT(zstr.avail_in == 0);
852 852
853 } while (flush != Z_FINISH); 853 } while (flush != Z_FINISH);
854 854
855 // Stream will be complete 855 // Stream will be complete
856 Q_ASSERT(zret == Z_STREAM_END); 856 Q_ASSERT(zret == Z_STREAM_END);
857 857
858 deflateEnd(&zstr); 858 deflateEnd(&zstr);
859 859
860 } // if (level != STORE) 860 } // if (level != STORE)
861 861
862 actualFile.close(); 862 actualFile.close();
863 } 863 }
864 864
865 // Store end of entry offset 865 // Store end of entry offset
866 quint32 current = device->pos(); 866 quint32 current = device->pos();
867 867
868 // Update crc and compressed size in local header 868 // Update crc and compressed size in local header
869 if (!device->seek(crcOffset)) 869 if (!device->seek(crcOffset))
870 { 870 {
871 delete h; 871 delete h;
872 return Zip::SeekFailed; 872 return Zip::SeekFailed;
873 } 873 }
874 874
875 h->crc = dirOnly ? 0 : crc; 875 h->crc = dirOnly ? 0 : crc;
876 h->szComp += written; 876 h->szComp += written;
877 877
878 setULong(h->crc, buffer1, 0); 878 setULong(h->crc, buffer1, 0);
879 setULong(h->szComp, buffer1, 4); 879 setULong(h->szComp, buffer1, 4);
880 if ( device->write(buffer1, 8) != 8) 880 if ( device->write(buffer1, 8) != 8)
881 { 881 {
882 delete h; 882 delete h;
883 return Zip::WriteFailed; 883 return Zip::WriteFailed;
884 } 884 }
885 885
886 // Seek to end of entry 886 // Seek to end of entry
887 if (!device->seek(current)) 887 if (!device->seek(current))
888 { 888 {
889 delete h; 889 delete h;
890 return Zip::SeekFailed; 890 return Zip::SeekFailed;
891 } 891 }
892 892
893 if ((h->gpFlag[0] & 8) == 8) 893 if ((h->gpFlag[0] & 8) == 8)
894 { 894 {
895 // Write data descriptor 895 // Write data descriptor
896 896
897 // Signature: PK\7\8 897 // Signature: PK\7\8
898 buffer1[0] = 'P'; 898 buffer1[0] = 'P';
899 buffer1[1] = 'K'; 899 buffer1[1] = 'K';
900 buffer1[2] = 0x07; 900 buffer1[2] = 0x07;
901 buffer1[3] = 0x08; 901 buffer1[3] = 0x08;
902 902
903 // CRC 903 // CRC
904 setULong(h->crc, buffer1, ZIP_DD_OFF_CRC32); 904 setULong(h->crc, buffer1, ZIP_DD_OFF_CRC32);
905 905
906 // Compressed size 906 // Compressed size
907 setULong(h->szComp, buffer1, ZIP_DD_OFF_CSIZE); 907 setULong(h->szComp, buffer1, ZIP_DD_OFF_CSIZE);
908 908
909 // Uncompressed size 909 // Uncompressed size
910 setULong(h->szUncomp, buffer1, ZIP_DD_OFF_USIZE); 910 setULong(h->szUncomp, buffer1, ZIP_DD_OFF_USIZE);
911 911
912 if (device->write(buffer1, ZIP_DD_SIZE_WS) != ZIP_DD_SIZE_WS) 912 if (device->write(buffer1, ZIP_DD_SIZE_WS) != ZIP_DD_SIZE_WS)
913 { 913 {
914 delete h; 914 delete h;
915 return Zip::WriteFailed; 915 return Zip::WriteFailed;
916 } 916 }
917 } 917 }
918 918
919 headers->insert(entryName, h); 919 headers->insert(entryName, h);
920 return Zip::Ok; 920 return Zip::Ok;
921} 921}
922 922
923//! \internal 923//! \internal
924int ZipPrivate::decryptByte(quint32 key2) const 924int ZipPrivate::decryptByte(quint32 key2) const
925{ 925{
926 quint16 temp = ((quint16)(key2) & 0xffff) | 2; 926 quint16 temp = ((quint16)(key2) & 0xffff) | 2;
927 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); 927 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
928} 928}
929 929
930//! \internal Writes an quint32 (4 bytes) to a byte array at given offset. 930//! \internal Writes an quint32 (4 bytes) to a byte array at given offset.
931void ZipPrivate::setULong(quint32 v, char* buffer, unsigned int offset) 931void ZipPrivate::setULong(quint32 v, char* buffer, unsigned int offset)
932{ 932{
933 buffer[offset+3] = ((v >> 24) & 0xFF); 933 buffer[offset+3] = ((v >> 24) & 0xFF);
934 buffer[offset+2] = ((v >> 16) & 0xFF); 934 buffer[offset+2] = ((v >> 16) & 0xFF);
935 buffer[offset+1] = ((v >> 8) & 0xFF); 935 buffer[offset+1] = ((v >> 8) & 0xFF);
936 buffer[offset] = (v & 0xFF); 936 buffer[offset] = (v & 0xFF);
937} 937}
938 938
939//! \internal Initializes decryption keys using a password. 939//! \internal Initializes decryption keys using a password.
940void ZipPrivate::initKeys(quint32* keys) const 940void ZipPrivate::initKeys(quint32* keys) const
941{ 941{
942 // Encryption keys initialization constants are taken from the 942 // Encryption keys initialization constants are taken from the
943 // PKZip file format specification docs 943 // PKZip file format specification docs
944 keys[0] = 305419896L; 944 keys[0] = 305419896L;
945 keys[1] = 591751049L; 945 keys[1] = 591751049L;
946 keys[2] = 878082192L; 946 keys[2] = 878082192L;
947 947
948 QByteArray pwdBytes = password.toAscii(); 948 QByteArray pwdBytes = password.toAscii();
949 int sz = pwdBytes.size(); 949 int sz = pwdBytes.size();
950 const char* ascii = pwdBytes.data(); 950 const char* ascii = pwdBytes.data();
951 951
952 for (int i=0; i<sz; ++i) 952 for (int i=0; i<sz; ++i)
953 updateKeys(keys, (int)ascii[i]); 953 updateKeys(keys, (int)ascii[i]);
954} 954}
955 955
956//! \internal Updates encryption keys. 956//! \internal Updates encryption keys.
957void ZipPrivate::updateKeys(quint32* keys, int c) const 957void ZipPrivate::updateKeys(quint32* keys, int c) const
958{ 958{
959 keys[0] = CRC32(keys[0], c); 959 keys[0] = CRC32(keys[0], c);
960 keys[1] += keys[0] & 0xff; 960 keys[1] += keys[0] & 0xff;
961 keys[1] = keys[1] * 134775813L + 1; 961 keys[1] = keys[1] * 134775813L + 1;
962 keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24); 962 keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24);
963} 963}
964 964
965//! \internal Encrypts a byte array. 965//! \internal Encrypts a byte array.
966void ZipPrivate::encryptBytes(quint32* keys, char* buffer, qint64 read) 966void ZipPrivate::encryptBytes(quint32* keys, char* buffer, qint64 read)
967{ 967{
968 char t; 968 char t;
969 969
970 for (int i=0; i<(int)read; ++i) 970 for (int i=0; i<(int)read; ++i)
971 { 971 {
972 t = buffer[i]; 972 t = buffer[i];
973 buffer[i] ^= decryptByte(keys[2]); 973 buffer[i] ^= decryptByte(keys[2]);
974 updateKeys(keys, t); 974 updateKeys(keys, t);
975 } 975 }
976} 976}
977 977
978//! \internal Detects the best compression level for a given file extension. 978//! \internal Detects the best compression level for a given file extension.
979Zip::CompressionLevel ZipPrivate::detectCompressionByMime(const QString& ext) 979Zip::CompressionLevel ZipPrivate::detectCompressionByMime(const QString& ext)
980{ 980{
981 // files really hard to compress 981 // files really hard to compress
982 if ((ext == "png") || 982 if ((ext == "png") ||
983 (ext == "jpg") || 983 (ext == "jpg") ||
984 (ext == "jpeg") || 984 (ext == "jpeg") ||
985 (ext == "mp3") || 985 (ext == "mp3") ||
986 (ext == "ogg") || 986 (ext == "ogg") ||
987 (ext == "ogm") || 987 (ext == "ogm") ||
988 (ext == "avi") || 988 (ext == "avi") ||
989 (ext == "mov") || 989 (ext == "mov") ||
990 (ext == "rm") || 990 (ext == "rm") ||
991 (ext == "ra") || 991 (ext == "ra") ||
992 (ext == "zip") || 992 (ext == "zip") ||
993 (ext == "rar") || 993 (ext == "rar") ||
994 (ext == "bz2") || 994 (ext == "bz2") ||
995 (ext == "gz") || 995 (ext == "gz") ||
996 (ext == "7z") || 996 (ext == "7z") ||
997 (ext == "z") || 997 (ext == "z") ||
998 (ext == "jar") 998 (ext == "jar")
999 ) return Zip::Store; 999 ) return Zip::Store;
1000 1000
1001 // files slow and hard to compress 1001 // files slow and hard to compress
1002 if ((ext == "exe") || 1002 if ((ext == "exe") ||
1003 (ext == "bin") || 1003 (ext == "bin") ||
1004 (ext == "rpm") || 1004 (ext == "rpm") ||
1005 (ext == "deb") 1005 (ext == "deb")
1006 ) return Zip::Deflate2; 1006 ) return Zip::Deflate2;
1007 1007
1008 return Zip::Deflate9; 1008 return Zip::Deflate9;
1009} 1009}
1010 1010
1011/*! 1011/*!
1012 Closes the current archive and writes out pending data. 1012 Closes the current archive and writes out pending data.
1013*/ 1013*/
1014Zip::ErrorCode ZipPrivate::closeArchive() 1014Zip::ErrorCode ZipPrivate::closeArchive()
1015{ 1015{
1016 // Close current archive by writing out central directory 1016 // Close current archive by writing out central directory
1017 // and free up resources 1017 // and free up resources
1018 1018
1019 if (device == 0) 1019 if (device == 0)
1020 return Zip::Ok; 1020 return Zip::Ok;
1021 1021
1022 if (headers == 0) 1022 if (headers == 0)
1023 return Zip::Ok; 1023 return Zip::Ok;
1024 1024
1025 const ZipEntryP* h; 1025 const ZipEntryP* h;
1026 1026
1027 unsigned int sz; 1027 unsigned int sz;
1028 quint32 szCentralDir = 0; 1028 quint32 szCentralDir = 0;
1029 quint32 offCentralDir = device->pos(); 1029 quint32 offCentralDir = device->pos();
1030 1030
1031 for (QMap<QString,ZipEntryP*>::ConstIterator itr = headers->constBegin(); itr != headers->constEnd(); ++itr) 1031 for (QMap<QString,ZipEntryP*>::ConstIterator itr = headers->constBegin(); itr != headers->constEnd(); ++itr)
1032 { 1032 {
1033 h = itr.value(); 1033 h = itr.value();
1034 1034
1035 // signature 1035 // signature
1036 buffer1[0] = 'P'; 1036 buffer1[0] = 'P';
1037 buffer1[1] = 'K'; 1037 buffer1[1] = 'K';
1038 buffer1[2] = 0x01; 1038 buffer1[2] = 0x01;
1039 buffer1[3] = 0x02; 1039 buffer1[3] = 0x02;
1040 1040
1041 // version made by (currently only MS-DOS/FAT - no symlinks or other stuff supported) 1041 // version made by (currently only MS-DOS/FAT - no symlinks or other stuff supported)
1042 buffer1[ZIP_CD_OFF_MADEBY] = buffer1[ZIP_CD_OFF_MADEBY + 1] = 0; 1042 buffer1[ZIP_CD_OFF_MADEBY] = buffer1[ZIP_CD_OFF_MADEBY + 1] = 0;
1043 1043
1044 // version needed to extract 1044 // version needed to extract
1045 buffer1[ZIP_CD_OFF_VERSION] = ZIP_VERSION; 1045 buffer1[ZIP_CD_OFF_VERSION] = ZIP_VERSION;
1046 buffer1[ZIP_CD_OFF_VERSION + 1] = 0; 1046 buffer1[ZIP_CD_OFF_VERSION + 1] = 0;
1047 1047
1048 // general purpose flag 1048 // general purpose flag
1049 buffer1[ZIP_CD_OFF_GPFLAG] = h->gpFlag[0]; 1049 buffer1[ZIP_CD_OFF_GPFLAG] = h->gpFlag[0];
1050 buffer1[ZIP_CD_OFF_GPFLAG + 1] = h->gpFlag[1]; 1050 buffer1[ZIP_CD_OFF_GPFLAG + 1] = h->gpFlag[1];
1051 1051
1052 // compression method 1052 // compression method
1053 buffer1[ZIP_CD_OFF_CMET] = h->compMethod & 0xFF; 1053 buffer1[ZIP_CD_OFF_CMET] = h->compMethod & 0xFF;
1054 buffer1[ZIP_CD_OFF_CMET + 1] = (h->compMethod >> 8) & 0xFF; 1054 buffer1[ZIP_CD_OFF_CMET + 1] = (h->compMethod >> 8) & 0xFF;
1055 1055
1056 // last mod file time 1056 // last mod file time
1057 buffer1[ZIP_CD_OFF_MODT] = h->modTime[0]; 1057 buffer1[ZIP_CD_OFF_MODT] = h->modTime[0];
1058 buffer1[ZIP_CD_OFF_MODT + 1] = h->modTime[1]; 1058 buffer1[ZIP_CD_OFF_MODT + 1] = h->modTime[1];
1059 1059
1060 // last mod file date 1060 // last mod file date
1061 buffer1[ZIP_CD_OFF_MODD] = h->modDate[0]; 1061 buffer1[ZIP_CD_OFF_MODD] = h->modDate[0];
1062 buffer1[ZIP_CD_OFF_MODD + 1] = h->modDate[1]; 1062 buffer1[ZIP_CD_OFF_MODD + 1] = h->modDate[1];
1063 1063
1064 // crc (4bytes) [16,17,18,19] 1064 // crc (4bytes) [16,17,18,19]
1065 setULong(h->crc, buffer1, ZIP_CD_OFF_CRC); 1065 setULong(h->crc, buffer1, ZIP_CD_OFF_CRC);
1066 1066
1067 // compressed size (4bytes: [20,21,22,23]) 1067 // compressed size (4bytes: [20,21,22,23])
1068 setULong(h->szComp, buffer1, ZIP_CD_OFF_CSIZE); 1068 setULong(h->szComp, buffer1, ZIP_CD_OFF_CSIZE);
1069 1069
1070 // uncompressed size [24,25,26,27] 1070 // uncompressed size [24,25,26,27]
1071 setULong(h->szUncomp, buffer1, ZIP_CD_OFF_USIZE); 1071 setULong(h->szUncomp, buffer1, ZIP_CD_OFF_USIZE);
1072 1072
1073 // filename 1073 // filename
1074 QByteArray fileNameBytes = itr.key().toAscii(); 1074 QByteArray fileNameBytes = itr.key().toAscii();
1075 sz = fileNameBytes.size(); 1075 sz = fileNameBytes.size();
1076 buffer1[ZIP_CD_OFF_NAMELEN] = sz & 0xFF; 1076 buffer1[ZIP_CD_OFF_NAMELEN] = sz & 0xFF;
1077 buffer1[ZIP_CD_OFF_NAMELEN + 1] = (sz >> 8) & 0xFF; 1077 buffer1[ZIP_CD_OFF_NAMELEN + 1] = (sz >> 8) & 0xFF;
1078 1078
1079 // extra field length 1079 // extra field length
1080 buffer1[ZIP_CD_OFF_XLEN] = buffer1[ZIP_CD_OFF_XLEN + 1] = 0; 1080 buffer1[ZIP_CD_OFF_XLEN] = buffer1[ZIP_CD_OFF_XLEN + 1] = 0;
1081 1081
1082 // file comment length 1082 // file comment length
1083 buffer1[ZIP_CD_OFF_COMMLEN] = buffer1[ZIP_CD_OFF_COMMLEN + 1] = 0; 1083 buffer1[ZIP_CD_OFF_COMMLEN] = buffer1[ZIP_CD_OFF_COMMLEN + 1] = 0;
1084 1084
1085 // disk number start 1085 // disk number start
1086 buffer1[ZIP_CD_OFF_DISKSTART] = buffer1[ZIP_CD_OFF_DISKSTART + 1] = 0; 1086 buffer1[ZIP_CD_OFF_DISKSTART] = buffer1[ZIP_CD_OFF_DISKSTART + 1] = 0;
1087 1087
1088 // internal file attributes 1088 // internal file attributes
1089 buffer1[ZIP_CD_OFF_IATTR] = buffer1[ZIP_CD_OFF_IATTR + 1] = 0; 1089 buffer1[ZIP_CD_OFF_IATTR] = buffer1[ZIP_CD_OFF_IATTR + 1] = 0;
1090 1090
1091 // external file attributes 1091 // external file attributes
1092 buffer1[ZIP_CD_OFF_EATTR] = 1092 buffer1[ZIP_CD_OFF_EATTR] =
1093 buffer1[ZIP_CD_OFF_EATTR + 1] = 1093 buffer1[ZIP_CD_OFF_EATTR + 1] =
1094 buffer1[ZIP_CD_OFF_EATTR + 2] = 1094 buffer1[ZIP_CD_OFF_EATTR + 2] =
1095 buffer1[ZIP_CD_OFF_EATTR + 3] = 0; 1095 buffer1[ZIP_CD_OFF_EATTR + 3] = 0;
1096 1096
1097 // relative offset of local header [42->45] 1097 // relative offset of local header [42->45]
1098 setULong(h->lhOffset, buffer1, ZIP_CD_OFF_LHOFF); 1098 setULong(h->lhOffset, buffer1, ZIP_CD_OFF_LHOFF);
1099 1099
1100 if (device->write(buffer1, ZIP_CD_SIZE) != ZIP_CD_SIZE) 1100 if (device->write(buffer1, ZIP_CD_SIZE) != ZIP_CD_SIZE)
1101 { 1101 {
1102 //! \todo See if we can detect QFile objects using the Qt Meta Object System 1102 //! \todo See if we can detect QFile objects using the Qt Meta Object System
1103 /* 1103 /*
1104 if (!device->remove()) 1104 if (!device->remove())
1105 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName()); 1105 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName());
1106 */ 1106 */
1107 return Zip::WriteFailed; 1107 return Zip::WriteFailed;
1108 } 1108 }
1109 1109
1110 // Write out filename 1110 // Write out filename
1111 if ((unsigned int)device->write(fileNameBytes) != sz) 1111 if ((unsigned int)device->write(fileNameBytes) != sz)
1112 { 1112 {
1113 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System 1113 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System
1114 /* 1114 /*
1115 if (!device->remove()) 1115 if (!device->remove())
1116 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName()); 1116 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName());
1117 */ 1117 */
1118 return Zip::WriteFailed; 1118 return Zip::WriteFailed;
1119 } 1119 }
1120 1120
1121 szCentralDir += (ZIP_CD_SIZE + sz); 1121 szCentralDir += (ZIP_CD_SIZE + sz);
1122 1122
1123 } // central dir headers loop 1123 } // central dir headers loop
1124 1124
1125 1125
1126 // Write end of central directory 1126 // Write end of central directory
1127 1127
1128 // signature 1128 // signature
1129 buffer1[0] = 'P'; 1129 buffer1[0] = 'P';
1130 buffer1[1] = 'K'; 1130 buffer1[1] = 'K';
1131 buffer1[2] = 0x05; 1131 buffer1[2] = 0x05;
1132 buffer1[3] = 0x06; 1132 buffer1[3] = 0x06;
1133 1133
1134 // number of this disk 1134 // number of this disk
1135 buffer1[ZIP_EOCD_OFF_DISKNUM] = buffer1[ZIP_EOCD_OFF_DISKNUM + 1] = 0; 1135 buffer1[ZIP_EOCD_OFF_DISKNUM] = buffer1[ZIP_EOCD_OFF_DISKNUM + 1] = 0;
1136 1136
1137 // number of disk with central directory 1137 // number of disk with central directory
1138 buffer1[ZIP_EOCD_OFF_CDDISKNUM] = buffer1[ZIP_EOCD_OFF_CDDISKNUM + 1] = 0; 1138 buffer1[ZIP_EOCD_OFF_CDDISKNUM] = buffer1[ZIP_EOCD_OFF_CDDISKNUM + 1] = 0;
1139 1139
1140 // number of entries in this disk 1140 // number of entries in this disk
1141 sz = headers->count(); 1141 sz = headers->count();
1142 buffer1[ZIP_EOCD_OFF_ENTRIES] = sz & 0xFF; 1142 buffer1[ZIP_EOCD_OFF_ENTRIES] = sz & 0xFF;
1143 buffer1[ZIP_EOCD_OFF_ENTRIES + 1] = (sz >> 8) & 0xFF; 1143 buffer1[ZIP_EOCD_OFF_ENTRIES + 1] = (sz >> 8) & 0xFF;
1144 1144
1145 // total number of entries 1145 // total number of entries
1146 buffer1[ZIP_EOCD_OFF_CDENTRIES] = buffer1[ZIP_EOCD_OFF_ENTRIES]; 1146 buffer1[ZIP_EOCD_OFF_CDENTRIES] = buffer1[ZIP_EOCD_OFF_ENTRIES];
1147 buffer1[ZIP_EOCD_OFF_CDENTRIES + 1] = buffer1[ZIP_EOCD_OFF_ENTRIES + 1]; 1147 buffer1[ZIP_EOCD_OFF_CDENTRIES + 1] = buffer1[ZIP_EOCD_OFF_ENTRIES + 1];
1148 1148
1149 // size of central directory [12->15] 1149 // size of central directory [12->15]
1150 setULong(szCentralDir, buffer1, ZIP_EOCD_OFF_CDSIZE); 1150 setULong(szCentralDir, buffer1, ZIP_EOCD_OFF_CDSIZE);
1151 1151
1152 // central dir offset [16->19] 1152 // central dir offset [16->19]
1153 setULong(offCentralDir, buffer1, ZIP_EOCD_OFF_CDOFF); 1153 setULong(offCentralDir, buffer1, ZIP_EOCD_OFF_CDOFF);
1154 1154
1155 // ZIP file comment length 1155 // ZIP file comment length
1156 QByteArray commentBytes = comment.toAscii(); 1156 QByteArray commentBytes = comment.toAscii();
1157 quint16 commentLength = commentBytes.size(); 1157 quint16 commentLength = commentBytes.size();
1158 1158
1159 if (commentLength == 0) 1159 if (commentLength == 0)
1160 { 1160 {
1161 buffer1[ZIP_EOCD_OFF_COMMLEN] = buffer1[ZIP_EOCD_OFF_COMMLEN + 1] = 0; 1161 buffer1[ZIP_EOCD_OFF_COMMLEN] = buffer1[ZIP_EOCD_OFF_COMMLEN + 1] = 0;
1162 } 1162 }
1163 else 1163 else
1164 { 1164 {
1165 buffer1[ZIP_EOCD_OFF_COMMLEN] = commentLength & 0xFF; 1165 buffer1[ZIP_EOCD_OFF_COMMLEN] = commentLength & 0xFF;
1166 buffer1[ZIP_EOCD_OFF_COMMLEN + 1] = (commentLength >> 8) & 0xFF; 1166 buffer1[ZIP_EOCD_OFF_COMMLEN + 1] = (commentLength >> 8) & 0xFF;
1167 } 1167 }
1168 1168
1169 if (device->write(buffer1, ZIP_EOCD_SIZE) != ZIP_EOCD_SIZE) 1169 if (device->write(buffer1, ZIP_EOCD_SIZE) != ZIP_EOCD_SIZE)
1170 { 1170 {
1171 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System 1171 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System
1172 /* 1172 /*
1173 if (!device->remove()) 1173 if (!device->remove())
1174 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName()); 1174 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName());
1175 */ 1175 */
1176 return Zip::WriteFailed; 1176 return Zip::WriteFailed;
1177 } 1177 }
1178 1178
1179 if (commentLength != 0) 1179 if (commentLength != 0)
1180 { 1180 {
1181 if ((unsigned int)device->write(commentBytes) != commentLength) 1181 if ((unsigned int)device->write(commentBytes) != commentLength)
1182 { 1182 {
1183 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System 1183 //! \todo SAME AS ABOVE: See if we can detect QFile objects using the Qt Meta Object System
1184 /* 1184 /*
1185 if (!device->remove()) 1185 if (!device->remove())
1186 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName()); 1186 qDebug() << tr("Unable to delete corrupted archive: %1").arg(device->fileName());
1187 */ 1187 */
1188 return Zip::WriteFailed; 1188 return Zip::WriteFailed;
1189 } 1189 }
1190 } 1190 }
1191 1191
1192 return Zip::Ok; 1192 return Zip::Ok;
1193} 1193}
1194 1194
1195//! \internal 1195//! \internal
1196void ZipPrivate::reset() 1196void ZipPrivate::reset()
1197{ 1197{
1198 comment.clear(); 1198 comment.clear();
1199 1199
1200 if (headers != 0) 1200 if (headers != 0)
1201 { 1201 {
1202 qDeleteAll(*headers); 1202 qDeleteAll(*headers);
1203 delete headers; 1203 delete headers;
1204 headers = 0; 1204 headers = 0;
1205 } 1205 }
1206 1206
1207 delete device; device = 0; 1207 delete device; device = 0;
1208} 1208}
1209 1209
1210//! \internal Returns the path of the parent directory 1210//! \internal Returns the path of the parent directory
1211QString ZipPrivate::extractRoot(const QString& p) 1211QString ZipPrivate::extractRoot(const QString& p)
1212{ 1212{
1213 QDir d(QDir::cleanPath(p)); 1213 QDir d(QDir::cleanPath(p));
1214 if (!d.exists()) 1214 if (!d.exists())
1215 return QString(); 1215 return QString();
1216 1216
1217 if (!d.cdUp()) 1217 if (!d.cdUp())
1218 return QString(); 1218 return QString();
1219 1219
1220 return d.absolutePath(); 1220 return d.absolutePath();
1221} 1221}
diff --git a/rbutil/rbutilqt/zip/zip.h b/rbutil/rbutilqt/zip/zip.h
index 44fdd08b5f..8f82f1738a 100644
--- a/rbutil/rbutilqt/zip/zip.h
+++ b/rbutil/rbutilqt/zip/zip.h
@@ -1,115 +1,115 @@
1/**************************************************************************** 1/****************************************************************************
2** Filename: zip.h 2** Filename: zip.h
3** Last updated [dd/mm/yyyy]: 01/02/2007 3** Last updated [dd/mm/yyyy]: 01/02/2007
4** 4**
5** pkzip 2.0 file compression. 5** pkzip 2.0 file compression.
6** 6**
7** Some of the code has been inspired by other open source projects, 7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip). 8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library. 9** Compression and decompression actually uses the zlib library.
10** 10**
11** Copyright (C) 2007 Angius Fabrizio. All rights reserved. 11** Copyright (C) 2007 Angius Fabrizio. All rights reserved.
12** 12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/). 13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14** 14**
15** This file may be distributed and/or modified under the terms of the 15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software 16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the 17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file. 18** packaging of this file.
19** 19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22** 22**
23** See the file LICENSE.GPL that came with this software distribution or 23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information. 24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25** 25**
26**********************************************************************/ 26**********************************************************************/
27 27
28#ifndef OSDAB_ZIP__H 28#ifndef OSDAB_ZIP__H
29#define OSDAB_ZIP__H 29#define OSDAB_ZIP__H
30 30
31#include <QtGlobal> 31#include <QtGlobal>
32#include <QMap> 32#include <QMap>
33 33
34#include <zlib/zlib.h> 34#include <zlib/zlib.h>
35 35
36class ZipPrivate; 36class ZipPrivate;
37 37
38class QIODevice; 38class QIODevice;
39class QFile; 39class QFile;
40class QDir; 40class QDir;
41class QStringList; 41class QStringList;
42class QString; 42class QString;
43 43
44 44
45class Zip 45class Zip
46{ 46{
47public: 47public:
48 enum ErrorCode 48 enum ErrorCode
49 { 49 {
50 Ok, 50 Ok,
51 ZlibInit, 51 ZlibInit,
52 ZlibError, 52 ZlibError,
53 FileExists, 53 FileExists,
54 OpenFailed, 54 OpenFailed,
55 NoOpenArchive, 55 NoOpenArchive,
56 FileNotFound, 56 FileNotFound,
57 ReadFailed, 57 ReadFailed,
58 WriteFailed, 58 WriteFailed,
59 SeekFailed 59 SeekFailed
60 }; 60 };
61 61
62 enum CompressionLevel 62 enum CompressionLevel
63 { 63 {
64 Store, 64 Store,
65 Deflate1 = 1, Deflate2, Deflate3, Deflate4, 65 Deflate1 = 1, Deflate2, Deflate3, Deflate4,
66 Deflate5, Deflate6, Deflate7, Deflate8, Deflate9, 66 Deflate5, Deflate6, Deflate7, Deflate8, Deflate9,
67 AutoCPU, AutoMIME, AutoFull 67 AutoCPU, AutoMIME, AutoFull
68 }; 68 };
69 69
70 enum CompressionOption 70 enum CompressionOption
71 { 71 {
72 //! Does not preserve absolute paths in the zip file when adding a file/directory (default) 72 //! Does not preserve absolute paths in the zip file when adding a file/directory (default)
73 RelativePaths = 0x0001, 73 RelativePaths = 0x0001,
74 //! Preserve absolute paths 74 //! Preserve absolute paths
75 AbsolutePaths = 0x0002, 75 AbsolutePaths = 0x0002,
76 //! Do not store paths. All the files are put in the (evtl. user defined) root of the zip file 76 //! Do not store paths. All the files are put in the (evtl. user defined) root of the zip file
77 IgnorePaths = 0x0004 77 IgnorePaths = 0x0004
78 }; 78 };
79 Q_DECLARE_FLAGS(CompressionOptions, CompressionOption) 79 Q_DECLARE_FLAGS(CompressionOptions, CompressionOption)
80 80
81 Zip(); 81 Zip();
82 virtual ~Zip(); 82 virtual ~Zip();
83 83
84 bool isOpen() const; 84 bool isOpen() const;
85 85
86 void setPassword(const QString& pwd); 86 void setPassword(const QString& pwd);
87 void clearPassword(); 87 void clearPassword();
88 QString password() const; 88 QString password() const;
89 89
90 ErrorCode createArchive(const QString& file, bool overwrite = true); 90 ErrorCode createArchive(const QString& file, bool overwrite = true);
91 ErrorCode createArchive(QIODevice* device); 91 ErrorCode createArchive(QIODevice* device);
92 92
93 QString archiveComment() const; 93 QString archiveComment() const;
94 void setArchiveComment(const QString& comment); 94 void setArchiveComment(const QString& comment);
95 95
96 ErrorCode addDirectoryContents(const QString& path, CompressionLevel level = AutoFull); 96 ErrorCode addDirectoryContents(const QString& path, CompressionLevel level = AutoFull);
97 ErrorCode addDirectoryContents(const QString& path, const QString& root, CompressionLevel level = AutoFull); 97 ErrorCode addDirectoryContents(const QString& path, const QString& root, CompressionLevel level = AutoFull);
98 98
99 ErrorCode addDirectory(const QString& path, CompressionOptions options = RelativePaths, CompressionLevel level = AutoFull); 99 ErrorCode addDirectory(const QString& path, CompressionOptions options = RelativePaths, CompressionLevel level = AutoFull);
100 ErrorCode addDirectory(const QString& path, const QString& root, CompressionLevel level = AutoFull); 100 ErrorCode addDirectory(const QString& path, const QString& root, CompressionLevel level = AutoFull);
101 ErrorCode addDirectory(const QString& path, const QString& root, CompressionOptions options = RelativePaths, CompressionLevel level = AutoFull); 101 ErrorCode addDirectory(const QString& path, const QString& root, CompressionOptions options = RelativePaths, CompressionLevel level = AutoFull);
102 102
103 ErrorCode closeArchive(); 103 ErrorCode closeArchive();
104 104
105 QString formatError(ErrorCode c) const; 105 QString formatError(ErrorCode c) const;
106 106
107 virtual void progress() {} 107 virtual void progress() {}
108 108
109private: 109private:
110 ZipPrivate* d; 110 ZipPrivate* d;
111}; 111};
112 112
113Q_DECLARE_OPERATORS_FOR_FLAGS(Zip::CompressionOptions) 113Q_DECLARE_OPERATORS_FOR_FLAGS(Zip::CompressionOptions)
114 114
115#endif // OSDAB_ZIP__H 115#endif // OSDAB_ZIP__H
diff --git a/rbutil/rbutilqt/zip/zip_p.h b/rbutil/rbutilqt/zip/zip_p.h
index b3c45ac7b8..8c57f99225 100644
--- a/rbutil/rbutilqt/zip/zip_p.h
+++ b/rbutil/rbutilqt/zip/zip_p.h
@@ -1,93 +1,93 @@
1/**************************************************************************** 1/****************************************************************************
2** Filename: zip_p.h 2** Filename: zip_p.h
3** Last updated [dd/mm/yyyy]: 28/01/2007 3** Last updated [dd/mm/yyyy]: 28/01/2007
4** 4**
5** pkzip 2.0 file compression. 5** pkzip 2.0 file compression.
6** 6**
7** Some of the code has been inspired by other open source projects, 7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip). 8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library. 9** Compression and decompression actually uses the zlib library.
10** 10**
11** Copyright (C) 2007 Angius Fabrizio. All rights reserved. 11** Copyright (C) 2007 Angius Fabrizio. All rights reserved.
12** 12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/). 13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14** 14**
15** This file may be distributed and/or modified under the terms of the 15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software 16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the 17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file. 18** packaging of this file.
19** 19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22** 22**
23** See the file LICENSE.GPL that came with this software distribution or 23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information. 24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25** 25**
26**********************************************************************/ 26**********************************************************************/
27 27
28// 28//
29// W A R N I N G 29// W A R N I N G
30// ------------- 30// -------------
31// 31//
32// This file is not part of the Zip/UnZip API. It exists purely as an 32// This file is not part of the Zip/UnZip API. It exists purely as an
33// implementation detail. This header file may change from version to 33// implementation detail. This header file may change from version to
34// version without notice, or even be removed. 34// version without notice, or even be removed.
35// 35//
36// We mean it. 36// We mean it.
37// 37//
38 38
39#ifndef OSDAB_ZIP_P__H 39#ifndef OSDAB_ZIP_P__H
40#define OSDAB_ZIP_P__H 40#define OSDAB_ZIP_P__H
41 41
42#include "zip.h" 42#include "zip.h"
43#include "zipentry_p.h" 43#include "zipentry_p.h"
44 44
45#include <QtGlobal> 45#include <QtGlobal>
46#include <QFileInfo> 46#include <QFileInfo>
47 47
48/*! 48/*!
49 zLib authors suggest using larger buffers (128K or 256K) for (de)compression (especially for inflate()) 49 zLib authors suggest using larger buffers (128K or 256K) for (de)compression (especially for inflate())
50 we use a 256K buffer here - if you want to use this code on a pre-iceage mainframe please change it ;) 50 we use a 256K buffer here - if you want to use this code on a pre-iceage mainframe please change it ;)
51*/ 51*/
52#define ZIP_READ_BUFFER (256*1024) 52#define ZIP_READ_BUFFER (256*1024)
53 53
54class ZipPrivate 54class ZipPrivate
55{ 55{
56public: 56public:
57 ZipPrivate(); 57 ZipPrivate();
58 virtual ~ZipPrivate(); 58 virtual ~ZipPrivate();
59 59
60 QMap<QString,ZipEntryP*>* headers; 60 QMap<QString,ZipEntryP*>* headers;
61 61
62 QIODevice* device; 62 QIODevice* device;
63 63
64 char buffer1[ZIP_READ_BUFFER]; 64 char buffer1[ZIP_READ_BUFFER];
65 char buffer2[ZIP_READ_BUFFER]; 65 char buffer2[ZIP_READ_BUFFER];
66 66
67 unsigned char* uBuffer; 67 unsigned char* uBuffer;
68 68
69 const quint32* crcTable; 69 const quint32* crcTable;
70 70
71 QString comment; 71 QString comment;
72 QString password; 72 QString password;
73 73
74 Zip::ErrorCode createArchive(QIODevice* device); 74 Zip::ErrorCode createArchive(QIODevice* device);
75 Zip::ErrorCode closeArchive(); 75 Zip::ErrorCode closeArchive();
76 void reset(); 76 void reset();
77 77
78 bool zLibInit(); 78 bool zLibInit();
79 79
80 Zip::ErrorCode createEntry(const QFileInfo& file, const QString& root, Zip::CompressionLevel level); 80 Zip::ErrorCode createEntry(const QFileInfo& file, const QString& root, Zip::CompressionLevel level);
81 Zip::CompressionLevel detectCompressionByMime(const QString& ext); 81 Zip::CompressionLevel detectCompressionByMime(const QString& ext);
82 82
83 inline void encryptBytes(quint32* keys, char* buffer, qint64 read); 83 inline void encryptBytes(quint32* keys, char* buffer, qint64 read);
84 84
85 inline void setULong(quint32 v, char* buffer, unsigned int offset); 85 inline void setULong(quint32 v, char* buffer, unsigned int offset);
86 inline void updateKeys(quint32* keys, int c) const; 86 inline void updateKeys(quint32* keys, int c) const;
87 inline void initKeys(quint32* keys) const; 87 inline void initKeys(quint32* keys) const;
88 inline int decryptByte(quint32 key2) const; 88 inline int decryptByte(quint32 key2) const;
89 89
90 inline QString extractRoot(const QString& p); 90 inline QString extractRoot(const QString& p);
91}; 91};
92 92
93#endif // OSDAB_ZIP_P__H 93#endif // OSDAB_ZIP_P__H
diff --git a/rbutil/rbutilqt/zip/zipentry_p.h b/rbutil/rbutilqt/zip/zipentry_p.h
index a201d0ac6e..dfdcf174d0 100644
--- a/rbutil/rbutilqt/zip/zipentry_p.h
+++ b/rbutil/rbutilqt/zip/zipentry_p.h
@@ -1,78 +1,78 @@
1/**************************************************************************** 1/****************************************************************************
2** Filename: ZipEntryP.h 2** Filename: ZipEntryP.h
3** Last updated [dd/mm/yyyy]: 28/01/2007 3** Last updated [dd/mm/yyyy]: 28/01/2007
4** 4**
5** Wrapper for a ZIP local header. 5** Wrapper for a ZIP local header.
6** 6**
7** Some of the code has been inspired by other open source projects, 7** Some of the code has been inspired by other open source projects,
8** (mainly Info-Zip and Gilles Vollant's minizip). 8** (mainly Info-Zip and Gilles Vollant's minizip).
9** Compression and decompression actually uses the zlib library. 9** Compression and decompression actually uses the zlib library.
10** 10**
11** Copyright (C) 2007 Angius Fabrizio. All rights reserved. 11** Copyright (C) 2007 Angius Fabrizio. All rights reserved.
12** 12**
13** This file is part of the OSDaB project (http://osdab.sourceforge.net/). 13** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14** 14**
15** This file may be distributed and/or modified under the terms of the 15** This file may be distributed and/or modified under the terms of the
16** GNU General Public License version 2 as published by the Free Software 16** GNU General Public License version 2 as published by the Free Software
17** Foundation and appearing in the file LICENSE.GPL included in the 17** Foundation and appearing in the file LICENSE.GPL included in the
18** packaging of this file. 18** packaging of this file.
19** 19**
20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 20** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22** 22**
23** See the file LICENSE.GPL that came with this software distribution or 23** See the file LICENSE.GPL that came with this software distribution or
24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information. 24** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
25** 25**
26**********************************************************************/ 26**********************************************************************/
27 27
28// 28//
29// W A R N I N G 29// W A R N I N G
30// ------------- 30// -------------
31// 31//
32// This file is not part of the Zip/UnZip API. It exists purely as an 32// This file is not part of the Zip/UnZip API. It exists purely as an
33// implementation detail. This header file may change from version to 33// implementation detail. This header file may change from version to
34// version without notice, or even be removed. 34// version without notice, or even be removed.
35// 35//
36// We mean it. 36// We mean it.
37// 37//
38 38
39#ifndef OSDAB_ZIPENTRY_P__H 39#ifndef OSDAB_ZIPENTRY_P__H
40#define OSDAB_ZIPENTRY_P__H 40#define OSDAB_ZIPENTRY_P__H
41 41
42#include <QtGlobal> 42#include <QtGlobal>
43#include <QString> 43#include <QString>
44 44
45class ZipEntryP 45class ZipEntryP
46{ 46{
47public: 47public:
48 ZipEntryP() 48 ZipEntryP()
49 { 49 {
50 lhOffset = 0; 50 lhOffset = 0;
51 dataOffset = 0; 51 dataOffset = 0;
52 gpFlag[0] = gpFlag[1] = 0; 52 gpFlag[0] = gpFlag[1] = 0;
53 compMethod = 0; 53 compMethod = 0;
54 modTime[0] = modTime[1] = 0; 54 modTime[0] = modTime[1] = 0;
55 modDate[0] = modDate[1] = 0; 55 modDate[0] = modDate[1] = 0;
56 crc = 0; 56 crc = 0;
57 szComp = szUncomp = 0; 57 szComp = szUncomp = 0;
58 lhEntryChecked = false; 58 lhEntryChecked = false;
59 } 59 }
60 60
61 quint32 lhOffset; // Offset of the local header record for this entry 61 quint32 lhOffset; // Offset of the local header record for this entry
62 quint32 dataOffset; // Offset of the file data for this entry 62 quint32 dataOffset; // Offset of the file data for this entry
63 unsigned char gpFlag[2]; // General purpose flag 63 unsigned char gpFlag[2]; // General purpose flag
64 quint16 compMethod; // Compression method 64 quint16 compMethod; // Compression method
65 unsigned char modTime[2]; // Last modified time 65 unsigned char modTime[2]; // Last modified time
66 unsigned char modDate[2]; // Last modified date 66 unsigned char modDate[2]; // Last modified date
67 quint32 crc; // CRC32 67 quint32 crc; // CRC32
68 quint32 szComp; // Compressed file size 68 quint32 szComp; // Compressed file size
69 quint32 szUncomp; // Uncompressed file size 69 quint32 szUncomp; // Uncompressed file size
70 QString comment; // File comment 70 QString comment; // File comment
71 71
72 bool lhEntryChecked; // Is true if the local header record for this entry has been parsed 72 bool lhEntryChecked; // Is true if the local header record for this entry has been parsed
73 73
74 inline bool isEncrypted() const { return gpFlag[0] & 0x01; } 74 inline bool isEncrypted() const { return gpFlag[0] & 0x01; }
75 inline bool hasDataDescriptor() const { return gpFlag[0] & 0x08; } 75 inline bool hasDataDescriptor() const { return gpFlag[0] & 0x08; }
76}; 76};
77 77
78#endif // OSDAB_ZIPENTRY_P__H 78#endif // OSDAB_ZIPENTRY_P__H