1 // 7zIn.h
2 
3 #ifndef __7Z_IN_H
4 #define __7Z_IN_H
5 
6 #include "../../../Common/MyCom.h"
7 
8 #include "../../IPassword.h"
9 #include "../../IStream.h"
10 
11 #include "../../Common/CreateCoder.h"
12 #include "../../Common/InBuffer.h"
13 
14 #include "7zItem.h"
15 
16 namespace NArchive {
17 namespace N7z {
18 
19 struct CInArchiveInfo
20 {
21   CArchiveVersion Version;
22   UInt64 StartPosition;
23   UInt64 StartPositionAfterHeader;
24   UInt64 DataStartPosition;
25   UInt64 DataStartPosition2;
26   CRecordVector<UInt64> FileInfoPopIDs;
ClearCInArchiveInfo27   void Clear()
28   {
29     FileInfoPopIDs.Clear();
30   }
31 };
32 
33 struct CArchiveDatabaseEx: public CArchiveDatabase
34 {
35   CInArchiveInfo ArchiveInfo;
36   CRecordVector<UInt64> PackStreamStartPositions;
37   CRecordVector<CNum> FolderStartPackStreamIndex;
38   CRecordVector<CNum> FolderStartFileIndex;
39   CRecordVector<CNum> FileIndexToFolderIndexMap;
40 
41   UInt64 HeadersSize;
42   UInt64 PhySize;
43 
ClearCArchiveDatabaseEx44   void Clear()
45   {
46     CArchiveDatabase::Clear();
47     ArchiveInfo.Clear();
48     PackStreamStartPositions.Clear();
49     FolderStartPackStreamIndex.Clear();
50     FolderStartFileIndex.Clear();
51     FileIndexToFolderIndexMap.Clear();
52 
53     HeadersSize = 0;
54     PhySize = 0;
55   }
56 
57   void FillFolderStartPackStream();
58   void FillStartPos();
59   void FillFolderStartFileIndex();
60 
FillCArchiveDatabaseEx61   void Fill()
62   {
63     FillFolderStartPackStream();
64     FillStartPos();
65     FillFolderStartFileIndex();
66   }
67 
GetFolderStreamPosCArchiveDatabaseEx68   UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
69   {
70     return ArchiveInfo.DataStartPosition +
71         PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];
72   }
73 
GetFolderFullPackSizeCArchiveDatabaseEx74   UInt64 GetFolderFullPackSize(int folderIndex) const
75   {
76     CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];
77     const CFolder &folder = Folders[folderIndex];
78     UInt64 size = 0;
79     for (int i = 0; i < folder.PackStreams.Size(); i++)
80       size += PackSizes[packStreamIndex + i];
81     return size;
82   }
83 
GetFolderPackStreamSizeCArchiveDatabaseEx84   UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
85   {
86     return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
87   }
88 
GetFilePackSizeCArchiveDatabaseEx89   UInt64 GetFilePackSize(CNum fileIndex) const
90   {
91     CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
92     if (folderIndex != kNumNoIndex)
93       if (FolderStartFileIndex[folderIndex] == fileIndex)
94         return GetFolderFullPackSize(folderIndex);
95     return 0;
96   }
97 };
98 
99 class CInByte2
100 {
101   const Byte *_buffer;
102   size_t _size;
103 public:
104   size_t _pos;
Init(const Byte * buffer,size_t size)105   void Init(const Byte *buffer, size_t size)
106   {
107     _buffer = buffer;
108     _size = size;
109     _pos = 0;
110   }
111   Byte ReadByte();
112   void ReadBytes(Byte *data, size_t size);
113   void SkipData(UInt64 size);
114   void SkipData();
115   UInt64 ReadNumber();
116   CNum ReadNum();
117   UInt32 ReadUInt32();
118   UInt64 ReadUInt64();
119   void ReadString(UString &s);
120 };
121 
122 class CStreamSwitch;
123 
124 const UInt32 kHeaderSize = 32;
125 
126 class CInArchive
127 {
128   friend class CStreamSwitch;
129 
130   CMyComPtr<IInStream> _stream;
131 
132   CObjectVector<CInByte2> _inByteVector;
133   CInByte2 *_inByteBack;
134 
135   UInt64 _arhiveBeginStreamPosition;
136 
137   Byte _header[kHeaderSize];
138 
139   UInt64 HeadersSize;
140 
AddByteStream(const Byte * buffer,size_t size)141   void AddByteStream(const Byte *buffer, size_t size)
142   {
143     _inByteVector.Add(CInByte2());
144     _inByteBack = &_inByteVector.Back();
145     _inByteBack->Init(buffer, size);
146   }
147 
DeleteByteStream()148   void DeleteByteStream()
149   {
150     _inByteVector.DeleteBack();
151     if (!_inByteVector.IsEmpty())
152       _inByteBack = &_inByteVector.Back();
153   }
154 
155 private:
156   HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
157 
ReadBytes(Byte * data,size_t size)158   void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
ReadByte()159   Byte ReadByte() { return _inByteBack->ReadByte(); }
ReadNumber()160   UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
ReadNum()161   CNum ReadNum() { return _inByteBack->ReadNum(); }
ReadID()162   UInt64 ReadID() { return _inByteBack->ReadNumber(); }
ReadUInt32()163   UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
ReadUInt64()164   UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
SkipData(UInt64 size)165   void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
SkipData()166   void SkipData() { _inByteBack->SkipData(); }
167   void WaitAttribute(UInt64 attribute);
168 
169   void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
170   void GetNextFolderItem(CFolder &itemInfo);
171   void ReadHashDigests(int numItems,
172       CBoolVector &digestsDefined, CRecordVector<UInt32> &digests);
173 
174   void ReadPackInfo(
175       UInt64 &dataOffset,
176       CRecordVector<UInt64> &packSizes,
177       CBoolVector &packCRCsDefined,
178       CRecordVector<UInt32> &packCRCs);
179 
180   void ReadUnpackInfo(
181       const CObjectVector<CByteBuffer> *dataVector,
182       CObjectVector<CFolder> &folders);
183 
184   void ReadSubStreamsInfo(
185       const CObjectVector<CFolder> &folders,
186       CRecordVector<CNum> &numUnpackStreamsInFolders,
187       CRecordVector<UInt64> &unpackSizes,
188       CBoolVector &digestsDefined,
189       CRecordVector<UInt32> &digests);
190 
191   void ReadStreamsInfo(
192       const CObjectVector<CByteBuffer> *dataVector,
193       UInt64 &dataOffset,
194       CRecordVector<UInt64> &packSizes,
195       CBoolVector &packCRCsDefined,
196       CRecordVector<UInt32> &packCRCs,
197       CObjectVector<CFolder> &folders,
198       CRecordVector<CNum> &numUnpackStreamsInFolders,
199       CRecordVector<UInt64> &unpackSizes,
200       CBoolVector &digestsDefined,
201       CRecordVector<UInt32> &digests);
202 
203 
204   void ReadBoolVector(int numItems, CBoolVector &v);
205   void ReadBoolVector2(int numItems, CBoolVector &v);
206   void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
207       CUInt64DefVector &v, int numFiles);
208   HRESULT ReadAndDecodePackedStreams(
209       DECL_EXTERNAL_CODECS_LOC_VARS
210       UInt64 baseOffset, UInt64 &dataOffset,
211       CObjectVector<CByteBuffer> &dataVector
212       #ifndef _NO_CRYPTO
213       , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
214       #endif
215       );
216   HRESULT ReadHeader(
217       DECL_EXTERNAL_CODECS_LOC_VARS
218       CArchiveDatabaseEx &db
219       #ifndef _NO_CRYPTO
220       ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
221       #endif
222       );
223   HRESULT ReadDatabase2(
224       DECL_EXTERNAL_CODECS_LOC_VARS
225       CArchiveDatabaseEx &db
226       #ifndef _NO_CRYPTO
227       ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
228       #endif
229       );
230 public:
231   HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
232   void Close();
233 
234   HRESULT ReadDatabase(
235       DECL_EXTERNAL_CODECS_LOC_VARS
236       CArchiveDatabaseEx &db
237       #ifndef _NO_CRYPTO
238       ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
239       #endif
240       );
241 };
242 
243 }}
244 
245 #endif
246