Home | History | Annotate | Download | only in 7z
      1 // 7zIn.h
      2 
      3 #ifndef __7Z_IN_H
      4 #define __7Z_IN_H
      5 
      6 #include "../../../Common/MyCom.h"
      7 
      8 #include "../../../Windows/PropVariant.h"
      9 
     10 #include "../../IPassword.h"
     11 #include "../../IStream.h"
     12 
     13 #include "../../Common/CreateCoder.h"
     14 #include "../../Common/InBuffer.h"
     15 
     16 #include "7zItem.h"
     17 
     18 namespace NArchive {
     19 namespace N7z {
     20 
     21 /*
     22   We don't need to init isEncrypted and passwordIsDefined
     23   We must upgrade them only */
     24 
     25 #ifdef _NO_CRYPTO
     26 #define _7Z_DECODER_CRYPRO_VARS_DECL
     27 #define _7Z_DECODER_CRYPRO_VARS
     28 #else
     29 #define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
     30 #define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password
     31 #endif
     32 
     33 struct CParsedMethods
     34 {
     35   Byte Lzma2Prop;
     36   UInt32 LzmaDic;
     37   CRecordVector<UInt64> IDs;
     38 
     39   CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
     40 };
     41 
     42 struct CFolderEx: public CFolder
     43 {
     44   unsigned UnpackCoder;
     45 };
     46 
     47 struct CFolders
     48 {
     49   CNum NumPackStreams;
     50   CNum NumFolders;
     51 
     52   CObjArray<UInt64> PackPositions; // NumPackStreams + 1
     53   // CUInt32DefVector PackCRCs; // we don't use PackCRCs now
     54 
     55   CUInt32DefVector FolderCRCs;             // NumFolders
     56   CObjArray<CNum> NumUnpackStreamsVector;  // NumFolders
     57 
     58   CObjArray<UInt64> CoderUnpackSizes;      // including unpack sizes of bond coders
     59   CObjArray<CNum> FoToCoderUnpackSizes;    // NumFolders + 1
     60   CObjArray<CNum> FoStartPackStreamIndex;  // NumFolders + 1
     61   CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
     62 
     63   CObjArray<size_t> FoCodersDataOffset;    // NumFolders + 1
     64   CByteBuffer CodersData;
     65 
     66   CParsedMethods ParsedMethods;
     67 
     68   void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
     69   void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const
     70   {
     71     ParseFolderInfo(folderIndex, folder);
     72     folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];
     73   }
     74 
     75   unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
     76   {
     77     return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
     78   }
     79 
     80   UInt64 GetFolderUnpackSize(unsigned folderIndex) const
     81   {
     82     return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];
     83   }
     84 
     85   UInt64 GetStreamPackSize(unsigned index) const
     86   {
     87     return PackPositions[index + 1] - PackPositions[index];
     88   }
     89 
     90   CFolders(): NumPackStreams(0), NumFolders(0) {}
     91 
     92   void Clear()
     93   {
     94     NumPackStreams = 0;
     95     PackPositions.Free();
     96     // PackCRCs.Clear();
     97 
     98     NumFolders = 0;
     99     FolderCRCs.Clear();
    100     NumUnpackStreamsVector.Free();
    101     CoderUnpackSizes.Free();
    102     FoToCoderUnpackSizes.Free();
    103     FoStartPackStreamIndex.Free();
    104     FoToMainUnpackSizeIndex.Free();
    105     FoCodersDataOffset.Free();
    106     CodersData.Free();
    107   }
    108 };
    109 
    110 struct CDatabase: public CFolders
    111 {
    112   CRecordVector<CFileItem> Files;
    113 
    114   CUInt64DefVector CTime;
    115   CUInt64DefVector ATime;
    116   CUInt64DefVector MTime;
    117   CUInt64DefVector StartPos;
    118   CUInt32DefVector Attrib;
    119   CBoolVector IsAnti;
    120   /*
    121   CBoolVector IsAux;
    122   CByteBuffer SecureBuf;
    123   CRecordVector<UInt32> SecureIDs;
    124   */
    125 
    126   CByteBuffer NamesBuf;
    127   CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols
    128 
    129   /*
    130   void ClearSecure()
    131   {
    132     SecureBuf.Free();
    133     SecureIDs.Clear();
    134   }
    135   */
    136 
    137   void Clear()
    138   {
    139     CFolders::Clear();
    140     // ClearSecure();
    141 
    142     NamesBuf.Free();
    143     NameOffsets.Free();
    144 
    145     Files.Clear();
    146     CTime.Clear();
    147     ATime.Clear();
    148     MTime.Clear();
    149     StartPos.Clear();
    150     Attrib.Clear();
    151     IsAnti.Clear();
    152     // IsAux.Clear();
    153   }
    154 
    155   bool IsSolid() const
    156   {
    157     for (CNum i = 0; i < NumFolders; i++)
    158       if (NumUnpackStreamsVector[i] > 1)
    159         return true;
    160     return false;
    161   }
    162   bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
    163   // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
    164 
    165   /*
    166   const void* GetName(unsigned index) const
    167   {
    168     if (!NameOffsets || !NamesBuf)
    169       return NULL;
    170     return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
    171   };
    172   */
    173   void GetPath(unsigned index, UString &path) const;
    174   HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
    175 };
    176 
    177 struct CInArchiveInfo
    178 {
    179   CArchiveVersion Version;
    180   UInt64 StartPosition;
    181   UInt64 StartPositionAfterHeader;
    182   UInt64 DataStartPosition;
    183   UInt64 DataStartPosition2;
    184   CRecordVector<UInt64> FileInfoPopIDs;
    185 
    186   void Clear()
    187   {
    188     StartPosition = 0;
    189     StartPositionAfterHeader = 0;
    190     DataStartPosition = 0;
    191     DataStartPosition2 = 0;
    192     FileInfoPopIDs.Clear();
    193   }
    194 };
    195 
    196 struct CDbEx: public CDatabase
    197 {
    198   CInArchiveInfo ArcInfo;
    199 
    200   CObjArray<CNum> FolderStartFileIndex;
    201   CObjArray<CNum> FileIndexToFolderIndexMap;
    202 
    203   UInt64 HeadersSize;
    204   UInt64 PhySize;
    205 
    206   /*
    207   CRecordVector<size_t> SecureOffsets;
    208   bool IsTree;
    209   bool ThereAreAltStreams;
    210   */
    211 
    212   bool IsArc;
    213   bool PhySizeWasConfirmed;
    214 
    215   bool ThereIsHeaderError;
    216   bool UnexpectedEnd;
    217   // bool UnsupportedVersion;
    218 
    219   bool StartHeaderWasRecovered;
    220   bool UnsupportedFeatureWarning;
    221   bool UnsupportedFeatureError;
    222 
    223   /*
    224   void ClearSecureEx()
    225   {
    226     ClearSecure();
    227     SecureOffsets.Clear();
    228   }
    229   */
    230 
    231   void Clear()
    232   {
    233     IsArc = false;
    234     PhySizeWasConfirmed = false;
    235 
    236     ThereIsHeaderError = false;
    237     UnexpectedEnd = false;
    238     // UnsupportedVersion = false;
    239 
    240     StartHeaderWasRecovered = false;
    241     UnsupportedFeatureError = false;
    242     UnsupportedFeatureWarning = false;
    243 
    244     /*
    245     IsTree = false;
    246     ThereAreAltStreams = false;
    247     */
    248 
    249     CDatabase::Clear();
    250 
    251     // SecureOffsets.Clear();
    252     ArcInfo.Clear();
    253     FolderStartFileIndex.Free();
    254     FileIndexToFolderIndexMap.Free();
    255 
    256     HeadersSize = 0;
    257     PhySize = 0;
    258   }
    259 
    260   bool CanUpdate() const
    261   {
    262     if (ThereIsHeaderError
    263         || UnexpectedEnd
    264         || StartHeaderWasRecovered
    265         || UnsupportedFeatureError)
    266       return false;
    267     return true;
    268   }
    269 
    270   void FillLinks();
    271 
    272   UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
    273   {
    274     return ArcInfo.DataStartPosition +
    275         PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
    276   }
    277 
    278   UInt64 GetFolderFullPackSize(CNum folderIndex) const
    279   {
    280     return
    281       PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
    282       PackPositions[FoStartPackStreamIndex[folderIndex]];
    283   }
    284 
    285   UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
    286   {
    287     size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
    288     return PackPositions[i + 1] - PackPositions[i];
    289   }
    290 
    291   UInt64 GetFilePackSize(CNum fileIndex) const
    292   {
    293     CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
    294     if (folderIndex != kNumNoIndex)
    295       if (FolderStartFileIndex[folderIndex] == fileIndex)
    296         return GetFolderFullPackSize(folderIndex);
    297     return 0;
    298   }
    299 };
    300 
    301 const unsigned kNumBufLevelsMax = 4;
    302 
    303 struct CInByte2
    304 {
    305   const Byte *_buffer;
    306 public:
    307   size_t _size;
    308   size_t _pos;
    309 
    310   size_t GetRem() const { return _size - _pos; }
    311   const Byte *GetPtr() const { return _buffer + _pos; }
    312   void Init(const Byte *buffer, size_t size)
    313   {
    314     _buffer = buffer;
    315     _size = size;
    316     _pos = 0;
    317   }
    318   Byte ReadByte();
    319   void ReadBytes(Byte *data, size_t size);
    320   void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
    321   void SkipData(UInt64 size);
    322 
    323   void SkipData();
    324   void SkipRem() { _pos = _size; }
    325   UInt64 ReadNumber();
    326   CNum ReadNum();
    327   UInt32 ReadUInt32();
    328   UInt64 ReadUInt64();
    329 
    330   void ParseFolder(CFolder &folder);
    331 };
    332 
    333 class CStreamSwitch;
    334 
    335 const UInt32 kHeaderSize = 32;
    336 
    337 class CInArchive
    338 {
    339   friend class CStreamSwitch;
    340 
    341   CMyComPtr<IInStream> _stream;
    342 
    343   unsigned _numInByteBufs;
    344   CInByte2 _inByteVector[kNumBufLevelsMax];
    345 
    346   CInByte2 *_inByteBack;
    347   bool ThereIsHeaderError;
    348 
    349   UInt64 _arhiveBeginStreamPosition;
    350   UInt64 _fileEndPosition;
    351 
    352   Byte _header[kHeaderSize];
    353 
    354   UInt64 HeadersSize;
    355 
    356   bool _useMixerMT;
    357 
    358   void AddByteStream(const Byte *buffer, size_t size);
    359 
    360   void DeleteByteStream(bool needUpdatePos)
    361   {
    362     _numInByteBufs--;
    363     if (_numInByteBufs > 0)
    364     {
    365       _inByteBack = &_inByteVector[_numInByteBufs - 1];
    366       if (needUpdatePos)
    367         _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;
    368     }
    369   }
    370 
    371   HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
    372 
    373   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
    374   Byte ReadByte() { return _inByteBack->ReadByte(); }
    375   UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
    376   CNum ReadNum() { return _inByteBack->ReadNum(); }
    377   UInt64 ReadID() { return _inByteBack->ReadNumber(); }
    378   UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
    379   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
    380   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
    381   void SkipData() { _inByteBack->SkipData(); }
    382   void WaitId(UInt64 id);
    383 
    384   void Read_UInt32_Vector(CUInt32DefVector &v);
    385 
    386   void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
    387   void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
    388 
    389   void ReadPackInfo(CFolders &f);
    390 
    391   void ReadUnpackInfo(
    392       const CObjectVector<CByteBuffer> *dataVector,
    393       CFolders &folders);
    394 
    395   void ReadSubStreamsInfo(
    396       CFolders &folders,
    397       CRecordVector<UInt64> &unpackSizes,
    398       CUInt32DefVector &digests);
    399 
    400   void ReadStreamsInfo(
    401       const CObjectVector<CByteBuffer> *dataVector,
    402       UInt64 &dataOffset,
    403       CFolders &folders,
    404       CRecordVector<UInt64> &unpackSizes,
    405       CUInt32DefVector &digests);
    406 
    407   void ReadBoolVector(unsigned numItems, CBoolVector &v);
    408   void ReadBoolVector2(unsigned numItems, CBoolVector &v);
    409   void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
    410       CUInt64DefVector &v, unsigned numItems);
    411   HRESULT ReadAndDecodePackedStreams(
    412       DECL_EXTERNAL_CODECS_LOC_VARS
    413       UInt64 baseOffset, UInt64 &dataOffset,
    414       CObjectVector<CByteBuffer> &dataVector
    415       _7Z_DECODER_CRYPRO_VARS_DECL
    416       );
    417   HRESULT ReadHeader(
    418       DECL_EXTERNAL_CODECS_LOC_VARS
    419       CDbEx &db
    420       _7Z_DECODER_CRYPRO_VARS_DECL
    421       );
    422   HRESULT ReadDatabase2(
    423       DECL_EXTERNAL_CODECS_LOC_VARS
    424       CDbEx &db
    425       _7Z_DECODER_CRYPRO_VARS_DECL
    426       );
    427 public:
    428   CInArchive(bool useMixerMT):
    429       _numInByteBufs(0),
    430       _useMixerMT(useMixerMT)
    431       {}
    432 
    433   HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
    434   void Close();
    435 
    436   HRESULT ReadDatabase(
    437       DECL_EXTERNAL_CODECS_LOC_VARS
    438       CDbEx &db
    439       _7Z_DECODER_CRYPRO_VARS_DECL
    440       );
    441 };
    442 
    443 }}
    444 
    445 #endif
    446