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