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 
546 
547  ec = seekToCentralDirectory();
548  if (ec != UnZip::Ok)
549  {
550  closeArchive();
551  return ec;
552  }
553 
555  if (cdEntryCount == 0)
556  {
557  return UnZip::Ok;
558  }
559 
560  bool continueParsing = true;
561 
562  while (continueParsing)
563  {
564  if (device->read(buffer1, 4) != 4)
566 
567  if (! (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x01 && buffer1[3] == 0x02) )
568  break;
569 
570  if ( (ec = parseCentralDirectoryRecord()) != UnZip::Ok )
571  break;
572  }
573 
574  if (ec != UnZip::Ok)
575  closeArchive();
576 
577  return ec;
578 }
579 
580 /*
581  \internal Parses a local header record and makes some consistency check
582  with the information stored in the Central Directory record for this entry
583  that has been previously parsed.
584  \todo Optional consistency check (as a ExtractionOptions flag)
585 
586  local file header signature 4 bytes (0x04034b50)
587  version needed to extract 2 bytes
588  general purpose bit flag 2 bytes
589  compression method 2 bytes
590  last mod file time 2 bytes
591  last mod file date 2 bytes
592  crc-32 4 bytes
593  compressed size 4 bytes
594  uncompressed size 4 bytes
595  file name length 2 bytes
596  extra field length 2 bytes
597 
598  file name (variable size)
599  extra field (variable size)
600 */
602 {
603  if (!device->seek(entry.lhOffset))
604  return UnZip::SeekFailed;
605 
606  // Test signature
607  if (device->read(buffer1, 4) != 4)
608  return UnZip::ReadFailed;
609 
610  if ((buffer1[0] != 'P') || (buffer1[1] != 'K') || (buffer1[2] != 0x03) || (buffer1[3] != 0x04))
611  return UnZip::InvalidArchive;
612 
613  if (device->read(buffer1, UNZIP_LOCAL_HEADER_SIZE) != UNZIP_LOCAL_HEADER_SIZE)
614  return UnZip::ReadFailed;
615 
616  /*
617  Check 3rd general purpose bit flag.
618 
619  "bit 3: If this bit is set, the fields crc-32, compressed size
620  and uncompressed size are set to zero in the local
621  header. The correct values are put in the data descriptor
622  immediately following the compressed data."
623  */
624  bool hasDataDescriptor = entry.hasDataDescriptor();
625 
626  bool checkFailed = false;
627 
628  if (!checkFailed)
629  checkFailed = entry.compMethod != getUShort(uBuffer, UNZIP_LH_OFF_CMETHOD);
630  if (!checkFailed)
631  checkFailed = entry.gpFlag[0] != uBuffer[UNZIP_LH_OFF_GPFLAG];
632  if (!checkFailed)
633  checkFailed = entry.gpFlag[1] != uBuffer[UNZIP_LH_OFF_GPFLAG + 1];
634  if (!checkFailed)
635  checkFailed = entry.modTime[0] != uBuffer[UNZIP_LH_OFF_MODT];
636  if (!checkFailed)
637  checkFailed = entry.modTime[1] != uBuffer[UNZIP_LH_OFF_MODT + 1];
638  if (!checkFailed)
639  checkFailed = entry.modDate[0] != uBuffer[UNZIP_LH_OFF_MODD];
640  if (!checkFailed)
641  checkFailed = entry.modDate[1] != uBuffer[UNZIP_LH_OFF_MODD + 1];
642  if (!hasDataDescriptor)
643  {
644  if (!checkFailed)
645  checkFailed = entry.crc != getULong(uBuffer, UNZIP_LH_OFF_CRC32);
646  if (!checkFailed)
647  checkFailed = entry.szComp != getULong(uBuffer, UNZIP_LH_OFF_CSIZE);
648  if (!checkFailed)
649  checkFailed = entry.szUncomp != getULong(uBuffer, UNZIP_LH_OFF_USIZE);
650  }
651 
652  if (checkFailed)
654 
655  // Check filename
656  quint16 szName = getUShort(uBuffer, UNZIP_LH_OFF_NAMELEN);
657  if (szName == 0)
659 
660  if (device->read(buffer2, szName) != szName)
661  return UnZip::ReadFailed;
662 
663  QString filename = QString::fromLatin1(buffer2, szName);
664  if (filename != path)
665  {
666  qDebug() << "Filename in local header mismatches.";
668  }
669 
670  // Skip extra field
671  quint16 szExtra = getUShort(uBuffer, UNZIP_LH_OFF_XLEN);
672  if (szExtra != 0)
673  {
674  if (!device->seek(device->pos() + szExtra))
675  return UnZip::SeekFailed;
676  }
677 
678  entry.dataOffset = device->pos();
679 
680  if (hasDataDescriptor)
681  {
682  /*
683  The data descriptor has this OPTIONAL signature: PK\7\8
684  We try to skip the compressed data relying on the size set in the
685  Central Directory record.
686  */
687  if (!device->seek(device->pos() + entry.szComp))
688  return UnZip::SeekFailed;
689 
690  // Read 4 bytes and check if there is a data descriptor signature
691  if (device->read(buffer2, 4) != 4)
692  return UnZip::ReadFailed;
693 
694  bool hasSignature = buffer2[0] == 'P' && buffer2[1] == 'K' && buffer2[2] == 0x07 && buffer2[3] == 0x08;
695  if (hasSignature)
696  {
697  if (device->read(buffer2, UNZIP_DD_SIZE) != UNZIP_DD_SIZE)
698  return UnZip::ReadFailed;
699  }
700  else
701  {
702  if (device->read(buffer2 + 4, UNZIP_DD_SIZE - 4) != UNZIP_DD_SIZE - 4)
703  return UnZip::ReadFailed;
704  }
705 
706  // DD: crc, compressed size, uncompressed size
707  if (
708  entry.crc != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CRC32) ||
709  entry.szComp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CSIZE) ||
710  entry.szUncomp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_USIZE)
711  )
713  }
714 
715  return UnZip::Ok;
716 }
717 
740 {
741  qint64 length = device->size();
742  qint64 offset = length - UNZIP_EOCD_SIZE;
743 
744  if (length < UNZIP_EOCD_SIZE)
745  return UnZip::InvalidArchive;
746 
747  if (!device->seek( offset ))
748  return UnZip::SeekFailed;
749 
750  if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
751  return UnZip::ReadFailed;
752 
753  bool eocdFound = (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x05 && buffer1[3] == 0x06);
754 
755  if (eocdFound)
756  {
757  // Zip file has no comment (the only variable length field in the EOCD record)
758  eocdOffset = offset;
759  }
760  else
761  {
762  char* p = nullptr;
763 
764  offset -= UNZIP_EOCD_SIZE;
765 
766  if (offset <= 0)
767  return UnZip::InvalidArchive;
768 
769  if (!device->seek( offset ))
770  return UnZip::SeekFailed;
771 
772  while (device->read(buffer1, UNZIP_EOCD_SIZE) >= 0)
773  {
774  if ( (p = strstr(buffer1, "PK\5\6")) != nullptr)
775  {
776  // Seek to the start of the EOCD record so we can read it fully
777  // Yes... we could simply read the missing bytes and append them to the buffer
778  // but this is far easier so heck it!
779  device->seek( offset + (p - buffer1) );
780  eocdFound = true;
781  eocdOffset = offset + (p - buffer1);
782 
783  // Read EOCD record
784  if (device->read(buffer1, UNZIP_EOCD_SIZE) != UNZIP_EOCD_SIZE)
785  return UnZip::ReadFailed;
786 
787  break;
788  }
789 
790  // TODO: This is very slow and only a temporary bug fix. Need some pattern matching algorithm here.
791  offset -= 1 /*UNZIP_EOCD_SIZE*/;
792  if (offset <= 0)
793  return UnZip::InvalidArchive;
794 
795  if (!device->seek( offset ))
796  return UnZip::SeekFailed;
797  }
798  }
799 
800  if (!eocdFound)
801  return UnZip::InvalidArchive;
802 
803  // Parse EOCD to locate CD offset
804  offset = getULong((const unsigned char*)buffer1, UNZIP_EOCD_OFF_CDOFF + 4);
805 
806  cdOffset = offset;
807 
808  cdEntryCount = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_ENTRIES + 4);
809 
810  quint16 commentLength = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_COMMLEN + 4);
811  if (commentLength != 0)
812  {
813  QByteArray c = device->read(commentLength);
814  if (c.count() != commentLength)
815  return UnZip::ReadFailed;
816 
817  comment = c;
818  }
819 
820  // Seek to the start of the CD record
821  if (!device->seek( cdOffset ))
822  return UnZip::SeekFailed;
823 
824  return UnZip::Ok;
825 }
826 
864 {
865  // Read CD record
866  if (device->read(buffer1, UNZIP_CD_ENTRY_SIZE_NS) != UNZIP_CD_ENTRY_SIZE_NS)
867  return UnZip::ReadFailed;
868 
869  bool skipEntry = false;
870 
871  // Get compression type so we can skip non compatible algorithms
872  quint16 compMethod = getUShort(uBuffer, UNZIP_CD_OFF_CMETHOD);
873 
874  // Get variable size fields length so we can skip the whole record
875  // if necessary
876  quint16 szName = getUShort(uBuffer, UNZIP_CD_OFF_NAMELEN);
877  quint16 szExtra = getUShort(uBuffer, UNZIP_CD_OFF_XLEN);
878  quint16 szComment = getUShort(uBuffer, UNZIP_CD_OFF_COMMLEN);
879 
880  quint32 skipLength = szName + szExtra + szComment;
881 
883 
884  if ((compMethod != 0) && (compMethod != 8))
885  {
886  qDebug() << "Unsupported compression method. Skipping file.";
887  skipEntry = true;
888  }
889 
890  // Header parsing may be a problem if version is bigger than UNZIP_VERSION
891  if (!skipEntry && buffer1[UNZIP_CD_OFF_VERSION] > UNZIP_VERSION)
892  {
893  qDebug() << "Unsupported PKZip version. Skipping file.";
894  skipEntry = true;
895  }
896 
897  if (!skipEntry && szName == 0)
898  {
899  qDebug() << "Skipping file with no name.";
900  skipEntry = true;
901  }
902 
903  if (!skipEntry && device->read(buffer2, szName) != szName)
904  {
905  ec = UnZip::ReadFailed;
906  skipEntry = true;
907  }
908 
909  if (skipEntry)
910  {
911  if (ec == UnZip::Ok)
912  {
913  if (!device->seek( device->pos() + skipLength ))
914  ec = UnZip::SeekFailed;
915 
916  unsupportedEntryCount++;
917  }
918 
919  return ec;
920  }
921 
922  QString filename = QString::fromLatin1(buffer2, szName);
923 
924  auto* h = new ZipEntryP;
925  h->compMethod = compMethod;
926 
927  h->gpFlag[0] = buffer1[UNZIP_CD_OFF_GPFLAG];
928  h->gpFlag[1] = buffer1[UNZIP_CD_OFF_GPFLAG + 1];
929 
930  h->modTime[0] = buffer1[UNZIP_CD_OFF_MODT];
931  h->modTime[1] = buffer1[UNZIP_CD_OFF_MODT + 1];
932 
933  h->modDate[0] = buffer1[UNZIP_CD_OFF_MODD];
934  h->modDate[1] = buffer1[UNZIP_CD_OFF_MODD + 1];
935 
936  h->crc = getULong(uBuffer, UNZIP_CD_OFF_CRC32);
937  h->szComp = getULong(uBuffer, UNZIP_CD_OFF_CSIZE);
938  h->szUncomp = getULong(uBuffer, UNZIP_CD_OFF_USIZE);
939 
940  // Skip extra field (if any)
941  if (szExtra != 0)
942  {
943  if (!device->seek( device->pos() + szExtra ))
944  {
945  delete h;
946  return UnZip::SeekFailed;
947  }
948  }
949 
950  // Read comment field (if any)
951  if (szComment != 0)
952  {
953  if (device->read(buffer2, szComment) != szComment)
954  {
955  delete h;
956  return UnZip::ReadFailed;
957  }
958 
959  h->comment = QString::fromLatin1(buffer2, szComment);
960  }
961 
962  h->lhOffset = getULong(uBuffer, UNZIP_CD_OFF_LHOFFSET);
963 
964  if (headers == nullptr)
965  headers = new QMap<QString, ZipEntryP*>();
966  headers->insert(filename, h);
967 
968  return UnZip::Ok;
969 }
970 
973 {
974  if (device == nullptr)
975  return;
976 
977  skipAllEncrypted = false;
978 
979  if (headers != nullptr)
980  {
981  qDeleteAll(*headers);
982  delete headers;
983  headers = nullptr;
984  }
985 
986  delete device; device = nullptr;
987 
988  cdOffset = eocdOffset = 0;
989  cdEntryCount = 0;
990  unsupportedEntryCount = 0;
991 
992  comment.clear();
993 }
994 
996 UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, const QDir& dir, UnZip::ExtractionOptions options)
997 {
998  QString name(path);
999  QString dirname;
1000  QString directory;
1001 
1002  int pos = name.lastIndexOf('/');
1003 
1004  // This entry is for a directory
1005  if (pos == name.length() - 1)
1006  {
1007  if (options.testFlag(UnZip::SkipPaths))
1008  return UnZip::Ok;
1009 
1010  directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(name));
1011  if (!createDirectory(directory))
1012  {
1013  qDebug() << QString("Unable to create directory: %1").arg(directory);
1014  return UnZip::CreateDirFailed;
1015  }
1016 
1017  return UnZip::Ok;
1018  }
1019 
1020  // Extract path from entry
1021  if (pos > 0)
1022  {
1023  // get directory part
1024  dirname = name.left(pos);
1025  if (options.testFlag(UnZip::SkipPaths))
1026  {
1027  directory = dir.absolutePath();
1028  }
1029  else
1030  {
1031  directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(dirname));
1032  if (!createDirectory(directory))
1033  {
1034  qDebug() << QString("Unable to create directory: %1").arg(directory);
1035  return UnZip::CreateDirFailed;
1036  }
1037  }
1038  name = name.right(name.length() - pos - 1);
1039  } else directory = dir.absolutePath();
1040 
1041  name = QString("%1/%2").arg(directory).arg(name);
1042 
1043  QFile outFile(name);
1044 
1045  if (!outFile.open(QIODevice::WriteOnly))
1046  {
1047  qDebug() << QString("Unable to open %1 for writing").arg(name);
1048  return UnZip::OpenFailed;
1049  }
1050 
1052 
1053  UnZip::ErrorCode ec = extractFile(path, entry, &outFile, options);
1054 
1055  outFile.close();
1056 
1057  if (ec != UnZip::Ok)
1058  {
1059  if (!outFile.remove())
1060  qDebug() << QString("Unable to remove corrupted file: %1").arg(name);
1061  }
1062 
1063  return ec;
1064 }
1065 
1067 UnZip::ErrorCode UnzipPrivate::extractFile(const QString& path, ZipEntryP& entry, QIODevice* dev, UnZip::ExtractionOptions options)
1068 {
1069  Q_UNUSED(options);
1070  Q_ASSERT(dev != nullptr);
1071 
1072  if (!entry.lhEntryChecked)
1073  {
1074  UnZip::ErrorCode ec = parseLocalHeaderRecord(path, entry);
1075  entry.lhEntryChecked = true;
1076 
1077  if (ec != UnZip::Ok)
1078  return ec;
1079  }
1080 
1081  if (!device->seek(entry.dataOffset))
1082  return UnZip::SeekFailed;
1083 
1084  // Encryption keys
1085  keyset keys;
1086 
1087  if (entry.isEncrypted())
1088  {
1089  UnZip::ErrorCode e = testPassword(keys, path, entry);
1090  if (e != UnZip::Ok)
1091  {
1092  qDebug() << QString("Unable to decrypt %1").arg(path);
1093  return e;
1094  }
1095  entry.szComp -= UNZIP_LOCAL_ENC_HEADER_SIZE; // remove encryption header size
1096  }
1097 
1098  if (entry.szComp == 0)
1099  {
1100  if (entry.crc != 0)
1101  return UnZip::Corrupted;
1102 
1103  return UnZip::Ok;
1104  }
1105 
1106  uInt rep = entry.szComp / UNZIP_READ_BUFFER;
1107  uInt rem = entry.szComp % UNZIP_READ_BUFFER;
1108  uInt cur = 0;
1109 
1110  // extract data
1111  qint64 read = 0;
1112  quint64 tot = 0;
1113 
1114  quint32 myCRC = crc32(0L, Z_NULL, 0);
1115 
1116  if (entry.compMethod == 0)
1117  {
1118  while ( (read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem)) > 0 )
1119  {
1120  if (entry.isEncrypted())
1121  decryptBytes(keys, buffer1, read);
1122 
1123  myCRC = crc32(myCRC, uBuffer, read);
1124 
1125  if (dev->write(buffer1, read) != read)
1126  return UnZip::WriteFailed;
1127 
1128  cur++;
1129  tot += read;
1130 
1131  if (tot == entry.szComp)
1132  break;
1133  }
1134 
1135  if (read < 0)
1136  return UnZip::ReadFailed;
1137  }
1138  else if (entry.compMethod == 8)
1139  {
1140  /* Allocate inflate state */
1141  z_stream zstr;
1142  zstr.zalloc = Z_NULL;
1143  zstr.zfree = Z_NULL;
1144  zstr.opaque = Z_NULL;
1145  zstr.next_in = Z_NULL;
1146  zstr.avail_in = 0;
1147 
1148  int zret = Z_OK;
1149 
1150  // Use inflateInit2 with negative windowBits to get raw decompression
1151  if (inflateInit2_(&zstr, -MAX_WBITS, ZLIB_VERSION, sizeof(z_stream)) != Z_OK )
1152  return UnZip::ZlibError;
1153 
1154  int szDecomp = 0;
1155 
1156  // Decompress until deflate stream ends or end of file
1157  do
1158  {
1159  read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem);
1160  if (read == 0)
1161  break;
1162  if (read < 0)
1163  {
1164  (void)inflateEnd(&zstr);
1165  return UnZip::ReadFailed;
1166  }
1167 
1168  if (entry.isEncrypted())
1169  decryptBytes(keys, buffer1, read);
1170 
1171  cur++;
1172  tot += read;
1173 
1174  zstr.avail_in = (uInt) read;
1175  zstr.next_in = (Bytef*) buffer1;
1176 
1177 
1178  // Run inflate() on input until output buffer not full
1179  do {
1180  zstr.avail_out = UNZIP_READ_BUFFER;
1181  zstr.next_out = (Bytef*) buffer2;;
1182 
1183  zret = inflate(&zstr, Z_NO_FLUSH);
1184 
1185  switch (zret) {
1186  case Z_NEED_DICT:
1187  case Z_DATA_ERROR:
1188  case Z_MEM_ERROR:
1189  inflateEnd(&zstr);
1190  return UnZip::WriteFailed;
1191  default:
1192  ;
1193  }
1194 
1195  szDecomp = UNZIP_READ_BUFFER - zstr.avail_out;
1196  if (dev->write(buffer2, szDecomp) != szDecomp)
1197  {
1198  inflateEnd(&zstr);
1199  return UnZip::ZlibError;
1200  }
1201 
1202  myCRC = crc32(myCRC, (const Bytef*) buffer2, szDecomp);
1203 
1204  } while (zstr.avail_out == 0);
1205 
1206  }
1207  while (zret != Z_STREAM_END);
1208 
1209  inflateEnd(&zstr);
1210  }
1211 
1212  if (myCRC != entry.crc)
1213  return UnZip::Corrupted;
1214 
1215  return UnZip::Ok;
1216 }
1217 
1219 bool UnzipPrivate::createDirectory(const QString& path)
1220 {
1221  QDir d(path);
1222  if (!d.exists())
1223  {
1224  int sep = path.lastIndexOf("/");
1225  if (sep <= 0) return true;
1226 
1227  if (!createDirectory(path.left(sep)))
1228  return false;
1229 
1230  if (!d.mkdir(path))
1231  {
1232  qDebug() << QString("Unable to create directory: %1").arg(path);
1233  return false;
1234  }
1235  }
1236 
1237  return true;
1238 }
1239 
1243 quint32 UnzipPrivate::getULong(const unsigned char* data, quint32 offset)
1244 {
1245  auto res = (quint32) data[offset];
1246  res |= (((quint32)data[offset+1]) << 8);
1247  res |= (((quint32)data[offset+2]) << 16);
1248  res |= (((quint32)data[offset+3]) << 24);
1249 
1250  return res;
1251 }
1252 
1256 quint64 UnzipPrivate::getULLong(const unsigned char* data, quint32 offset)
1257 {
1258  auto res = (quint64) data[offset];
1259  res |= (((quint64)data[offset+1]) << 8);
1260  res |= (((quint64)data[offset+2]) << 16);
1261  res |= (((quint64)data[offset+3]) << 24);
1262  res |= (((quint64)data[offset+1]) << 32);
1263  res |= (((quint64)data[offset+2]) << 40);
1264  res |= (((quint64)data[offset+3]) << 48);
1265  res |= (((quint64)data[offset+3]) << 56);
1266 
1267  return res;
1268 }
1269 
1273 quint16 UnzipPrivate::getUShort(const unsigned char* data, quint32 offset)
1274 {
1275  return (quint16) data[offset] | (((quint16)data[offset+1]) << 8);
1276 }
1277 
1281 int UnzipPrivate::decryptByte(quint32 key2)
1282 {
1283  quint16 temp = ((quint16)(key2) & 0xffff) | 2;
1284  return ((temp * (temp ^ 1)) >> 8) & 0xff;
1285 }
1286 
1290 void UnzipPrivate::updateKeys(keyset keys, int c) const
1291 {
1292  keys[0] = CRC32(keys[0], c);
1293  keys[1] += keys[0] & 0xff;
1294  keys[1] = keys[1] * 134775813L + 1;
1295  keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24);
1296 }
1297 
1302 void UnzipPrivate::initKeys(const QString& pwd, keyset keys) const
1303 {
1304  keys[0] = 305419896L;
1305  keys[1] = 591751049L;
1306  keys[2] = 878082192L;
1307 
1308  QByteArray pwdBytes = pwd.toLatin1();
1309  int sz = pwdBytes.size();
1310  const char* ascii = pwdBytes.data();
1311 
1312  for (int i=0; i<sz; ++i)
1313  updateKeys(keys, (int)ascii[i]);
1314 }
1315 
1322 {
1323  Q_UNUSED(file);
1324 
1325  // read encryption keys
1326  if (device->read(buffer1, 12) != 12)
1327  return UnZip::Corrupted;
1328 
1329  // Replace this code if you want to i.e. call some dialog and ask the user for a password
1330  initKeys(password, keys);
1331  if (testKeys(header, keys))
1332  return UnZip::Ok;
1333 
1334  return UnZip::Skip;
1335 }
1336 
1340 bool UnzipPrivate::testKeys(const ZipEntryP& header, keyset keys)
1341 {
1342  char lastByte = 0;
1343 
1344  // decrypt encryption header
1345  for (int i=0; i<11; ++i)
1346  updateKeys(keys, buffer1[i] ^ decryptByte(keys[2]));
1347  updateKeys(keys, lastByte = buffer1[11] ^ decryptByte(keys[2]));
1348 
1349  // if there is an extended header (bit in the gp flag) buffer[11] is a byte from the file time
1350  // with no extended header we have to check the crc high-order byte
1351  char c = ((header.gpFlag[0] & 0x08) == 8) ? header.modTime[1] : header.crc >> 24;
1352 
1353  return (lastByte == c);
1354 }
1355 
1359 void UnzipPrivate::decryptBytes(keyset keys, char* buffer, qint64 read) const
1360 {
1361  for (int i=0; i<(int)read; ++i)
1362  updateKeys(keys, buffer[i] ^= decryptByte(keys[2]));
1363 }
1364 
1368 QDateTime UnzipPrivate::convertDateTime(const std::array<uint8_t,2> &date, const std::array<uint8_t,2> &time)
1369 {
1370  QDateTime dt;
1371 
1372  // Usual PKZip low-byte to high-byte order
1373 
1374  // Date: 7 bits = years from 1980, 4 bits = month, 5 bits = day
1375  quint16 year = (date[1] >> 1) & 127;
1376  quint16 month = ((date[1] << 3) & 14) | ((date[0] >> 5) & 7);
1377  quint16 day = date[0] & 31;
1378 
1379  // Time: 5 bits hour, 6 bits minutes, 5 bits seconds with a 2sec precision
1380  quint16 hour = (time[1] >> 3) & 31;
1381  quint16 minutes = ((time[1] << 3) & 56) | ((time[0] >> 5) & 7);
1382  quint16 seconds = (time[0] & 31) * 2;
1383 
1384  dt = QDateTime(QDate(1980 + year, month, day),
1385  QTime(hour, minutes, seconds), Qt::UTC);
1386  return dt;
1387 }
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:76
UnzipPrivate::device
QIODevice * device
Definition: unzip_p.h:65
e
QDomElement e
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1423
UNZIP_LH_OFF_CSIZE
#define UNZIP_LH_OFF_CSIZE
Definition: unzip.cpp:151
ZipEntryP::szUncomp
quint32 szUncomp
Definition: zipentry_p.h:71
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:1273
ZipEntryP::gpFlag
std::array< uint8_t, 2 > gpFlag
Definition: zipentry_p.h:65
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:66
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:1219
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:1256
UNZIP_DD_OFF_CRC32
#define UNZIP_DD_OFF_CRC32
Definition: unzip.cpp:157
UnzipPrivate::closeArchive
void closeArchive()
Definition: unzip.cpp:972
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:48
build_compdb.file
file
Definition: build_compdb.py:55
UnzipPrivate::getULong
static quint32 getULong(const unsigned char *data, quint32 offset)
Definition: unzip.cpp:1243
UnzipPrivate
Definition: unzip_p.h:54
UnzipPrivate::decryptBytes
void decryptBytes(keyset keys, char *buffer, qint64 read) const
Definition: unzip.cpp:1359
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:77
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:1340
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:1321
UnzipPrivate::initKeys
void initKeys(const QString &pwd, keyset keys) const
Definition: unzip.cpp:1302
UNZIP_DD_OFF_USIZE
#define UNZIP_DD_OFF_USIZE
Definition: unzip.cpp:159
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:53
ZipEntryP::lhEntryChecked
bool lhEntryChecked
Definition: zipentry_p.h:74
UnZip::ZipEntry::ZipEntry
ZipEntry()
Definition: unzip.cpp:506
UnzipPrivate::parseCentralDirectoryRecord
UnZip::ErrorCode parseCentralDirectoryRecord()
Definition: unzip.cpp:863
UnzipPrivate::extractFile
UnZip::ErrorCode extractFile(const QString &path, ZipEntryP &entry, const QDir &dir, UnZip::ExtractionOptions options)
Definition: unzip.cpp:996
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:640
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:70
UnzipPrivate::parseLocalHeaderRecord
UnZip::ErrorCode parseLocalHeaderRecord(const QString &path, ZipEntryP &entry)
Definition: unzip.cpp:601
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:67
UnzipPrivate::updateKeys
void updateKeys(keyset keys, int c) const
Definition: unzip.cpp:1290
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:64
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:69
ZipEntryP::lhOffset
quint32 lhOffset
Definition: zipentry_p.h:63
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:1177
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
UnzipPrivate::convertDateTime
static QDateTime convertDateTime(const std::array< uint8_t, 2 > &date, const std::array< uint8_t, 2 > &time)
Definition: unzip.cpp:1368
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:1281
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:68
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:739
UnZip::ZipEntry
Definition: unzip.h:94
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:72
UNZIP_EOCD_OFF_CDOFF
#define UNZIP_EOCD_OFF_CDOFF
Definition: unzip.cpp:163