• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   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 
ClearCDatabase136   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 
IsSolidCDatabase153   bool IsSolid() const
154   {
155     for (CNum i = 0; i < NumFolders; i++)
156       if (NumUnpackStreamsVector[i] > 1)
157         return true;
158     return false;
159   }
IsItemAntiCDatabase160   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 
ClearCInArchiveInfo184   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 
ClearCDbEx229   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 
GetFolderStreamPosCDbEx260   UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
261   {
262     return ArcInfo.DataStartPosition +
263         PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
264   }
265 
GetFolderFullPackSizeCDbEx266   UInt64 GetFolderFullPackSize(CNum folderIndex) const
267   {
268     return
269       PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
270       PackPositions[FoStartPackStreamIndex[folderIndex]];
271   }
272 
GetFolderPackStreamSizeCDbEx273   UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
274   {
275     size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
276     return PackPositions[i + 1] - PackPositions[i];
277   }
278 
GetFilePackSizeCDbEx279   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 
GetRemCInByte2298   size_t GetRem() const { return _size - _pos; }
GetPtrCInByte2299   const Byte *GetPtr() const { return _buffer + _pos; }
InitCInByte2300   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);
SkipDataNoCheckCInByte2308   void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
309   void SkipData(UInt64 size);
310 
311   void SkipData();
SkipRemCInByte2312   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 
DeleteByteStream(bool needUpdatePos)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 
ReadBytes(Byte * data,size_t size)361   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
ReadByte()362   Byte ReadByte() { return _inByteBack->ReadByte(); }
ReadNumber()363   UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
ReadNum()364   CNum ReadNum() { return _inByteBack->ReadNum(); }
ReadID()365   UInt64 ReadID() { return _inByteBack->ReadNumber(); }
ReadUInt32()366   UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
ReadUInt64()367   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
SkipData(UInt64 size)368   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
SkipData()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:
CInArchive(bool useMixerMT)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