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; } }
void ZLZipHeader::skipEntry(ZLInputStream &stream, const ZLZipHeader &header) { if (header.Flags & 0x08) { stream.seek(header.ExtraLength); ZLZDecompressor decompressor((size_t)-1); while (decompressor.decompress(stream, 0, 2048) == 2048) { } stream.seek(16); } else { stream.seek(header.ExtraLength + header.CompressedSize); } }
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; } }
void ZLZipHeader::skipEntry(ZLInputStream &stream, ZLZipHeader &header) { switch (header.Signature) { default: break; case SignatureLocalFile: if ((header.Flags & 0x08) == 0x08 && header.CompressionMethod != 0) { stream.seek(header.ExtraLength, false); ZLZDecompressor decompressor((std::size_t)-1); std::size_t size; do { size = decompressor.decompress(stream, 0, 2048); header.UncompressedSize += size; } while (size == 2048); //stream.seek(16, false); } else { stream.seek(header.ExtraLength + header.CompressedSize, false); } break; } }
bool PdfBookReader::readReferenceTable(ZLInputStream &stream, int xrefOffset) { while (true) { stream.seek(xrefOffset, true); readLine(stream, myBuffer); stripBuffer(myBuffer); if (myBuffer != "xref") { return false; } while (true) { readLine(stream, myBuffer); stripBuffer(myBuffer); if (myBuffer == "trailer") { break; } const int index = myBuffer.find(' '); const int start = atoi(myBuffer.c_str()); const int len = atoi(myBuffer.c_str() + index + 1); for (int i = 0; i < len; ++i) { readLine(stream, myBuffer); stripBuffer(myBuffer); if (myBuffer.length() != 18) { return false; } const int objectOffset = atoi(myBuffer.c_str()); const int objectGeneration = atoi(myBuffer.c_str() + 11); const bool objectInUse = myBuffer[17] == 'n'; if (objectInUse) { myObjectLocationMap[std::pair<int,int>(start + i, objectGeneration)] = objectOffset; } } } char ch = 0; shared_ptr<PdfObject> trailer = PdfObject::readObject(stream, ch); if (trailer.isNull() || (trailer->type() != PdfObject::DICTIONARY)) { return false; } if (myTrailer.isNull()) { myTrailer = trailer; } PdfDictionaryObject &trailerDictionary = (PdfDictionaryObject&)*trailer; shared_ptr<PdfObject> previous = trailerDictionary["Prev"]; if (previous.isNull()) { return true; } if (previous->type() != PdfObject::INTEGER_NUMBER) { return false; } xrefOffset = ((PdfIntegerObject&)*previous).value(); } }
ZLTarHeaderCache::ZLTarHeaderCache(ZLInputStream &baseStream) { if (!baseStream.open()) { return; } ZLTarHeader header; while (header.read(baseStream)) { if (header.IsRegularFile) { myHeaderMap[header.Name] = header; } baseStream.seek((header.Size + 0x1ff) & -0x200, false); header.erase(); } baseStream.close(); }
void ZLZipHeader::skipEntry(ZLInputStream &stream, ZLZipHeader &header) { switch (header.Signature) { default: break; case SignatureLocalFile: if (header.Flags & 0x08) { stream.seek(header.ExtraLength, false); AppLog("ZLZDecompressor decompressor %d", (size_t)-1); ZLZDecompressor decompressor((size_t)-1); size_t size; do { //AppLog("ZLZipHeader::skipEntry 1"); size = decompressor.decompress(stream, 0, BUFFER_SIZE); //AppLog("decompress size=%d",size); header.UncompressedSize += size; } while (size == BUFFER_SIZE); AppLog("header.UncompressedSize %d",header.UncompressedSize); //stream.seek(16, false); } else { stream.seek(header.ExtraLength + header.CompressedSize, false); } break; } }
bool CHMFileInfo::moveToEntry(ZLInputStream &stream, const std::string &entryName) { RecordMap::const_iterator it = myRecords.find(entryName); if (it == myRecords.end()) { return false; } RecordInfo recordInfo = it->second; if (recordInfo.Section > mySectionInfos.size()) { return false; } if (recordInfo.Section != 0) { // TODO: ??? return false; } stream.seek(mySection0Offset + recordInfo.Offset, true); return true; }
bool PPLBookReader::readDocument(ZLInputStream &stream) { std::cout<<"PPLBookReader::readDocument\n"; if (!stream.open()) { return false; } myModelReader.setMainTextModel(); myModelReader.pushKind(REGULAR); myCurrentParagraph.erase(); myEmptyLineCounter = 0; // "PPL\r\n" stream.seek(5); size_t size; do { size = stream.read(myBuffer, BUFFER_SIZE); myBuffer[size] = '\0'; const char *start = myBuffer; const char *end = myBuffer + size; const char *eol; do { eol = strchr(start, '\n'); if (eol != 0) { if (start < eol) { myConverter->convert(myCurrentParagraph, start, eol); } addParagraph(); start = eol + 1; } else { if (start < end) { myConverter->convert(myCurrentParagraph, start, end); } } } while (eol != 0); } while (size == BUFFER_SIZE); addParagraph(); stream.close(); return true; }
HuffDecompressor::HuffDecompressor(ZLInputStream& stream, const std::vector<unsigned long>::const_iterator beginIt, const std::vector<unsigned long>::const_iterator endIt, const unsigned long endHuffDataOffset, const unsigned long extraFlags) : myExtraFlags(extraFlags), myErrorCode(ERROR_NONE) { const unsigned long huffHeaderOffset = *beginIt; const unsigned long huffRecordsNumber = endIt - beginIt; const unsigned long huffDataOffset = *(beginIt + 1); stream.seek(huffHeaderOffset, true); stream.seek(16, false); unsigned long cacheTableOffset, baseTableOffset; PdbUtil::readUnsignedLongBE(stream, cacheTableOffset); PdbUtil::readUnsignedLongBE(stream, baseTableOffset); myCacheTable = new unsigned long[256]; stream.seek(huffHeaderOffset + cacheTableOffset, true); for (size_t i = 0; i < 256; ++i) { PdbUtil::readUnsignedLongLE(stream, myCacheTable[i]); //LE } myBaseTable = new unsigned long[64]; stream.seek(huffHeaderOffset + baseTableOffset, true); for (size_t i = 0; i < 64; ++i) { PdbUtil::readUnsignedLongLE(stream, myBaseTable[i]); //LE } stream.seek(huffDataOffset + 12, true); PdbUtil::readUnsignedLongBE(stream, myEntryBits); size_t huffDataSize = endHuffDataOffset - huffDataOffset; myData = new unsigned char[huffDataSize]; stream.seek(huffDataOffset, true); if (huffDataSize == stream.read((char*)myData, huffDataSize)) { myDicts = new unsigned char* [huffRecordsNumber - 1]; for(size_t i = 0; i < huffRecordsNumber - 1; ++i) { size_t shift = *(beginIt + i + 1) - huffDataOffset; myDicts[i] = myData + shift; } } else { myErrorCode = ERROR_CORRUPTED_FILE; } myTargetBuffer = 0; myTargetBufferEnd = 0; myTargetBufferPtr = 0; }
shared_ptr<PdfObject> PdfBookReader::readObjectFromLocation(ZLInputStream &stream, const std::pair<int,int> &address) { std::map<std::pair<int,int>,int>::const_iterator jt = myObjectLocationMap.find(address); if (jt == myObjectLocationMap.end()) { return 0; } stream.seek(jt->second, true); char ch = 0; PdfObject::readToken(stream, myBuffer, ch); if (address.first != atoi(myBuffer.c_str())) { return 0; } PdfObject::readToken(stream, myBuffer, ch); if (address.second != atoi(myBuffer.c_str())) { return 0; } PdfObject::readToken(stream, myBuffer, ch); if (myBuffer != "obj") { return 0; } return PdfObject::readObject(stream, ch); }
size_t ZLZDecompressor::decompress(ZLInputStream &stream, char *buffer, size_t maxSize) { while ((myBuffer.length() < maxSize) && (myAvailableSize > 0)) { size_t size = std::min(myAvailableSize, (size_t)IN_BUFFER_SIZE); myZStream->next_in = (Bytef*)myInBuffer; myZStream->avail_in = stream.read(myInBuffer, size); if (myZStream->avail_in == size) { myAvailableSize -= size; } else { myAvailableSize = 0; } while (myZStream->avail_in == 0) { break; } while (myZStream->avail_in > 0) { myZStream->avail_out = OUT_BUFFER_SIZE; myZStream->next_out = (Bytef*)myOutBuffer; int code = ::inflate(myZStream, Z_SYNC_FLUSH); if ((code != Z_OK) && (code != Z_STREAM_END)) { break; } if (OUT_BUFFER_SIZE == myZStream->avail_out) { break; } myBuffer.append(myOutBuffer, OUT_BUFFER_SIZE - myZStream->avail_out); if (code == Z_STREAM_END) { myAvailableSize = 0; stream.seek(0 - myZStream->avail_in, false); break; } } } size_t realSize = std::min(maxSize, myBuffer.length()); if (buffer != 0) { memcpy(buffer, myBuffer.data(), realSize); } myBuffer.erase(0, realSize); return realSize; }
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; }