OpenCoverage

qzip.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qzip.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include <qglobal.h>-
41-
42#ifndef QT_NO_TEXTODFWRITER-
43-
44#include "qzipreader_p.h"-
45#include "qzipwriter_p.h"-
46#include <qdatetime.h>-
47#include <qendian.h>-
48#include <qdebug.h>-
49#include <qdir.h>-
50-
51#include <zlib.h>-
52-
53// Zip standard version for archives handled by this API-
54// (actually, the only basic support of this version is implemented but it is enough for now)-
55#define ZIP_VERSION 20-
56-
57#if 0-
58#define ZDEBUG qDebug-
59#else-
60#define ZDEBUG if (0) qDebug-
61#endif-
62-
63QT_BEGIN_NAMESPACE-
64-
65static inline uint readUInt(const uchar *data)-
66{-
67 return (data[0]) + (data[1]<<8) + (data[2]<<16) + (data[3]<<24);
never executed: return (data[0]) + (data[1]<<8) + (data[2]<<16) + (data[3]<<24);
0
68}-
69-
70static inline ushort readUShort(const uchar *data)-
71{-
72 return (data[0]) + (data[1]<<8);
never executed: return (data[0]) + (data[1]<<8);
0
73}-
74-
75static inline void writeUInt(uchar *data, uint i)-
76{-
77 data[0] = i & 0xff;-
78 data[1] = (i>>8) & 0xff;-
79 data[2] = (i>>16) & 0xff;-
80 data[3] = (i>>24) & 0xff;-
81}
never executed: end of block
0
82-
83static inline void writeUShort(uchar *data, ushort i)-
84{-
85 data[0] = i & 0xff;-
86 data[1] = (i>>8) & 0xff;-
87}
never executed: end of block
0
88-
89static inline void copyUInt(uchar *dest, const uchar *src)-
90{-
91 dest[0] = src[0];-
92 dest[1] = src[1];-
93 dest[2] = src[2];-
94 dest[3] = src[3];-
95}
never executed: end of block
0
96-
97static inline void copyUShort(uchar *dest, const uchar *src)-
98{-
99 dest[0] = src[0];-
100 dest[1] = src[1];-
101}
never executed: end of block
0
102-
103static void writeMSDosDate(uchar *dest, const QDateTime& dt)-
104{-
105 if (dt.isValid()) {
dt.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
106 quint16 time =-
107 (dt.time().hour() << 11) // 5 bit hour-
108 | (dt.time().minute() << 5) // 6 bit minute-
109 | (dt.time().second() >> 1); // 5 bit double seconds-
110-
111 dest[0] = time & 0xff;-
112 dest[1] = time >> 8;-
113-
114 quint16 date =-
115 ((dt.date().year() - 1980) << 9) // 7 bit year 1980-based-
116 | (dt.date().month() << 5) // 4 bit month-
117 | (dt.date().day()); // 5 bit day-
118-
119 dest[2] = char(date);-
120 dest[3] = char(date >> 8);-
121 } else {
never executed: end of block
0
122 dest[0] = 0;-
123 dest[1] = 0;-
124 dest[2] = 0;-
125 dest[3] = 0;-
126 }
never executed: end of block
0
127}-
128-
129static int inflate(Bytef *dest, ulong *destLen, const Bytef *source, ulong sourceLen)-
130{-
131 z_stream stream;-
132 int err;-
133-
134 stream.next_in = const_cast<Bytef*>(source);-
135 stream.avail_in = (uInt)sourceLen;-
136 if ((uLong)stream.avail_in != sourceLen)
(uLong)stream....n != sourceLenDescription
TRUEnever evaluated
FALSEnever evaluated
0
137 return Z_BUF_ERROR;
never executed: return (-5);
0
138-
139 stream.next_out = dest;-
140 stream.avail_out = (uInt)*destLen;-
141 if ((uLong)stream.avail_out != *destLen)
(uLong)stream....ut != *destLenDescription
TRUEnever evaluated
FALSEnever evaluated
0
142 return Z_BUF_ERROR;
never executed: return (-5);
0
143-
144 stream.zalloc = (alloc_func)0;-
145 stream.zfree = (free_func)0;-
146-
147 err = inflateInit2(&stream, -MAX_WBITS);-
148 if (err != Z_OK)
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
149 return err;
never executed: return err;
0
150-
151 err = inflate(&stream, Z_FINISH);-
152 if (err != Z_STREAM_END) {
err != 1Description
TRUEnever evaluated
FALSEnever evaluated
0
153 inflateEnd(&stream);-
154 if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
err == 2Description
TRUEnever evaluated
FALSEnever evaluated
err == (-5)Description
TRUEnever evaluated
FALSEnever evaluated
stream.avail_in == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
155 return Z_DATA_ERROR;
never executed: return (-3);
0
156 return err;
never executed: return err;
0
157 }-
158 *destLen = stream.total_out;-
159-
160 err = inflateEnd(&stream);-
161 return err;
never executed: return err;
0
162}-
163-
164static int deflate (Bytef *dest, ulong *destLen, const Bytef *source, ulong sourceLen)-
165{-
166 z_stream stream;-
167 int err;-
168-
169 stream.next_in = const_cast<Bytef*>(source);-
170 stream.avail_in = (uInt)sourceLen;-
171 stream.next_out = dest;-
172 stream.avail_out = (uInt)*destLen;-
173 if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
never executed: return (-5);
(uLong)stream....ut != *destLenDescription
TRUEnever evaluated
FALSEnever evaluated
0
174-
175 stream.zalloc = (alloc_func)0;-
176 stream.zfree = (free_func)0;-
177 stream.opaque = (voidpf)0;-
178-
179 err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);-
180 if (err != Z_OK) return err;
never executed: return err;
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
181-
182 err = deflate(&stream, Z_FINISH);-
183 if (err != Z_STREAM_END) {
err != 1Description
TRUEnever evaluated
FALSEnever evaluated
0
184 deflateEnd(&stream);-
185 return err == Z_OK ? Z_BUF_ERROR : err;
never executed: return err == 0 ? (-5) : err;
0
186 }-
187 *destLen = stream.total_out;-
188-
189 err = deflateEnd(&stream);-
190 return err;
never executed: return err;
0
191}-
192-
193-
194namespace WindowsFileAttributes {-
195enum {-
196 Dir = 0x10, // FILE_ATTRIBUTE_DIRECTORY-
197 File = 0x80, // FILE_ATTRIBUTE_NORMAL-
198 TypeMask = 0x90,-
199-
200 ReadOnly = 0x01, // FILE_ATTRIBUTE_READONLY-
201 PermMask = 0x01-
202};-
203}-
204-
205namespace UnixFileAttributes {-
206enum {-
207 Dir = 0040000, // __S_IFDIR-
208 File = 0100000, // __S_IFREG-
209 SymLink = 0120000, // __S_IFLNK-
210 TypeMask = 0170000, // __S_IFMT-
211-
212 ReadUser = 0400, // __S_IRUSR-
213 WriteUser = 0200, // __S_IWUSR-
214 ExeUser = 0100, // __S_IXUSR-
215 ReadGroup = 0040, // __S_IRGRP-
216 WriteGroup = 0020, // __S_IWGRP-
217 ExeGroup = 0010, // __S_IXGRP-
218 ReadOther = 0004, // __S_IROTH-
219 WriteOther = 0002, // __S_IWOTH-
220 ExeOther = 0001, // __S_IXOTH-
221 PermMask = 0777-
222};-
223}-
224-
225static QFile::Permissions modeToPermissions(quint32 mode)-
226{-
227 QFile::Permissions ret;-
228 if (mode & UnixFileAttributes::ReadUser)
mode & UnixFil...utes::ReadUserDescription
TRUEnever evaluated
FALSEnever evaluated
0
229 ret |= QFile::ReadOwner | QFile::ReadUser;
never executed: ret |= QFile::ReadOwner | QFile::ReadUser;
0
230 if (mode & UnixFileAttributes::WriteUser)
mode & UnixFil...tes::WriteUserDescription
TRUEnever evaluated
FALSEnever evaluated
0
231 ret |= QFile::WriteOwner | QFile::WriteUser;
never executed: ret |= QFile::WriteOwner | QFile::WriteUser;
0
232 if (mode & UnixFileAttributes::ExeUser)
mode & UnixFil...butes::ExeUserDescription
TRUEnever evaluated
FALSEnever evaluated
0
233 ret |= QFile::ExeOwner | QFile::ExeUser;
never executed: ret |= QFile::ExeOwner | QFile::ExeUser;
0
234 if (mode & UnixFileAttributes::ReadGroup)
mode & UnixFil...tes::ReadGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
235 ret |= QFile::ReadGroup;
never executed: ret |= QFile::ReadGroup;
0
236 if (mode & UnixFileAttributes::WriteGroup)
mode & UnixFil...es::WriteGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
237 ret |= QFile::WriteGroup;
never executed: ret |= QFile::WriteGroup;
0
238 if (mode & UnixFileAttributes::ExeGroup)
mode & UnixFil...utes::ExeGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
239 ret |= QFile::ExeGroup;
never executed: ret |= QFile::ExeGroup;
0
240 if (mode & UnixFileAttributes::ReadOther)
mode & UnixFil...tes::ReadOtherDescription
TRUEnever evaluated
FALSEnever evaluated
0
241 ret |= QFile::ReadOther;
never executed: ret |= QFile::ReadOther;
0
242 if (mode & UnixFileAttributes::WriteOther)
mode & UnixFil...es::WriteOtherDescription
TRUEnever evaluated
FALSEnever evaluated
0
243 ret |= QFile::WriteOther;
never executed: ret |= QFile::WriteOther;
0
244 if (mode & UnixFileAttributes::ExeOther)
mode & UnixFil...utes::ExeOtherDescription
TRUEnever evaluated
FALSEnever evaluated
0
245 ret |= QFile::ExeOther;
never executed: ret |= QFile::ExeOther;
0
246 return ret;
never executed: return ret;
0
247}-
248-
249static quint32 permissionsToMode(QFile::Permissions perms)-
250{-
251 quint32 mode = 0;-
252 if (perms & (QFile::ReadOwner | QFile::ReadUser))
perms & (QFile...ile::ReadUser)Description
TRUEnever evaluated
FALSEnever evaluated
0
253 mode |= UnixFileAttributes::ReadUser;
never executed: mode |= UnixFileAttributes::ReadUser;
0
254 if (perms & (QFile::WriteOwner | QFile::WriteUser))
perms & (QFile...le::WriteUser)Description
TRUEnever evaluated
FALSEnever evaluated
0
255 mode |= UnixFileAttributes::WriteUser;
never executed: mode |= UnixFileAttributes::WriteUser;
0
256 if (perms & (QFile::ExeOwner | QFile::ExeUser))
perms & (QFile...File::ExeUser)Description
TRUEnever evaluated
FALSEnever evaluated
0
257 mode |= UnixFileAttributes::WriteUser;
never executed: mode |= UnixFileAttributes::WriteUser;
0
258 if (perms & QFile::ReadGroup)
perms & QFile::ReadGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
259 mode |= UnixFileAttributes::ReadGroup;
never executed: mode |= UnixFileAttributes::ReadGroup;
0
260 if (perms & QFile::WriteGroup)
perms & QFile::WriteGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
261 mode |= UnixFileAttributes::WriteGroup;
never executed: mode |= UnixFileAttributes::WriteGroup;
0
262 if (perms & QFile::ExeGroup)
perms & QFile::ExeGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
263 mode |= UnixFileAttributes::ExeGroup;
never executed: mode |= UnixFileAttributes::ExeGroup;
0
264 if (perms & QFile::ReadOther)
perms & QFile::ReadOtherDescription
TRUEnever evaluated
FALSEnever evaluated
0
265 mode |= UnixFileAttributes::ReadOther;
never executed: mode |= UnixFileAttributes::ReadOther;
0
266 if (perms & QFile::WriteOther)
perms & QFile::WriteOtherDescription
TRUEnever evaluated
FALSEnever evaluated
0
267 mode |= UnixFileAttributes::WriteOther;
never executed: mode |= UnixFileAttributes::WriteOther;
0
268 if (perms & QFile::ExeOther)
perms & QFile::ExeOtherDescription
TRUEnever evaluated
FALSEnever evaluated
0
269 mode |= UnixFileAttributes::ExeOther;
never executed: mode |= UnixFileAttributes::ExeOther;
0
270 return mode;
never executed: return mode;
0
271}-
272-
273static QDateTime readMSDosDate(const uchar *src)-
274{-
275 uint dosDate = readUInt(src);-
276 quint64 uDate;-
277 uDate = (quint64)(dosDate >> 16);-
278 uint tm_mday = (uDate & 0x1f);-
279 uint tm_mon = ((uDate & 0x1E0) >> 5);-
280 uint tm_year = (((uDate & 0x0FE00) >> 9) + 1980);-
281 uint tm_hour = ((dosDate & 0xF800) >> 11);-
282 uint tm_min = ((dosDate & 0x7E0) >> 5);-
283 uint tm_sec = ((dosDate & 0x1f) << 1);-
284-
285 return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec));
never executed: return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec));
0
286}-
287-
288// for details, see http://www.pkware.com/documents/casestudies/APPNOTE.TXT-
289-
290enum HostOS {-
291 HostFAT = 0,-
292 HostAMIGA = 1,-
293 HostVMS = 2, // VAX/VMS-
294 HostUnix = 3,-
295 HostVM_CMS = 4,-
296 HostAtari = 5, // what if it's a minix filesystem? [cjh]-
297 HostHPFS = 6, // filesystem used by OS/2 (and NT 3.x)-
298 HostMac = 7,-
299 HostZ_System = 8,-
300 HostCPM = 9,-
301 HostTOPS20 = 10, // pkzip 2.50 NTFS-
302 HostNTFS = 11, // filesystem used by Windows NT-
303 HostQDOS = 12, // SMS/QDOS-
304 HostAcorn = 13, // Archimedes Acorn RISC OS-
305 HostVFAT = 14, // filesystem used by Windows 95, NT-
306 HostMVS = 15,-
307 HostBeOS = 16, // hybrid POSIX/database filesystem-
308 HostTandem = 17,-
309 HostOS400 = 18,-
310 HostOSX = 19-
311};-
312Q_DECLARE_TYPEINFO(HostOS, Q_PRIMITIVE_TYPE);-
313-
314enum GeneralPurposeFlag {-
315 Encrypted = 0x01,-
316 AlgTune1 = 0x02,-
317 AlgTune2 = 0x04,-
318 HasDataDescriptor = 0x08,-
319 PatchedData = 0x20,-
320 StrongEncrypted = 0x40,-
321 Utf8Names = 0x0800,-
322 CentralDirectoryEncrypted = 0x2000-
323};-
324Q_DECLARE_TYPEINFO(GeneralPurposeFlag, Q_PRIMITIVE_TYPE);-
325-
326enum CompressionMethod {-
327 CompressionMethodStored = 0,-
328 CompressionMethodShrunk = 1,-
329 CompressionMethodReduced1 = 2,-
330 CompressionMethodReduced2 = 3,-
331 CompressionMethodReduced3 = 4,-
332 CompressionMethodReduced4 = 5,-
333 CompressionMethodImploded = 6,-
334 CompressionMethodReservedTokenizing = 7, // reserved for tokenizing-
335 CompressionMethodDeflated = 8,-
336 CompressionMethodDeflated64 = 9,-
337 CompressionMethodPKImploding = 10,-
338-
339 CompressionMethodBZip2 = 12,-
340-
341 CompressionMethodLZMA = 14,-
342-
343 CompressionMethodTerse = 18,-
344 CompressionMethodLz77 = 19,-
345-
346 CompressionMethodJpeg = 96,-
347 CompressionMethodWavPack = 97,-
348 CompressionMethodPPMd = 98,-
349 CompressionMethodWzAES = 99-
350};-
351Q_DECLARE_TYPEINFO(CompressionMethod, Q_PRIMITIVE_TYPE);-
352-
353struct LocalFileHeader-
354{-
355 uchar signature[4]; // 0x04034b50-
356 uchar version_needed[2];-
357 uchar general_purpose_bits[2];-
358 uchar compression_method[2];-
359 uchar last_mod_file[4];-
360 uchar crc_32[4];-
361 uchar compressed_size[4];-
362 uchar uncompressed_size[4];-
363 uchar file_name_length[2];-
364 uchar extra_field_length[2];-
365};-
366Q_DECLARE_TYPEINFO(LocalFileHeader, Q_PRIMITIVE_TYPE);-
367-
368struct DataDescriptor-
369{-
370 uchar crc_32[4];-
371 uchar compressed_size[4];-
372 uchar uncompressed_size[4];-
373};-
374Q_DECLARE_TYPEINFO(DataDescriptor, Q_PRIMITIVE_TYPE);-
375-
376struct CentralFileHeader-
377{-
378 uchar signature[4]; // 0x02014b50-
379 uchar version_made[2];-
380 uchar version_needed[2];-
381 uchar general_purpose_bits[2];-
382 uchar compression_method[2];-
383 uchar last_mod_file[4];-
384 uchar crc_32[4];-
385 uchar compressed_size[4];-
386 uchar uncompressed_size[4];-
387 uchar file_name_length[2];-
388 uchar extra_field_length[2];-
389 uchar file_comment_length[2];-
390 uchar disk_start[2];-
391 uchar internal_file_attributes[2];-
392 uchar external_file_attributes[4];-
393 uchar offset_local_header[4];-
394 LocalFileHeader toLocalHeader() const;-
395};-
396Q_DECLARE_TYPEINFO(CentralFileHeader, Q_PRIMITIVE_TYPE);-
397-
398struct EndOfDirectory-
399{-
400 uchar signature[4]; // 0x06054b50-
401 uchar this_disk[2];-
402 uchar start_of_directory_disk[2];-
403 uchar num_dir_entries_this_disk[2];-
404 uchar num_dir_entries[2];-
405 uchar directory_size[4];-
406 uchar dir_start_offset[4];-
407 uchar comment_length[2];-
408};-
409Q_DECLARE_TYPEINFO(EndOfDirectory, Q_PRIMITIVE_TYPE);-
410-
411struct FileHeader-
412{-
413 CentralFileHeader h;-
414 QByteArray file_name;-
415 QByteArray extra_field;-
416 QByteArray file_comment;-
417};-
418Q_DECLARE_TYPEINFO(FileHeader, Q_MOVABLE_TYPE);-
419-
420class QZipPrivate-
421{-
422public:-
423 QZipPrivate(QIODevice *device, bool ownDev)-
424 : device(device), ownDevice(ownDev), dirtyFileTree(true), start_of_directory(0)-
425 {-
426 }
never executed: end of block
0
427-
428 ~QZipPrivate()-
429 {-
430 if (ownDevice)
ownDeviceDescription
TRUEnever evaluated
FALSEnever evaluated
0
431 delete device;
never executed: delete device;
0
432 }
never executed: end of block
0
433-
434 QZipReader::FileInfo fillFileInfo(int index) const;-
435-
436 QIODevice *device;-
437 bool ownDevice;-
438 bool dirtyFileTree;-
439 QVector<FileHeader> fileHeaders;-
440 QByteArray comment;-
441 uint start_of_directory;-
442};-
443-
444QZipReader::FileInfo QZipPrivate::fillFileInfo(int index) const-
445{-
446 QZipReader::FileInfo fileInfo;-
447 FileHeader header = fileHeaders.at(index);-
448 quint32 mode = readUInt(header.h.external_file_attributes);-
449 const HostOS hostOS = HostOS(readUShort(header.h.version_made) >> 8);-
450 switch (hostOS) {-
451 case HostUnix:
never executed: case HostUnix:
0
452 mode = (mode >> 16) & 0xffff;-
453 switch (mode & UnixFileAttributes::TypeMask) {-
454 case UnixFileAttributes::SymLink:
never executed: case UnixFileAttributes::SymLink:
0
455 fileInfo.isSymLink = true;-
456 break;
never executed: break;
0
457 case UnixFileAttributes::Dir:
never executed: case UnixFileAttributes::Dir:
0
458 fileInfo.isDir = true;-
459 break;
never executed: break;
0
460 case UnixFileAttributes::File:
never executed: case UnixFileAttributes::File:
0
461 default: // ### just for the case; should we warn?
never executed: default:
0
462 fileInfo.isFile = true;-
463 break;
never executed: break;
0
464 }-
465 fileInfo.permissions = modeToPermissions(mode);-
466 break;
never executed: break;
0
467 case HostFAT:
never executed: case HostFAT:
0
468 case HostNTFS:
never executed: case HostNTFS:
0
469 case HostHPFS:
never executed: case HostHPFS:
0
470 case HostVFAT:
never executed: case HostVFAT:
0
471 switch (mode & WindowsFileAttributes::TypeMask) {-
472 case WindowsFileAttributes::Dir:
never executed: case WindowsFileAttributes::Dir:
0
473 fileInfo.isDir = true;-
474 break;
never executed: break;
0
475 case WindowsFileAttributes::File:
never executed: case WindowsFileAttributes::File:
0
476 default:
never executed: default:
0
477 fileInfo.isFile = true;-
478 break;
never executed: break;
0
479 }-
480 fileInfo.permissions |= QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther;-
481 if ((mode & WindowsFileAttributes::ReadOnly) == 0)
(mode & Window...ReadOnly) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
482 fileInfo.permissions |= QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther;
never executed: fileInfo.permissions |= QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther;
0
483 if (fileInfo.isDir)
fileInfo.isDirDescription
TRUEnever evaluated
FALSEnever evaluated
0
484 fileInfo.permissions |= QFile::ExeOwner | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther;
never executed: fileInfo.permissions |= QFile::ExeOwner | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther;
0
485 break;
never executed: break;
0
486 default:
never executed: default:
0
487 qWarning("QZip: Zip entry format at %d is not supported.", index);-
488 return fileInfo; // we don't support anything else
never executed: return fileInfo;
0
489 }-
490-
491 ushort general_purpose_bits = readUShort(header.h.general_purpose_bits);-
492 // if bit 11 is set, the filename and comment fields must be encoded using UTF-8-
493 const bool inUtf8 = (general_purpose_bits & Utf8Names) != 0;-
494 fileInfo.filePath = inUtf8 ? QString::fromUtf8(header.file_name) : QString::fromLocal8Bit(header.file_name);
inUtf8Description
TRUEnever evaluated
FALSEnever evaluated
0
495 fileInfo.crc = readUInt(header.h.crc_32);-
496 fileInfo.size = readUInt(header.h.uncompressed_size);-
497 fileInfo.lastModified = readMSDosDate(header.h.last_mod_file);-
498-
499 // fix the file path, if broken (convert separators, eat leading and trailing ones)-
500 fileInfo.filePath = QDir::fromNativeSeparators(fileInfo.filePath);-
501 while (!fileInfo.filePath.isEmpty() && (fileInfo.filePath.at(0) == QLatin1Char('.') || fileInfo.filePath.at(0) == QLatin1Char('/')))
!fileInfo.filePath.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
fileInfo.fileP...atin1Char('.')Description
TRUEnever evaluated
FALSEnever evaluated
fileInfo.fileP...atin1Char('/')Description
TRUEnever evaluated
FALSEnever evaluated
0
502 fileInfo.filePath = fileInfo.filePath.mid(1);
never executed: fileInfo.filePath = fileInfo.filePath.mid(1);
0
503 while (!fileInfo.filePath.isEmpty() && fileInfo.filePath.at(fileInfo.filePath.size() - 1) == QLatin1Char('/'))
!fileInfo.filePath.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
fileInfo.fileP...atin1Char('/')Description
TRUEnever evaluated
FALSEnever evaluated
0
504 fileInfo.filePath.chop(1);
never executed: fileInfo.filePath.chop(1);
0
505-
506 return fileInfo;
never executed: return fileInfo;
0
507}-
508-
509class QZipReaderPrivate : public QZipPrivate-
510{-
511public:-
512 QZipReaderPrivate(QIODevice *device, bool ownDev)-
513 : QZipPrivate(device, ownDev), status(QZipReader::NoError)-
514 {-
515 }
never executed: end of block
0
516-
517 void scanFiles();-
518-
519 QZipReader::Status status;-
520};-
521-
522class QZipWriterPrivate : public QZipPrivate-
523{-
524public:-
525 QZipWriterPrivate(QIODevice *device, bool ownDev)-
526 : QZipPrivate(device, ownDev),-
527 status(QZipWriter::NoError),-
528 permissions(QFile::ReadOwner | QFile::WriteOwner),-
529 compressionPolicy(QZipWriter::AlwaysCompress)-
530 {-
531 }
never executed: end of block
0
532-
533 QZipWriter::Status status;-
534 QFile::Permissions permissions;-
535 QZipWriter::CompressionPolicy compressionPolicy;-
536-
537 enum EntryType { Directory, File, Symlink };-
538-
539 void addEntry(EntryType type, const QString &fileName, const QByteArray &contents);-
540};-
541-
542LocalFileHeader CentralFileHeader::toLocalHeader() const-
543{-
544 LocalFileHeader h;-
545 writeUInt(h.signature, 0x04034b50);-
546 copyUShort(h.version_needed, version_needed);-
547 copyUShort(h.general_purpose_bits, general_purpose_bits);-
548 copyUShort(h.compression_method, compression_method);-
549 copyUInt(h.last_mod_file, last_mod_file);-
550 copyUInt(h.crc_32, crc_32);-
551 copyUInt(h.compressed_size, compressed_size);-
552 copyUInt(h.uncompressed_size, uncompressed_size);-
553 copyUShort(h.file_name_length, file_name_length);-
554 copyUShort(h.extra_field_length, extra_field_length);-
555 return h;
never executed: return h;
0
556}-
557-
558void QZipReaderPrivate::scanFiles()-
559{-
560 if (!dirtyFileTree)
!dirtyFileTreeDescription
TRUEnever evaluated
FALSEnever evaluated
0
561 return;
never executed: return;
0
562-
563 if (! (device->isOpen() || device->open(QIODevice::ReadOnly))) {
device->isOpen()Description
TRUEnever evaluated
FALSEnever evaluated
device->open(Q...ice::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
564 status = QZipReader::FileOpenError;-
565 return;
never executed: return;
0
566 }-
567-
568 if ((device->openMode() & QIODevice::ReadOnly) == 0) { // only read the index from readable files.
(device->openM...ReadOnly) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
569 status = QZipReader::FileReadError;-
570 return;
never executed: return;
0
571 }-
572-
573 dirtyFileTree = false;-
574 uchar tmp[4];-
575 device->read((char *)tmp, 4);-
576 if (readUInt(tmp) != 0x04034b50) {
readUInt(tmp) != 0x04034b50Description
TRUEnever evaluated
FALSEnever evaluated
0
577 qWarning("QZip: not a zip file!");-
578 return;
never executed: return;
0
579 }-
580-
581 // find EndOfDirectory header-
582 int i = 0;-
583 int start_of_directory = -1;-
584 int num_dir_entries = 0;-
585 EndOfDirectory eod;-
586 while (start_of_directory == -1) {
start_of_directory == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
587 const int pos = device->size() - int(sizeof(EndOfDirectory)) - i;-
588 if (pos < 0 || i > 65535) {
pos < 0Description
TRUEnever evaluated
FALSEnever evaluated
i > 65535Description
TRUEnever evaluated
FALSEnever evaluated
0
589 qWarning("QZip: EndOfDirectory not found");-
590 return;
never executed: return;
0
591 }-
592-
593 device->seek(pos);-
594 device->read((char *)&eod, sizeof(EndOfDirectory));-
595 if (readUInt(eod.signature) == 0x06054b50)
readUInt(eod.s... == 0x06054b50Description
TRUEnever evaluated
FALSEnever evaluated
0
596 break;
never executed: break;
0
597 ++i;-
598 }
never executed: end of block
0
599-
600 // have the eod-
601 start_of_directory = readUInt(eod.dir_start_offset);-
602 num_dir_entries = readUShort(eod.num_dir_entries);-
603 ZDEBUG("start_of_directory at %d, num_dir_entries=%d", start_of_directory, num_dir_entries);
dead code: QMessageLogger(__FILE__, 603, __PRETTY_FUNCTION__).debug("start_of_directory at %d, num_dir_entries=%d", start_of_directory, num_dir_entries);
-
604 int comment_length = readUShort(eod.comment_length);-
605 if (comment_length != i)
comment_length != iDescription
TRUEnever evaluated
FALSEnever evaluated
0
606 qWarning("QZip: failed to parse zip file.");
never executed: QMessageLogger(__FILE__, 606, __PRETTY_FUNCTION__).warning("QZip: failed to parse zip file.");
0
607 comment = device->read(qMin(comment_length, i));-
608-
609-
610 device->seek(start_of_directory);-
611 for (i = 0; i < num_dir_entries; ++i) {
i < num_dir_entriesDescription
TRUEnever evaluated
FALSEnever evaluated
0
612 FileHeader header;-
613 int read = device->read((char *) &header.h, sizeof(CentralFileHeader));-
614 if (read < (int)sizeof(CentralFileHeader)) {
read < (int)si...ralFileHeader)Description
TRUEnever evaluated
FALSEnever evaluated
0
615 qWarning("QZip: Failed to read complete header, index may be incomplete");-
616 break;
never executed: break;
0
617 }-
618 if (readUInt(header.h.signature) != 0x02014b50) {
readUInt(heade... != 0x02014b50Description
TRUEnever evaluated
FALSEnever evaluated
0
619 qWarning("QZip: invalid header signature, index may be incomplete");-
620 break;
never executed: break;
0
621 }-
622-
623 int l = readUShort(header.h.file_name_length);-
624 header.file_name = device->read(l);-
625 if (header.file_name.length() != l) {
header.file_name.length() != lDescription
TRUEnever evaluated
FALSEnever evaluated
0
626 qWarning("QZip: Failed to read filename from zip index, index may be incomplete");-
627 break;
never executed: break;
0
628 }-
629 l = readUShort(header.h.extra_field_length);-
630 header.extra_field = device->read(l);-
631 if (header.extra_field.length() != l) {
header.extra_f....length() != lDescription
TRUEnever evaluated
FALSEnever evaluated
0
632 qWarning("QZip: Failed to read extra field in zip file, skipping file, index may be incomplete");-
633 break;
never executed: break;
0
634 }-
635 l = readUShort(header.h.file_comment_length);-
636 header.file_comment = device->read(l);-
637 if (header.file_comment.length() != l) {
header.file_co....length() != lDescription
TRUEnever evaluated
FALSEnever evaluated
0
638 qWarning("QZip: Failed to read read file comment, index may be incomplete");-
639 break;
never executed: break;
0
640 }-
641-
642 ZDEBUG("found file '%s'", header.file_name.data());
dead code: QMessageLogger(__FILE__, 642, __PRETTY_FUNCTION__).debug("found file '%s'", header.file_name.data());
-
643 fileHeaders.append(header);-
644 }
never executed: end of block
0
645}
never executed: end of block
0
646-
647void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const QByteArray &contents/*, QFile::Permissions permissions, QZip::Method m*/)-
648{-
649#ifndef NDEBUG-
650 static const char *const entryTypes[] = {-
651 "directory",-
652 "file ",-
653 "symlink " };-
654 ZDEBUG() << "adding" << entryTypes[type] <<":" << fileName.toUtf8().data() << (type == 2 ? QByteArray(" -> " + contents).constData() : "");
dead code: QMessageLogger(__FILE__, 654, __PRETTY_FUNCTION__).debug() << "adding" << entryTypes[type] <<":" << fileName.toUtf8().data() << (type == 2 ? QByteArray(" -> " + contents).constData() : "");
-
655#endif-
656-
657 if (! (device->isOpen() || device->open(QIODevice::WriteOnly))) {
device->isOpen()Description
TRUEnever evaluated
FALSEnever evaluated
device->open(Q...ce::WriteOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
658 status = QZipWriter::FileOpenError;-
659 return;
never executed: return;
0
660 }-
661 device->seek(start_of_directory);-
662-
663 // don't compress small files-
664 QZipWriter::CompressionPolicy compression = compressionPolicy;-
665 if (compressionPolicy == QZipWriter::AutoCompress) {
compressionPol...::AutoCompressDescription
TRUEnever evaluated
FALSEnever evaluated
0
666 if (contents.length() < 64)
contents.length() < 64Description
TRUEnever evaluated
FALSEnever evaluated
0
667 compression = QZipWriter::NeverCompress;
never executed: compression = QZipWriter::NeverCompress;
0
668 else-
669 compression = QZipWriter::AlwaysCompress;
never executed: compression = QZipWriter::AlwaysCompress;
0
670 }-
671-
672 FileHeader header;-
673 memset(&header.h, 0, sizeof(CentralFileHeader));-
674 writeUInt(header.h.signature, 0x02014b50);-
675-
676 writeUShort(header.h.version_needed, ZIP_VERSION);-
677 writeUInt(header.h.uncompressed_size, contents.length());-
678 writeMSDosDate(header.h.last_mod_file, QDateTime::currentDateTime());-
679 QByteArray data = contents;-
680 if (compression == QZipWriter::AlwaysCompress) {
compression ==...AlwaysCompressDescription
TRUEnever evaluated
FALSEnever evaluated
0
681 writeUShort(header.h.compression_method, CompressionMethodDeflated);-
682-
683 ulong len = contents.length();-
684 // shamelessly copied form zlib-
685 len += (len >> 12) + (len >> 14) + 11;-
686 int res;-
687 do {-
688 data.resize(len);-
689 res = deflate((uchar*)data.data(), &len, (const uchar*)contents.constData(), contents.length());-
690-
691 switch (res) {-
692 case Z_OK:
never executed: case 0:
0
693 data.resize(len);-
694 break;
never executed: break;
0
695 case Z_MEM_ERROR:
never executed: case (-4):
0
696 qWarning("QZip: Z_MEM_ERROR: Not enough memory to compress file, skipping");-
697 data.resize(0);-
698 break;
never executed: break;
0
699 case Z_BUF_ERROR:
never executed: case (-5):
0
700 len *= 2;-
701 break;
never executed: break;
0
702 }-
703 } while (res == Z_BUF_ERROR);
never executed: end of block
res == (-5)Description
TRUEnever evaluated
FALSEnever evaluated
0
704 }
never executed: end of block
0
705// TODO add a check if data.length() > contents.length(). Then try to store the original and revert the compression method to be uncompressed-
706 writeUInt(header.h.compressed_size, data.length());-
707 uint crc_32 = ::crc32(0, 0, 0);-
708 crc_32 = ::crc32(crc_32, (const uchar *)contents.constData(), contents.length());-
709 writeUInt(header.h.crc_32, crc_32);-
710-
711 // if bit 11 is set, the filename and comment fields must be encoded using UTF-8-
712 ushort general_purpose_bits = Utf8Names; // always use utf-8-
713 writeUShort(header.h.general_purpose_bits, general_purpose_bits);-
714-
715 const bool inUtf8 = (general_purpose_bits & Utf8Names) != 0;-
716 header.file_name = inUtf8 ? fileName.toUtf8() : fileName.toLocal8Bit();
inUtf8Description
TRUEnever evaluated
FALSEnever evaluated
0
717 if (header.file_name.size() > 0xffff) {
header.file_na...ize() > 0xffffDescription
TRUEnever evaluated
FALSEnever evaluated
0
718 qWarning("QZip: Filename is too long, chopping it to 65535 bytes");-
719 header.file_name = header.file_name.left(0xffff); // ### don't break the utf-8 sequence, if any-
720 }
never executed: end of block
0
721 if (header.file_comment.size() + header.file_name.size() > 0xffff) {
header.file_co...ize() > 0xffffDescription
TRUEnever evaluated
FALSEnever evaluated
0
722 qWarning("QZip: File comment is too long, chopping it to 65535 bytes");-
723 header.file_comment.truncate(0xffff - header.file_name.size()); // ### don't break the utf-8 sequence, if any-
724 }
never executed: end of block
0
725 writeUShort(header.h.file_name_length, header.file_name.length());-
726 //h.extra_field_length[2];-
727-
728 writeUShort(header.h.version_made, HostUnix << 8);-
729 //uchar internal_file_attributes[2];-
730 //uchar external_file_attributes[4];-
731 quint32 mode = permissionsToMode(permissions);-
732 switch (type) {-
733 case Symlink:
never executed: case Symlink:
0
734 mode |= UnixFileAttributes::SymLink;-
735 break;
never executed: break;
0
736 case Directory:
never executed: case Directory:
0
737 mode |= UnixFileAttributes::Dir;-
738 break;
never executed: break;
0
739 case File:
never executed: case File:
0
740 mode |= UnixFileAttributes::File;-
741 break;
never executed: break;
0
742 default:
never executed: default:
0
743 Q_UNREACHABLE();-
744 break;
never executed: break;
0
745 }-
746 writeUInt(header.h.external_file_attributes, mode << 16);-
747 writeUInt(header.h.offset_local_header, start_of_directory);-
748-
749-
750 fileHeaders.append(header);-
751-
752 LocalFileHeader h = header.h.toLocalHeader();-
753 device->write((const char *)&h, sizeof(LocalFileHeader));-
754 device->write(header.file_name);-
755 device->write(data);-
756 start_of_directory = device->pos();-
757 dirtyFileTree = true;-
758}
never executed: end of block
0
759-
760////////////////////////////// Reader-
761-
762/*!-
763 \class QZipReader::FileInfo-
764 \internal-
765 Represents one entry in the zip table of contents.-
766*/-
767-
768/*!-
769 \variable FileInfo::filePath-
770 The full filepath inside the archive.-
771*/-
772-
773/*!-
774 \variable FileInfo::isDir-
775 A boolean type indicating if the entry is a directory.-
776*/-
777-
778/*!-
779 \variable FileInfo::isFile-
780 A boolean type, if it is one this entry is a file.-
781*/-
782-
783/*!-
784 \variable FileInfo::isSymLink-
785 A boolean type, if it is one this entry is symbolic link.-
786*/-
787-
788/*!-
789 \variable FileInfo::permissions-
790 A list of flags for the permissions of this entry.-
791*/-
792-
793/*!-
794 \variable FileInfo::crc-
795 The calculated checksum as a crc type.-
796*/-
797-
798/*!-
799 \variable FileInfo::size-
800 The total size of the unpacked content.-
801*/-
802-
803/*!-
804 \class QZipReader-
805 \internal-
806 \since 4.5-
807-
808 \brief the QZipReader class provides a way to inspect the contents of a zip-
809 archive and extract individual files from it.-
810-
811 QZipReader can be used to read a zip archive either from a file or from any-
812 device. An in-memory QBuffer for instance. The reader can be used to read-
813 which files are in the archive using fileInfoList() and entryInfoAt() but-
814 also to extract individual files using fileData() or even to extract all-
815 files in the archive using extractAll()-
816*/-
817-
818/*!-
819 Create a new zip archive that operates on the \a fileName. The file will be-
820 opened with the \a mode.-
821*/-
822QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode)-
823{-
824 QScopedPointer<QFile> f(new QFile(archive));-
825 const bool result = f->open(mode);-
826 QZipReader::Status status;-
827 const QFileDevice::FileError error = f->error();-
828 if (result && error == QFile::NoError) {
resultDescription
TRUEnever evaluated
FALSEnever evaluated
error == QFile::NoErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
829 status = NoError;-
830 } else {
never executed: end of block
0
831 if (error == QFile::ReadError)
error == QFile::ReadErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
832 status = FileReadError;
never executed: status = FileReadError;
0
833 else if (error == QFile::OpenError)
error == QFile::OpenErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
834 status = FileOpenError;
never executed: status = FileOpenError;
0
835 else if (error == QFile::PermissionsError)
error == QFile...rmissionsErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
836 status = FilePermissionsError;
never executed: status = FilePermissionsError;
0
837 else-
838 status = FileError;
never executed: status = FileError;
0
839 }-
840-
841 d = new QZipReaderPrivate(f.data(), /*ownDevice=*/true);-
842 f.take();-
843 d->status = status;-
844}
never executed: end of block
0
845-
846/*!-
847 Create a new zip archive that operates on the archive found in \a device.-
848 You have to open the device previous to calling the constructor and only a-
849 device that is readable will be scanned for zip filecontent.-
850 */-
851QZipReader::QZipReader(QIODevice *device)-
852 : d(new QZipReaderPrivate(device, /*ownDevice=*/false))-
853{-
854 Q_ASSERT(device);-
855}
never executed: end of block
0
856-
857/*!-
858 Desctructor-
859*/-
860QZipReader::~QZipReader()-
861{-
862 close();-
863 delete d;-
864}
never executed: end of block
0
865-
866/*!-
867 Returns device used for reading zip archive.-
868*/-
869QIODevice* QZipReader::device() const-
870{-
871 return d->device;
never executed: return d->device;
0
872}-
873-
874/*!-
875 Returns \c true if the user can read the file; otherwise returns \c false.-
876*/-
877bool QZipReader::isReadable() const-
878{-
879 return d->device->isReadable();
never executed: return d->device->isReadable();
0
880}-
881-
882/*!-
883 Returns \c true if the file exists; otherwise returns \c false.-
884*/-
885bool QZipReader::exists() const-
886{-
887 QFile *f = qobject_cast<QFile*> (d->device);-
888 if (f == 0)
f == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
889 return true;
never executed: return true;
0
890 return f->exists();
never executed: return f->exists();
0
891}-
892-
893/*!-
894 Returns the list of files the archive contains.-
895*/-
896QVector<QZipReader::FileInfo> QZipReader::fileInfoList() const-
897{-
898 d->scanFiles();-
899 QVector<FileInfo> files;-
900 const int numFileHeaders = d->fileHeaders.size();-
901 files.reserve(numFileHeaders);-
902 for (int i = 0; i < numFileHeaders; ++i)
i < numFileHeadersDescription
TRUEnever evaluated
FALSEnever evaluated
0
903 files.append(d->fillFileInfo(i));
never executed: files.append(d->fillFileInfo(i));
0
904 return files;
never executed: return files;
0
905-
906}-
907-
908/*!-
909 Return the number of items in the zip archive.-
910*/-
911int QZipReader::count() const-
912{-
913 d->scanFiles();-
914 return d->fileHeaders.count();
never executed: return d->fileHeaders.count();
0
915}-
916-
917/*!-
918 Returns a FileInfo of an entry in the zipfile.-
919 The \a index is the index into the directory listing of the zipfile.-
920 Returns an invalid FileInfo if \a index is out of boundaries.-
921-
922 \sa fileInfoList()-
923*/-
924QZipReader::FileInfo QZipReader::entryInfoAt(int index) const-
925{-
926 d->scanFiles();-
927 if (index >= 0 && index < d->fileHeaders.count())
index >= 0Description
TRUEnever evaluated
FALSEnever evaluated
index < d->fileHeaders.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
928 return d->fillFileInfo(index);
never executed: return d->fillFileInfo(index);
0
929 return QZipReader::FileInfo();
never executed: return QZipReader::FileInfo();
0
930}-
931-
932/*!-
933 Fetch the file contents from the zip archive and return the uncompressed bytes.-
934*/-
935QByteArray QZipReader::fileData(const QString &fileName) const-
936{-
937 d->scanFiles();-
938 int i;-
939 for (i = 0; i < d->fileHeaders.size(); ++i) {
i < d->fileHeaders.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
940 if (QString::fromLocal8Bit(d->fileHeaders.at(i).file_name) == fileName)
QString::fromL...e) == fileNameDescription
TRUEnever evaluated
FALSEnever evaluated
0
941 break;
never executed: break;
0
942 }
never executed: end of block
0
943 if (i == d->fileHeaders.size())
i == d->fileHeaders.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
944 return QByteArray();
never executed: return QByteArray();
0
945-
946 FileHeader header = d->fileHeaders.at(i);-
947-
948 ushort version_needed = readUShort(header.h.version_needed);-
949 if (version_needed > ZIP_VERSION) {
version_needed > 20Description
TRUEnever evaluated
FALSEnever evaluated
0
950 qWarning("QZip: .ZIP specification version %d implementationis needed to extract the data.", version_needed);-
951 return QByteArray();
never executed: return QByteArray();
0
952 }-
953-
954 ushort general_purpose_bits = readUShort(header.h.general_purpose_bits);-
955 int compressed_size = readUInt(header.h.compressed_size);-
956 int uncompressed_size = readUInt(header.h.uncompressed_size);-
957 int start = readUInt(header.h.offset_local_header);-
958 //qDebug("uncompressing file %d: local header at %d", i, start);-
959-
960 d->device->seek(start);-
961 LocalFileHeader lh;-
962 d->device->read((char *)&lh, sizeof(LocalFileHeader));-
963 uint skip = readUShort(lh.file_name_length) + readUShort(lh.extra_field_length);-
964 d->device->seek(d->device->pos() + skip);-
965-
966 int compression_method = readUShort(lh.compression_method);-
967 //qDebug("file=%s: compressed_size=%d, uncompressed_size=%d", fileName.toLocal8Bit().data(), compressed_size, uncompressed_size);-
968-
969 if ((general_purpose_bits & Encrypted) != 0) {
(general_purpo...ncrypted) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
970 qWarning("QZip: Unsupported encryption method is needed to extract the data.");-
971 return QByteArray();
never executed: return QByteArray();
0
972 }-
973-
974 //qDebug("file at %lld", d->device->pos());-
975 QByteArray compressed = d->device->read(compressed_size);-
976 if (compression_method == CompressionMethodStored) {
compression_me...onMethodStoredDescription
TRUEnever evaluated
FALSEnever evaluated
0
977 // no compression-
978 compressed.truncate(uncompressed_size);-
979 return compressed;
never executed: return compressed;
0
980 } else if (compression_method == CompressionMethodDeflated) {
compression_me...MethodDeflatedDescription
TRUEnever evaluated
FALSEnever evaluated
0
981 // Deflate-
982 //qDebug("compressed=%d", compressed.size());-
983 compressed.truncate(compressed_size);-
984 QByteArray baunzip;-
985 ulong len = qMax(uncompressed_size, 1);-
986 int res;-
987 do {-
988 baunzip.resize(len);-
989 res = inflate((uchar*)baunzip.data(), &len,-
990 (const uchar*)compressed.constData(), compressed_size);-
991-
992 switch (res) {-
993 case Z_OK:
never executed: case 0:
0
994 if ((int)len != baunzip.size())
(int)len != baunzip.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
995 baunzip.resize(len);
never executed: baunzip.resize(len);
0
996 break;
never executed: break;
0
997 case Z_MEM_ERROR:
never executed: case (-4):
0
998 qWarning("QZip: Z_MEM_ERROR: Not enough memory");-
999 break;
never executed: break;
0
1000 case Z_BUF_ERROR:
never executed: case (-5):
0
1001 len *= 2;-
1002 break;
never executed: break;
0
1003 case Z_DATA_ERROR:
never executed: case (-3):
0
1004 qWarning("QZip: Z_DATA_ERROR: Input data is corrupted");-
1005 break;
never executed: break;
0
1006 }-
1007 } while (res == Z_BUF_ERROR);
never executed: end of block
res == (-5)Description
TRUEnever evaluated
FALSEnever evaluated
0
1008 return baunzip;
never executed: return baunzip;
0
1009 }-
1010-
1011 qWarning("QZip: Unsupported compression method %d is needed to extract the data.", compression_method);-
1012 return QByteArray();
never executed: return QByteArray();
0
1013}-
1014-
1015/*!-
1016 Extracts the full contents of the zip file into \a destinationDir on-
1017 the local filesystem.-
1018 In case writing or linking a file fails, the extraction will be aborted.-
1019*/-
1020bool QZipReader::extractAll(const QString &destinationDir) const-
1021{-
1022 QDir baseDir(destinationDir);-
1023-
1024 // create directories first-
1025 const QVector<FileInfo> allFiles = fileInfoList();-
1026 for (const FileInfo &fi : allFiles) {-
1027 const QString absPath = destinationDir + QDir::separator() + fi.filePath;-
1028 if (fi.isDir) {
fi.isDirDescription
TRUEnever evaluated
FALSEnever evaluated
0
1029 if (!baseDir.mkpath(fi.filePath))
!baseDir.mkpath(fi.filePath)Description
TRUEnever evaluated
FALSEnever evaluated
0
1030 return false;
never executed: return false;
0
1031 if (!QFile::setPermissions(absPath, fi.permissions))
!QFile::setPer...i.permissions)Description
TRUEnever evaluated
FALSEnever evaluated
0
1032 return false;
never executed: return false;
0
1033 }
never executed: end of block
0
1034 }
never executed: end of block
0
1035-
1036 // set up symlinks-
1037 for (const FileInfo &fi : allFiles) {-
1038 const QString absPath = destinationDir + QDir::separator() + fi.filePath;-
1039 if (fi.isSymLink) {
fi.isSymLinkDescription
TRUEnever evaluated
FALSEnever evaluated
0
1040 QString destination = QFile::decodeName(fileData(fi.filePath));-
1041 if (destination.isEmpty())
destination.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1042 return false;
never executed: return false;
0
1043 QFileInfo linkFi(absPath);-
1044 if (!QFile::exists(linkFi.absolutePath()))
!QFile::exists...bsolutePath())Description
TRUEnever evaluated
FALSEnever evaluated
0
1045 QDir::root().mkpath(linkFi.absolutePath());
never executed: QDir::root().mkpath(linkFi.absolutePath());
0
1046 if (!QFile::link(destination, absPath))
!QFile::link(d...tion, absPath)Description
TRUEnever evaluated
FALSEnever evaluated
0
1047 return false;
never executed: return false;
0
1048 /* cannot change permission of links-
1049 if (!QFile::setPermissions(absPath, fi.permissions))-
1050 return false;-
1051 */-
1052 }
never executed: end of block
0
1053 }
never executed: end of block
0
1054-
1055 for (const FileInfo &fi : allFiles) {-
1056 const QString absPath = destinationDir + QDir::separator() + fi.filePath;-
1057 if (fi.isFile) {
fi.isFileDescription
TRUEnever evaluated
FALSEnever evaluated
0
1058 QFile f(absPath);-
1059 if (!f.open(QIODevice::WriteOnly))
!f.open(QIODevice::WriteOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
1060 return false;
never executed: return false;
0
1061 f.write(fileData(fi.filePath));-
1062 f.setPermissions(fi.permissions);-
1063 f.close();-
1064 }
never executed: end of block
0
1065 }
never executed: end of block
0
1066-
1067 return true;
never executed: return true;
0
1068}-
1069-
1070/*!-
1071 \enum QZipReader::Status-
1072-
1073 The following status values are possible:-
1074-
1075 \value NoError No error occurred.-
1076 \value FileReadError An error occurred when reading from the file.-
1077 \value FileOpenError The file could not be opened.-
1078 \value FilePermissionsError The file could not be accessed.-
1079 \value FileError Another file error occurred.-
1080*/-
1081-
1082/*!-
1083 Returns a status code indicating the first error that was met by QZipReader,-
1084 or QZipReader::NoError if no error occurred.-
1085*/-
1086QZipReader::Status QZipReader::status() const-
1087{-
1088 return d->status;
never executed: return d->status;
0
1089}-
1090-
1091/*!-
1092 Close the zip file.-
1093*/-
1094void QZipReader::close()-
1095{-
1096 d->device->close();-
1097}
never executed: end of block
0
1098-
1099////////////////////////////// Writer-
1100-
1101/*!-
1102 \class QZipWriter-
1103 \internal-
1104 \since 4.5-
1105-
1106 \brief the QZipWriter class provides a way to create a new zip archive.-
1107-
1108 QZipWriter can be used to create a zip archive containing any number of files-
1109 and directories. The files in the archive will be compressed in a way that is-
1110 compatible with common zip reader applications.-
1111*/-
1112-
1113-
1114/*!-
1115 Create a new zip archive that operates on the \a archive filename. The file will-
1116 be opened with the \a mode.-
1117 \sa isValid()-
1118*/-
1119QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode)-
1120{-
1121 QScopedPointer<QFile> f(new QFile(fileName));-
1122 QZipWriter::Status status;-
1123 if (f->open(mode) && f->error() == QFile::NoError)
f->open(mode)Description
TRUEnever evaluated
FALSEnever evaluated
f->error() == QFile::NoErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1124 status = QZipWriter::NoError;
never executed: status = QZipWriter::NoError;
0
1125 else {-
1126 if (f->error() == QFile::WriteError)
f->error() == ...le::WriteErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1127 status = QZipWriter::FileWriteError;
never executed: status = QZipWriter::FileWriteError;
0
1128 else if (f->error() == QFile::OpenError)
f->error() == QFile::OpenErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1129 status = QZipWriter::FileOpenError;
never executed: status = QZipWriter::FileOpenError;
0
1130 else if (f->error() == QFile::PermissionsError)
f->error() == ...rmissionsErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1131 status = QZipWriter::FilePermissionsError;
never executed: status = QZipWriter::FilePermissionsError;
0
1132 else-
1133 status = QZipWriter::FileError;
never executed: status = QZipWriter::FileError;
0
1134 }-
1135-
1136 d = new QZipWriterPrivate(f.data(), /*ownDevice=*/true);-
1137 f.take();-
1138 d->status = status;-
1139}
never executed: end of block
0
1140-
1141/*!-
1142 Create a new zip archive that operates on the archive found in \a device.-
1143 You have to open the device previous to calling the constructor and-
1144 only a device that is readable will be scanned for zip filecontent.-
1145 */-
1146QZipWriter::QZipWriter(QIODevice *device)-
1147 : d(new QZipWriterPrivate(device, /*ownDevice=*/false))-
1148{-
1149 Q_ASSERT(device);-
1150}
never executed: end of block
0
1151-
1152QZipWriter::~QZipWriter()-
1153{-
1154 close();-
1155 delete d;-
1156}
never executed: end of block
0
1157-
1158/*!-
1159 Returns device used for writing zip archive.-
1160*/-
1161QIODevice* QZipWriter::device() const-
1162{-
1163 return d->device;
never executed: return d->device;
0
1164}-
1165-
1166/*!-
1167 Returns \c true if the user can write to the archive; otherwise returns \c false.-
1168*/-
1169bool QZipWriter::isWritable() const-
1170{-
1171 return d->device->isWritable();
never executed: return d->device->isWritable();
0
1172}-
1173-
1174/*!-
1175 Returns \c true if the file exists; otherwise returns \c false.-
1176*/-
1177bool QZipWriter::exists() const-
1178{-
1179 QFile *f = qobject_cast<QFile*> (d->device);-
1180 if (f == 0)
f == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1181 return true;
never executed: return true;
0
1182 return f->exists();
never executed: return f->exists();
0
1183}-
1184-
1185/*!-
1186 \enum QZipWriter::Status-
1187-
1188 The following status values are possible:-
1189-
1190 \value NoError No error occurred.-
1191 \value FileWriteError An error occurred when writing to the device.-
1192 \value FileOpenError The file could not be opened.-
1193 \value FilePermissionsError The file could not be accessed.-
1194 \value FileError Another file error occurred.-
1195*/-
1196-
1197/*!-
1198 Returns a status code indicating the first error that was met by QZipWriter,-
1199 or QZipWriter::NoError if no error occurred.-
1200*/-
1201QZipWriter::Status QZipWriter::status() const-
1202{-
1203 return d->status;
never executed: return d->status;
0
1204}-
1205-
1206/*!-
1207 \enum QZipWriter::CompressionPolicy-
1208-
1209 \value AlwaysCompress A file that is added is compressed.-
1210 \value NeverCompress A file that is added will be stored without changes.-
1211 \value AutoCompress A file that is added will be compressed only if that will give a smaller file.-
1212*/-
1213-
1214/*!-
1215 Sets the policy for compressing newly added files to the new \a policy.-
1216-
1217 \note the default policy is AlwaysCompress-
1218-
1219 \sa compressionPolicy()-
1220 \sa addFile()-
1221*/-
1222void QZipWriter::setCompressionPolicy(CompressionPolicy policy)-
1223{-
1224 d->compressionPolicy = policy;-
1225}
never executed: end of block
0
1226-
1227/*!-
1228 Returns the currently set compression policy.-
1229 \sa setCompressionPolicy()-
1230 \sa addFile()-
1231*/-
1232QZipWriter::CompressionPolicy QZipWriter::compressionPolicy() const-
1233{-
1234 return d->compressionPolicy;
never executed: return d->compressionPolicy;
0
1235}-
1236-
1237/*!-
1238 Sets the permissions that will be used for newly added files.-
1239-
1240 \note the default permissions are QFile::ReadOwner | QFile::WriteOwner.-
1241-
1242 \sa creationPermissions()-
1243 \sa addFile()-
1244*/-
1245void QZipWriter::setCreationPermissions(QFile::Permissions permissions)-
1246{-
1247 d->permissions = permissions;-
1248}
never executed: end of block
0
1249-
1250/*!-
1251 Returns the currently set creation permissions.-
1252-
1253 \sa setCreationPermissions()-
1254 \sa addFile()-
1255*/-
1256QFile::Permissions QZipWriter::creationPermissions() const-
1257{-
1258 return d->permissions;
never executed: return d->permissions;
0
1259}-
1260-
1261/*!-
1262 Add a file to the archive with \a data as the file contents.-
1263 The file will be stored in the archive using the \a fileName which-
1264 includes the full path in the archive.-
1265-
1266 The new file will get the file permissions based on the current-
1267 creationPermissions and it will be compressed using the zip compression-
1268 based on the current compression policy.-
1269-
1270 \sa setCreationPermissions()-
1271 \sa setCompressionPolicy()-
1272*/-
1273void QZipWriter::addFile(const QString &fileName, const QByteArray &data)-
1274{-
1275 d->addEntry(QZipWriterPrivate::File, QDir::fromNativeSeparators(fileName), data);-
1276}
never executed: end of block
0
1277-
1278/*!-
1279 Add a file to the archive with \a device as the source of the contents.-
1280 The contents returned from QIODevice::readAll() will be used as the-
1281 filedata.-
1282 The file will be stored in the archive using the \a fileName which-
1283 includes the full path in the archive.-
1284*/-
1285void QZipWriter::addFile(const QString &fileName, QIODevice *device)-
1286{-
1287 Q_ASSERT(device);-
1288 QIODevice::OpenMode mode = device->openMode();-
1289 bool opened = false;-
1290 if ((mode & QIODevice::ReadOnly) == 0) {
(mode & QIODev...ReadOnly) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1291 opened = true;-
1292 if (! device->open(QIODevice::ReadOnly)) {
! device->open...ice::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
1293 d->status = FileOpenError;-
1294 return;
never executed: return;
0
1295 }-
1296 }
never executed: end of block
0
1297 d->addEntry(QZipWriterPrivate::File, QDir::fromNativeSeparators(fileName), device->readAll());-
1298 if (opened)
openedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1299 device->close();
never executed: device->close();
0
1300}
never executed: end of block
0
1301-
1302/*!-
1303 Create a new directory in the archive with the specified \a dirName and-
1304 the \a permissions;-
1305*/-
1306void QZipWriter::addDirectory(const QString &dirName)-
1307{-
1308 QString name(QDir::fromNativeSeparators(dirName));-
1309 // separator is mandatory-
1310 if (!name.endsWith(QLatin1Char('/')))
!name.endsWith...tin1Char('/'))Description
TRUEnever evaluated
FALSEnever evaluated
0
1311 name.append(QLatin1Char('/'));
never executed: name.append(QLatin1Char('/'));
0
1312 d->addEntry(QZipWriterPrivate::Directory, name, QByteArray());-
1313}
never executed: end of block
0
1314-
1315/*!-
1316 Create a new symbolic link in the archive with the specified \a dirName-
1317 and the \a permissions;-
1318 A symbolic link contains the destination (relative) path and name.-
1319*/-
1320void QZipWriter::addSymLink(const QString &fileName, const QString &destination)-
1321{-
1322 d->addEntry(QZipWriterPrivate::Symlink, QDir::fromNativeSeparators(fileName), QFile::encodeName(destination));-
1323}
never executed: end of block
0
1324-
1325/*!-
1326 Closes the zip file.-
1327*/-
1328void QZipWriter::close()-
1329{-
1330 if (!(d->device->openMode() & QIODevice::WriteOnly)) {
!(d->device->o...ce::WriteOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
1331 d->device->close();-
1332 return;
never executed: return;
0
1333 }-
1334-
1335 //qDebug("QZip::close writing directory, %d entries", d->fileHeaders.size());-
1336 d->device->seek(d->start_of_directory);-
1337 // write new directory-
1338 for (int i = 0; i < d->fileHeaders.size(); ++i) {
i < d->fileHeaders.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1339 const FileHeader &header = d->fileHeaders.at(i);-
1340 d->device->write((const char *)&header.h, sizeof(CentralFileHeader));-
1341 d->device->write(header.file_name);-
1342 d->device->write(header.extra_field);-
1343 d->device->write(header.file_comment);-
1344 }
never executed: end of block
0
1345 int dir_size = d->device->pos() - d->start_of_directory;-
1346 // write end of directory-
1347 EndOfDirectory eod;-
1348 memset(&eod, 0, sizeof(EndOfDirectory));-
1349 writeUInt(eod.signature, 0x06054b50);-
1350 //uchar this_disk[2];-
1351 //uchar start_of_directory_disk[2];-
1352 writeUShort(eod.num_dir_entries_this_disk, d->fileHeaders.size());-
1353 writeUShort(eod.num_dir_entries, d->fileHeaders.size());-
1354 writeUInt(eod.directory_size, dir_size);-
1355 writeUInt(eod.dir_start_offset, d->start_of_directory);-
1356 writeUShort(eod.comment_length, d->comment.length());-
1357-
1358 d->device->write((const char *)&eod, sizeof(EndOfDirectory));-
1359 d->device->write(d->comment);-
1360 d->device->close();-
1361}
never executed: end of block
0
1362-
1363QT_END_NAMESPACE-
1364-
1365#endif // QT_NO_TEXTODFWRITER-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9