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
16namespace NArchive {
17namespace N7z {
18
19struct CInArchiveInfo
20{
21  CArchiveVersion Version;
22  UInt64 StartPosition;
23  UInt64 StartPositionAfterHeader;
24  UInt64 DataStartPosition;
25  UInt64 DataStartPosition2;
26  CRecordVector<UInt64> FileInfoPopIDs;
27  void Clear()
28  {
29    FileInfoPopIDs.Clear();
30  }
31};
32
33struct 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
44  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
61  void Fill()
62  {
63    FillFolderStartPackStream();
64    FillStartPos();
65    FillFolderStartFileIndex();
66  }
67
68  UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
69  {
70    return ArchiveInfo.DataStartPosition +
71        PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];
72  }
73
74  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
84  UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
85  {
86    return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
87  }
88
89  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
99class CInByte2
100{
101  const Byte *_buffer;
102  size_t _size;
103public:
104  size_t _pos;
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
122class CStreamSwitch;
123
124const UInt32 kHeaderSize = 32;
125
126class 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
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
148  void DeleteByteStream()
149  {
150    _inByteVector.DeleteBack();
151    if (!_inByteVector.IsEmpty())
152      _inByteBack = &_inByteVector.Back();
153  }
154
155private:
156  HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
157
158  void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
159  Byte ReadByte() { return _inByteBack->ReadByte(); }
160  UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
161  CNum ReadNum() { return _inByteBack->ReadNum(); }
162  UInt64 ReadID() { return _inByteBack->ReadNumber(); }
163  UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
164  UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
165  void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
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      );
230public:
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