// 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../../Windows/PropVariant.h" #include "../../IPassword.h" #include "../../IStream.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { /* We don't need to init isEncrypted and passwordIsDefined We must upgrade them only */ #ifdef _NO_CRYPTO #define _7Z_DECODER_CRYPRO_VARS_DECL #define _7Z_DECODER_CRYPRO_VARS #else #define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined #define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined #endif struct CParsedMethods { Byte Lzma2Prop; UInt32 LzmaDic; CRecordVector<UInt64> IDs; CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} }; struct CFolders { CNum NumPackStreams; CNum NumFolders; CObjArray<UInt64> PackPositions; // NumPackStreams + 1 // CUInt32DefVector PackCRCs; // we don't use PackCRCs now CUInt32DefVector FolderCRCs; // NumFolders CObjArray<CNum> NumUnpackStreamsVector; // NumFolders CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1 CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1 CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders CObjArray<size_t> FoCodersDataOffset; // NumFolders + 1 CByteBuffer CodersData; CParsedMethods ParsedMethods; void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const; unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const { return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]; } UInt64 GetFolderUnpackSize(unsigned folderIndex) const { return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]]; } UInt64 GetStreamPackSize(unsigned index) const { return PackPositions[index + 1] - PackPositions[index]; } void Clear() { NumPackStreams = 0; PackPositions.Free(); // PackCRCs.Clear(); NumFolders = 0; FolderCRCs.Clear(); NumUnpackStreamsVector.Free(); CoderUnpackSizes.Free(); FoToCoderUnpackSizes.Free(); FoStartPackStreamIndex.Free(); FoToMainUnpackSizeIndex.Free(); FoCodersDataOffset.Free(); CodersData.Free(); } }; struct CDatabase: public CFolders { CRecordVector<CFileItem> Files; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CRecordVector<bool> IsAnti; /* CRecordVector<bool> IsAux; CByteBuffer SecureBuf; CRecordVector<UInt32> SecureIDs; */ CByteBuffer NamesBuf; CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols /* void ClearSecure() { SecureBuf.Free(); SecureIDs.Clear(); } */ void Clear() { CFolders::Clear(); // ClearSecure(); NamesBuf.Free(); NameOffsets.Free(); Files.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); IsAnti.Clear(); // IsAux.Clear(); } bool IsSolid() const { for (CNum i = 0; i < NumFolders; i++) if (NumUnpackStreamsVector[i] > 1) return true; return false; } bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } const void * GetName(unsigned index) const { if (!NameOffsets || !NamesBuf) return NULL; return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); }; void GetPath(unsigned index, UString &path) const; HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); }; struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector<UInt64> FileInfoPopIDs; void Clear() { StartPosition = 0; StartPositionAfterHeader = 0; DataStartPosition = 0; DataStartPosition2 = 0; FileInfoPopIDs.Clear(); } }; struct CDbEx: public CDatabase { CInArchiveInfo ArcInfo; CRecordVector<CNum> FolderStartFileIndex; CRecordVector<CNum> FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; /* CRecordVector<size_t> SecureOffsets; bool IsTree; bool ThereAreAltStreams; */ bool IsArc; bool PhySizeWasConfirmed; bool ThereIsHeaderError; bool UnexpectedEnd; // bool UnsupportedVersion; bool StartHeaderWasRecovered; bool UnsupportedFeatureWarning; bool UnsupportedFeatureError; /* void ClearSecureEx() { ClearSecure(); SecureOffsets.Clear(); } */ void Clear() { IsArc = false; PhySizeWasConfirmed = false; ThereIsHeaderError = false; UnexpectedEnd = false; // UnsupportedVersion = false; StartHeaderWasRecovered = false; UnsupportedFeatureError = false; UnsupportedFeatureWarning = false; /* IsTree = false; ThereAreAltStreams = false; */ CDatabase::Clear(); // SecureOffsets.Clear(); ArcInfo.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); HeadersSize = 0; PhySize = 0; } void FillLinks(); UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const { return ArcInfo.DataStartPosition + PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(unsigned folderIndex) const { return PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - PackPositions[FoStartPackStreamIndex[folderIndex]]; } UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const { unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex; return PackPositions[i + 1] - PackPositions[i]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; const unsigned kNumBufLevelsMax = 4; struct CInByte2 { const Byte *_buffer; public: size_t _size; size_t _pos; size_t GetRem() const { return _size - _pos; } const Byte *GetPtr() const { return _buffer + _pos; } void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } void SkipData(UInt64 size); void SkipData(); void SkipRem() { _pos = _size; } UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ParseFolder(CFolder &folder); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr<IInStream> _stream; unsigned _numInByteBufs; CInByte2 _inByteVector[kNumBufLevelsMax]; CInByte2 *_inByteBack; bool ThereIsHeaderError; UInt64 _arhiveBeginStreamPosition; UInt64 _fileEndPosition; Byte _header[kHeaderSize]; UInt64 HeadersSize; void AddByteStream(const Byte *buffer, size_t size); void DeleteByteStream(bool needUpdatePos) { _numInByteBufs--; if (_numInByteBufs > 0) { _inByteBack = &_inByteVector[_numInByteBufs - 1]; if (needUpdatePos) _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; } } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkipData(UInt64 size) { _inByteBack->SkipData(size); } void SkipData() { _inByteBack->SkipData(); } void WaitId(UInt64 id); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); void ReadPackInfo(CFolders &f); void ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CFolders &folders); void ReadSubStreamsInfo( CFolders &folders, CRecordVector<UInt64> &unpackSizes, CUInt32DefVector &digests); void ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CFolders &folders, CRecordVector<UInt64> &unpackSizes, CUInt32DefVector &digests); void ReadBoolVector(unsigned numItems, CBoolVector &v); void ReadBoolVector2(unsigned numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, unsigned numItems); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector _7Z_DECODER_CRYPRO_VARS_DECL ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db _7Z_DECODER_CRYPRO_VARS_DECL ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db _7Z_DECODER_CRYPRO_VARS_DECL ); public: CInArchive(): _numInByteBufs(0) { } HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db _7Z_DECODER_CRYPRO_VARS_DECL ); }; }} #endif