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 
260   void FillLinks();
261 
GetFolderStreamPosCDbEx262   UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
263   {
264     return ArcInfo.DataStartPosition +
265         PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
266   }
267 
GetFolderFullPackSizeCDbEx268   UInt64 GetFolderFullPackSize(CNum folderIndex) const
269   {
270     return
271       PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
272       PackPositions[FoStartPackStreamIndex[folderIndex]];
273   }
274 
GetFolderPackStreamSizeCDbEx275   UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
276   {
277     size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
278     return PackPositions[i + 1] - PackPositions[i];
279   }
280 
GetFilePackSizeCDbEx281   UInt64 GetFilePackSize(CNum fileIndex) const
282   {
283     CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
284     if (folderIndex != kNumNoIndex)
285       if (FolderStartFileIndex[folderIndex] == fileIndex)
286         return GetFolderFullPackSize(folderIndex);
287     return 0;
288   }
289 };
290 
291 const unsigned kNumBufLevelsMax = 4;
292 
293 struct CInByte2
294 {
295   const Byte *_buffer;
296 public:
297   size_t _size;
298   size_t _pos;
299 
GetRemCInByte2300   size_t GetRem() const { return _size - _pos; }
GetPtrCInByte2301   const Byte *GetPtr() const { return _buffer + _pos; }
InitCInByte2302   void Init(const Byte *buffer, size_t size)
303   {
304     _buffer = buffer;
305     _size = size;
306     _pos = 0;
307   }
308   Byte ReadByte();
309   void ReadBytes(Byte *data, size_t size);
SkipDataNoCheckCInByte2310   void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
311   void SkipData(UInt64 size);
312 
313   void SkipData();
SkipRemCInByte2314   void SkipRem() { _pos = _size; }
315   UInt64 ReadNumber();
316   CNum ReadNum();
317   UInt32 ReadUInt32();
318   UInt64 ReadUInt64();
319 
320   void ParseFolder(CFolder &folder);
321 };
322 
323 class CStreamSwitch;
324 
325 const UInt32 kHeaderSize = 32;
326 
327 class CInArchive
328 {
329   friend class CStreamSwitch;
330 
331   CMyComPtr<IInStream> _stream;
332 
333   unsigned _numInByteBufs;
334   CInByte2 _inByteVector[kNumBufLevelsMax];
335 
336   CInByte2 *_inByteBack;
337   bool ThereIsHeaderError;
338 
339   UInt64 _arhiveBeginStreamPosition;
340   UInt64 _fileEndPosition;
341 
342   Byte _header[kHeaderSize];
343 
344   UInt64 HeadersSize;
345 
346   bool _useMixerMT;
347 
348   void AddByteStream(const Byte *buffer, size_t size);
349 
DeleteByteStream(bool needUpdatePos)350   void DeleteByteStream(bool needUpdatePos)
351   {
352     _numInByteBufs--;
353     if (_numInByteBufs > 0)
354     {
355       _inByteBack = &_inByteVector[_numInByteBufs - 1];
356       if (needUpdatePos)
357         _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;
358     }
359   }
360 
361   HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
362 
ReadBytes(Byte * data,size_t size)363   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
ReadByte()364   Byte ReadByte() { return _inByteBack->ReadByte(); }
ReadNumber()365   UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
ReadNum()366   CNum ReadNum() { return _inByteBack->ReadNum(); }
ReadID()367   UInt64 ReadID() { return _inByteBack->ReadNumber(); }
ReadUInt32()368   UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
ReadUInt64()369   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
SkipData(UInt64 size)370   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
SkipData()371   void SkipData() { _inByteBack->SkipData(); }
372   void WaitId(UInt64 id);
373 
374   void Read_UInt32_Vector(CUInt32DefVector &v);
375 
376   void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
377   void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
378 
379   void ReadPackInfo(CFolders &f);
380 
381   void ReadUnpackInfo(
382       const CObjectVector<CByteBuffer> *dataVector,
383       CFolders &folders);
384 
385   void ReadSubStreamsInfo(
386       CFolders &folders,
387       CRecordVector<UInt64> &unpackSizes,
388       CUInt32DefVector &digests);
389 
390   void ReadStreamsInfo(
391       const CObjectVector<CByteBuffer> *dataVector,
392       UInt64 &dataOffset,
393       CFolders &folders,
394       CRecordVector<UInt64> &unpackSizes,
395       CUInt32DefVector &digests);
396 
397   void ReadBoolVector(unsigned numItems, CBoolVector &v);
398   void ReadBoolVector2(unsigned numItems, CBoolVector &v);
399   void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
400       CUInt64DefVector &v, unsigned numItems);
401   HRESULT ReadAndDecodePackedStreams(
402       DECL_EXTERNAL_CODECS_LOC_VARS
403       UInt64 baseOffset, UInt64 &dataOffset,
404       CObjectVector<CByteBuffer> &dataVector
405       _7Z_DECODER_CRYPRO_VARS_DECL
406       );
407   HRESULT ReadHeader(
408       DECL_EXTERNAL_CODECS_LOC_VARS
409       CDbEx &db
410       _7Z_DECODER_CRYPRO_VARS_DECL
411       );
412   HRESULT ReadDatabase2(
413       DECL_EXTERNAL_CODECS_LOC_VARS
414       CDbEx &db
415       _7Z_DECODER_CRYPRO_VARS_DECL
416       );
417 public:
CInArchive(bool useMixerMT)418   CInArchive(bool useMixerMT):
419       _numInByteBufs(0),
420       _useMixerMT(useMixerMT)
421       {}
422 
423   HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
424   void Close();
425 
426   HRESULT ReadDatabase(
427       DECL_EXTERNAL_CODECS_LOC_VARS
428       CDbEx &db
429       _7Z_DECODER_CRYPRO_VARS_DECL
430       );
431 };
432 
433 }}
434 
435 #endif
436