1 // 7zIn.h
2 
3 #ifndef __7Z_IN_H
4 #define __7Z_IN_H
5 
6 #include "../../IStream.h"
7 #include "../../IPassword.h"
8 #include "../../../Common/MyCom.h"
9 #include "../../Common/InBuffer.h"
10 
11 #include "7zHeader.h"
12 #include "7zItem.h"
13 
14 namespace NArchive {
15 namespace N7z {
16 
17 class CInArchiveException
18 {
19 public:
20   enum CCauseType
21   {
22     kUnsupportedVersion = 0,
23     kUnexpectedEndOfArchive = 0,
24     kIncorrectHeader,
25   } Cause;
26   CInArchiveException(CCauseType cause);
27 };
28 
29 struct CInArchiveInfo
30 {
31   CArchiveVersion Version;
32   UInt64 StartPosition;
33   UInt64 StartPositionAfterHeader;
34   UInt64 DataStartPosition;
35   UInt64 DataStartPosition2;
36   CRecordVector<UInt64> FileInfoPopIDs;
ClearCInArchiveInfo37   void Clear()
38   {
39     FileInfoPopIDs.Clear();
40   }
41 };
42 
43 
44 struct CArchiveDatabaseEx: public CArchiveDatabase
45 {
46   CInArchiveInfo ArchiveInfo;
47   CRecordVector<UInt64> PackStreamStartPositions;
48   CRecordVector<CNum> FolderStartPackStreamIndex;
49   CRecordVector<CNum> FolderStartFileIndex;
50   CRecordVector<CNum> FileIndexToFolderIndexMap;
51 
ClearCArchiveDatabaseEx52   void Clear()
53   {
54     CArchiveDatabase::Clear();
55     ArchiveInfo.Clear();
56     PackStreamStartPositions.Clear();
57     FolderStartPackStreamIndex.Clear();
58     FolderStartFileIndex.Clear();
59     FileIndexToFolderIndexMap.Clear();
60   }
61 
62   void FillFolderStartPackStream();
63   void FillStartPos();
64   void FillFolderStartFileIndex();
65 
FillCArchiveDatabaseEx66   void Fill()
67   {
68     FillFolderStartPackStream();
69     FillStartPos();
70     FillFolderStartFileIndex();
71   }
72 
GetFolderStreamPosCArchiveDatabaseEx73   UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
74   {
75     return ArchiveInfo.DataStartPosition +
76         PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] +
77         indexInFolder];
78   }
79 
GetFolderFullPackSizeCArchiveDatabaseEx80   UInt64 GetFolderFullPackSize(int folderIndex) const
81   {
82     CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];
83     const CFolder &folder = Folders[folderIndex];
84     UInt64 size = 0;
85     for (int i = 0; i < folder.PackStreams.Size(); i++)
86       size += PackSizes[packStreamIndex + i];
87     return size;
88   }
89 
GetFolderPackStreamSizeCArchiveDatabaseEx90   UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
91   {
92     return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
93   }
94 
GetFilePackSizeCArchiveDatabaseEx95   UInt64 GetFilePackSize(CNum fileIndex) const
96   {
97     CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
98     if (folderIndex >= 0)
99     {
100       if (FolderStartFileIndex[folderIndex] == fileIndex)
101         return GetFolderFullPackSize(folderIndex);
102     }
103     return 0;
104   }
105 };
106 
107 class CInByte2
108 {
109   const Byte *_buffer;
110   size_t _size;
111   size_t _pos;
112 public:
Init(const Byte * buffer,size_t size)113   void Init(const Byte *buffer, size_t size)
114   {
115     _buffer = buffer;
116     _size = size;
117     _pos = 0;
118   }
ReadByte(Byte & b)119   bool ReadByte(Byte &b)
120   {
121     if(_pos >= _size)
122       return false;
123     b = _buffer[_pos++];
124     return true;
125   }
ReadBytes(void * data,size_t size,size_t & processedSize)126   void ReadBytes(void *data, size_t size, size_t &processedSize)
127   {
128     for(processedSize = 0; processedSize < size && _pos < _size; processedSize++)
129       ((Byte *)data)[processedSize] = _buffer[_pos++];
130   }
131 
ReadBytes(void * data,size_t size)132   bool ReadBytes(void *data, size_t size)
133   {
134     size_t processedSize;
135     ReadBytes(data, size, processedSize);
136     return (processedSize == size);
137   }
138 
GetProcessedSize()139   size_t GetProcessedSize() const { return _pos; }
140 };
141 
142 class CStreamSwitch;
143 class CInArchive
144 {
145   friend class CStreamSwitch;
146 
147   CMyComPtr<IInStream> _stream;
148   #ifdef _7Z_VOL
149   bool _finishSignature;
150   #endif
151 
152   CObjectVector<CInByte2> _inByteVector;
153   CInByte2 *_inByteBack;
154 
155   UInt64 _arhiveBeginStreamPosition;
156   UInt64 _position;
157 
AddByteStream(const Byte * buffer,size_t size)158   void AddByteStream(const Byte *buffer, size_t size)
159   {
160     _inByteVector.Add(CInByte2());
161     _inByteBack = &_inByteVector.Back();
162     _inByteBack->Init(buffer, size);
163   }
164 
DeleteByteStream()165   void DeleteByteStream()
166   {
167     _inByteVector.DeleteBack();
168     if (!_inByteVector.IsEmpty())
169       _inByteBack = &_inByteVector.Back();
170   }
171 
172 private:
173   HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
174   #ifdef _7Z_VOL
175   HRESULT FindFinishSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
176   #endif
177 
178   HRESULT ReadFileNames(CObjectVector<CFileItem> &files);
179 
180   HRESULT ReadDirect(IInStream *stream, void *data, UInt32 size,
181       UInt32 *processedSize);
182   HRESULT ReadDirect(void *data, UInt32 size, UInt32 *processedSize);
183   HRESULT SafeReadDirect(void *data, UInt32 size);
184   HRESULT SafeReadDirectByte(Byte &b);
185   HRESULT SafeReadDirectUInt32(UInt32 &value);
186   HRESULT SafeReadDirectUInt64(UInt64 &value);
187 
ReadBytes(void * data,size_t size)188   HRESULT ReadBytes(void *data, size_t size)
189   {
190     if (!_inByteBack->ReadBytes(data, size))
191       return E_FAIL;
192     return S_OK;
193   }
194 
ReadByte(Byte & b)195   HRESULT ReadByte(Byte &b)
196   {
197     if (!_inByteBack->ReadByte(b))
198       return E_FAIL;
199     return S_OK;
200   }
201 
ReadWideCharLE(wchar_t & c)202   HRESULT ReadWideCharLE(wchar_t &c)
203   {
204     Byte b1;
205     if (!_inByteBack->ReadByte(b1))
206       return E_FAIL;
207     Byte b2;
208     if (!_inByteBack->ReadByte(b2))
209       return E_FAIL;
210     c = (wchar_t(b2) << 8) + b1;
211     return S_OK;
212   }
213 
214   HRESULT ReadNumber(UInt64 &value);
215   HRESULT ReadNum(CNum &value);
ReadID(UInt64 & value)216   HRESULT ReadID(UInt64 &value) { return ReadNumber(value); }
217   HRESULT ReadUInt32(UInt32 &value);
218   HRESULT ReadUInt64(UInt64 &value);
219 
220   HRESULT SkeepData(UInt64 size);
221   HRESULT SkeepData();
222   HRESULT WaitAttribute(UInt64 attribute);
223 
224   HRESULT ReadArchiveProperties(CInArchiveInfo &archiveInfo);
225   HRESULT GetNextFolderItem(CFolder &itemInfo);
226   HRESULT ReadHashDigests(int numItems,
227       CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests);
228 
229   HRESULT ReadPackInfo(
230       UInt64 &dataOffset,
231       CRecordVector<UInt64> &packSizes,
232       CRecordVector<bool> &packCRCsDefined,
233       CRecordVector<UInt32> &packCRCs);
234 
235   HRESULT ReadUnPackInfo(
236       const CObjectVector<CByteBuffer> *dataVector,
237       CObjectVector<CFolder> &folders);
238 
239   HRESULT ReadSubStreamsInfo(
240       const CObjectVector<CFolder> &folders,
241       CRecordVector<CNum> &numUnPackStreamsInFolders,
242       CRecordVector<UInt64> &unPackSizes,
243       CRecordVector<bool> &digestsDefined,
244       CRecordVector<UInt32> &digests);
245 
246   HRESULT ReadStreamsInfo(
247       const CObjectVector<CByteBuffer> *dataVector,
248       UInt64 &dataOffset,
249       CRecordVector<UInt64> &packSizes,
250       CRecordVector<bool> &packCRCsDefined,
251       CRecordVector<UInt32> &packCRCs,
252       CObjectVector<CFolder> &folders,
253       CRecordVector<CNum> &numUnPackStreamsInFolders,
254       CRecordVector<UInt64> &unPackSizes,
255       CRecordVector<bool> &digestsDefined,
256       CRecordVector<UInt32> &digests);
257 
258 
259   HRESULT GetNextFileItem(CFileItem &itemInfo);
260   HRESULT ReadBoolVector(int numItems, CBoolVector &v);
261   HRESULT ReadBoolVector2(int numItems, CBoolVector &v);
262   HRESULT ReadTime(const CObjectVector<CByteBuffer> &dataVector,
263       CObjectVector<CFileItem> &files, UInt64 type);
264   HRESULT ReadAndDecodePackedStreams(UInt64 baseOffset, UInt64 &dataOffset,
265       CObjectVector<CByteBuffer> &dataVector
266       #ifndef _NO_CRYPTO
267       , ICryptoGetTextPassword *getTextPassword
268       #endif
269       );
270   HRESULT ReadHeader(CArchiveDatabaseEx &database
271       #ifndef _NO_CRYPTO
272       ,ICryptoGetTextPassword *getTextPassword
273       #endif
274       );
275 public:
276   HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
277   void Close();
278 
279   HRESULT ReadDatabase(CArchiveDatabaseEx &database
280       #ifndef _NO_CRYPTO
281       ,ICryptoGetTextPassword *getTextPassword
282       #endif
283       );
284 };
285 
286 }}
287 
288 #endif
289