bool ZLZipHeader::readFrom(ZLInputStream &stream) { size_t startOffset = stream.offset(); Signature = readLong(stream); switch (Signature) { default: return false; case SignatureLocalFile: Version = readShort(stream); Flags = readShort(stream); CompressionMethod = readShort(stream); ModificationTime = readShort(stream); ModificationDate = readShort(stream); CRC32 = readLong(stream); CompressedSize = readLong(stream); UncompressedSize = readLong(stream); if (CompressionMethod == 0 && CompressedSize != UncompressedSize) { ZLLogger::Instance().println("zip", "Different compressed & uncompressed size for stored entry; the uncompressed one will be used."); CompressedSize = UncompressedSize; } NameLength = readShort(stream); ExtraLength = readShort(stream); return stream.offset() == startOffset + 30 && NameLength != 0; case SignatureData: CRC32 = readLong(stream); CompressedSize = readLong(stream); UncompressedSize = readLong(stream); NameLength = 0; ExtraLength = 0; return stream.offset() == startOffset + 16; } }
bool ZLZipHeader::readFrom(ZLInputStream &stream) { size_t startOffset = stream.offset(); Signature = readLong(stream); Version = readShort(stream); Flags = readShort(stream); CompressionMethod = readShort(stream); ModificationTime = readShort(stream); ModificationDate = readShort(stream); CRC32 = readLong(stream); CompressedSize = readLong(stream); UncompressedSize = readLong(stream); NameLength = readShort(stream); ExtraLength = readShort(stream); return (Signature == 0x04034B50) && (stream.offset() == startOffset + 30) && (NameLength != 0); }
ZLZipEntryCache::ZLZipEntryCache(const std::string &containerName, ZLInputStream &containerStream) : myContainerName(containerName) { //ZLLogger::Instance().println("ZipEntryCache", "creating cache for " + containerName); myLastModifiedTime = ZLFile(containerName).lastModified(); if (!containerStream.open()) { return; } ZLZipHeader header; while (header.readFrom(containerStream)) { Info *infoPtr = 0; if (header.Signature == (unsigned long)ZLZipHeader::SignatureLocalFile) { std::string entryName(header.NameLength, '\0'); if ((unsigned int)containerStream.read((char*)entryName.data(), header.NameLength) == header.NameLength) { entryName = AndroidUtil::convertNonUtfString(entryName); Info &info = myInfoMap[entryName]; info.Offset = containerStream.offset() + header.ExtraLength; info.CompressionMethod = header.CompressionMethod; info.CompressedSize = header.CompressedSize; info.UncompressedSize = header.UncompressedSize; infoPtr = &info; } } ZLZipHeader::skipEntry(containerStream, header); if (infoPtr != 0) { infoPtr->UncompressedSize = header.UncompressedSize; } } containerStream.close(); }
ZLZipEntryCache::ZLZipEntryCache(ZLInputStream &baseStream) { if (!baseStream.open()) { return; } ZLZipHeader header; while (header.readFrom(baseStream)) { Info *infoPtr = 0; if (header.Signature == ZLZipHeader::SignatureLocalFile) { std::string entryName(header.NameLength, '\0'); if ((unsigned int)baseStream.read((char*)entryName.data(), header.NameLength) == header.NameLength) { Info &info = myInfoMap[entryName]; info.Offset = baseStream.offset() + header.ExtraLength; info.CompressionMethod = header.CompressionMethod; info.CompressedSize = header.CompressedSize; info.UncompressedSize = header.UncompressedSize; infoPtr = &info; } } ZLZipHeader::skipEntry(baseStream, header); if (infoPtr != 0) { infoPtr->UncompressedSize = header.UncompressedSize; } } baseStream.close(); }
bool ZLTarHeader::read(ZLInputStream &stream) { size_t startOffset = stream.offset(); char fileName[101]; stream.read(fileName, 100); if (fileName[0] == '\0') { return false; } fileName[100] = '\0'; if (Name.empty()) { Name = fileName; } stream.seek(24, false); char fileSizeString[12]; stream.read(fileSizeString, 12); Size = 0; for (int i = 0; i < 12; ++i) { if (!isdigit(fileSizeString[i])) { break; } Size *= 8; Size += fileSizeString[i] - '0'; } stream.seek(20, false); char linkFlag; stream.read(&linkFlag, 1); IsRegularFile = (linkFlag == '\0') || (linkFlag == '0'); stream.seek(355, false); if (((linkFlag == 'L') || (linkFlag == 'K')) && (Name == "././@LongLink") && (Size < 10240)) { Name.erase(); Name.append(Size - 1, '\0'); stream.read(const_cast<char*>(Name.data()), Size - 1); const int skip = 512 - (Size & 0x1ff); stream.seek(skip + 1, false); return (stream.offset() == startOffset + Size + skip + 512) && read(stream); } else { DataOffset = stream.offset(); return DataOffset == startOffset + 512; } }
bool ZLZipHeader::readFrom(ZLInputStream &stream) { std::size_t startOffset = stream.offset(); Signature = readLong(stream); switch (Signature) { default: return stream.offset() == startOffset + 4; case SignatureCentralDirectory: { Version = readLong(stream); Flags = readShort(stream); CompressionMethod = readShort(stream); ModificationTime = readShort(stream); ModificationDate = readShort(stream); CRC32 = readLong(stream); CompressedSize = readLong(stream); UncompressedSize = readLong(stream); if (CompressionMethod == 0 && CompressedSize != UncompressedSize) { ZLLogger::Instance().println("zip", "Different compressed & uncompressed size for stored entry; the uncompressed one will be used."); CompressedSize = UncompressedSize; } NameLength = readShort(stream); ExtraLength = readShort(stream); const unsigned short toSkip = readShort(stream); stream.seek(12 + NameLength + ExtraLength + toSkip, false); return stream.offset() == startOffset + 42 + NameLength + ExtraLength + toSkip; } case SignatureLocalFile: Version = readShort(stream); Flags = readShort(stream); CompressionMethod = readShort(stream); ModificationTime = readShort(stream); ModificationDate = readShort(stream); CRC32 = readLong(stream); CompressedSize = readLong(stream); UncompressedSize = readLong(stream); if (CompressionMethod == 0 && CompressedSize != UncompressedSize) { ZLLogger::Instance().println("zip", "Different compressed & uncompressed size for stored entry; the uncompressed one will be used."); CompressedSize = UncompressedSize; } NameLength = readShort(stream); ExtraLength = readShort(stream); return stream.offset() == startOffset + 30 && NameLength != 0; case SignatureEndOfCentralDirectory: { stream.seek(16, false); const unsigned short toSkip = readShort(stream); stream.seek(toSkip, false); UncompressedSize = 0; return stream.offset() == startOffset + 18 + toSkip; } case SignatureData: CRC32 = readLong(stream); CompressedSize = readLong(stream); UncompressedSize = readLong(stream); NameLength = 0; ExtraLength = 0; return stream.offset() == startOffset + 16; } }
bool CHMFileInfo::init(ZLInputStream &stream) { { // header start if (readString(stream, 4) != "ITSF") { return false; } unsigned long version = readUnsignedDWord(stream); // DWORD total length // DWORD unknown // DWORD timestamp // DWORD language id // 0x10 bytes 1st GUID // 0x10 bytes 2nd GUID // QWORD section 0 offset // QWORD section 0 length stream.seek(4 * 4 + 2 * 0x10 + 2 * 8, false); unsigned long long sectionOffset1 = readUnsignedQWord(stream); unsigned long long sectionLength1 = readUnsignedQWord(stream); mySection0Offset = sectionOffset1 + sectionLength1; // header end // additional header data start if (version > 2) { mySection0Offset = readUnsignedQWord(stream); } // additional header data end stream.seek(sectionOffset1, true); // header section 1 start // directory header start if (readString(stream, 4) != "ITSP") { return false; } // DWORD version // DWORD length // DWORD 0x000A // DWORD chunk size // DWORD density // DWORD depth // DWORD root chunk number // DWORD first chunk number // DWORD last chunk number // DWORD -1 stream.seek(10 * 4, false); unsigned long dirChunkNumber = readUnsignedDWord(stream); // ... stream.seek(36, false); // header section 1 end std::size_t nextOffset = stream.offset(); for (unsigned long i = 0; i < dirChunkNumber; ++i) { nextOffset += 4096; std::string header = readString(stream, 4); if (header == "PMGL") { unsigned long quickRefAreaSize = readUnsignedDWord(stream) % 4096; stream.seek(12, false); std::size_t startOffset = stream.offset(); std::size_t oldOffset = startOffset; while (startOffset < nextOffset - quickRefAreaSize) { int nameLength = readEncodedInteger(stream); std::string name = readString(stream, nameLength); int contentSection = readEncodedInteger(stream); int offset = readEncodedInteger(stream); int length = readEncodedInteger(stream); if (name.substr(0, 2) != "::") { name = ZLUnicodeUtil::toLower(name); } myRecords.insert( std::make_pair( name, CHMFileInfo::RecordInfo(contentSection, offset, length) ) ); startOffset = stream.offset(); if (oldOffset == startOffset) { break; } oldOffset = startOffset; } } else if (header == "PMGI") { unsigned long quickRefAreaSize = readUnsignedDWord(stream); std::size_t startOffset = stream.offset(); std::size_t oldOffset = startOffset; while (startOffset < nextOffset - quickRefAreaSize) { int nameLength = readEncodedInteger(stream); std::string name = readString(stream, nameLength); // chunk number readEncodedInteger(stream); startOffset = stream.offset(); if (oldOffset == startOffset) { break; } oldOffset = startOffset; } } stream.seek(nextOffset, true); if (stream.offset() != nextOffset) { break; } } } { if (!moveToEntry(stream, "::DataSpace/NameList")) { return false; } stream.seek(2, false); const int sectionNumber = readUnsignedWord(stream); for (int i = 0; i < sectionNumber; ++i) { const int length = readUnsignedWord(stream); std::string sectionName; sectionName.reserve(length); for (int j = 0; j < length; ++j) { sectionName += (char)readUnsignedWord(stream); } stream.seek(2, false); mySectionNames.push_back(sectionName); } } { for (unsigned int i = 1; i < mySectionNames.size(); ++i) { RecordMap::const_iterator it = myRecords.find("::DataSpace/Storage/" + mySectionNames[i] + "/Content"); if (it == myRecords.end()) { return false; } RecordInfo recordInfo = it->second; if (recordInfo.Section != 0) { return false; } mySectionInfos.push_back(SectionInfo()); SectionInfo &info = mySectionInfos.back(); info.Offset = mySection0Offset + recordInfo.Offset; info.Length = recordInfo.Length; if (!moveToEntry(stream, "::DataSpace/Storage/" + mySectionNames[i] + "/ControlData")) { return false; } stream.seek(4, false); std::string lzxc = readString(stream, 4); if (lzxc != "LZXC") { return false; } const int version = readUnsignedDWord(stream); if ((version <= 0) || (version > 2)) { return false; } info.ResetInterval = readUnsignedDWord(stream); if (version == 1) { info.ResetInterval /= 0x8000; } info.WindowSizeIndex = (version == 1) ? 0 : 15; { int ws = readUnsignedDWord(stream); if (ws > 0) { while ((ws & 1) == 0) { ws >>= 1; info.WindowSizeIndex++; } } } if (!moveToEntry(stream, "::DataSpace/Storage/" + mySectionNames[i] + "/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTable")) { return false; } stream.seek(4, false); const std::size_t entriesNumber = readUnsignedDWord(stream); if (entriesNumber == 0) { return false; } if (entriesNumber > 2048) { // file size is greater than 60 Mb return false; } info.ResetTable.reserve(entriesNumber); stream.seek(8, false); info.UncompressedSize = readUnsignedQWord(stream); if ((info.UncompressedSize - 1) / 0x8000 != entriesNumber - 1) { return false; } info.CompressedSize = readUnsignedQWord(stream); stream.seek(8, false); std::size_t previous = 0; for (std::size_t j = 0; j < entriesNumber; ++j) { std::size_t value = readUnsignedQWord(stream); if ((j > 0) == (value <= previous)) { return false; } info.ResetTable.push_back(value); previous = value; } } } return true; }