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   CBoolVector IsAnti;
    119   /*
    120   CBoolVector IsAux;
    121   CByteBuffer SecureBuf;
    122   CRecordVector<UInt32> SecureIDs;
    123   */
    124 
    125   CByteBuffer NamesBuf;
    126   CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols
    127 
    128   /*
    129   void ClearSecure()
    130   {
    131     SecureBuf.Free();
    132     SecureIDs.Clear();
    133   }
    134   */
    135 
    136   void Clear()
    137   {
    138     CFolders::Clear();
    139     // ClearSecure();
    140 
    141     NamesBuf.Free();
    142     NameOffsets.Free();
    143 
    144     Files.Clear();
    145     CTime.Clear();
    146     ATime.Clear();
    147     MTime.Clear();
    148     StartPos.Clear();
    149     IsAnti.Clear();
    150     // IsAux.Clear();
    151   }
    152 
    153   bool IsSolid() const
    154   {
    155     for (CNum i = 0; i < NumFolders; i++)
    156       if (NumUnpackStreamsVector[i] > 1)
    157         return true;
    158     return false;
    159   }
    160   bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
    161   // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
    162 
    163   /*
    164   const void* GetName(unsigned index) const
    165   {
    166     if (!NameOffsets || !NamesBuf)
    167       return NULL;
    168     return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
    169   };
    170   */
    171   void GetPath(unsigned index, UString &path) const;
    172   HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
    173 };
    174 
    175 struct CInArchiveInfo
    176 {
    177   CArchiveVersion Version;
    178   UInt64 StartPosition;
    179   UInt64 StartPositionAfterHeader;
    180   UInt64 DataStartPosition;
    181   UInt64 DataStartPosition2;
    182   CRecordVector<UInt64> FileInfoPopIDs;
    183 
    184   void Clear()
    185   {
    186     StartPosition = 0;
    187     StartPositionAfterHeader = 0;
    188     DataStartPosition = 0;
    189     DataStartPosition2 = 0;
    190     FileInfoPopIDs.Clear();
    191   }
    192 };
    193 
    194 struct CDbEx: public CDatabase
    195 {
    196   CInArchiveInfo ArcInfo;
    197 
    198   CObjArray<CNum> FolderStartFileIndex;
    199   CObjArray<CNum> FileIndexToFolderIndexMap;
    200 
    201   UInt64 HeadersSize;
    202   UInt64 PhySize;
    203 
    204   /*
    205   CRecordVector<size_t> SecureOffsets;
    206   bool IsTree;
    207   bool ThereAreAltStreams;
    208   */
    209 
    210   bool IsArc;
    211   bool PhySizeWasConfirmed;
    212 
    213   bool ThereIsHeaderError;
    214   bool UnexpectedEnd;
    215   // bool UnsupportedVersion;
    216 
    217   bool StartHeaderWasRecovered;
    218   bool UnsupportedFeatureWarning;
    219   bool UnsupportedFeatureError;
    220 
    221   /*
    222   void ClearSecureEx()
    223   {
    224     ClearSecure();
    225     SecureOffsets.Clear();
    226   }
    227   */
    228 
    229   void Clear()
    230   {
    231     IsArc = false;
    232     PhySizeWasConfirmed = false;
    233 
    234     ThereIsHeaderError = false;
    235     UnexpectedEnd = false;
    236     // UnsupportedVersion = false;
    237 
    238     StartHeaderWasRecovered = false;
    239     UnsupportedFeatureError = false;
    240     UnsupportedFeatureWarning = false;
    241 
    242     /*
    243     IsTree = false;
    244     ThereAreAltStreams = false;
    245     */
    246 
    247     CDatabase::Clear();
    248 
    249     // SecureOffsets.Clear();
    250     ArcInfo.Clear();
    251     FolderStartFileIndex.Free();
    252     FileIndexToFolderIndexMap.Free();
    253 
    254     HeadersSize = 0;
    255     PhySize = 0;
    256   }
    257 
    258   void FillLinks();
    259 
    260   UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
    261   {
    262     return ArcInfo.DataStartPosition +
    263         PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
    264   }
    265 
    266   UInt64 GetFolderFullPackSize(CNum folderIndex) const
    267   {
    268     return
    269       PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
    270       PackPositions[FoStartPackStreamIndex[folderIndex]];
    271   }
    272 
    273   UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
    274   {
    275     size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
    276     return PackPositions[i + 1] - PackPositions[i];
    277   }
    278 
    279   UInt64 GetFilePackSize(CNum fileIndex) const
    280   {
    281     CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
    282     if (folderIndex != kNumNoIndex)
    283       if (FolderStartFileIndex[folderIndex] == fileIndex)
    284         return GetFolderFullPackSize(folderIndex);
    285     return 0;
    286   }
    287 };
    288 
    289 const unsigned kNumBufLevelsMax = 4;
    290 
    291 struct CInByte2
    292 {
    293   const Byte *_buffer;
    294 public:
    295   size_t _size;
    296   size_t _pos;
    297 
    298   size_t GetRem() const { return _size - _pos; }
    299   const Byte *GetPtr() const { return _buffer + _pos; }
    300   void Init(const Byte *buffer, size_t size)
    301   {
    302     _buffer = buffer;
    303     _size = size;
    304     _pos = 0;
    305   }
    306   Byte ReadByte();
    307   void ReadBytes(Byte *data, size_t size);
    308   void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
    309   void SkipData(UInt64 size);
    310 
    311   void SkipData();
    312   void SkipRem() { _pos = _size; }
    313   UInt64 ReadNumber();
    314   CNum ReadNum();
    315   UInt32 ReadUInt32();
    316   UInt64 ReadUInt64();
    317 
    318   void ParseFolder(CFolder &folder);
    319 };
    320 
    321 class CStreamSwitch;
    322 
    323 const UInt32 kHeaderSize = 32;
    324 
    325 class CInArchive
    326 {
    327   friend class CStreamSwitch;
    328 
    329   CMyComPtr<IInStream> _stream;
    330 
    331   unsigned _numInByteBufs;
    332   CInByte2 _inByteVector[kNumBufLevelsMax];
    333 
    334   CInByte2 *_inByteBack;
    335   bool ThereIsHeaderError;
    336 
    337   UInt64 _arhiveBeginStreamPosition;
    338   UInt64 _fileEndPosition;
    339 
    340   Byte _header[kHeaderSize];
    341 
    342   UInt64 HeadersSize;
    343 
    344   bool _useMixerMT;
    345 
    346   void AddByteStream(const Byte *buffer, size_t size);
    347 
    348   void DeleteByteStream(bool needUpdatePos)
    349   {
    350     _numInByteBufs--;
    351     if (_numInByteBufs > 0)
    352     {
    353       _inByteBack = &_inByteVector[_numInByteBufs - 1];
    354       if (needUpdatePos)
    355         _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;
    356     }
    357   }
    358 
    359   HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
    360 
    361   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
    362   Byte ReadByte() { return _inByteBack->ReadByte(); }
    363   UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
    364   CNum ReadNum() { return _inByteBack->ReadNum(); }
    365   UInt64 ReadID() { return _inByteBack->ReadNumber(); }
    366   UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
    367   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
    368   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
    369   void SkipData() { _inByteBack->SkipData(); }
    370   void WaitId(UInt64 id);
    371 
    372   void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
    373   void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
    374 
    375   void ReadPackInfo(CFolders &f);
    376 
    377   void ReadUnpackInfo(
    378       const CObjectVector<CByteBuffer> *dataVector,
    379       CFolders &folders);
    380 
    381   void ReadSubStreamsInfo(
    382       CFolders &folders,
    383       CRecordVector<UInt64> &unpackSizes,
    384       CUInt32DefVector &digests);
    385 
    386   void ReadStreamsInfo(
    387       const CObjectVector<CByteBuffer> *dataVector,
    388       UInt64 &dataOffset,
    389       CFolders &folders,
    390       CRecordVector<UInt64> &unpackSizes,
    391       CUInt32DefVector &digests);
    392 
    393   void ReadBoolVector(unsigned numItems, CBoolVector &v);
    394   void ReadBoolVector2(unsigned numItems, CBoolVector &v);
    395   void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
    396       CUInt64DefVector &v, unsigned numItems);
    397   HRESULT ReadAndDecodePackedStreams(
    398       DECL_EXTERNAL_CODECS_LOC_VARS
    399       UInt64 baseOffset, UInt64 &dataOffset,
    400       CObjectVector<CByteBuffer> &dataVector
    401       _7Z_DECODER_CRYPRO_VARS_DECL
    402       );
    403   HRESULT ReadHeader(
    404       DECL_EXTERNAL_CODECS_LOC_VARS
    405       CDbEx &db
    406       _7Z_DECODER_CRYPRO_VARS_DECL
    407       );
    408   HRESULT ReadDatabase2(
    409       DECL_EXTERNAL_CODECS_LOC_VARS
    410       CDbEx &db
    411       _7Z_DECODER_CRYPRO_VARS_DECL
    412       );
    413 public:
    414   CInArchive(bool useMixerMT):
    415       _numInByteBufs(0),
    416       _useMixerMT(useMixerMT)
    417       {}
    418 
    419   HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
    420   void Close();
    421 
    422   HRESULT ReadDatabase(
    423       DECL_EXTERNAL_CODECS_LOC_VARS
    424       CDbEx &db
    425       _7Z_DECODER_CRYPRO_VARS_DECL
    426       );
    427 };
    428 
    429 }}
    430 
    431 #endif
    432