HRESULT CHandler::Open2(IInStream *stream) { UInt64 archiveStartPos; RINOK(stream->Seek(0, STREAM_SEEK_SET, &archiveStartPos)); const UInt32 kHeaderSize = 0x1C; Byte buf[kHeaderSize]; RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)); UInt32 size = Get16(buf + 4); // UInt32 ver = Get16(buf + 6); // == 0 if (Get32(buf) != 0x78617221 || size != kHeaderSize) return S_FALSE; UInt64 packSize = Get64(buf + 8); UInt64 unpackSize = Get64(buf + 0x10); // UInt32 checkSumAlogo = Get32(buf + 0x18); if (unpackSize >= kXmlSizeMax) return S_FALSE; _dataStartPos = archiveStartPos + kHeaderSize + packSize; char *ss = _xml.GetBuffer((int)unpackSize + 1); NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec; CLimitedSequentialInStream *inStreamLimSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStreamLim(inStreamLimSpec); inStreamLimSpec->SetStream(stream); inStreamLimSpec->Init(packSize); CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream; CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec); outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize); RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL)); if (outStreamLimSpec->GetPos() != (size_t)unpackSize) return S_FALSE; ss[(size_t)unpackSize] = 0; _xml.ReleaseBuffer(); CXml xml; if (!xml.Parse(_xml)) return S_FALSE; if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1) return S_FALSE; const CXmlItem &toc = xml.Root.SubItems[0]; if (!toc.IsTagged("toc")) return S_FALSE; if (!AddItem(toc, _files, -1)) return S_FALSE; return S_OK; }
HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { CRecordVector<UInt64> packSizes; CBoolVector packCRCsDefined; CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; CRecordVector<CNum> numUnpackStreamsInFolders; CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for (int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unpackSize64 = folder.GetUnpackSize(); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.SetCapacity(unpackSize); CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #if !defined(_7ZIP_ST) && !defined(_SFX) , false, 1 #endif ); RINOK(result); if (folder.UnpackCRCDefined) if (CrcCalc(data, unpackSize) != folder.UnpackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) { UInt64 packSize = packSizes[packIndex++]; dataStartPos += packSize; HeadersSize += packSize; } } return S_OK; }
HRESULT CHandler::Open2(IInStream *stream) { const UInt32 kHeaderSize = 0x1C; Byte buf[kHeaderSize]; RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)); UInt32 size = Get16(buf + 4); // UInt32 ver = Get16(buf + 6); // == 1 if (Get32(buf) != 0x78617221 || size != kHeaderSize) return S_FALSE; UInt64 packSize = Get64(buf + 8); UInt64 unpackSize = Get64(buf + 0x10); // _checkSumAlgo = Get32(buf + 0x18); if (packSize >= kXmlPackSizeMax || unpackSize >= kXmlSizeMax) return S_FALSE; _dataStartPos = kHeaderSize + packSize; _phySize = _dataStartPos; _xml.Alloc((size_t)unpackSize + 1); _xmlLen = (size_t)unpackSize; NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec; CLimitedSequentialInStream *inStreamLimSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStreamLim(inStreamLimSpec); inStreamLimSpec->SetStream(stream); inStreamLimSpec->Init(packSize); CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream; CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec); outStreamLimSpec->Init(_xml, (size_t)unpackSize); RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL)); if (outStreamLimSpec->GetPos() != (size_t)unpackSize) return S_FALSE; _xml[(size_t)unpackSize] = 0; if (strlen((const char *)(const Byte *)_xml) != unpackSize) return S_FALSE; CXml xml; if (!xml.Parse((const char *)(const Byte *)_xml)) return S_FALSE; if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1) return S_FALSE; const CXmlItem &toc = xml.Root.SubItems[0]; if (!toc.IsTagged("toc")) return S_FALSE; if (!AddItem(toc, _files, -1)) return S_FALSE; UInt64 totalPackSize = 0; unsigned numMainFiles = 0; FOR_VECTOR (i, _files) { const CFile &file = _files[i]; file.UpdateTotalPackSize(totalPackSize); if (file.Name == "Payload" || file.Name == "Content") { _mainSubfile = i; numMainFiles++; } else if (file.Name == "PackageInfo") _is_pkg = true; } if (numMainFiles > 1) _mainSubfile = -1; _phySize = _dataStartPos + totalPackSize; return S_OK; }