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 
CParsedMethodsCParsedMethods39   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 
GetNumFolderUnpackSizesCFolders65   unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
66   {
67     return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex];
68   }
69 
GetFolderUnpackSizeCFolders70   UInt64 GetFolderUnpackSize(unsigned folderIndex) const
71   {
72     return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];
73   }
74 
GetStreamPackSizeCFolders75   UInt64 GetStreamPackSize(unsigned index) const
76   {
77     return PackPositions[index + 1] - PackPositions[index];
78   }
79 
ClearCFolders80   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 
ClearCDatabase124   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 
IsSolidCDatabase141   bool IsSolid() const
142   {
143     for (CNum i = 0; i < NumFolders; i++)
144       if (NumUnpackStreamsVector[i] > 1)
145         return true;
146     return false;
147   }
IsItemAntiCDatabase148   bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
149   // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
150 
GetNameCDatabase151   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 
ClearCInArchiveInfo171   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 
ClearCDbEx215   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 
GetFolderStreamPosCDbEx246   UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const
247   {
248     return ArcInfo.DataStartPosition +
249         PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
250   }
251 
GetFolderFullPackSizeCDbEx252   UInt64 GetFolderFullPackSize(unsigned folderIndex) const
253   {
254     return
255       PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
256       PackPositions[FoStartPackStreamIndex[folderIndex]];
257   }
258 
GetFolderPackStreamSizeCDbEx259   UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const
260   {
261     unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex;
262     return PackPositions[i + 1] - PackPositions[i];
263   }
264 
GetFilePackSizeCDbEx265   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 
GetRemCInByte2284   size_t GetRem() const { return _size - _pos; }
GetPtrCInByte2285   const Byte *GetPtr() const { return _buffer + _pos; }
InitCInByte2286   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);
SkipDataNoCheckCInByte2294   void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
295   void SkipData(UInt64 size);
296 
297   void SkipData();
SkipRemCInByte2298   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 
DeleteByteStream(bool needUpdatePos)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 
ReadBytes(Byte * data,size_t size)346   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
ReadByte()347   Byte ReadByte() { return _inByteBack->ReadByte(); }
ReadNumber()348   UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
ReadNum()349   CNum ReadNum() { return _inByteBack->ReadNum(); }
ReadID()350   UInt64 ReadID() { return _inByteBack->ReadNumber(); }
ReadUInt32()351   UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
ReadUInt64()352   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
SkipData(UInt64 size)353   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
SkipData()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:
CInArchive()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