MythTV  master
unzip.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Filename: unzip.cpp
3 ** Last updated [dd/mm/yyyy]: 07/09/2008
4 **
5 ** pkzip 2.0 decompression.
6 **
7 ** Some of the code has been inspired by other open source projects,
8 ** (mainly Info-Zip and Gilles Vollant's minizip).
9 ** Compression and decompression actually uses the zlib library.
10 **
11 ** Copyright (C) 2007-2008 Angius Fabrizio. All rights reserved.
12 **
13 ** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
14 **
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
17 ** Foundation and appearing in the file LICENSE.GPL included in the
18 ** packaging of this file.
19 **
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.
22 **
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.
25 **
26 **********************************************************************/
27 
28 #include "unzip.h"
29 #include "unzip_p.h"
30 #include "zipentry_p.h"
31 
32 #include <QString>
33 #include <QStringList>
34 #include <QDir>
35 #include <QFile>
36 #include <QCoreApplication>
37 
38 // You can remove this #include if you replace the qDebug() statements.
39 #include <QtDebug>
40 
119 #define UNZIP_LOCAL_HEADER_SIZE 26
121 #define UNZIP_CD_ENTRY_SIZE_NS 42
123 #define UNZIP_DD_SIZE 12
125 #define UNZIP_EOCD_SIZE 22
127 #define UNZIP_LOCAL_ENC_HEADER_SIZE 12
129 
130 // Some offsets inside a CD record (excluding signature)
131 #define UNZIP_CD_OFF_VERSION 0
132 #define UNZIP_CD_OFF_GPFLAG 4
133 #define UNZIP_CD_OFF_CMETHOD 6
134 #define UNZIP_CD_OFF_MODT 8
135 #define UNZIP_CD_OFF_MODD 10
136 #define UNZIP_CD_OFF_CRC32 12
137 #define UNZIP_CD_OFF_CSIZE 16
138 #define UNZIP_CD_OFF_USIZE 20
139 #define UNZIP_CD_OFF_NAMELEN 24
140 #define UNZIP_CD_OFF_XLEN 26
141 #define UNZIP_CD_OFF_COMMLEN 28
142 #define UNZIP_CD_OFF_LHOFFSET 38
143 
144 // Some offsets inside a local header record (excluding signature)
145 #define UNZIP_LH_OFF_VERSION 0
146 #define UNZIP_LH_OFF_GPFLAG 2
147 #define UNZIP_LH_OFF_CMETHOD 4
148 #define UNZIP_LH_OFF_MODT 6
149 #define UNZIP_LH_OFF_MODD 8
150 #define UNZIP_LH_OFF_CRC32 10
151 #define UNZIP_LH_OFF_CSIZE 14
152 #define UNZIP_LH_OFF_USIZE 18
153 #define UNZIP_LH_OFF_NAMELEN 22
154 #define UNZIP_LH_OFF_XLEN 24
155 
156 // Some offsets inside a data descriptor record (excluding signature)
157 #define UNZIP_DD_OFF_CRC32 0
158 #define UNZIP_DD_OFF_CSIZE 4
159 #define UNZIP_DD_OFF_USIZE 8
160 
161 // Some offsets inside a EOCD record
162 #define UNZIP_EOCD_OFF_ENTRIES 6
163 #define UNZIP_EOCD_OFF_CDOFF 12
164 #define UNZIP_EOCD_OFF_COMMLEN 16
165 
172 #define UNZIP_VERSION 0x1B
173 #define UNZIP_VERSION_STRICT 0x14
175 
177 #define CRC32(c, b) crcTable[((int)(c)^(b)) & 0xff] ^ ((c) >> 8)
178 
180 #define UNZIP_CHECK_FOR_VALID_DATA \
181  {\
182  if (headers != nullptr)\
183  {\
184  qDebug() << "Corrupted zip archive. Some files might be extracted.";\
185  ec = headers->empty() ? UnZip::Corrupted : UnZip::PartiallyCorrupted;\
186  break;\
187  }\
188  delete device; \
189  device = nullptr; \
190  qDebug() << "Corrupted or invalid zip archive"; \
191  ec = UnZip::Corrupted; \
192  break; \
193  }
194 
195 
196 /************************************************************************
197  Public interface
198 *************************************************************************/
199 
204 {
205  d = new UnzipPrivate;
206 }
207 
212 {
213  closeArchive();
214  delete d;
215 }
216 
220 bool UnZip::isOpen() const
221 {
222  return d->device != nullptr;
223 }
224 
229 {
230  auto* file = new QFile(filename);
231 
232  if (!file->exists()) {
233  delete file;
234  return UnZip::FileNotFound;
235  }
236 
237  if (!file->open(QIODevice::ReadOnly)) {
238  delete file;
239  return UnZip::OpenFailed;
240  }
241 
242  return openArchive(file);
243 }
244 
251 {
252  if (device == nullptr)
253  {
254  qDebug() << "Invalid device.";
255  return UnZip::InvalidDevice;
256  }
257 
258  return d->openArchive(device);
259 }
260 
265 {
266  d->closeArchive();
267 }
268 
269 QString UnZip::archiveComment() const
270 {
271  if (d->device == nullptr)
272  return QString();
273  return d->comment;
274 }
275 
280 {
281  switch (c)
282  {
283  case Ok: return QCoreApplication::translate("UnZip", "ZIP operation completed successfully."); break;
284  case ZlibInit: return QCoreApplication::translate("UnZip", "Failed to initialize or load zlib library."); break;
285  case ZlibError: return QCoreApplication::translate("UnZip", "zlib library error."); break;
286  case OpenFailed: return QCoreApplication::translate("UnZip", "Unable to create or open file."); break;
287  case PartiallyCorrupted: return QCoreApplication::translate("UnZip", "Partially corrupted archive. Some files might be extracted."); break;
288  case Corrupted: return QCoreApplication::translate("UnZip", "Corrupted archive."); break;
289  case WrongPassword: return QCoreApplication::translate("UnZip", "Wrong password."); break;
290  case NoOpenArchive: return QCoreApplication::translate("UnZip", "No archive has been created yet."); break;
291  case FileNotFound: return QCoreApplication::translate("UnZip", "File or directory does not exist."); break;
292  case ReadFailed: return QCoreApplication::translate("UnZip", "File read error."); break;
293  case WriteFailed: return QCoreApplication::translate("UnZip", "File write error."); break;
294  case SeekFailed: return QCoreApplication::translate("UnZip", "File seek error."); break;
295  case CreateDirFailed: return QCoreApplication::translate("UnZip", "Unable to create a directory."); break;
296  case InvalidDevice: return QCoreApplication::translate("UnZip", "Invalid device."); break;
297  case InvalidArchive: return QCoreApplication::translate("UnZip", "Invalid or incompatible zip archive."); break;
298  case HeaderConsistencyError: return QCoreApplication::translate("UnZip", "Inconsistent headers. Archive might be corrupted."); break;
299  default: ;
300  }
301 
302  return QCoreApplication::translate("UnZip", "Unknown error.");
303 }
304 
308 bool UnZip::contains(const QString& file) const
309 {
310  if (d->headers == nullptr)
311  return false;
312 
313  return d->headers->contains(file);
314 }
315 
319 QStringList UnZip::fileList() const
320 {
321  return d->headers == nullptr ? QStringList() : d->headers->keys();
322 }
323 
327 QList<UnZip::ZipEntry> UnZip::entryList() const
328 {
329  QList<UnZip::ZipEntry> list;
330 
331  if (d->headers != nullptr)
332  {
333  for (QMap<QString,ZipEntryP*>::ConstIterator it = d->headers->constBegin(); it != d->headers->constEnd(); ++it)
334  {
335  const ZipEntryP* entry = it.value();
336  Q_ASSERT(entry != nullptr);
337 
338  ZipEntry z;
339 
340  z.filename = it.key();
341  if (!entry->comment.isEmpty())
342  z.comment = entry->comment;
343  z.compressedSize = entry->szComp;
344  z.uncompressedSize = entry->szUncomp;
345  z.crc32 = entry->crc;
347 
348  z.compression = entry->compMethod == 0 ? NoCompression : entry->compMethod == 8 ? Deflated : UnknownCompression;
349  z.type = z.filename.endsWith("/") ? Directory : File;
350 
351  z.encrypted = entry->isEncrypted();
352 
353  list.append(z);
354  }
355  }
356 
357  return list;
358 }
359 
363 UnZip::ErrorCode UnZip::extractAll(const QString& dirname, ExtractionOptions options)
364 {
365  return extractAll(QDir(dirname), options);
366 }
367 
371 UnZip::ErrorCode UnZip::extractAll(const QDir& dir, ExtractionOptions options)
372 {
373  // this should only happen if we didn't call openArchive() yet
374  if (d->device == nullptr)
375  return NoOpenArchive;
376 
377  if (d->headers == nullptr)
378  return Ok;
379 
380  bool end = false;
381  for (QMap<QString,ZipEntryP*>::Iterator itr = d->headers->begin(); itr != d->headers->end(); ++itr)
382  {
383  ZipEntryP* entry = itr.value();
384  Q_ASSERT(entry != nullptr);
385 
386  if ((entry->isEncrypted()) && d->skipAllEncrypted)
387  continue;
388 
389  switch (d->extractFile(itr.key(), *entry, dir, options))
390  {
391  case Corrupted:
392  qDebug() << "Removing corrupted entry" << itr.key();
393  d->headers->erase(itr++);
394  if (itr == d->headers->end())
395  end = true;
396  break;
397  case CreateDirFailed:
398  case Skip:
399  break;
400  case SkipAll:
401  d->skipAllEncrypted = true;
402  break;
403  default:
404  ;
405  }
406 
407  if (end)
408  break;
409  }
410 
411  return Ok;
412 }
413 
417 UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QString& dirname, ExtractionOptions options)
418 {
419  return extractFile(filename, QDir(dirname), options);
420 }
421 
425 UnZip::ErrorCode UnZip::extractFile(const QString& filename, const QDir& dir, ExtractionOptions options)
426 {
427  QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename);
428  if (itr != d->headers->end())
429  {
430  ZipEntryP* entry = itr.value();
431  Q_ASSERT(entry != nullptr);
432  return d->extractFile(itr.key(), *entry, dir, options);
433  }
434 
435  return FileNotFound;
436 }
437 
441 UnZip::ErrorCode UnZip::extractFile(const QString& filename, QIODevice* dev, ExtractionOptions options)
442 {
443  if (dev == nullptr)
444  return InvalidDevice;
445 
446  QMap<QString,ZipEntryP*>::Iterator itr = d->headers->find(filename);
447  if (itr != d->headers->end()) {
448  ZipEntryP* entry = itr.value();
449  Q_ASSERT(entry != nullptr);
450  return d->extractFile(itr.key(), *entry, dev, options);
451  }
452 
453  return FileNotFound;
454 }
455 
460 UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options)
461 {
462  QDir dir(dirname);
463 
464  for (QStringList::ConstIterator itr = filenames.constBegin(); itr != filenames.constEnd(); ++itr)
465  {
466  ErrorCode ec = extractFile(*itr, dir, options);
467  if (ec == FileNotFound)
468  continue;
469  if (ec != Ok)
470  return ec;
471  }
472 
473  return Ok;
474 }
475 
480 UnZip::ErrorCode UnZip::extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options)
481 {
482 
483  for (QStringList::ConstIterator itr = filenames.constBegin(); itr != filenames.constEnd(); ++itr)
484  {
485  ErrorCode ec = extractFile(*itr, dir, options);
486  if (ec == FileNotFound)
487  continue;
488  if (ec != Ok)
489  return ec;
490  }
491 
492  return Ok;
493 }
494 
498 void UnZip::setPassword(const QString& pwd)
499 {
500  d->password = pwd;
501 }
502 
507 {
510  type = File;
511  encrypted = false;
512 }
513 
514 
515 /************************************************************************
516  Private interface
517 *************************************************************************/
518 
521 {
522  uBuffer = (unsigned char*) buffer1;
523  crcTable = (const quint32*) get_crc_table();
524 }
525 
528 {
529  Q_ASSERT(dev != nullptr);
530 
531  if (device != nullptr)
532  closeArchive();
533 
534  device = dev;
535 
536  if (!(device->isOpen() || device->open(QIODevice::ReadOnly)))
537  {
538  delete device;
539  device = nullptr;
540 
541  qDebug() << "Unable to open device for reading";
542  return UnZip::OpenFailed;
543  }
544 
545  UnZip::ErrorCode ec = seekToCentralDirectory();
546  if (ec != UnZip::Ok)
547  {
548  closeArchive();
549  return ec;
550  }
551 
553  if (cdEntryCount == 0)
554  {
555  return UnZip::Ok;
556  }
557 
558  while (true)
559  {
560  if (device->read(buffer1, 4) != 4)
562 
563  if (! (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x01 && buffer1[3] == 0x02) )
564  break;
565 
566  if ( (ec = parseCentralDirectoryRecord()) != UnZip::Ok )
567  break;
568  }
569 
570  if (ec != UnZip::Ok)
571  closeArchive();
572 
573  return ec;
574 }
575 
576 /*
577  \internal Parses a local header record and makes some consistency check
578  with the information stored in the Central Directory record for this entry
579  that has been previously parsed.
580  \todo Optional consistency check (as a ExtractionOptions flag)
581 
582  local file header signature 4 bytes (0x04034b50)
583  version needed to extract 2 bytes
584  general purpose bit flag 2 bytes
585  compression method 2 bytes
586  last mod file time 2 bytes
587  last mod file date 2 bytes
588  crc-32 4 bytes
589  compressed size 4 bytes
590  uncompressed size 4 bytes
591  file name length 2 bytes
592  extra field length 2 bytes
593 
594  file name (variable size)
595  extra field (variable size)
596 */
598 {
599  if (!device->seek(entry.lhOffset))
600  return UnZip::SeekFailed;
601 
602  // Test signature
603  if (device->read(buffer1, 4) != 4)
604  return UnZip::ReadFailed;
605 
606  if ((buffer1[0] != 'P') || (buffer1[1] != 'K') || (buffer1[2] != 0x03) || (buffer1[3] != 0x04))
607  return UnZip::InvalidArchive;
608 
609  if (device->read(buffer1, UNZIP_LOCAL_HEADER_SIZE) != UNZIP_LOCAL_HEADER_SIZE)
610  return UnZip::ReadFailed;
611 
612  /*
613  Check 3rd general purpose bit flag.
614 
615  "bit 3: If this bit is set, the fields crc-32, compressed size
616  and uncompressed size are set to zero in the local
617  header. The correct values are put in the data descriptor
618  immediately following the compressed data."
619  */
620  bool hasDataDescriptor = entry.hasDataDescriptor();
621 
622  bool checkFailed = entry.compMethod != getUShort(uBuffer, UNZIP_LH_OFF_CMETHOD);
623  if (!checkFailed)
624  checkFailed = entry.gpFlag[0] != uBuffer[UNZIP_LH_OFF_GPFLAG];
625  if (!checkFailed)
626  checkFailed = entry.gpFlag[1] != uBuffer[UNZIP_LH_OFF_GPFLAG + 1];
627  if (!checkFailed)
628  checkFailed = entry.modTime[0] != uBuffer[UNZIP_LH_OFF_MODT];
629  if (!checkFailed)
630  checkFailed = entry.modTime[1] != uBuffer[UNZIP_LH_OFF_MODT + 1];
631  if (!checkFailed)
632  checkFailed = entry.modDate[0] != uBuffer[UNZIP_LH_OFF_MODD];
633  if (!checkFailed)
634  checkFailed = entry.modDate[1] != uBuffer[UNZIP_LH_OFF_MODD + 1];
635  if (!hasDataDescriptor)
636  {
637  if (!checkFailed)
638  checkFailed = entry.crc != getULong(uBuffer, UNZIP_LH_OFF_CRC32);
639  if (!checkFailed)
640  checkFailed = entry.szComp != getULong(uBuffer, UNZIP_LH_OFF_CSIZE);
641  if (!checkFailed)
642  checkFailed = entry.szUncomp != getULong(uBuffer, UNZIP_LH_OFF_USIZE);
643  }
644 
645  if (checkFailed)
647 
648  // Check filename
649  quint16 szName = getUShort(uBuffer, UNZIP_LH_OFF_NAMELEN);
650  if (szName == 0)
652 
653  if (device->read(buffer2, szName) != szName)
654  return UnZip::ReadFailed;
655 
656  QString filename = QString::fromLatin1(buffer2, szName);
657  if (filename != path)
658  {
659  qDebug() << "Filename in local header mismatches.";
661  }
662 
663  // Skip extra field
664  quint16 szExtra = getUShort(uBuffer, UNZIP_LH_OFF_XLEN);
665  if (szExtra != 0)
666  {
667  if (!device->seek(device->pos() + szExtra))
668  return UnZip::SeekFailed;
669  }
670 
671  entry.dataOffset = device->pos();
672 
673  if (hasDataDescriptor)
674  {
675  /*
676  The data descriptor has this OPTIONAL signature: PK\7\8
677  We try to skip the compressed data relying on the size set in the
678  Central Directory record.
679  */
680  if (!device->seek(device->pos() + entry.szComp))
681  return UnZip::SeekFailed;
682 
683  // Read 4 bytes and check if there is a data descriptor signature
684  if (device->read(buffer2, 4) != 4)
685  return UnZip::ReadFailed;
686 
687  bool hasSignature = buffer2[0] == 'P' && buffer2[1] == 'K' && buffer2[2] == 0x07 && buffer2[3] == 0x08;
688  if (hasSignature)
689  {
690  if (device->read(buffer2, UNZIP_DD_SIZE) != UNZIP_DD_SIZE)
691  return UnZip::ReadFailed;
692  }
693  else
694  {
695  if (device->read(buffer2 + 4, UNZIP_DD_SIZE - 4) != UNZIP_DD_SIZE - 4)
696  return UnZip::ReadFailed;
697  }
698 
699  // DD: crc, compressed size, uncompressed size
700  if (
701  entry.crc != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CRC32) ||
702  entry.szComp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CSIZE) ||
703  entry.szUncomp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_USIZE)
704  )
706  }
707 
708  return UnZip::Ok;
709 }
710 
733 {
734  qint64 length = device->size();
735  qint64 offset = length - UNZIP_EOCD_SIZE;
736 
737  if (length < UNZIP_EOCD_SIZE)
738  return UnZip::InvalidArchive;
739 
740  if (!device->seek( offset ))
741  return UnZip::SeekFailed;
742 
743  if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
744  return UnZip::ReadFailed;
745 
746  bool eocdFound = (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x05 && buffer1[3] == 0x06);
747 
748  if (eocdFound)
749  {
750  // Zip file has no comment (the only variable length field in the EOCD record)
751  eocdOffset = offset;
752  }
753  else
754  {
755  char* p = nullptr;
756 
757  offset -= UNZIP_EOCD_SIZE;
758 
759  if (offset <= 0)
760  return UnZip::InvalidArchive;
761 
762  if (!device->seek( offset ))
763  return UnZip::SeekFailed;
764 
765  while (device->read(buffer1, UNZIP_EOCD_SIZE) >= 0)
766  {
767  if ( (p = strstr(buffer1, "PK\5\6")) != nullptr)
768  {
769  // Seek to the start of the EOCD record so we can read it fully
770  // Yes... we could simply read the missing bytes and append them to the buffer
771  // but this is far easier so heck it!
772  device->seek( offset + (p - buffer1) );
773  eocdFound = true;
774  eocdOffset = offset + (p - buffer1);
775 
776  // Read EOCD record
777  if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
778  return UnZip::ReadFailed;
779 
780  break;
781  }
782 
783  // TODO: This is very slow and only a temporary bug fix. Need some pattern matching algorithm here.
784  offset -= 1 /*UNZIP_EOCD_SIZE*/;
785  if (offset <= 0)
786  return UnZip::InvalidArchive;
787 
788  if (!device->seek( offset ))
789  return UnZip::SeekFailed;
790  }
791  }
792 
793  if (!eocdFound)
794  return UnZip::InvalidArchive;
795 
796  // Parse EOCD to locate CD offset
797  offset = getULong((const unsigned char*)buffer1, UNZIP_EOCD_OFF_CDOFF + 4);
798 
799  cdOffset = offset;
800 
801  cdEntryCount = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_ENTRIES + 4);
802 
803  quint16 commentLength = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_COMMLEN + 4);
804  if (commentLength != 0)
805  {
806  QByteArray c = device->read(commentLength);
807  if (c.count() != commentLength)
808  return UnZip::ReadFailed;
809 
810  comment = c;
811  }
812 
813  // Seek to the start of the CD record
814  if (!device->seek( cdOffset ))
815  return UnZip::SeekFailed;
816 
817  return UnZip::Ok;
818 }
819 
857 {
858  // Read CD record
859  if (device->read(buffer1, UNZIP_CD_ENTRY_SIZE_NS) != UNZIP_CD_ENTRY_SIZE_NS)
860  return UnZip::ReadFailed;
861 
862  bool skipEntry = false;
863 
864  // Get compression type so we can skip non compatible algorithms
865  quint16 compMethod = getUShort(uBuffer, UNZIP_CD_OFF_CMETHOD);
866 
867  // Get variable size fields length so we can skip the whole record
868  // if necessary
869  quint16 szName = getUShort(uBuffer, UNZIP_CD_OFF_NAMELEN);
870  quint16 szExtra = getUShort(uBuffer, UNZIP_CD_OFF_XLEN);
871  quint16 szComment = getUShort(uBuffer, UNZIP_CD_OFF_COMMLEN);
872 
873  quint32 skipLength = szName + szExtra + szComment;
874 
876 
877  if ((compMethod != 0) && (compMethod != 8))
878  {
879  qDebug() << "Unsupported compression method. Skipping file.";
880  skipEntry = true;
881  }
882 
883  // Header parsing may be a problem if version is bigger than UNZIP_VERSION
884  if (!skipEntry && buffer1[UNZIP_CD_OFF_VERSION] > UNZIP_VERSION)
885  {
886  qDebug() << "Unsupported PKZip version. Skipping file.";
887  skipEntry = true;
888  }
889 
890  if (!skipEntry && szName == 0)
891  {
892  qDebug() << "Skipping file with no name.";
893  skipEntry = true;
894  }
895 
896  if (!skipEntry && device->read(buffer2, szName) != szName)
897  {
898  ec = UnZip::ReadFailed;
899  skipEntry = true;
900  }
901 
902  if (skipEntry)
903  {
904  if (ec == UnZip::Ok)
905  {
906  if (!device->seek( device->pos() + skipLength ))
907  ec = UnZip::SeekFailed;
908 
909  unsupportedEntryCount++;
910  }
911 
912  return ec;
913  }
914 
915  QString filename = QString::fromLatin1(buffer2, szName);
916 
917  auto* h = new ZipEntryP;
918  h->compMethod = compMethod;
919 
920  h->gpFlag[0] = buffer1[UNZIP_CD_OFF_GPFLAG];
921  h->gpFlag[1] = buffer1[UNZIP_CD_OFF_GPFLAG + 1];
922 
923  h->modTime[0] = buffer1[UNZIP_CD_OFF_MODT];
924  h->modTime[1] = buffer1[UNZIP_CD_OFF_MODT + 1];
925 
926  h->modDate[0] = buffer1[UNZIP_CD_OFF_MODD];
927  h->modDate[1] = buffer1[UNZIP_CD_OFF_MODD + 1];
928 
929  h->crc = getULong(uBuffer, UNZIP_CD_OFF_CRC32);
930  h->szComp = getULong(uBuffer, UNZIP_CD_OFF_CSIZE);
931  h->szUncomp = getULong(uBuffer, UNZIP_CD_OFF_USIZE);
932 
933  // Skip extra field (if any)
934  if (szExtra != 0)
935  {
936  if (!device->seek( device->pos() + szExtra ))
937  {
938  delete h;
939  return UnZip::SeekFailed;
940  }
941  }
942 
943  // Read comment field (if any)
944  if (szComment != 0)
945  {
946  if (device->read(buffer2, szComment) != szComment)
947  {
948  delete h;
949  return UnZip::ReadFailed;
950  }
951 
952  h->comment = QString::fromLatin1(buffer2, szComment);
953  }
954 
955  h->lhOffset = getULong(uBuffer, UNZIP_CD_OFF_LHOFFSET);
956 
957  if (headers == nullptr)
958  headers = new QMap<QString, ZipEntryP*>();
959  headers->insert(filename, h);
960 
961  return UnZip::Ok;
962 }
963 
966 {
967  if (device == nullptr)
968  return;
969 
970  skipAllEncrypted = false;
971 
972  if (headers != nullptr)
973  {
974  qDeleteAll(*headers);
975  delete headers;
976  headers = nullptr;
977  }
978 
979  delete device; device = nullptr;
980 
981  cdOffset = eocdOffset = 0;
982  cdEntryCount = 0;
983  unsupportedEntryCount = 0;
984 
985  comment.clear();
986 }
987 
989 UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options)
990 {
991  QString name(path);
992  QString dirname;
993  QString directory;
994 
995  int pos = name.lastIndexOf('/');
996 
997  // This entry is for a directory
998  if (pos == name.length() - 1)
999  {
1000  if (options.testFlag(UnZip::SkipPaths))
1001  return UnZip::Ok;
1002 
1003  directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(name));
1004  if (!createDirectory(directory))
1005  {
1006  qDebug() << QString("Unable to create directory: %1").arg(directory);
1007  return UnZip::CreateDirFailed;
1008  }
1009 
1010  return UnZip::Ok;
1011  }
1012 
1013  // Extract path from entry
1014  if (pos > 0)
1015  {
1016  // get directory part
1017  dirname = name.left(pos);
1018  if (options.testFlag(UnZip::SkipPaths))
1019  {
1020  directory = dir.absolutePath();
1021  }
1022  else
1023  {
1024  directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(dirname));
1025  if (!createDirectory(directory))
1026  {
1027  qDebug() << QString("Unable to create directory: %1").arg(directory);
1028  return UnZip::CreateDirFailed;
1029  }
1030  }
1031  name = name.right(name.length() - pos - 1);
1032  } else directory = dir.absolutePath();
1033 
1034  name = QString("%1/%2").arg(directory).arg(name);
1035 
1036  QFile outFile(name);
1037 
1038  if (!outFile.open(QIODevice::WriteOnly))
1039  {
1040  qDebug() << QString("Unable to open %1 for writing").arg(name);
1041  return UnZip::OpenFailed;
1042  }
1043 
1045 
1046  UnZip::ErrorCode ec = extractFile(path, entry, &outFile, options);
1047 
1048  outFile.close();
1049 
1050  if (ec != UnZip::Ok)
1051  {
1052  if (!outFile.remove())
1053  qDebug() << QString("Unable to remove corrupted file: %1").arg(name);
1054  }
1055 
1056  return ec;
1057 }
1058 
1060 UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, QIODevice* dev, UnZip::ExtractionOptions options)
1061 {
1062  Q_UNUSED(options);
1063  Q_ASSERT(dev != nullptr);
1064 
1065  if (!entry.lhEntryChecked)
1066  {
1067  UnZip::ErrorCode ec = parseLocalHeaderRecord(path, entry);
1068  entry.lhEntryChecked = true;
1069 
1070  if (ec != UnZip::Ok)
1071  return ec;
1072  }
1073 
1074  if (!device->seek(entry.dataOffset))
1075  return UnZip::SeekFailed;
1076 
1077  // Encryption keys
1078  keyset keys { 0 };
1079 
1080  if (entry.isEncrypted())
1081  {
1082  UnZip::ErrorCode e = testPassword(keys, path, entry);
1083  if (e != UnZip::Ok)
1084  {
1085  qDebug() << QString("Unable to decrypt %1").arg(path);
1086  return e;
1087  }
1088  entry.szComp -= UNZIP_LOCAL_ENC_HEADER_SIZE; // remove encryption header size
1089  }
1090 
1091  if (entry.szComp == 0)
1092  {
1093  if (entry.crc != 0)
1094  return UnZip::Corrupted;
1095 
1096  return UnZip::Ok;
1097  }
1098 
1099  uInt rep = entry.szComp / UNZIP_READ_BUFFER;
1100  uInt rem = entry.szComp % UNZIP_READ_BUFFER;
1101  uInt cur = 0;
1102 
1103  // extract data
1104  qint64 read = 0;
1105  quint64 tot = 0;
1106 
1107  quint32 myCRC = crc32(0L, Z_NULL, 0);
1108 
1109  if (entry.compMethod == 0)
1110  {
1111  while ( (read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem)) > 0 )
1112  {
1113  if (entry.isEncrypted())
1114  decryptBytes(keys, buffer1, read);
1115 
1116  myCRC = crc32(myCRC, uBuffer, read);
1117 
1118  if (dev->write(buffer1, read) != read)
1119  return UnZip::WriteFailed;
1120 
1121  cur++;
1122  tot += read;
1123 
1124  if (tot == entry.szComp)
1125  break;
1126  }
1127 
1128  if (read < 0)
1129  return UnZip::ReadFailed;
1130  }
1131  else if (entry.compMethod == 8)
1132  {
1133  /* Allocate inflate state */
1134  z_stream zstr;
1135  zstr.zalloc = Z_NULL;
1136  zstr.zfree = Z_NULL;
1137  zstr.opaque = Z_NULL;
1138  zstr.next_in = Z_NULL;
1139  zstr.avail_in = 0;
1140 
1141  int zret = Z_OK;
1142 
1143  // Use inflateInit2 with negative windowBits to get raw decompression
1144  if (inflateInit2_(&zstr, -MAX_WBITS, ZLIB_VERSION, sizeof(z_stream)) != Z_OK )
1145  return UnZip::ZlibError;
1146 
1147  int szDecomp = 0;
1148 
1149  // Decompress until deflate stream ends or end of file
1150  do
1151  {
1152  read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem);
1153  if (read == 0)
1154  break;
1155  if (read < 0)
1156  {
1157  (void)inflateEnd(&zstr);
1158  return UnZip::ReadFailed;
1159  }
1160 
1161  if (entry.isEncrypted())
1162  decryptBytes(keys, buffer1, read);
1163 
1164  cur++;
1165  tot += read;
1166 
1167  zstr.avail_in = (uInt) read;
1168  zstr.next_in = (Bytef*) buffer1;
1169 
1170 
1171  // Run inflate() on input until output buffer not full
1172  do {
1173  zstr.avail_out = UNZIP_READ_BUFFER;
1174  zstr.next_out = (Bytef*) buffer2;;
1175 
1176  zret = inflate(&zstr, Z_NO_FLUSH);
1177 
1178  switch (zret) {
1179  case Z_NEED_DICT:
1180  case Z_DATA_ERROR:
1181  case Z_MEM_ERROR:
1182  inflateEnd(&zstr);
1183  return UnZip::WriteFailed;
1184  default:
1185  ;
1186  }
1187 
1188  szDecomp = UNZIP_READ_BUFFER - zstr.avail_out;
1189  if (dev->write(buffer2, szDecomp) != szDecomp)
1190  {
1191  inflateEnd(&zstr);
1192  return UnZip::ZlibError;
1193  }
1194 
1195  myCRC = crc32(myCRC, (const Bytef*) buffer2, szDecomp);
1196 
1197  } while (zstr.avail_out == 0);
1198 
1199  }
1200  while (zret != Z_STREAM_END);
1201 
1202  inflateEnd(&zstr);
1203  }
1204 
1205  if (myCRC != entry.crc)
1206  return UnZip::Corrupted;
1207 
1208  return UnZip::Ok;
1209 }
1210 
1212 bool UnzipPrivate::createDirectory(const QString& path)
1213 {
1214  QDir d(path);
1215  if (!d.exists())
1216  {
1217  int sep = path.lastIndexOf("/");
1218  if (sep <= 0) return true;
1219 
1220  if (!createDirectory(path.left(sep)))
1221  return false;
1222 
1223  if (!d.mkdir(path))
1224  {
1225  qDebug() << QString("Unable to create directory: %1").arg(path);
1226  return false;
1227  }
1228  }
1229 
1230  return true;
1231 }
1232 
1236 quint32 UnzipPrivate::getULong(const unsigned char* data, quint32 offset)
1237 {
1238  auto res = (quint32) data[offset];
1239  res |= (((quint32)data[offset+1]) << 8);
1240  res |= (((quint32)data[offset+2]) << 16);
1241  res |= (((quint32)data[offset+3]) << 24);
1242 
1243  return res;
1244 }
1245 
1249 quint64 UnzipPrivate::getULLong(const unsigned char* data, quint32 offset)
1250 {
1251  auto res = (quint64) data[offset];
1252  res |= (((quint64)data[offset+1]) << 8);
1253  res |= (((quint64)data[offset+2]) << 16);
1254  res |= (((quint64)data[offset+3]) << 24);
1255  res |= (((quint64)data[offset+1]) << 32);
1256  res |= (((quint64)data[offset+2]) << 40);
1257  res |= (((quint64)data[offset+3]) << 48);
1258  res |= (((quint64)data[offset+3]) << 56);
1259 
1260  return res;
1261 }
1262 
1266 quint16 UnzipPrivate::getUShort(const unsigned char* data, quint32 offset)
1267 {
1268  return (quint16) data[offset] | (((quint16)data[offset+1]) << 8);
1269 }
1270 
1274 int UnzipPrivate::decryptByte(quint32 key2)
1275 {
1276  quint16 temp = ((quint16)(key2) & 0xffff) | 2;
1277  return ((temp * (temp ^ 1)) >> 8) & 0xff;
1278 }
1279 
1283 void UnzipPrivate::updateKeys(keyset keys, int c) const
1284 {
1285  keys[0] = CRC32(keys[0], c);
1286  keys[1] += keys[0] & 0xff;
1287  keys[1] = keys[1] * 134775813L + 1;
1288  keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24);
1289 }
1290 
1295 void UnzipPrivate::initKeys(const QString& pwd, keyset keys) const
1296 {
1297  keys[0] = 305419896L;
1298  keys[1] = 591751049L;
1299  keys[2] = 878082192L;
1300 
1301  QByteArray pwdBytes = pwd.toLatin1();
1302  int sz = pwdBytes.size();
1303  const char* ascii = pwdBytes.data();
1304 
1305  for (int i=0; i<sz; ++i)
1306  updateKeys(keys, (int)ascii[i]);
1307 }
1308 
1315 {
1316  Q_UNUSED(file);
1317 
1318  // read encryption keys
1319  if (device->read(buffer1, 12) != 12)
1320  return UnZip::Corrupted;
1321 
1322  // Replace this code if you want to i.e. call some dialog and ask the user for a password
1323  initKeys(password, keys);
1324  if (testKeys(header, keys))
1325  return UnZip::Ok;
1326 
1327  return UnZip::Skip;
1328 }
1329 
1333 bool UnzipPrivate::testKeys(const ZipEntryP& header, keyset keys)
1334 {
1335  char lastByte = 0;
1336 
1337  // decrypt encryption header
1338  for (int i=0; i<11; ++i)
1339  updateKeys(keys, buffer1[i] ^ decryptByte(keys[2]));
1340  updateKeys(keys, lastByte = buffer1[11] ^ decryptByte(keys[2]));
1341 
1342  // if there is an extended header (bit in the gp flag) buffer[11] is a byte from the file time
1343  // with no extended header we have to check the crc high-order byte
1344  char c = ((header.gpFlag[0] & 0x08) == 8) ? header.modTime[1] : header.crc >> 24;
1345 
1346  return (lastByte == c);
1347 }
1348 
1352 void UnzipPrivate::decryptBytes(keyset keys, char* buffer, qint64 read) const
1353 {
1354  for (int i=0; i<(int)read; ++i)
1355  updateKeys(keys, buffer[i] ^= decryptByte(keys[2]));
1356 }
1357 
1361 QDateTime UnzipPrivate::convertDateTime(const std::array<uint8_t,2> date, const std::array<uint8_t,2> time)
1362 {
1363  QDateTime dt;
1364 
1365  // Usual PKZip low-byte to high-byte order
1366 
1367  // Date: 7 bits = years from 1980, 4 bits = month, 5 bits = day
1368  quint16 year = (date[1] >> 1) & 127;
1369  quint16 month = ((date[1] << 3) & 14) | ((date[0] >> 5) & 7);
1370  quint16 day = date[0] & 31;
1371 
1372  // Time: 5 bits hour, 6 bits minutes, 5 bits seconds with a 2sec precision
1373  quint16 hour = (time[1] >> 3) & 31;
1374  quint16 minutes = ((time[1] << 3) & 56) | ((time[0] >> 5) & 7);
1375  quint16 seconds = (time[0] & 31) * 2;
1376 
1377  dt = QDateTime(QDate(1980 + year, month, day),
1378  QTime(hour, minutes, seconds), Qt::UTC);
1379  return dt;
1380 }
UnZip::SkipPaths
@ SkipPaths
Ignores paths and extracts all the files to the same directory.
Definition: unzip.h:79
UnZip::NoCompression
@ NoCompression
Definition: unzip.h:85
ZipEntryP::isEncrypted
bool isEncrypted() const
Definition: zipentry_p.h:101
UnzipPrivate::device
QIODevice * device
Definition: unzip_p.h:65
e
QDomElement e
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1420
UNZIP_LH_OFF_CSIZE
#define UNZIP_LH_OFF_CSIZE
Definition: unzip.cpp:151
ZipEntryP::szUncomp
quint32 szUncomp
Definition: zipentry_p.h:96
UnZip::SeekFailed
@ SeekFailed
Definition: unzip.h:65
UnzipPrivate::password
QString password
Definition: unzip_p.h:59
UnZip::ZipEntry::encrypted
bool encrypted
Definition: unzip.h:109
UnZip::ZipEntry::compressedSize
quint32 compressedSize
Definition: unzip.h:100
UnZip::InvalidDevice
@ InvalidDevice
Definition: unzip.h:67
UnzipPrivate::comment
QString comment
Definition: unzip_p.h:84
UnZip::extractFiles
ErrorCode extractFiles(const QStringList &filenames, const QString &dirname, ExtractionOptions options=ExtractPaths)
Definition: unzip.cpp:460
UnzipPrivate::getUShort
static quint16 getUShort(const unsigned char *data, quint32 offset)
Definition: unzip.cpp:1266
ZipEntryP::gpFlag
std::array< uint8_t, 2 > gpFlag
Definition: zipentry_p.h:90
UNZIP_LH_OFF_GPFLAG
#define UNZIP_LH_OFF_GPFLAG
Definition: unzip.cpp:146
UNZIP_CD_OFF_CSIZE
#define UNZIP_CD_OFF_CSIZE
Definition: unzip.cpp:137
ZipEntryP::compMethod
quint16 compMethod
Definition: zipentry_p.h:91
UnZip::ZipEntry::lastModified
QDateTime lastModified
Definition: unzip.h:104
UNZIP_CD_OFF_CMETHOD
#define UNZIP_CD_OFF_CMETHOD
Definition: unzip.cpp:133
discid.disc.read
def read(device=None, features=[])
Definition: disc.py:35
UnZip::ZlibInit
@ ZlibInit
Definition: unzip.h:55
keyset
std::array< quint32, 3 > keyset
Definition: unzip_p.h:47
UnZip::ZipEntry::comment
QString comment
Definition: unzip.h:98
UnZip::WrongPassword
@ WrongPassword
Definition: unzip.h:60
UnzipPrivate::createDirectory
bool createDirectory(const QString &path)
Definition: unzip.cpp:1212
UnzipPrivate::skipAllEncrypted
bool skipAllEncrypted
Definition: unzip_p.h:61
UnZip::fileList
QStringList fileList() const
Definition: unzip.cpp:319
UnzipPrivate::getULLong
static quint64 getULLong(const unsigned char *data, quint32 offset)
Definition: unzip.cpp:1249
UNZIP_DD_OFF_CRC32
#define UNZIP_DD_OFF_CRC32
Definition: unzip.cpp:157
UnzipPrivate::closeArchive
void closeArchive()
Definition: unzip.cpp:965
UNZIP_CD_OFF_LHOFFSET
#define UNZIP_CD_OFF_LHOFFSET
Definition: unzip.cpp:142
UnZip::openArchive
ErrorCode openArchive(const QString &filename)
Definition: unzip.cpp:228
unzip.h
UnZip::OpenFailed
@ OpenFailed
Definition: unzip.h:57
UnZip::extractAll
ErrorCode extractAll(const QString &dirname, ExtractionOptions options=ExtractPaths)
Definition: unzip.cpp:363
UnZip::Deflated
@ Deflated
Definition: unzip.h:85
ZipEntryP
Definition: zipentry_p.h:47
build_compdb.file
file
Definition: build_compdb.py:55
UnzipPrivate::getULong
static quint32 getULong(const unsigned char *data, quint32 offset)
Definition: unzip.cpp:1236
UnzipPrivate
Definition: unzip_p.h:53
UnzipPrivate::decryptBytes
void decryptBytes(keyset keys, char *buffer, qint64 read) const
Definition: unzip.cpp:1352
UNZIP_CD_OFF_MODT
#define UNZIP_CD_OFF_MODT
Definition: unzip.cpp:134
UnZip::setPassword
void setPassword(const QString &pwd)
Definition: unzip.cpp:498
UNZIP_DD_SIZE
#define UNZIP_DD_SIZE
Data descriptor size (excluding signature)
Definition: unzip.cpp:124
UnZip::extractFile
ErrorCode extractFile(const QString &filename, const QString &dirname, ExtractionOptions options=ExtractPaths)
Definition: unzip.cpp:417
UNZIP_READ_BUFFER
#define UNZIP_READ_BUFFER
Definition: unzip_p.h:51
UnZip::closeArchive
void closeArchive()
Definition: unzip.cpp:264
UnZip::ZipEntry::type
FileType type
Definition: unzip.h:107
UnzipPrivate::UnzipPrivate
UnzipPrivate()
Definition: unzip.cpp:520
UNZIP_LOCAL_ENC_HEADER_SIZE
#define UNZIP_LOCAL_ENC_HEADER_SIZE
Local header entry encryption header size.
Definition: unzip.cpp:128
ZipEntryP::hasDataDescriptor
bool hasDataDescriptor() const
Definition: zipentry_p.h:102
UnzipPrivate::openArchive
UnZip::ErrorCode openArchive(QIODevice *device)
Definition: unzip.cpp:527
unzip_p.h
zipentry_p.h
UnZip::~UnZip
virtual ~UnZip()
Definition: unzip.cpp:211
UnZip::WriteFailed
@ WriteFailed
Definition: unzip.h:64
UnZip::HeaderConsistencyError
@ HeaderConsistencyError
Definition: unzip.h:69
UnZip::isOpen
bool isOpen() const
Definition: unzip.cpp:220
UnZip::SkipAll
@ SkipAll
Definition: unzip.h:71
UnZip::File
@ File
Definition: unzip.h:90
UnzipPrivate::testKeys
bool testKeys(const ZipEntryP &header, keyset keys)
Definition: unzip.cpp:1333
UNZIP_VERSION
#define UNZIP_VERSION
Definition: unzip.cpp:172
hardwareprofile.config.p
p
Definition: config.py:33
UnzipPrivate::testPassword
UnZip::ErrorCode testPassword(keyset keys, const QString &file, const ZipEntryP &header)
Definition: unzip.cpp:1314
UnzipPrivate::initKeys
void initKeys(const QString &pwd, keyset keys) const
Definition: unzip.cpp:1295
UNZIP_DD_OFF_USIZE
#define UNZIP_DD_OFF_USIZE
Definition: unzip.cpp:159
UnzipPrivate::convertDateTime
static QDateTime convertDateTime(std::array< uint8_t, 2 > date, std::array< uint8_t, 2 > time)
Definition: unzip.cpp:1361
UNZIP_CD_ENTRY_SIZE_NS
#define UNZIP_CD_ENTRY_SIZE_NS
Central Directory file entry size (excluding signature, excluding variable length fields)
Definition: unzip.cpp:122
UnZip::ErrorCode
ErrorCode
Definition: unzip.h:52
ZipEntryP::lhEntryChecked
bool lhEntryChecked
Definition: zipentry_p.h:99
UnZip::ZipEntry::ZipEntry
ZipEntry()
Definition: unzip.cpp:506
UnzipPrivate::parseCentralDirectoryRecord
UnZip::ErrorCode parseCentralDirectoryRecord()
Definition: unzip.cpp:856
UnzipPrivate::extractFile
UnZip::ErrorCode extractFile(const QString &path, ZipEntryP &entry, const QDir &dir, UnZip::ExtractionOptions options)
Definition: unzip.cpp:989
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:637
UnZip::entryList
QList< ZipEntry > entryList() const
Definition: unzip.cpp:327
UnZip::FileNotFound
@ FileNotFound
Definition: unzip.h:62
UnZip::ZipEntry::filename
QString filename
Definition: unzip.h:97
UnZip::ZipEntry::crc32
quint32 crc32
Definition: unzip.h:102
ZipEntryP::szComp
quint32 szComp
Definition: zipentry_p.h:95
UnzipPrivate::parseLocalHeaderRecord
UnZip::ErrorCode parseLocalHeaderRecord(const QString &path, ZipEntryP &entry)
Definition: unzip.cpp:597
UNZIP_LH_OFF_USIZE
#define UNZIP_LH_OFF_USIZE
Definition: unzip.cpp:152
UNZIP_CHECK_FOR_VALID_DATA
#define UNZIP_CHECK_FOR_VALID_DATA
Checks if some file has been already extracted.
Definition: unzip.cpp:180
UnZip::ReadFailed
@ ReadFailed
Definition: unzip.h:63
Z_NULL
#define Z_NULL
Definition: unzip.h:37
UnZip::ZlibError
@ ZlibError
Definition: unzip.h:56
UnZip::ZipEntry::compression
CompressionMethod compression
Definition: unzip.h:106
ZipEntryP::modTime
std::array< uint8_t, 2 > modTime
Definition: zipentry_p.h:92
UnzipPrivate::updateKeys
void updateKeys(keyset keys, int c) const
Definition: unzip.cpp:1283
UnZip::Directory
@ Directory
Definition: unzip.h:90
UNZIP_CD_OFF_XLEN
#define UNZIP_CD_OFF_XLEN
Definition: unzip.cpp:140
UNZIP_EOCD_OFF_COMMLEN
#define UNZIP_EOCD_OFF_COMMLEN
Definition: unzip.cpp:164
ZipEntryP::dataOffset
quint32 dataOffset
Definition: zipentry_p.h:89
UnZip::NoOpenArchive
@ NoOpenArchive
Definition: unzip.h:61
UNZIP_CD_OFF_GPFLAG
#define UNZIP_CD_OFF_GPFLAG
Definition: unzip.cpp:132
UnZip::PartiallyCorrupted
@ PartiallyCorrupted
Definition: unzip.h:58
UNZIP_LH_OFF_XLEN
#define UNZIP_LH_OFF_XLEN
Definition: unzip.cpp:154
CRC32
#define CRC32(c, b)
CRC32 routine.
Definition: unzip.cpp:177
ZipEntryP::crc
quint32 crc
Definition: zipentry_p.h:94
ZipEntryP::lhOffset
quint32 lhOffset
Definition: zipentry_p.h:88
UnZip::archiveComment
QString archiveComment() const
Definition: unzip.cpp:269
UNZIP_LOCAL_HEADER_SIZE
#define UNZIP_LOCAL_HEADER_SIZE
Local header size (excluding signature, excluding variable length fields)
Definition: unzip.cpp:120
UNZIP_CD_OFF_COMMLEN
#define UNZIP_CD_OFF_COMMLEN
Definition: unzip.cpp:141
dir
QDir dir
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1174
UNZIP_LH_OFF_MODD
#define UNZIP_LH_OFF_MODD
Definition: unzip.cpp:149
UnZip::formatError
static QString formatError(UnZip::ErrorCode c)
Definition: unzip.cpp:279
UNZIP_CD_OFF_NAMELEN
#define UNZIP_CD_OFF_NAMELEN
Definition: unzip.cpp:139
UNZIP_EOCD_OFF_ENTRIES
#define UNZIP_EOCD_OFF_ENTRIES
Definition: unzip.cpp:162
UNZIP_CD_OFF_VERSION
#define UNZIP_CD_OFF_VERSION
Definition: unzip.cpp:131
UNZIP_CD_OFF_CRC32
#define UNZIP_CD_OFF_CRC32
Definition: unzip.cpp:136
UNZIP_LH_OFF_CRC32
#define UNZIP_LH_OFF_CRC32
Definition: unzip.cpp:150
UNZIP_LH_OFF_CMETHOD
#define UNZIP_LH_OFF_CMETHOD
Definition: unzip.cpp:147
UnzipPrivate::decryptByte
static int decryptByte(quint32 key2)
Definition: unzip.cpp:1274
UnZip::UnknownCompression
@ UnknownCompression
Definition: unzip.h:85
UnZip::ZipEntry::uncompressedSize
quint32 uncompressedSize
Definition: unzip.h:101
UnZip::Ok
@ Ok
Definition: unzip.h:54
UNZIP_EOCD_SIZE
#define UNZIP_EOCD_SIZE
End Of Central Directory size (including signature, excluding variable length fields)
Definition: unzip.cpp:126
UnZip::InvalidArchive
@ InvalidArchive
Definition: unzip.h:68
UnZip::Corrupted
@ Corrupted
Definition: unzip.h:59
UnZip::CreateDirFailed
@ CreateDirFailed
Definition: unzip.h:66
UnZip::d
UnzipPrivate * d
Definition: unzip.h:146
UNZIP_DD_OFF_CSIZE
#define UNZIP_DD_OFF_CSIZE
Definition: unzip.cpp:158
UnzipPrivate::headers
QMap< QString, ZipEntryP * > * headers
Definition: unzip_p.h:63
ZipEntryP::modDate
std::array< uint8_t, 2 > modDate
Definition: zipentry_p.h:93
UnZip::Skip
@ Skip
Definition: unzip.h:71
initKeys
static void initKeys(void)
Definition: mythtv/programs/mythwelcome/main.cpp:33
crc32
static uint32_t crc32(const unsigned char *data, int len)
Definition: dsmcc.cpp:612
UNZIP_LH_OFF_NAMELEN
#define UNZIP_LH_OFF_NAMELEN
Definition: unzip.cpp:153
UnzipPrivate::seekToCentralDirectory
UnZip::ErrorCode seekToCentralDirectory()
Definition: unzip.cpp:732
UnZip::ZipEntry
Definition: unzip.h:93
UnZip::contains
bool contains(const QString &file) const
Definition: unzip.cpp:308
UNZIP_CD_OFF_MODD
#define UNZIP_CD_OFF_MODD
Definition: unzip.cpp:135
UNZIP_LH_OFF_MODT
#define UNZIP_LH_OFF_MODT
Definition: unzip.cpp:148
build_compdb.options
options
Definition: build_compdb.py:11
UNZIP_CD_OFF_USIZE
#define UNZIP_CD_OFF_USIZE
Definition: unzip.cpp:138
UnZip::UnZip
UnZip()
Definition: unzip.cpp:203
ZipEntryP::comment
QString comment
Definition: zipentry_p.h:97
UNZIP_EOCD_OFF_CDOFF
#define UNZIP_EOCD_OFF_CDOFF
Definition: unzip.cpp:163