// 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 |