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 
CParsedMethodsCParsedMethods39   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;
ParseFolderExCFolders69   void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const
70   {
71     ParseFolderInfo(folderIndex, folder);
72     folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];
73   }
74 
GetNumFolderUnpackSizesCFolders75   unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
76   {
77     return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
78   }
79 
GetFolderUnpackSizeCFolders80   UInt64 GetFolderUnpackSize(unsigned folderIndex) const
81   {
82     return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];
83   }
84 
GetStreamPackSizeCFolders85   UInt64 GetStreamPackSize(unsigned index) const
86   {
87     return PackPositions[index + 1] - PackPositions[index];
88   }
89 
CFoldersCFolders90   CFolders(): NumPackStreams(0), NumFolders(0) {}
91 
ClearCFolders92   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 
ClearCDatabase137   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 
IsSolidCDatabase155   bool IsSolid() const
156   {
157     for (CNum i = 0; i < NumFolders; i++)
158       if (NumUnpackStreamsVector[i] > 1)
159         return true;
160     return false;
161   }
IsItemAntiCDatabase162   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 
ClearCInArchiveInfo186   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 
ClearCDbEx231   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 
CanUpdateCDbEx260   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 
GetFolderStreamPosCDbEx272   UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
273   {
274     return ArcInfo.DataStartPosition +
275         PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
276   }
277 
GetFolderFullPackSizeCDbEx278   UInt64 GetFolderFullPackSize(CNum folderIndex) const
279   {
280     return
281       PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
282       PackPositions[FoStartPackStreamIndex[folderIndex]];
283   }
284 
GetFolderPackStreamSizeCDbEx285   UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
286   {
287     size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
288     return PackPositions[i + 1] - PackPositions[i];
289   }
290 
GetFilePackSizeCDbEx291   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 
GetRemCInByte2310   size_t GetRem() const { return _size - _pos; }
GetPtrCInByte2311   const Byte *GetPtr() const { return _buffer + _pos; }
InitCInByte2312   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);
SkipDataNoCheckCInByte2320   void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
321   void SkipData(UInt64 size);
322 
323   void SkipData();
SkipRemCInByte2324   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 
DeleteByteStream(bool needUpdatePos)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 
ReadBytes(Byte * data,size_t size)373   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
ReadByte()374   Byte ReadByte() { return _inByteBack->ReadByte(); }
ReadNumber()375   UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
ReadNum()376   CNum ReadNum() { return _inByteBack->ReadNum(); }
ReadID()377   UInt64 ReadID() { return _inByteBack->ReadNumber(); }
ReadUInt32()378   UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
ReadUInt64()379   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
SkipData(UInt64 size)380   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
SkipData()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:
CInArchive(bool useMixerMT)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