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 
178 struct CInArchiveInfo
179 {
180   CArchiveVersion Version;
181   UInt64 StartPosition;               // in stream
182   UInt64 StartPositionAfterHeader;    // in stream
183   UInt64 DataStartPosition;           // in stream
184   UInt64 DataStartPosition2;          // in stream. it's for headers
185   CRecordVector<UInt64> FileInfoPopIDs;
186 
ClearCInArchiveInfo187   void Clear()
188   {
189     StartPosition = 0;
190     StartPositionAfterHeader = 0;
191     DataStartPosition = 0;
192     DataStartPosition2 = 0;
193     FileInfoPopIDs.Clear();
194   }
195 };
196 
197 
198 struct CDbEx: public CDatabase
199 {
200   CInArchiveInfo ArcInfo;
201 
202   CObjArray<CNum> FolderStartFileIndex;
203   CObjArray<CNum> FileIndexToFolderIndexMap;
204 
205   UInt64 HeadersSize;
206   UInt64 PhySize;
207   // UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes)
208 
209   /*
210   CRecordVector<size_t> SecureOffsets;
211   bool IsTree;
212   bool ThereAreAltStreams;
213   */
214 
215   bool IsArc;
216   bool PhySizeWasConfirmed;
217 
218   bool ThereIsHeaderError;
219   bool UnexpectedEnd;
220   // bool UnsupportedVersion;
221 
222   bool StartHeaderWasRecovered;
223   bool UnsupportedFeatureWarning;
224   bool UnsupportedFeatureError;
225 
226   /*
227   void ClearSecureEx()
228   {
229     ClearSecure();
230     SecureOffsets.Clear();
231   }
232   */
233 
ClearCDbEx234   void Clear()
235   {
236     IsArc = false;
237     PhySizeWasConfirmed = false;
238 
239     ThereIsHeaderError = false;
240     UnexpectedEnd = false;
241     // UnsupportedVersion = false;
242 
243     StartHeaderWasRecovered = false;
244     UnsupportedFeatureError = false;
245     UnsupportedFeatureWarning = false;
246 
247     /*
248     IsTree = false;
249     ThereAreAltStreams = false;
250     */
251 
252     CDatabase::Clear();
253 
254     // SecureOffsets.Clear();
255     ArcInfo.Clear();
256     FolderStartFileIndex.Free();
257     FileIndexToFolderIndexMap.Free();
258 
259     HeadersSize = 0;
260     PhySize = 0;
261     // EndHeaderOffset = 0;
262   }
263 
CanUpdateCDbEx264   bool CanUpdate() const
265   {
266     if (ThereIsHeaderError
267         || UnexpectedEnd
268         || StartHeaderWasRecovered
269         || UnsupportedFeatureError)
270       return false;
271     return true;
272   }
273 
274   void FillLinks();
275 
GetFolderStreamPosCDbEx276   UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
277   {
278     return ArcInfo.DataStartPosition +
279         PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
280   }
281 
GetFolderFullPackSizeCDbEx282   UInt64 GetFolderFullPackSize(CNum folderIndex) const
283   {
284     return
285       PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
286       PackPositions[FoStartPackStreamIndex[folderIndex]];
287   }
288 
GetFolderPackStreamSizeCDbEx289   UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
290   {
291     size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
292     return PackPositions[i + 1] - PackPositions[i];
293   }
294 
GetFilePackSizeCDbEx295   UInt64 GetFilePackSize(CNum fileIndex) const
296   {
297     CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
298     if (folderIndex != kNumNoIndex)
299       if (FolderStartFileIndex[folderIndex] == fileIndex)
300         return GetFolderFullPackSize(folderIndex);
301     return 0;
302   }
303 };
304 
305 const unsigned kNumBufLevelsMax = 4;
306 
307 struct CInByte2
308 {
309   const Byte *_buffer;
310 public:
311   size_t _size;
312   size_t _pos;
313 
GetRemCInByte2314   size_t GetRem() const { return _size - _pos; }
GetPtrCInByte2315   const Byte *GetPtr() const { return _buffer + _pos; }
InitCInByte2316   void Init(const Byte *buffer, size_t size)
317   {
318     _buffer = buffer;
319     _size = size;
320     _pos = 0;
321   }
322   Byte ReadByte();
323   void ReadBytes(Byte *data, size_t size);
SkipDataNoCheckCInByte2324   void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
325   void SkipData(UInt64 size);
326 
327   void SkipData();
SkipRemCInByte2328   void SkipRem() { _pos = _size; }
329   UInt64 ReadNumber();
330   CNum ReadNum();
331   UInt32 ReadUInt32();
332   UInt64 ReadUInt64();
333 
334   void ParseFolder(CFolder &folder);
335 };
336 
337 class CStreamSwitch;
338 
339 const UInt32 kHeaderSize = 32;
340 
341 class CInArchive
342 {
343   friend class CStreamSwitch;
344 
345   CMyComPtr<IInStream> _stream;
346 
347   unsigned _numInByteBufs;
348   CInByte2 _inByteVector[kNumBufLevelsMax];
349 
350   CInByte2 *_inByteBack;
351   bool ThereIsHeaderError;
352 
353   UInt64 _arhiveBeginStreamPosition;
354   UInt64 _fileEndPosition;
355 
356   UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes)
357 
358   Byte _header[kHeaderSize];
359 
360   UInt64 HeadersSize;
361 
362   bool _useMixerMT;
363 
364   void AddByteStream(const Byte *buffer, size_t size);
365 
DeleteByteStream(bool needUpdatePos)366   void DeleteByteStream(bool needUpdatePos)
367   {
368     _numInByteBufs--;
369     if (_numInByteBufs > 0)
370     {
371       _inByteBack = &_inByteVector[_numInByteBufs - 1];
372       if (needUpdatePos)
373         _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;
374     }
375   }
376 
377   HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
378 
ReadBytes(Byte * data,size_t size)379   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
ReadByte()380   Byte ReadByte() { return _inByteBack->ReadByte(); }
ReadNumber()381   UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
ReadNum()382   CNum ReadNum() { return _inByteBack->ReadNum(); }
ReadID()383   UInt64 ReadID() { return _inByteBack->ReadNumber(); }
ReadUInt32()384   UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
ReadUInt64()385   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
SkipData(UInt64 size)386   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
SkipData()387   void SkipData() { _inByteBack->SkipData(); }
388   void WaitId(UInt64 id);
389 
390   void Read_UInt32_Vector(CUInt32DefVector &v);
391 
392   void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
393   void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
394 
395   void ReadPackInfo(CFolders &f);
396 
397   void ReadUnpackInfo(
398       const CObjectVector<CByteBuffer> *dataVector,
399       CFolders &folders);
400 
401   void ReadSubStreamsInfo(
402       CFolders &folders,
403       CRecordVector<UInt64> &unpackSizes,
404       CUInt32DefVector &digests);
405 
406   void ReadStreamsInfo(
407       const CObjectVector<CByteBuffer> *dataVector,
408       UInt64 &dataOffset,
409       CFolders &folders,
410       CRecordVector<UInt64> &unpackSizes,
411       CUInt32DefVector &digests);
412 
413   void ReadBoolVector(unsigned numItems, CBoolVector &v);
414   void ReadBoolVector2(unsigned numItems, CBoolVector &v);
415   void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
416       CUInt64DefVector &v, unsigned numItems);
417   HRESULT ReadAndDecodePackedStreams(
418       DECL_EXTERNAL_CODECS_LOC_VARS
419       UInt64 baseOffset, UInt64 &dataOffset,
420       CObjectVector<CByteBuffer> &dataVector
421       _7Z_DECODER_CRYPRO_VARS_DECL
422       );
423   HRESULT ReadHeader(
424       DECL_EXTERNAL_CODECS_LOC_VARS
425       CDbEx &db
426       _7Z_DECODER_CRYPRO_VARS_DECL
427       );
428   HRESULT ReadDatabase2(
429       DECL_EXTERNAL_CODECS_LOC_VARS
430       CDbEx &db
431       _7Z_DECODER_CRYPRO_VARS_DECL
432       );
433 public:
CInArchive(bool useMixerMT)434   CInArchive(bool useMixerMT):
435       _numInByteBufs(0),
436       _useMixerMT(useMixerMT)
437       {}
438 
439   HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
440   void Close();
441 
442   HRESULT ReadDatabase(
443       DECL_EXTERNAL_CODECS_LOC_VARS
444       CDbEx &db
445       _7Z_DECODER_CRYPRO_VARS_DECL
446       );
447 };
448 
449 }}
450 
451 #endif
452