FFSM++ 1.1.0
French Forest Sector Model ++
Loading...
Searching...
No Matches
UnzipPrivate Class Reference

#include <unzip_p.h>

Public Member Functions

 UnzipPrivate ()
 
UnZip::ErrorCode openArchive (QIODevice *device)
 
UnZip::ErrorCode seekToCentralDirectory ()
 
UnZip::ErrorCode parseCentralDirectoryRecord ()
 
UnZip::ErrorCode parseLocalHeaderRecord (const QString &path, ZipEntryP &entry)
 
void closeArchive ()
 
UnZip::ErrorCode extractFile (const QString &path, ZipEntryP &entry, const QDir &dir, UnZip::ExtractionOptions options)
 
UnZip::ErrorCode extractFile (const QString &path, ZipEntryP &entry, QIODevice *device, UnZip::ExtractionOptions options)
 
UnZip::ErrorCode testPassword (quint32 *keys, const QString &file, const ZipEntryP &header)
 
bool testKeys (const ZipEntryP &header, quint32 *keys)
 
bool createDirectory (const QString &path)
 
void decryptBytes (quint32 *keys, char *buffer, qint64 read)
 
quint32 getULong (const unsigned char *data, quint32 offset) const
 
quint64 getULLong (const unsigned char *data, quint32 offset) const
 
quint16 getUShort (const unsigned char *data, quint32 offset) const
 
int decryptByte (quint32 key2) const
 
void updateKeys (quint32 *keys, int c) const
 
void initKeys (const QString &pwd, quint32 *keys) const
 
QDateTime convertDateTime (const unsigned char date[2], const unsigned char time[2]) const
 

Public Attributes

QString password
 
bool skipAllEncrypted
 
QMap< QString, ZipEntryP * > * headers
 
QIODevice * device
 
char buffer1 [UNZIP_READ_BUFFER]
 
char buffer2 [UNZIP_READ_BUFFER]
 
unsigned char * uBuffer
 
const quint32 * crcTable
 
quint32 cdOffset
 
quint32 eocdOffset
 
quint16 cdEntryCount
 
quint16 unsupportedEntryCount
 
QString comment
 

Detailed Description

Definition at line 51 of file unzip_p.h.

Constructor & Destructor Documentation

◆ UnzipPrivate()

Definition at line 485 of file unzip.cpp.

486{
487 skipAllEncrypted = false;
488 headers = 0;
489 device = 0;
490
491 uBuffer = (unsigned char*) buffer1;
492 crcTable = (quint32*) get_crc_table();
493
494 cdOffset = eocdOffset = 0;
495 cdEntryCount = 0;
497}
char buffer1[UNZIP_READ_BUFFER]
Definition unzip_p.h:65
quint32 eocdOffset
Definition unzip_p.h:74
QIODevice * device
Definition unzip_p.h:63
quint32 cdOffset
Definition unzip_p.h:72
bool skipAllEncrypted
Definition unzip_p.h:59
unsigned char * uBuffer
Definition unzip_p.h:68
const quint32 * crcTable
Definition unzip_p.h:69
quint16 unsupportedEntryCount
Definition unzip_p.h:80
quint16 cdEntryCount
Definition unzip_p.h:77
QMap< QString, ZipEntryP * > * headers
Definition unzip_p.h:61

Member Function Documentation

◆ closeArchive()

void closeArchive ( )

Definition at line 948 of file unzip.cpp.

949{
950 if (device == 0)
951 return;
952
953 skipAllEncrypted = false;
954
955 if (headers != 0)
956 {
957 qDeleteAll(*headers);
958 delete headers;
959 headers = 0;
960 }
961
962 delete device; device = 0;
963
964 cdOffset = eocdOffset = 0;
965 cdEntryCount = 0;
967
968 comment.clear();
969}
QString comment
Definition unzip_p.h:82

Referenced by UnZip::closeArchive().

Here is the caller graph for this function:

◆ convertDateTime()

QDateTime convertDateTime ( const unsigned char  date[2],
const unsigned char  time[2] 
) const
inline

Definition at line 1345 of file unzip.cpp.

1346{
1347 QDateTime dt;
1348
1349 // Usual PKZip low-byte to high-byte order
1350
1351 // Date: 7 bits = years from 1980, 4 bits = month, 5 bits = day
1352 quint16 year = (date[1] >> 1) & 127;
1353 quint16 month = ((date[1] << 3) & 14) | ((date[0] >> 5) & 7);
1354 quint16 day = date[0] & 31;
1355
1356 // Time: 5 bits hour, 6 bits minutes, 5 bits seconds with a 2sec precision
1357 quint16 hour = (time[1] >> 3) & 31;
1358 quint16 minutes = ((time[1] << 3) & 56) | ((time[0] >> 5) & 7);
1359 quint16 seconds = (time[0] & 31) * 2;
1360
1361 dt.setDate(QDate(1980 + year, month, day));
1362 dt.setTime(QTime(hour, minutes, seconds));
1363 return dt;
1364}

Referenced by UnZip::entryList().

Here is the caller graph for this function:

◆ createDirectory()

bool createDirectory ( const QString &  path)

Definition at line 1195 of file unzip.cpp.

1196{
1197 QDir d(path);
1198 if (!d.exists())
1199 {
1200 int sep = path.lastIndexOf("/");
1201 if (sep <= 0) return true;
1202
1203 if (!createDirectory(path.left(sep)))
1204 return false;
1205
1206 if (!d.mkdir(path))
1207 {
1208 qDebug() << QString("Unable to create directory: %1").arg(path);
1209 return false;
1210 }
1211 }
1212
1213 return true;
1214}
bool createDirectory(const QString &path)
Definition unzip.cpp:1195

◆ decryptByte()

int decryptByte ( quint32  key2) const
inline

Definition at line 1257 of file unzip.cpp.

1258{
1259 quint16 temp = ((quint16)(key2) & 0xffff) | 2;
1260 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
1261}

◆ decryptBytes()

void decryptBytes ( quint32 *  keys,
char *  buffer,
qint64  read 
)
inline

Definition at line 1336 of file unzip.cpp.

1337{
1338 for (int i=0; i<(int)read; ++i)
1339 updateKeys(keys, buffer[i] ^= decryptByte(keys[2]));
1340}
int decryptByte(quint32 key2) const
Definition unzip.cpp:1257
void updateKeys(quint32 *keys, int c) const
Definition unzip.cpp:1266

◆ extractFile() [1/2]

UnZip::ErrorCode extractFile ( const QString &  path,
ZipEntryP entry,
const QDir &  dir,
UnZip::ExtractionOptions  options 
)
Todo:
Set creation/last_modified date/time

Definition at line 972 of file unzip.cpp.

973{
974 QString name(path);
975 QString dirname;
976 QString directory;
977
978 int pos = name.lastIndexOf('/');
979
980 // This entry is for a directory
981 if (pos == name.length() - 1)
982 {
983 if (options.testFlag(UnZip::SkipPaths))
984 return UnZip::Ok;
985
986 directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(name));
987 if (!createDirectory(directory))
988 {
989 qDebug() << QString("Unable to create directory: %1").arg(directory);
991 }
992
993 return UnZip::Ok;
994 }
995
996 // Extract path from entry
997 if (pos > 0)
998 {
999 // get directory part
1000 dirname = name.left(pos);
1001 if (options.testFlag(UnZip::SkipPaths))
1002 {
1003 directory = dir.absolutePath();
1004 }
1005 else
1006 {
1007 directory = QString("%1/%2").arg(dir.absolutePath()).arg(QDir::cleanPath(dirname));
1008 if (!createDirectory(directory))
1009 {
1010 qDebug() << QString("Unable to create directory: %1").arg(directory);
1012 }
1013 }
1014 name = name.right(name.length() - pos - 1);
1015 } else directory = dir.absolutePath();
1016
1017 name = QString("%1/%2").arg(directory).arg(name);
1018
1019 QFile outFile(name);
1020
1021 if (!outFile.open(QIODevice::WriteOnly))
1022 {
1023 qDebug() << QString("Unable to open %1 for writing").arg(name);
1024 return UnZip::OpenFailed;
1025 }
1026
1027 //! \todo Set creation/last_modified date/time
1028
1029 UnZip::ErrorCode ec = extractFile(path, entry, &outFile, options);
1030
1031 outFile.close();
1032
1033 if (ec != UnZip::Ok)
1034 {
1035 if (!outFile.remove())
1036 qDebug() << QString("Unable to remove corrupted file: %1").arg(name);
1037 }
1038
1039 return ec;
1040}
ErrorCode
Definition unzip.h:49
@ OpenFailed
Definition unzip.h:53
@ Ok
Definition unzip.h:50
@ CreateDirFailed
Definition unzip.h:62
@ SkipPaths
Ignores paths and extracts all the files to the same directory.
Definition unzip.h:75
UnZip::ErrorCode extractFile(const QString &path, ZipEntryP &entry, const QDir &dir, UnZip::ExtractionOptions options)
Definition unzip.cpp:972

Referenced by UnZip::extractAll(), UnZip::extractFile(), and UnZip::extractFile().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ extractFile() [2/2]

UnZip::ErrorCode extractFile ( const QString &  path,
ZipEntryP entry,
QIODevice *  device,
UnZip::ExtractionOptions  options 
)

Encryption header size

Definition at line 1043 of file unzip.cpp.

1044{
1045 Q_UNUSED(options);
1046 Q_ASSERT(dev != 0);
1047
1048 if (!entry.lhEntryChecked)
1049 {
1050 UnZip::ErrorCode ec = parseLocalHeaderRecord(path, entry);
1051 entry.lhEntryChecked = true;
1052
1053 if (ec != UnZip::Ok)
1054 return ec;
1055 }
1056
1057 if (!device->seek(entry.dataOffset))
1058 return UnZip::SeekFailed;
1059
1060 // Encryption keys
1061 quint32 keys[3];
1062
1063 if (entry.isEncrypted())
1064 {
1065 UnZip::ErrorCode e = testPassword(keys, path, entry);
1066 if (e != UnZip::Ok)
1067 {
1068 qDebug() << QString("Unable to decrypt %1").arg(path);
1069 return e;
1070 }//! Encryption header size
1071 entry.szComp -= UNZIP_LOCAL_ENC_HEADER_SIZE; // remove encryption header size
1072 }
1073
1074 if (entry.szComp == 0)
1075 {
1076 if (entry.crc != 0)
1077 return UnZip::Corrupted;
1078
1079 return UnZip::Ok;
1080 }
1081
1082 uInt rep = entry.szComp / UNZIP_READ_BUFFER;
1083 uInt rem = entry.szComp % UNZIP_READ_BUFFER;
1084 uInt cur = 0;
1085
1086 // extract data
1087 qint64 read;
1088 quint64 tot = 0;
1089
1090 quint32 myCRC = crc32(0L, Z_NULL, 0);
1091
1092 if (entry.compMethod == 0)
1093 {
1094 while ( (read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem)) > 0 )
1095 {
1096 if (entry.isEncrypted())
1097 decryptBytes(keys, buffer1, read);
1098
1099 myCRC = crc32(myCRC, uBuffer, read);
1100
1101 if (dev->write(buffer1, read) != read)
1102 return UnZip::WriteFailed;
1103
1104 cur++;
1105 tot += read;
1106
1107 if (tot == entry.szComp)
1108 break;
1109 }
1110
1111 if (read < 0)
1112 return UnZip::ReadFailed;
1113 }
1114 else if (entry.compMethod == 8)
1115 {
1116 /* Allocate inflate state */
1117 z_stream zstr;
1118 zstr.zalloc = Z_NULL;
1119 zstr.zfree = Z_NULL;
1120 zstr.opaque = Z_NULL;
1121 zstr.next_in = Z_NULL;
1122 zstr.avail_in = 0;
1123
1124 int zret;
1125
1126 // Use inflateInit2 with negative windowBits to get raw decompression
1127 if ( (zret = inflateInit2_(&zstr, -MAX_WBITS, ZLIB_VERSION, sizeof(z_stream))) != Z_OK )
1128 return UnZip::ZlibError;
1129
1130 int szDecomp;
1131
1132 // Decompress until deflate stream ends or end of file
1133 do
1134 {
1135 read = device->read(buffer1, cur < rep ? UNZIP_READ_BUFFER : rem);
1136 if (read == 0)
1137 break;
1138 if (read < 0)
1139 {
1140 (void)inflateEnd(&zstr);
1141 return UnZip::ReadFailed;
1142 }
1143
1144 if (entry.isEncrypted())
1145 decryptBytes(keys, buffer1, read);
1146
1147 cur++;
1148 tot += read;
1149
1150 zstr.avail_in = (uInt) read;
1151 zstr.next_in = (Bytef*) buffer1;
1152
1153
1154 // Run inflate() on input until output buffer not full
1155 do {
1156 zstr.avail_out = UNZIP_READ_BUFFER;
1157 zstr.next_out = (Bytef*) buffer2;;
1158
1159 zret = inflate(&zstr, Z_NO_FLUSH);
1160
1161 switch (zret) {
1162 case Z_NEED_DICT:
1163 case Z_DATA_ERROR:
1164 case Z_MEM_ERROR:
1165 inflateEnd(&zstr);
1166 return UnZip::WriteFailed;
1167 default:
1168 ;
1169 }
1170
1171 szDecomp = UNZIP_READ_BUFFER - zstr.avail_out;
1172 if (dev->write(buffer2, szDecomp) != szDecomp)
1173 {
1174 inflateEnd(&zstr);
1175 return UnZip::ZlibError;
1176 }
1177
1178 myCRC = crc32(myCRC, (const Bytef*) buffer2, szDecomp);
1179
1180 } while (zstr.avail_out == 0);
1181
1182 }
1183 while (zret != Z_STREAM_END);
1184
1185 inflateEnd(&zstr);
1186 }
1187
1188 if (myCRC != entry.crc)
1189 return UnZip::Corrupted;
1190
1191 return UnZip::Ok;
1192}
@ ZlibError
Definition unzip.h:52
@ ReadFailed
Definition unzip.h:59
@ SeekFailed
Definition unzip.h:61
@ Corrupted
Definition unzip.h:55
@ WriteFailed
Definition unzip.h:60
char buffer2[UNZIP_READ_BUFFER]
Definition unzip_p.h:66
UnZip::ErrorCode parseLocalHeaderRecord(const QString &path, ZipEntryP &entry)
Definition unzip.cpp:574
UnZip::ErrorCode testPassword(quint32 *keys, const QString &file, const ZipEntryP &header)
Definition unzip.cpp:1298
void decryptBytes(quint32 *keys, char *buffer, qint64 read)
Definition unzip.cpp:1336
quint32 crc
Definition zipentry_p.h:67
quint32 szComp
Definition zipentry_p.h:68
bool isEncrypted() const
Definition zipentry_p.h:74
quint16 compMethod
Definition zipentry_p.h:64
quint32 dataOffset
Definition zipentry_p.h:62
bool lhEntryChecked
Definition zipentry_p.h:72
#define UNZIP_LOCAL_ENC_HEADER_SIZE
Local header entry encryption header size.
Definition unzip.cpp:87
#define UNZIP_READ_BUFFER
Definition unzip_p.h:49
Here is the call graph for this function:

◆ getULLong()

quint64 getULLong ( const unsigned char *  data,
quint32  offset 
) const
inline

Definition at line 1232 of file unzip.cpp.

1233{
1234 quint64 res = (quint64) data[offset];
1235 res |= (((quint64)data[offset+1]) << 8);
1236 res |= (((quint64)data[offset+2]) << 16);
1237 res |= (((quint64)data[offset+3]) << 24);
1238 res |= (((quint64)data[offset+1]) << 32);
1239 res |= (((quint64)data[offset+2]) << 40);
1240 res |= (((quint64)data[offset+3]) << 48);
1241 res |= (((quint64)data[offset+3]) << 56);
1242
1243 return res;
1244}

◆ getULong()

quint32 getULong ( const unsigned char *  data,
quint32  offset 
) const
inline

Definition at line 1219 of file unzip.cpp.

1220{
1221 quint32 res = (quint32) data[offset];
1222 res |= (((quint32)data[offset+1]) << 8);
1223 res |= (((quint32)data[offset+2]) << 16);
1224 res |= (((quint32)data[offset+3]) << 24);
1225
1226 return res;
1227}

◆ getUShort()

quint16 getUShort ( const unsigned char *  data,
quint32  offset 
) const
inline

Definition at line 1249 of file unzip.cpp.

1250{
1251 return (quint16) data[offset] | (((quint16)data[offset+1]) << 8);
1252}

◆ initKeys()

void initKeys ( const QString &  pwd,
quint32 *  keys 
) const
inline

Definition at line 1278 of file unzip.cpp.

1279{
1280 keys[0] = 305419896L;
1281 keys[1] = 591751049L;
1282 keys[2] = 878082192L;
1283
1284 //QByteArray pwdBytes = pwd.toAscii(); // Qt4
1285 QByteArray pwdBytes = pwd.toLatin1(); // Qt5
1286 int sz = pwdBytes.size();
1287 const char* ascii = pwdBytes.data();
1288
1289 for (int i=0; i<sz; ++i)
1290 updateKeys(keys, (int)ascii[i]);
1291}

◆ openArchive()

UnZip::ErrorCode openArchive ( QIODevice *  device)
Todo:
Ignore CD entry count? CD may be corrupted.

Definition at line 500 of file unzip.cpp.

501{
502 Q_ASSERT(dev != 0);
503
504 if (device != 0)
505 closeArchive();
506
507 device = dev;
508
509 if (!(device->isOpen() || device->open(QIODevice::ReadOnly)))
510 {
511 delete device;
512 device = 0;
513
514 qDebug() << "Unable to open device for reading";
515 return UnZip::OpenFailed;
516 }
517
519
521 if (ec != UnZip::Ok)
522 {
523 closeArchive();
524 return ec;
525 }
526
527 //! \todo Ignore CD entry count? CD may be corrupted.
528 if (cdEntryCount == 0)
529 {
530 return UnZip::Ok;
531 }
532
533 bool continueParsing = true;
534
535 while (continueParsing)
536 {
537 if (device->read(buffer1, 4) != 4)
539
540 if (! (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x01 && buffer1[3] == 0x02) )
541 break;
542
543 if ( (ec = parseCentralDirectoryRecord()) != UnZip::Ok )
544 break;
545 }
546
547 if (ec != UnZip::Ok)
548 closeArchive();
549
550 return ec;
551}
void closeArchive()
Definition unzip.cpp:948
UnZip::ErrorCode seekToCentralDirectory()
Definition unzip.cpp:713
UnZip::ErrorCode parseCentralDirectoryRecord()
Definition unzip.cpp:837
#define UNZIP_CHECK_FOR_VALID_DATA
Checks if some file has been already extracted.
Definition unzip.cpp:139

Referenced by UnZip::openArchive().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseCentralDirectoryRecord()

UnZip::ErrorCode parseCentralDirectoryRecord ( )

Definition at line 837 of file unzip.cpp.

838{
839 // Read CD record
841 return UnZip::ReadFailed;
842
843 bool skipEntry = false;
844
845 // Get compression type so we can skip non compatible algorithms
846 quint16 compMethod = getUShort(uBuffer, UNZIP_CD_OFF_CMETHOD);
847
848 // Get variable size fields length so we can skip the whole record
849 // if necessary
850 quint16 szName = getUShort(uBuffer, UNZIP_CD_OFF_NAMELEN);
851 quint16 szExtra = getUShort(uBuffer, UNZIP_CD_OFF_XLEN);
852 quint16 szComment = getUShort(uBuffer, UNZIP_CD_OFF_COMMLEN);
853
854 quint32 skipLength = szName + szExtra + szComment;
855
857
858 if ((compMethod != 0) && (compMethod != 8))
859 {
860 qDebug() << "Unsupported compression method. Skipping file.";
861 skipEntry = true;
862 }
863
864 // Header parsing may be a problem if version is bigger than UNZIP_VERSION
865 if (!skipEntry && buffer1[UNZIP_CD_OFF_VERSION] > UNZIP_VERSION)
866 {
867 qDebug() << "Unsupported PKZip version. Skipping file.";
868 skipEntry = true;
869 }
870
871 if (!skipEntry && szName == 0)
872 {
873 qDebug() << "Skipping file with no name.";
874 skipEntry = true;
875 }
876
877 if (!skipEntry && device->read(buffer2, szName) != szName)
878 {
880 skipEntry = true;
881 }
882
883 if (skipEntry)
884 {
885 if (ec == UnZip::Ok)
886 {
887 if (!device->seek( device->pos() + skipLength ))
889
891 }
892
893 return ec;
894 }
895
896 //QString filename = QString::fromAscii(buffer2, szName); // Qt4
897 QString filename = QString::fromLatin1(buffer2, szName); // Qt5
898
899 ZipEntryP* h = new ZipEntryP;
900 h->compMethod = compMethod;
901
904
906 h->modTime[1] = buffer1[UNZIP_CD_OFF_MODT + 1];
907
909 h->modDate[1] = buffer1[UNZIP_CD_OFF_MODD + 1];
910
914
915 // Skip extra field (if any)
916 if (szExtra != 0)
917 {
918 if (!device->seek( device->pos() + szExtra ))
919 {
920 delete h;
921 return UnZip::SeekFailed;
922 }
923 }
924
925 // Read comment field (if any)
926 if (szComment != 0)
927 {
928 if (device->read(buffer2, szComment) != szComment)
929 {
930 delete h;
931 return UnZip::ReadFailed;
932 }
933
934 //h->comment = QString::fromAscii(buffer2, szComment); // Qt4
935 h->comment = QString::fromLatin1(buffer2, szComment); // Qt5
936 }
937
939
940 if (headers == 0)
941 headers = new QMap<QString, ZipEntryP*>();
942 headers->insert(filename, h);
943
944 return UnZip::Ok;
945}
quint16 getUShort(const unsigned char *data, quint32 offset) const
Definition unzip.cpp:1249
quint32 getULong(const unsigned char *data, quint32 offset) const
Definition unzip.cpp:1219
unsigned char gpFlag[2]
Definition zipentry_p.h:63
QString comment
Definition zipentry_p.h:70
quint32 szUncomp
Definition zipentry_p.h:69
unsigned char modTime[2]
Definition zipentry_p.h:65
unsigned char modDate[2]
Definition zipentry_p.h:66
quint32 lhOffset
Definition zipentry_p.h:61
#define UNZIP_CD_ENTRY_SIZE_NS
Central Directory file entry size (excluding signature, excluding variable length fields)
Definition unzip.cpp:81
#define UNZIP_CD_OFF_VERSION
Definition unzip.cpp:90
#define UNZIP_CD_OFF_GPFLAG
Definition unzip.cpp:91
#define UNZIP_CD_OFF_MODD
Definition unzip.cpp:94
#define UNZIP_CD_OFF_CMETHOD
Definition unzip.cpp:92
#define UNZIP_CD_OFF_USIZE
Definition unzip.cpp:97
#define UNZIP_VERSION
Definition unzip.cpp:131
#define UNZIP_CD_OFF_XLEN
Definition unzip.cpp:99
#define UNZIP_CD_OFF_LHOFFSET
Definition unzip.cpp:101
#define UNZIP_CD_OFF_NAMELEN
Definition unzip.cpp:98
#define UNZIP_CD_OFF_COMMLEN
Definition unzip.cpp:100
#define UNZIP_CD_OFF_CSIZE
Definition unzip.cpp:96
#define UNZIP_CD_OFF_CRC32
Definition unzip.cpp:95
#define UNZIP_CD_OFF_MODT
Definition unzip.cpp:93

◆ parseLocalHeaderRecord()

UnZip::ErrorCode parseLocalHeaderRecord ( const QString &  path,
ZipEntryP entry 
)

Definition at line 574 of file unzip.cpp.

575{
576 if (!device->seek(entry.lhOffset))
577 return UnZip::SeekFailed;
578
579 // Test signature
580 if (device->read(buffer1, 4) != 4)
581 return UnZip::ReadFailed;
582
583 if ((buffer1[0] != 'P') || (buffer1[1] != 'K') || (buffer1[2] != 0x03) || (buffer1[3] != 0x04))
585
587 return UnZip::ReadFailed;
588
589 /*
590 Check 3rd general purpose bit flag.
591
592 "bit 3: If this bit is set, the fields crc-32, compressed size
593 and uncompressed size are set to zero in the local
594 header. The correct values are put in the data descriptor
595 immediately following the compressed data."
596 */
597 bool hasDataDescriptor = entry.hasDataDescriptor();
598
599 bool checkFailed = false;
600
601 if (!checkFailed)
602 checkFailed = entry.compMethod != getUShort(uBuffer, UNZIP_LH_OFF_CMETHOD);
603 if (!checkFailed)
604 checkFailed = entry.gpFlag[0] != uBuffer[UNZIP_LH_OFF_GPFLAG];
605 if (!checkFailed)
606 checkFailed = entry.gpFlag[1] != uBuffer[UNZIP_LH_OFF_GPFLAG + 1];
607 if (!checkFailed)
608 checkFailed = entry.modTime[0] != uBuffer[UNZIP_LH_OFF_MODT];
609 if (!checkFailed)
610 checkFailed = entry.modTime[1] != uBuffer[UNZIP_LH_OFF_MODT + 1];
611 if (!checkFailed)
612 checkFailed = entry.modDate[0] != uBuffer[UNZIP_LH_OFF_MODD];
613 if (!checkFailed)
614 checkFailed = entry.modDate[1] != uBuffer[UNZIP_LH_OFF_MODD + 1];
615 if (!hasDataDescriptor)
616 {
617 if (!checkFailed)
618 checkFailed = entry.crc != getULong(uBuffer, UNZIP_LH_OFF_CRC32);
619 if (!checkFailed)
620 checkFailed = entry.szComp != getULong(uBuffer, UNZIP_LH_OFF_CSIZE);
621 if (!checkFailed)
622 checkFailed = entry.szUncomp != getULong(uBuffer, UNZIP_LH_OFF_USIZE);
623 }
624
625 if (checkFailed)
627
628 // Check filename
629 quint16 szName = getUShort(uBuffer, UNZIP_LH_OFF_NAMELEN);
630 if (szName == 0)
632
633 if (device->read(buffer2, szName) != szName)
634 return UnZip::ReadFailed;
635
636 //QString filename = QString::fromAscii(buffer2, szName); // Qt4
637 QString filename = QString::fromLatin1(buffer2, szName); // Qt5
638 if (filename != path)
639 {
640 qDebug() << "Filename in local header mismatches.";
642 }
643
644 // Skip extra field
645 quint16 szExtra = getUShort(uBuffer, UNZIP_LH_OFF_XLEN);
646 if (szExtra != 0)
647 {
648 if (!device->seek(device->pos() + szExtra))
649 return UnZip::SeekFailed;
650 }
651
652 entry.dataOffset = device->pos();
653
654 if (hasDataDescriptor)
655 {
656 /*
657 The data descriptor has this OPTIONAL signature: PK\7\8
658 We try to skip the compressed data relying on the size set in the
659 Central Directory record.
660 */
661 if (!device->seek(device->pos() + entry.szComp))
662 return UnZip::SeekFailed;
663
664 // Read 4 bytes and check if there is a data descriptor signature
665 if (device->read(buffer2, 4) != 4)
666 return UnZip::ReadFailed;
667
668 bool hasSignature = buffer2[0] == 'P' && buffer2[1] == 'K' && buffer2[2] == 0x07 && buffer2[3] == 0x08;
669 if (hasSignature)
670 {
672 return UnZip::ReadFailed;
673 }
674 else
675 {
676 if (device->read(buffer2 + 4, UNZIP_DD_SIZE - 4) != UNZIP_DD_SIZE - 4)
677 return UnZip::ReadFailed;
678 }
679
680 // DD: crc, compressed size, uncompressed size
681 if (
682 entry.crc != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CRC32) ||
683 entry.szComp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_CSIZE) ||
684 entry.szUncomp != getULong((unsigned char*)buffer2, UNZIP_DD_OFF_USIZE)
685 )
687 }
688
689 return UnZip::Ok;
690}
@ HeaderConsistencyError
Definition unzip.h:65
@ InvalidArchive
Definition unzip.h:64
bool hasDataDescriptor() const
Definition zipentry_p.h:75
#define UNZIP_LH_OFF_USIZE
Definition unzip.cpp:111
#define UNZIP_LH_OFF_CRC32
Definition unzip.cpp:109
#define UNZIP_DD_OFF_CSIZE
Definition unzip.cpp:117
#define UNZIP_LH_OFF_MODT
Definition unzip.cpp:107
#define UNZIP_LH_OFF_NAMELEN
Definition unzip.cpp:112
#define UNZIP_DD_OFF_CRC32
Definition unzip.cpp:116
#define UNZIP_LOCAL_HEADER_SIZE
Local header size (excluding signature, excluding variable length fields)
Definition unzip.cpp:79
#define UNZIP_LH_OFF_GPFLAG
Definition unzip.cpp:105
#define UNZIP_DD_SIZE
Data descriptor size (excluding signature)
Definition unzip.cpp:83
#define UNZIP_LH_OFF_CSIZE
Definition unzip.cpp:110
#define UNZIP_LH_OFF_MODD
Definition unzip.cpp:108
#define UNZIP_LH_OFF_CMETHOD
Definition unzip.cpp:106
#define UNZIP_DD_OFF_USIZE
Definition unzip.cpp:118
#define UNZIP_LH_OFF_XLEN
Definition unzip.cpp:113
Here is the call graph for this function:

◆ seekToCentralDirectory()

UnZip::ErrorCode seekToCentralDirectory ( )

Definition at line 713 of file unzip.cpp.

714{
715 qint64 length = device->size();
716 qint64 offset = length - UNZIP_EOCD_SIZE;
717
718 if (length < UNZIP_EOCD_SIZE)
720
721 if (!device->seek( offset ))
722 return UnZip::SeekFailed;
723
725 return UnZip::ReadFailed;
726
727 bool eocdFound = (buffer1[0] == 'P' && buffer1[1] == 'K' && buffer1[2] == 0x05 && buffer1[3] == 0x06);
728
729 if (eocdFound)
730 {
731 // Zip file has no comment (the only variable length field in the EOCD record)
732 eocdOffset = offset;
733 }
734 else
735 {
736 qint64 read;
737 char* p = 0;
738
739 offset -= UNZIP_EOCD_SIZE;
740
741 if (offset <= 0)
743
744 if (!device->seek( offset ))
745 return UnZip::SeekFailed;
746
747 while ((read = device->read(buffer1, UNZIP_EOCD_SIZE)) >= 0)
748 {
749 if ( (p = strstr(buffer1, "PK\5\6")) != 0)
750 {
751 // Seek to the start of the EOCD record so we can read it fully
752 // Yes... we could simply read the missing bytes and append them to the buffer
753 // but this is far easier so heck it!
754 device->seek( offset + (p - buffer1) );
755 eocdFound = true;
756 eocdOffset = offset + (p - buffer1);
757
758 // Read EOCD record
760 return UnZip::ReadFailed;
761
762 break;
763 }
764
765 offset -= UNZIP_EOCD_SIZE;
766 if (offset <= 0)
768
769 if (!device->seek( offset ))
770 return UnZip::SeekFailed;
771 }
772 }
773
774 if (!eocdFound)
776
777 // Parse EOCD to locate CD offset
778 offset = getULong((const unsigned char*)buffer1, UNZIP_EOCD_OFF_CDOFF + 4);
779
780 cdOffset = offset;
781
782 cdEntryCount = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_ENTRIES + 4);
783
784 quint16 commentLength = getUShort((const unsigned char*)buffer1, UNZIP_EOCD_OFF_COMMLEN + 4);
785 if (commentLength != 0)
786 {
787 QByteArray c = device->read(commentLength);
788 if (c.count() != commentLength)
789 return UnZip::ReadFailed;
790
791 comment = c;
792 }
793
794 // Seek to the start of the CD record
795 if (!device->seek( cdOffset ))
796 return UnZip::SeekFailed;
797
798 return UnZip::Ok;
799}
#define UNZIP_EOCD_OFF_ENTRIES
Definition unzip.cpp:121
#define UNZIP_EOCD_OFF_CDOFF
Definition unzip.cpp:122
#define UNZIP_EOCD_OFF_COMMLEN
Definition unzip.cpp:123
#define UNZIP_EOCD_SIZE
End Of Central Directory size (including signature, excluding variable length fields)
Definition unzip.cpp:85

◆ testKeys()

bool testKeys ( const ZipEntryP header,
quint32 *  keys 
)

Definition at line 1317 of file unzip.cpp.

1318{
1319 char lastByte;
1320
1321 // decrypt encryption header
1322 for (int i=0; i<11; ++i)
1323 updateKeys(keys, lastByte = buffer1[i] ^ decryptByte(keys[2]));
1324 updateKeys(keys, lastByte = buffer1[11] ^ decryptByte(keys[2]));
1325
1326 // if there is an extended header (bit in the gp flag) buffer[11] is a byte from the file time
1327 // with no extended header we have to check the crc high-order byte
1328 char c = ((header.gpFlag[0] & 0x08) == 8) ? header.modTime[1] : header.crc >> 24;
1329
1330 return (lastByte == c);
1331}

◆ testPassword()

UnZip::ErrorCode testPassword ( quint32 *  keys,
const QString &  file,
const ZipEntryP header 
)

Definition at line 1298 of file unzip.cpp.

1299{
1300 Q_UNUSED(file);
1301
1302 // read encryption keys
1303 if (device->read(buffer1, 12) != 12)
1304 return UnZip::Corrupted;
1305
1306 // Replace this code if you want to i.e. call some dialog and ask the user for a password
1307 initKeys(password, keys);
1308 if (testKeys(header, keys))
1309 return UnZip::Ok;
1310
1311 return UnZip::Skip;
1312}
@ Skip
Definition unzip.h:67
void initKeys(const QString &pwd, quint32 *keys) const
Definition unzip.cpp:1278
bool testKeys(const ZipEntryP &header, quint32 *keys)
Definition unzip.cpp:1317
QString password
Definition unzip_p.h:57

◆ updateKeys()

void updateKeys ( quint32 *  keys,
int  c 
) const
inline

Definition at line 1266 of file unzip.cpp.

1267{
1268 keys[0] = CRC32(keys[0], c);
1269 keys[1] += keys[0] & 0xff;
1270 keys[1] = keys[1] * 134775813L + 1;
1271 keys[2] = CRC32(keys[2], ((int)keys[1]) >> 24);
1272}
#define CRC32(c, b)
CRC32 routine.
Definition unzip.cpp:136

Member Data Documentation

◆ buffer1

char buffer1[UNZIP_READ_BUFFER]

Definition at line 65 of file unzip_p.h.

◆ buffer2

char buffer2[UNZIP_READ_BUFFER]

Definition at line 66 of file unzip_p.h.

◆ cdEntryCount

quint16 cdEntryCount

Definition at line 77 of file unzip_p.h.

◆ cdOffset

quint32 cdOffset

Definition at line 72 of file unzip_p.h.

◆ comment

QString comment

Definition at line 82 of file unzip_p.h.

Referenced by UnZip::archiveComment().

◆ crcTable

const quint32* crcTable

Definition at line 69 of file unzip_p.h.

◆ device

QIODevice* device

Definition at line 63 of file unzip_p.h.

Referenced by UnZip::archiveComment(), UnZip::extractAll(), and UnZip::isOpen().

◆ eocdOffset

quint32 eocdOffset

Definition at line 74 of file unzip_p.h.

◆ headers

◆ password

QString password

Definition at line 57 of file unzip_p.h.

Referenced by UnZip::setPassword().

◆ skipAllEncrypted

bool skipAllEncrypted

Definition at line 59 of file unzip_p.h.

Referenced by UnZip::extractAll().

◆ uBuffer

unsigned char* uBuffer

Definition at line 68 of file unzip_p.h.

◆ unsupportedEntryCount

quint16 unsupportedEntryCount

Definition at line 80 of file unzip_p.h.


The documentation for this class was generated from the following files: