1*f6dc9357SAndroid Build Coastguard Worker // 7zIn.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
6*f6dc9357SAndroid Build Coastguard Worker #include <wchar.h>
7*f6dc9357SAndroid Build Coastguard Worker #else
8*f6dc9357SAndroid Build Coastguard Worker #include <ctype.h>
9*f6dc9357SAndroid Build Coastguard Worker #endif
10*f6dc9357SAndroid Build Coastguard Worker
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/7zCrc.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyBuffer2.h"
15*f6dc9357SAndroid Build Coastguard Worker // #include "../../../Common/UTFConvert.h"
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
19*f6dc9357SAndroid Build Coastguard Worker
20*f6dc9357SAndroid Build Coastguard Worker #include "7zDecode.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "7zIn.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
24*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
25*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader
28*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
29*f6dc9357SAndroid Build Coastguard Worker #define FORMAT_7Z_RECOVERY
30*f6dc9357SAndroid Build Coastguard Worker #endif
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
33*f6dc9357SAndroid Build Coastguard Worker using namespace NCOM;
34*f6dc9357SAndroid Build Coastguard Worker
35*f6dc9357SAndroid Build Coastguard Worker unsigned BoolVector_CountSum(const CBoolVector &v);
36*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
BoolVector_CountSum(const CBoolVector & v)37*f6dc9357SAndroid Build Coastguard Worker unsigned BoolVector_CountSum(const CBoolVector &v)
38*f6dc9357SAndroid Build Coastguard Worker {
39*f6dc9357SAndroid Build Coastguard Worker unsigned sum = 0;
40*f6dc9357SAndroid Build Coastguard Worker const unsigned size = v.Size();
41*f6dc9357SAndroid Build Coastguard Worker if (size)
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker const bool *p = v.ConstData();
44*f6dc9357SAndroid Build Coastguard Worker const bool * const lim = p + size;
45*f6dc9357SAndroid Build Coastguard Worker do
46*f6dc9357SAndroid Build Coastguard Worker if (*p)
47*f6dc9357SAndroid Build Coastguard Worker sum++;
48*f6dc9357SAndroid Build Coastguard Worker while (++p != lim);
49*f6dc9357SAndroid Build Coastguard Worker }
50*f6dc9357SAndroid Build Coastguard Worker return sum;
51*f6dc9357SAndroid Build Coastguard Worker }
52*f6dc9357SAndroid Build Coastguard Worker
BoolVector_Item_IsValidAndTrue(const CBoolVector & v,unsigned i)53*f6dc9357SAndroid Build Coastguard Worker static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)
54*f6dc9357SAndroid Build Coastguard Worker {
55*f6dc9357SAndroid Build Coastguard Worker return i < v.Size() ? v[i] : false;
56*f6dc9357SAndroid Build Coastguard Worker }
57*f6dc9357SAndroid Build Coastguard Worker
58*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
BoolVector_Fill_False(CBoolVector & v,unsigned size)59*f6dc9357SAndroid Build Coastguard Worker static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
60*f6dc9357SAndroid Build Coastguard Worker {
61*f6dc9357SAndroid Build Coastguard Worker v.ClearAndSetSize(size);
62*f6dc9357SAndroid Build Coastguard Worker bool *p = v.NonConstData();
63*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < size; i++)
64*f6dc9357SAndroid Build Coastguard Worker p[i] = false;
65*f6dc9357SAndroid Build Coastguard Worker }
66*f6dc9357SAndroid Build Coastguard Worker
67*f6dc9357SAndroid Build Coastguard Worker
68*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
69*f6dc9357SAndroid Build Coastguard Worker namespace N7z {
70*f6dc9357SAndroid Build Coastguard Worker
71*f6dc9357SAndroid Build Coastguard Worker #define k_Scan_NumCoders_MAX 64
72*f6dc9357SAndroid Build Coastguard Worker #define k_Scan_NumCodersStreams_in_Folder_MAX 64
73*f6dc9357SAndroid Build Coastguard Worker
74*f6dc9357SAndroid Build Coastguard Worker class CInArchiveException {};
75*f6dc9357SAndroid Build Coastguard Worker class CUnsupportedFeatureException: public CInArchiveException {};
76*f6dc9357SAndroid Build Coastguard Worker
77*f6dc9357SAndroid Build Coastguard Worker Z7_ATTR_NORETURN
ThrowException()78*f6dc9357SAndroid Build Coastguard Worker static void ThrowException() { throw CInArchiveException(); }
79*f6dc9357SAndroid Build Coastguard Worker Z7_ATTR_NORETURN
ThrowEndOfData()80*f6dc9357SAndroid Build Coastguard Worker static inline void ThrowEndOfData() { ThrowException(); }
81*f6dc9357SAndroid Build Coastguard Worker Z7_ATTR_NORETURN
ThrowUnsupported()82*f6dc9357SAndroid Build Coastguard Worker static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); }
83*f6dc9357SAndroid Build Coastguard Worker Z7_ATTR_NORETURN
ThrowIncorrect()84*f6dc9357SAndroid Build Coastguard Worker static inline void ThrowIncorrect() { ThrowException(); }
85*f6dc9357SAndroid Build Coastguard Worker
86*f6dc9357SAndroid Build Coastguard Worker class CStreamSwitch
87*f6dc9357SAndroid Build Coastguard Worker {
88*f6dc9357SAndroid Build Coastguard Worker CInArchive *_archive;
89*f6dc9357SAndroid Build Coastguard Worker bool _needRemove;
90*f6dc9357SAndroid Build Coastguard Worker bool _needUpdatePos;
91*f6dc9357SAndroid Build Coastguard Worker public:
CStreamSwitch()92*f6dc9357SAndroid Build Coastguard Worker CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {}
~CStreamSwitch()93*f6dc9357SAndroid Build Coastguard Worker ~CStreamSwitch() { Remove(); }
94*f6dc9357SAndroid Build Coastguard Worker void Remove();
95*f6dc9357SAndroid Build Coastguard Worker void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos);
96*f6dc9357SAndroid Build Coastguard Worker void Set(CInArchive *archive, const CByteBuffer &byteBuffer);
97*f6dc9357SAndroid Build Coastguard Worker void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);
98*f6dc9357SAndroid Build Coastguard Worker };
99*f6dc9357SAndroid Build Coastguard Worker
Remove()100*f6dc9357SAndroid Build Coastguard Worker void CStreamSwitch::Remove()
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker if (_needRemove)
103*f6dc9357SAndroid Build Coastguard Worker {
104*f6dc9357SAndroid Build Coastguard Worker if (_archive->_inByteBack->GetRem() != 0)
105*f6dc9357SAndroid Build Coastguard Worker _archive->ThereIsHeaderError = true;
106*f6dc9357SAndroid Build Coastguard Worker _archive->DeleteByteStream(_needUpdatePos);
107*f6dc9357SAndroid Build Coastguard Worker _needRemove = false;
108*f6dc9357SAndroid Build Coastguard Worker }
109*f6dc9357SAndroid Build Coastguard Worker }
110*f6dc9357SAndroid Build Coastguard Worker
Set(CInArchive * archive,const Byte * data,size_t size,bool needUpdatePos)111*f6dc9357SAndroid Build Coastguard Worker void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos)
112*f6dc9357SAndroid Build Coastguard Worker {
113*f6dc9357SAndroid Build Coastguard Worker Remove();
114*f6dc9357SAndroid Build Coastguard Worker _archive = archive;
115*f6dc9357SAndroid Build Coastguard Worker _archive->AddByteStream(data, size);
116*f6dc9357SAndroid Build Coastguard Worker _needRemove = true;
117*f6dc9357SAndroid Build Coastguard Worker _needUpdatePos = needUpdatePos;
118*f6dc9357SAndroid Build Coastguard Worker }
119*f6dc9357SAndroid Build Coastguard Worker
Set(CInArchive * archive,const CByteBuffer & byteBuffer)120*f6dc9357SAndroid Build Coastguard Worker void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)
121*f6dc9357SAndroid Build Coastguard Worker {
122*f6dc9357SAndroid Build Coastguard Worker Set(archive, byteBuffer, byteBuffer.Size(), false);
123*f6dc9357SAndroid Build Coastguard Worker }
124*f6dc9357SAndroid Build Coastguard Worker
Set(CInArchive * archive,const CObjectVector<CByteBuffer> * dataVector)125*f6dc9357SAndroid Build Coastguard Worker void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)
126*f6dc9357SAndroid Build Coastguard Worker {
127*f6dc9357SAndroid Build Coastguard Worker Remove();
128*f6dc9357SAndroid Build Coastguard Worker const Byte external = archive->ReadByte();
129*f6dc9357SAndroid Build Coastguard Worker if (external != 0)
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker if (!dataVector)
132*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
133*f6dc9357SAndroid Build Coastguard Worker const CNum dataIndex = archive->ReadNum();
134*f6dc9357SAndroid Build Coastguard Worker if (dataIndex >= dataVector->Size())
135*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
136*f6dc9357SAndroid Build Coastguard Worker Set(archive, (*dataVector)[dataIndex]);
137*f6dc9357SAndroid Build Coastguard Worker }
138*f6dc9357SAndroid Build Coastguard Worker }
139*f6dc9357SAndroid Build Coastguard Worker
AddByteStream(const Byte * buf,size_t size)140*f6dc9357SAndroid Build Coastguard Worker void CInArchive::AddByteStream(const Byte *buf, size_t size)
141*f6dc9357SAndroid Build Coastguard Worker {
142*f6dc9357SAndroid Build Coastguard Worker if (_numInByteBufs == kNumBufLevelsMax)
143*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
144*f6dc9357SAndroid Build Coastguard Worker _inByteBack = &_inByteVector[_numInByteBufs++];
145*f6dc9357SAndroid Build Coastguard Worker _inByteBack->Init(buf, size);
146*f6dc9357SAndroid Build Coastguard Worker }
147*f6dc9357SAndroid Build Coastguard Worker
148*f6dc9357SAndroid Build Coastguard Worker
ReadByte()149*f6dc9357SAndroid Build Coastguard Worker Byte CInByte2::ReadByte()
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker if (_pos >= _size)
152*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
153*f6dc9357SAndroid Build Coastguard Worker return _buffer[_pos++];
154*f6dc9357SAndroid Build Coastguard Worker }
155*f6dc9357SAndroid Build Coastguard Worker
ReadBytes(Byte * data,size_t size)156*f6dc9357SAndroid Build Coastguard Worker void CInByte2::ReadBytes(Byte *data, size_t size)
157*f6dc9357SAndroid Build Coastguard Worker {
158*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
159*f6dc9357SAndroid Build Coastguard Worker return;
160*f6dc9357SAndroid Build Coastguard Worker if (size > _size - _pos)
161*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
162*f6dc9357SAndroid Build Coastguard Worker memcpy(data, _buffer + _pos, size);
163*f6dc9357SAndroid Build Coastguard Worker _pos += size;
164*f6dc9357SAndroid Build Coastguard Worker }
165*f6dc9357SAndroid Build Coastguard Worker
SkipData(UInt64 size)166*f6dc9357SAndroid Build Coastguard Worker void CInByte2::SkipData(UInt64 size)
167*f6dc9357SAndroid Build Coastguard Worker {
168*f6dc9357SAndroid Build Coastguard Worker if (size > _size - _pos)
169*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
170*f6dc9357SAndroid Build Coastguard Worker _pos += (size_t)size;
171*f6dc9357SAndroid Build Coastguard Worker }
172*f6dc9357SAndroid Build Coastguard Worker
SkipData()173*f6dc9357SAndroid Build Coastguard Worker void CInByte2::SkipData()
174*f6dc9357SAndroid Build Coastguard Worker {
175*f6dc9357SAndroid Build Coastguard Worker SkipData(ReadNumber());
176*f6dc9357SAndroid Build Coastguard Worker }
177*f6dc9357SAndroid Build Coastguard Worker
ReadNumberSpec(const Byte * p,size_t size,size_t & processed)178*f6dc9357SAndroid Build Coastguard Worker static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
179*f6dc9357SAndroid Build Coastguard Worker {
180*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
181*f6dc9357SAndroid Build Coastguard Worker {
182*f6dc9357SAndroid Build Coastguard Worker processed = 0;
183*f6dc9357SAndroid Build Coastguard Worker return 0;
184*f6dc9357SAndroid Build Coastguard Worker }
185*f6dc9357SAndroid Build Coastguard Worker
186*f6dc9357SAndroid Build Coastguard Worker const unsigned b = *p++;
187*f6dc9357SAndroid Build Coastguard Worker size--;
188*f6dc9357SAndroid Build Coastguard Worker
189*f6dc9357SAndroid Build Coastguard Worker if ((b & 0x80) == 0)
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker processed = 1;
192*f6dc9357SAndroid Build Coastguard Worker return b;
193*f6dc9357SAndroid Build Coastguard Worker }
194*f6dc9357SAndroid Build Coastguard Worker
195*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
196*f6dc9357SAndroid Build Coastguard Worker {
197*f6dc9357SAndroid Build Coastguard Worker processed = 0;
198*f6dc9357SAndroid Build Coastguard Worker return 0;
199*f6dc9357SAndroid Build Coastguard Worker }
200*f6dc9357SAndroid Build Coastguard Worker
201*f6dc9357SAndroid Build Coastguard Worker UInt64 value = (UInt64)*p;
202*f6dc9357SAndroid Build Coastguard Worker p++;
203*f6dc9357SAndroid Build Coastguard Worker size--;
204*f6dc9357SAndroid Build Coastguard Worker
205*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 1; i < 8; i++)
206*f6dc9357SAndroid Build Coastguard Worker {
207*f6dc9357SAndroid Build Coastguard Worker const unsigned mask = (unsigned)0x80 >> i;
208*f6dc9357SAndroid Build Coastguard Worker if ((b & mask) == 0)
209*f6dc9357SAndroid Build Coastguard Worker {
210*f6dc9357SAndroid Build Coastguard Worker const UInt64 high = b & (mask - 1);
211*f6dc9357SAndroid Build Coastguard Worker value |= (high << (i * 8));
212*f6dc9357SAndroid Build Coastguard Worker processed = i + 1;
213*f6dc9357SAndroid Build Coastguard Worker return value;
214*f6dc9357SAndroid Build Coastguard Worker }
215*f6dc9357SAndroid Build Coastguard Worker
216*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
217*f6dc9357SAndroid Build Coastguard Worker {
218*f6dc9357SAndroid Build Coastguard Worker processed = 0;
219*f6dc9357SAndroid Build Coastguard Worker return 0;
220*f6dc9357SAndroid Build Coastguard Worker }
221*f6dc9357SAndroid Build Coastguard Worker
222*f6dc9357SAndroid Build Coastguard Worker value |= ((UInt64)*p << (i * 8));
223*f6dc9357SAndroid Build Coastguard Worker p++;
224*f6dc9357SAndroid Build Coastguard Worker size--;
225*f6dc9357SAndroid Build Coastguard Worker }
226*f6dc9357SAndroid Build Coastguard Worker
227*f6dc9357SAndroid Build Coastguard Worker processed = 9;
228*f6dc9357SAndroid Build Coastguard Worker return value;
229*f6dc9357SAndroid Build Coastguard Worker }
230*f6dc9357SAndroid Build Coastguard Worker
ReadNumber()231*f6dc9357SAndroid Build Coastguard Worker UInt64 CInByte2::ReadNumber()
232*f6dc9357SAndroid Build Coastguard Worker {
233*f6dc9357SAndroid Build Coastguard Worker size_t processed;
234*f6dc9357SAndroid Build Coastguard Worker const UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed);
235*f6dc9357SAndroid Build Coastguard Worker if (processed == 0)
236*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
237*f6dc9357SAndroid Build Coastguard Worker _pos += processed;
238*f6dc9357SAndroid Build Coastguard Worker return res;
239*f6dc9357SAndroid Build Coastguard Worker }
240*f6dc9357SAndroid Build Coastguard Worker
ReadNum()241*f6dc9357SAndroid Build Coastguard Worker CNum CInByte2::ReadNum()
242*f6dc9357SAndroid Build Coastguard Worker {
243*f6dc9357SAndroid Build Coastguard Worker /*
244*f6dc9357SAndroid Build Coastguard Worker if (_pos < _size)
245*f6dc9357SAndroid Build Coastguard Worker {
246*f6dc9357SAndroid Build Coastguard Worker Byte val = _buffer[_pos];
247*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)val < 0x80)
248*f6dc9357SAndroid Build Coastguard Worker {
249*f6dc9357SAndroid Build Coastguard Worker _pos++;
250*f6dc9357SAndroid Build Coastguard Worker return (unsigned)val;
251*f6dc9357SAndroid Build Coastguard Worker }
252*f6dc9357SAndroid Build Coastguard Worker }
253*f6dc9357SAndroid Build Coastguard Worker */
254*f6dc9357SAndroid Build Coastguard Worker const UInt64 value = ReadNumber();
255*f6dc9357SAndroid Build Coastguard Worker if (value > kNumMax)
256*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
257*f6dc9357SAndroid Build Coastguard Worker return (CNum)value;
258*f6dc9357SAndroid Build Coastguard Worker }
259*f6dc9357SAndroid Build Coastguard Worker
ReadUInt32()260*f6dc9357SAndroid Build Coastguard Worker UInt32 CInByte2::ReadUInt32()
261*f6dc9357SAndroid Build Coastguard Worker {
262*f6dc9357SAndroid Build Coastguard Worker if (_pos + 4 > _size)
263*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
264*f6dc9357SAndroid Build Coastguard Worker const UInt32 res = Get32(_buffer + _pos);
265*f6dc9357SAndroid Build Coastguard Worker _pos += 4;
266*f6dc9357SAndroid Build Coastguard Worker return res;
267*f6dc9357SAndroid Build Coastguard Worker }
268*f6dc9357SAndroid Build Coastguard Worker
ReadUInt64()269*f6dc9357SAndroid Build Coastguard Worker UInt64 CInByte2::ReadUInt64()
270*f6dc9357SAndroid Build Coastguard Worker {
271*f6dc9357SAndroid Build Coastguard Worker if (_pos + 8 > _size)
272*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
273*f6dc9357SAndroid Build Coastguard Worker const UInt64 res = Get64(_buffer + _pos);
274*f6dc9357SAndroid Build Coastguard Worker _pos += 8;
275*f6dc9357SAndroid Build Coastguard Worker return res;
276*f6dc9357SAndroid Build Coastguard Worker }
277*f6dc9357SAndroid Build Coastguard Worker
278*f6dc9357SAndroid Build Coastguard Worker #define Y0 '7'
279*f6dc9357SAndroid Build Coastguard Worker #define Y1 'z'
280*f6dc9357SAndroid Build Coastguard Worker #define Y2 0xBC
281*f6dc9357SAndroid Build Coastguard Worker #define Y3 0xAF
282*f6dc9357SAndroid Build Coastguard Worker #define Y4 0x27
283*f6dc9357SAndroid Build Coastguard Worker #define Y5 0x1C
284*f6dc9357SAndroid Build Coastguard Worker
285*f6dc9357SAndroid Build Coastguard Worker #define IS_SIGNATURE(p)( \
286*f6dc9357SAndroid Build Coastguard Worker (p)[2] == Y2 && \
287*f6dc9357SAndroid Build Coastguard Worker (p)[3] == Y3 && \
288*f6dc9357SAndroid Build Coastguard Worker (p)[5] == Y5 && \
289*f6dc9357SAndroid Build Coastguard Worker (p)[4] == Y4 && \
290*f6dc9357SAndroid Build Coastguard Worker (p)[1] == Y1 && \
291*f6dc9357SAndroid Build Coastguard Worker (p)[0] == Y0)
292*f6dc9357SAndroid Build Coastguard Worker
293*f6dc9357SAndroid Build Coastguard Worker /* FindSignature_10() is allowed to access data up to and including &limit[9].
294*f6dc9357SAndroid Build Coastguard Worker limit[10] access is not allowed.
295*f6dc9357SAndroid Build Coastguard Worker return:
296*f6dc9357SAndroid Build Coastguard Worker (return_ptr < limit) : signature was found at (return_ptr)
297*f6dc9357SAndroid Build Coastguard Worker (return_ptr >= limit) : limit was reached or crossed. So no signature found before limit
298*f6dc9357SAndroid Build Coastguard Worker */
299*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
FindSignature_10(const Byte * p,const Byte * limit)300*f6dc9357SAndroid Build Coastguard Worker static const Byte *FindSignature_10(const Byte *p, const Byte *limit)
301*f6dc9357SAndroid Build Coastguard Worker {
302*f6dc9357SAndroid Build Coastguard Worker for (;;)
303*f6dc9357SAndroid Build Coastguard Worker {
304*f6dc9357SAndroid Build Coastguard Worker for (;;)
305*f6dc9357SAndroid Build Coastguard Worker {
306*f6dc9357SAndroid Build Coastguard Worker if (p >= limit)
307*f6dc9357SAndroid Build Coastguard Worker return limit;
308*f6dc9357SAndroid Build Coastguard Worker const Byte b = p[5];
309*f6dc9357SAndroid Build Coastguard Worker p += 6;
310*f6dc9357SAndroid Build Coastguard Worker if (b == Y0) { break; }
311*f6dc9357SAndroid Build Coastguard Worker if (b == Y1) { p -= 1; break; }
312*f6dc9357SAndroid Build Coastguard Worker if (b == Y2) { p -= 2; break; }
313*f6dc9357SAndroid Build Coastguard Worker if (b == Y3) { p -= 3; break; }
314*f6dc9357SAndroid Build Coastguard Worker if (b == Y4) { p -= 4; break; }
315*f6dc9357SAndroid Build Coastguard Worker if (b == Y5) { p -= 5; break; }
316*f6dc9357SAndroid Build Coastguard Worker }
317*f6dc9357SAndroid Build Coastguard Worker if (IS_SIGNATURE(p - 1))
318*f6dc9357SAndroid Build Coastguard Worker return p - 1;
319*f6dc9357SAndroid Build Coastguard Worker }
320*f6dc9357SAndroid Build Coastguard Worker }
321*f6dc9357SAndroid Build Coastguard Worker
322*f6dc9357SAndroid Build Coastguard Worker
TestStartCrc(const Byte * p)323*f6dc9357SAndroid Build Coastguard Worker static inline bool TestStartCrc(const Byte *p)
324*f6dc9357SAndroid Build Coastguard Worker {
325*f6dc9357SAndroid Build Coastguard Worker return CrcCalc(p + 12, 20) == Get32(p + 8);
326*f6dc9357SAndroid Build Coastguard Worker }
327*f6dc9357SAndroid Build Coastguard Worker
TestSignature2(const Byte * p)328*f6dc9357SAndroid Build Coastguard Worker static inline bool TestSignature2(const Byte *p)
329*f6dc9357SAndroid Build Coastguard Worker {
330*f6dc9357SAndroid Build Coastguard Worker if (!IS_SIGNATURE(p))
331*f6dc9357SAndroid Build Coastguard Worker return false;
332*f6dc9357SAndroid Build Coastguard Worker #ifdef FORMAT_7Z_RECOVERY
333*f6dc9357SAndroid Build Coastguard Worker if (TestStartCrc(p))
334*f6dc9357SAndroid Build Coastguard Worker return true;
335*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 8; i < kHeaderSize; i++)
336*f6dc9357SAndroid Build Coastguard Worker if (p[i] != 0)
337*f6dc9357SAndroid Build Coastguard Worker return false;
338*f6dc9357SAndroid Build Coastguard Worker return (p[6] != 0 || p[7] != 0);
339*f6dc9357SAndroid Build Coastguard Worker #else
340*f6dc9357SAndroid Build Coastguard Worker return TestStartCrc(p);
341*f6dc9357SAndroid Build Coastguard Worker #endif
342*f6dc9357SAndroid Build Coastguard Worker }
343*f6dc9357SAndroid Build Coastguard Worker
344*f6dc9357SAndroid Build Coastguard Worker
FindAndReadSignature(IInStream * stream,const UInt64 * searchHeaderSizeLimit)345*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
346*f6dc9357SAndroid Build Coastguard Worker {
347*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, _header, kHeaderSize))
348*f6dc9357SAndroid Build Coastguard Worker
349*f6dc9357SAndroid Build Coastguard Worker if (TestSignature2(_header))
350*f6dc9357SAndroid Build Coastguard Worker return S_OK;
351*f6dc9357SAndroid Build Coastguard Worker if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
352*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
353*f6dc9357SAndroid Build Coastguard Worker
354*f6dc9357SAndroid Build Coastguard Worker const UInt32 kBufSize = (1 << 15) + kHeaderSize; // must be > (kHeaderSize * 2)
355*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer1 buf(kBufSize);
356*f6dc9357SAndroid Build Coastguard Worker memcpy(buf, _header, kHeaderSize);
357*f6dc9357SAndroid Build Coastguard Worker UInt64 offset = 0;
358*f6dc9357SAndroid Build Coastguard Worker
359*f6dc9357SAndroid Build Coastguard Worker for (;;)
360*f6dc9357SAndroid Build Coastguard Worker {
361*f6dc9357SAndroid Build Coastguard Worker UInt32 readSize =
362*f6dc9357SAndroid Build Coastguard Worker (offset == 0) ?
363*f6dc9357SAndroid Build Coastguard Worker kBufSize - kHeaderSize - kHeaderSize :
364*f6dc9357SAndroid Build Coastguard Worker kBufSize - kHeaderSize;
365*f6dc9357SAndroid Build Coastguard Worker if (searchHeaderSizeLimit)
366*f6dc9357SAndroid Build Coastguard Worker {
367*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = *searchHeaderSizeLimit - offset;
368*f6dc9357SAndroid Build Coastguard Worker if (readSize > rem)
369*f6dc9357SAndroid Build Coastguard Worker readSize = (UInt32)rem;
370*f6dc9357SAndroid Build Coastguard Worker if (readSize == 0)
371*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
372*f6dc9357SAndroid Build Coastguard Worker }
373*f6dc9357SAndroid Build Coastguard Worker
374*f6dc9357SAndroid Build Coastguard Worker UInt32 processed = 0;
375*f6dc9357SAndroid Build Coastguard Worker RINOK(stream->Read(buf + kHeaderSize, readSize, &processed))
376*f6dc9357SAndroid Build Coastguard Worker if (processed == 0)
377*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
378*f6dc9357SAndroid Build Coastguard Worker
379*f6dc9357SAndroid Build Coastguard Worker /* &buf[0] was already tested for signature before.
380*f6dc9357SAndroid Build Coastguard Worker So first search here will be for &buf[1] */
381*f6dc9357SAndroid Build Coastguard Worker
382*f6dc9357SAndroid Build Coastguard Worker for (UInt32 pos = 0;;)
383*f6dc9357SAndroid Build Coastguard Worker {
384*f6dc9357SAndroid Build Coastguard Worker const Byte *p = buf + pos + 1;
385*f6dc9357SAndroid Build Coastguard Worker const Byte *lim = buf + processed + 1;
386*f6dc9357SAndroid Build Coastguard Worker /* we have (kHeaderSize - 1 = 31) filled bytes starting from (lim),
387*f6dc9357SAndroid Build Coastguard Worker and it's safe to access just 10 bytes in that reserved area */
388*f6dc9357SAndroid Build Coastguard Worker p = FindSignature_10(p, lim);
389*f6dc9357SAndroid Build Coastguard Worker if (p >= lim)
390*f6dc9357SAndroid Build Coastguard Worker break;
391*f6dc9357SAndroid Build Coastguard Worker pos = (UInt32)(p - buf);
392*f6dc9357SAndroid Build Coastguard Worker if (TestStartCrc(p))
393*f6dc9357SAndroid Build Coastguard Worker {
394*f6dc9357SAndroid Build Coastguard Worker memcpy(_header, p, kHeaderSize);
395*f6dc9357SAndroid Build Coastguard Worker _arhiveBeginStreamPosition += offset + pos;
396*f6dc9357SAndroid Build Coastguard Worker return InStream_SeekSet(stream, _arhiveBeginStreamPosition + kHeaderSize);
397*f6dc9357SAndroid Build Coastguard Worker }
398*f6dc9357SAndroid Build Coastguard Worker }
399*f6dc9357SAndroid Build Coastguard Worker
400*f6dc9357SAndroid Build Coastguard Worker offset += processed;
401*f6dc9357SAndroid Build Coastguard Worker memmove(buf, buf + processed, kHeaderSize);
402*f6dc9357SAndroid Build Coastguard Worker }
403*f6dc9357SAndroid Build Coastguard Worker }
404*f6dc9357SAndroid Build Coastguard Worker
405*f6dc9357SAndroid Build Coastguard Worker // S_FALSE means that file is not archive
Open(IInStream * stream,const UInt64 * searchHeaderSizeLimit)406*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
407*f6dc9357SAndroid Build Coastguard Worker {
408*f6dc9357SAndroid Build Coastguard Worker HeadersSize = 0;
409*f6dc9357SAndroid Build Coastguard Worker Close();
410*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetPos_GetSize(stream, _arhiveBeginStreamPosition, _fileEndPosition))
411*f6dc9357SAndroid Build Coastguard Worker RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit))
412*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
413*f6dc9357SAndroid Build Coastguard Worker return S_OK;
414*f6dc9357SAndroid Build Coastguard Worker }
415*f6dc9357SAndroid Build Coastguard Worker
Close()416*f6dc9357SAndroid Build Coastguard Worker void CInArchive::Close()
417*f6dc9357SAndroid Build Coastguard Worker {
418*f6dc9357SAndroid Build Coastguard Worker _numInByteBufs = 0;
419*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
420*f6dc9357SAndroid Build Coastguard Worker ThereIsHeaderError = false;
421*f6dc9357SAndroid Build Coastguard Worker }
422*f6dc9357SAndroid Build Coastguard Worker
ReadArchiveProperties(CInArchiveInfo &)423*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
424*f6dc9357SAndroid Build Coastguard Worker {
425*f6dc9357SAndroid Build Coastguard Worker for (;;)
426*f6dc9357SAndroid Build Coastguard Worker {
427*f6dc9357SAndroid Build Coastguard Worker if (ReadID() == NID::kEnd)
428*f6dc9357SAndroid Build Coastguard Worker break;
429*f6dc9357SAndroid Build Coastguard Worker SkipData();
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker }
432*f6dc9357SAndroid Build Coastguard Worker
433*f6dc9357SAndroid Build Coastguard Worker // CFolder &folder can be non empty. So we must set all fields
434*f6dc9357SAndroid Build Coastguard Worker
ParseFolder(CFolder & folder)435*f6dc9357SAndroid Build Coastguard Worker void CInByte2::ParseFolder(CFolder &folder)
436*f6dc9357SAndroid Build Coastguard Worker {
437*f6dc9357SAndroid Build Coastguard Worker const UInt32 numCoders = ReadNum();
438*f6dc9357SAndroid Build Coastguard Worker
439*f6dc9357SAndroid Build Coastguard Worker if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
440*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
441*f6dc9357SAndroid Build Coastguard Worker
442*f6dc9357SAndroid Build Coastguard Worker folder.Coders.SetSize(numCoders);
443*f6dc9357SAndroid Build Coastguard Worker
444*f6dc9357SAndroid Build Coastguard Worker UInt32 numInStreams = 0;
445*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
446*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numCoders; i++)
447*f6dc9357SAndroid Build Coastguard Worker {
448*f6dc9357SAndroid Build Coastguard Worker CCoderInfo &coder = folder.Coders[i];
449*f6dc9357SAndroid Build Coastguard Worker {
450*f6dc9357SAndroid Build Coastguard Worker const Byte mainByte = ReadByte();
451*f6dc9357SAndroid Build Coastguard Worker if ((mainByte & 0xC0) != 0)
452*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
453*f6dc9357SAndroid Build Coastguard Worker const unsigned idSize = (mainByte & 0xF);
454*f6dc9357SAndroid Build Coastguard Worker if (idSize > 8 || idSize > GetRem())
455*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
456*f6dc9357SAndroid Build Coastguard Worker const Byte *longID = GetPtr();
457*f6dc9357SAndroid Build Coastguard Worker UInt64 id = 0;
458*f6dc9357SAndroid Build Coastguard Worker for (unsigned j = 0; j < idSize; j++)
459*f6dc9357SAndroid Build Coastguard Worker id = ((id << 8) | longID[j]);
460*f6dc9357SAndroid Build Coastguard Worker SkipDataNoCheck(idSize);
461*f6dc9357SAndroid Build Coastguard Worker coder.MethodID = id;
462*f6dc9357SAndroid Build Coastguard Worker
463*f6dc9357SAndroid Build Coastguard Worker if ((mainByte & 0x10) != 0)
464*f6dc9357SAndroid Build Coastguard Worker {
465*f6dc9357SAndroid Build Coastguard Worker coder.NumStreams = ReadNum();
466*f6dc9357SAndroid Build Coastguard Worker // if (coder.NumStreams > k_Scan_NumCodersStreams_in_Folder_MAX) ThrowUnsupported();
467*f6dc9357SAndroid Build Coastguard Worker /* numOutStreams = */ ReadNum();
468*f6dc9357SAndroid Build Coastguard Worker // if (ReadNum() != 1) // numOutStreams ThrowUnsupported();
469*f6dc9357SAndroid Build Coastguard Worker }
470*f6dc9357SAndroid Build Coastguard Worker else
471*f6dc9357SAndroid Build Coastguard Worker {
472*f6dc9357SAndroid Build Coastguard Worker coder.NumStreams = 1;
473*f6dc9357SAndroid Build Coastguard Worker }
474*f6dc9357SAndroid Build Coastguard Worker
475*f6dc9357SAndroid Build Coastguard Worker if ((mainByte & 0x20) != 0)
476*f6dc9357SAndroid Build Coastguard Worker {
477*f6dc9357SAndroid Build Coastguard Worker const CNum propsSize = ReadNum();
478*f6dc9357SAndroid Build Coastguard Worker coder.Props.Alloc((size_t)propsSize);
479*f6dc9357SAndroid Build Coastguard Worker ReadBytes((Byte *)coder.Props, (size_t)propsSize);
480*f6dc9357SAndroid Build Coastguard Worker }
481*f6dc9357SAndroid Build Coastguard Worker else
482*f6dc9357SAndroid Build Coastguard Worker coder.Props.Free();
483*f6dc9357SAndroid Build Coastguard Worker }
484*f6dc9357SAndroid Build Coastguard Worker numInStreams += coder.NumStreams;
485*f6dc9357SAndroid Build Coastguard Worker }
486*f6dc9357SAndroid Build Coastguard Worker
487*f6dc9357SAndroid Build Coastguard Worker const UInt32 numBonds = numCoders - 1;
488*f6dc9357SAndroid Build Coastguard Worker folder.Bonds.SetSize(numBonds);
489*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numBonds; i++)
490*f6dc9357SAndroid Build Coastguard Worker {
491*f6dc9357SAndroid Build Coastguard Worker CBond &bp = folder.Bonds[i];
492*f6dc9357SAndroid Build Coastguard Worker bp.PackIndex = ReadNum();
493*f6dc9357SAndroid Build Coastguard Worker bp.UnpackIndex = ReadNum();
494*f6dc9357SAndroid Build Coastguard Worker }
495*f6dc9357SAndroid Build Coastguard Worker
496*f6dc9357SAndroid Build Coastguard Worker if (numInStreams < numBonds)
497*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
498*f6dc9357SAndroid Build Coastguard Worker const UInt32 numPackStreams = numInStreams - numBonds;
499*f6dc9357SAndroid Build Coastguard Worker folder.PackStreams.SetSize(numPackStreams);
500*f6dc9357SAndroid Build Coastguard Worker
501*f6dc9357SAndroid Build Coastguard Worker if (numPackStreams == 1)
502*f6dc9357SAndroid Build Coastguard Worker {
503*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numInStreams; i++)
504*f6dc9357SAndroid Build Coastguard Worker if (folder.FindBond_for_PackStream(i) < 0)
505*f6dc9357SAndroid Build Coastguard Worker {
506*f6dc9357SAndroid Build Coastguard Worker folder.PackStreams[0] = i;
507*f6dc9357SAndroid Build Coastguard Worker break;
508*f6dc9357SAndroid Build Coastguard Worker }
509*f6dc9357SAndroid Build Coastguard Worker if (i == numInStreams)
510*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
511*f6dc9357SAndroid Build Coastguard Worker }
512*f6dc9357SAndroid Build Coastguard Worker else
513*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numPackStreams; i++)
514*f6dc9357SAndroid Build Coastguard Worker folder.PackStreams[i] = ReadNum();
515*f6dc9357SAndroid Build Coastguard Worker }
516*f6dc9357SAndroid Build Coastguard Worker
ParseFolderInfo(unsigned folderIndex,CFolder & folder) const517*f6dc9357SAndroid Build Coastguard Worker void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const
518*f6dc9357SAndroid Build Coastguard Worker {
519*f6dc9357SAndroid Build Coastguard Worker const size_t startPos = FoCodersDataOffset[folderIndex];
520*f6dc9357SAndroid Build Coastguard Worker CInByte2 inByte;
521*f6dc9357SAndroid Build Coastguard Worker inByte.Init(CodersData.ConstData() + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);
522*f6dc9357SAndroid Build Coastguard Worker inByte.ParseFolder(folder);
523*f6dc9357SAndroid Build Coastguard Worker if (inByte.GetRem() != 0)
524*f6dc9357SAndroid Build Coastguard Worker throw 20120424;
525*f6dc9357SAndroid Build Coastguard Worker }
526*f6dc9357SAndroid Build Coastguard Worker
527*f6dc9357SAndroid Build Coastguard Worker
GetPath(unsigned index,UString & path) const528*f6dc9357SAndroid Build Coastguard Worker void CDatabase::GetPath(unsigned index, UString &path) const
529*f6dc9357SAndroid Build Coastguard Worker {
530*f6dc9357SAndroid Build Coastguard Worker path.Empty();
531*f6dc9357SAndroid Build Coastguard Worker if (!NameOffsets || !NamesBuf)
532*f6dc9357SAndroid Build Coastguard Worker return;
533*f6dc9357SAndroid Build Coastguard Worker
534*f6dc9357SAndroid Build Coastguard Worker const size_t offset = NameOffsets[index];
535*f6dc9357SAndroid Build Coastguard Worker const size_t size = NameOffsets[index + 1] - offset;
536*f6dc9357SAndroid Build Coastguard Worker
537*f6dc9357SAndroid Build Coastguard Worker if (size >= (1 << 28))
538*f6dc9357SAndroid Build Coastguard Worker return;
539*f6dc9357SAndroid Build Coastguard Worker
540*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = path.GetBuf((unsigned)size - 1);
541*f6dc9357SAndroid Build Coastguard Worker
542*f6dc9357SAndroid Build Coastguard Worker const Byte *p = ((const Byte *)NamesBuf + offset * 2);
543*f6dc9357SAndroid Build Coastguard Worker
544*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && defined(MY_CPU_LE)
545*f6dc9357SAndroid Build Coastguard Worker
546*f6dc9357SAndroid Build Coastguard Worker wmemcpy(s, (const wchar_t *)(const void *)p, size);
547*f6dc9357SAndroid Build Coastguard Worker
548*f6dc9357SAndroid Build Coastguard Worker #else
549*f6dc9357SAndroid Build Coastguard Worker
550*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < size; i++)
551*f6dc9357SAndroid Build Coastguard Worker {
552*f6dc9357SAndroid Build Coastguard Worker *s = Get16(p);
553*f6dc9357SAndroid Build Coastguard Worker p += 2;
554*f6dc9357SAndroid Build Coastguard Worker s++;
555*f6dc9357SAndroid Build Coastguard Worker }
556*f6dc9357SAndroid Build Coastguard Worker
557*f6dc9357SAndroid Build Coastguard Worker #endif
558*f6dc9357SAndroid Build Coastguard Worker
559*f6dc9357SAndroid Build Coastguard Worker path.ReleaseBuf_SetLen((unsigned)size - 1);
560*f6dc9357SAndroid Build Coastguard Worker }
561*f6dc9357SAndroid Build Coastguard Worker
GetPath_Prop(unsigned index,PROPVARIANT * path) const562*f6dc9357SAndroid Build Coastguard Worker HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
563*f6dc9357SAndroid Build Coastguard Worker {
564*f6dc9357SAndroid Build Coastguard Worker PropVariant_Clear(path);
565*f6dc9357SAndroid Build Coastguard Worker if (!NameOffsets || !NamesBuf)
566*f6dc9357SAndroid Build Coastguard Worker return S_OK;
567*f6dc9357SAndroid Build Coastguard Worker
568*f6dc9357SAndroid Build Coastguard Worker const size_t offset = NameOffsets[index];
569*f6dc9357SAndroid Build Coastguard Worker const size_t size = NameOffsets[index + 1] - offset;
570*f6dc9357SAndroid Build Coastguard Worker
571*f6dc9357SAndroid Build Coastguard Worker if (size >= (1 << 14))
572*f6dc9357SAndroid Build Coastguard Worker return S_OK;
573*f6dc9357SAndroid Build Coastguard Worker
574*f6dc9357SAndroid Build Coastguard Worker // (size) includes null terminator
575*f6dc9357SAndroid Build Coastguard Worker
576*f6dc9357SAndroid Build Coastguard Worker /*
577*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_MAX > 0xffff
578*f6dc9357SAndroid Build Coastguard Worker
579*f6dc9357SAndroid Build Coastguard Worker const Byte *p = ((const Byte *)NamesBuf + offset * 2);
580*f6dc9357SAndroid Build Coastguard Worker size = Utf16LE__Get_Num_WCHARs(p, size - 1);
581*f6dc9357SAndroid Build Coastguard Worker // (size) doesn't include null terminator
582*f6dc9357SAndroid Build Coastguard Worker RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size));
583*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = path->bstrVal;
584*f6dc9357SAndroid Build Coastguard Worker wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, size, s);
585*f6dc9357SAndroid Build Coastguard Worker *sEnd = 0;
586*f6dc9357SAndroid Build Coastguard Worker if (s + size != sEnd) return E_FAIL;
587*f6dc9357SAndroid Build Coastguard Worker
588*f6dc9357SAndroid Build Coastguard Worker #else
589*f6dc9357SAndroid Build Coastguard Worker */
590*f6dc9357SAndroid Build Coastguard Worker
591*f6dc9357SAndroid Build Coastguard Worker RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1))
592*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = path->bstrVal;
593*f6dc9357SAndroid Build Coastguard Worker const Byte *p = ((const Byte *)NamesBuf + offset * 2);
594*f6dc9357SAndroid Build Coastguard Worker // Utf16LE__To_WCHARs_Sep(p, size, s);
595*f6dc9357SAndroid Build Coastguard Worker
596*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < size; i++)
597*f6dc9357SAndroid Build Coastguard Worker {
598*f6dc9357SAndroid Build Coastguard Worker wchar_t c = Get16(p);
599*f6dc9357SAndroid Build Coastguard Worker p += 2;
600*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_PATH_SEPARATOR != L'/'
601*f6dc9357SAndroid Build Coastguard Worker if (c == L'/')
602*f6dc9357SAndroid Build Coastguard Worker c = WCHAR_PATH_SEPARATOR;
603*f6dc9357SAndroid Build Coastguard Worker else if (c == L'\\')
604*f6dc9357SAndroid Build Coastguard Worker c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme
605*f6dc9357SAndroid Build Coastguard Worker #endif
606*f6dc9357SAndroid Build Coastguard Worker *s++ = c;
607*f6dc9357SAndroid Build Coastguard Worker }
608*f6dc9357SAndroid Build Coastguard Worker
609*f6dc9357SAndroid Build Coastguard Worker // #endif
610*f6dc9357SAndroid Build Coastguard Worker
611*f6dc9357SAndroid Build Coastguard Worker return S_OK;
612*f6dc9357SAndroid Build Coastguard Worker
613*f6dc9357SAndroid Build Coastguard Worker /*
614*f6dc9357SAndroid Build Coastguard Worker unsigned cur = index;
615*f6dc9357SAndroid Build Coastguard Worker unsigned size = 0;
616*f6dc9357SAndroid Build Coastguard Worker
617*f6dc9357SAndroid Build Coastguard Worker for (int i = 0;; i++)
618*f6dc9357SAndroid Build Coastguard Worker {
619*f6dc9357SAndroid Build Coastguard Worker size_t len = NameOffsets[cur + 1] - NameOffsets[cur];
620*f6dc9357SAndroid Build Coastguard Worker size += (unsigned)len;
621*f6dc9357SAndroid Build Coastguard Worker if (i > 256 || len > (1 << 14) || size > (1 << 14))
622*f6dc9357SAndroid Build Coastguard Worker return PropVarEm_Set_Str(path, "[TOO-LONG]");
623*f6dc9357SAndroid Build Coastguard Worker cur = Files[cur].Parent;
624*f6dc9357SAndroid Build Coastguard Worker if (cur < 0)
625*f6dc9357SAndroid Build Coastguard Worker break;
626*f6dc9357SAndroid Build Coastguard Worker }
627*f6dc9357SAndroid Build Coastguard Worker size--;
628*f6dc9357SAndroid Build Coastguard Worker
629*f6dc9357SAndroid Build Coastguard Worker RINOK(PropVarEm_Alloc_Bstr(path, size));
630*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = path->bstrVal;
631*f6dc9357SAndroid Build Coastguard Worker s += size;
632*f6dc9357SAndroid Build Coastguard Worker *s = 0;
633*f6dc9357SAndroid Build Coastguard Worker cur = index;
634*f6dc9357SAndroid Build Coastguard Worker
635*f6dc9357SAndroid Build Coastguard Worker for (;;)
636*f6dc9357SAndroid Build Coastguard Worker {
637*f6dc9357SAndroid Build Coastguard Worker unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
638*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
639*f6dc9357SAndroid Build Coastguard Worker for (; len != 0; len--)
640*f6dc9357SAndroid Build Coastguard Worker {
641*f6dc9357SAndroid Build Coastguard Worker p -= 2;
642*f6dc9357SAndroid Build Coastguard Worker --s;
643*f6dc9357SAndroid Build Coastguard Worker wchar_t c = Get16(p);
644*f6dc9357SAndroid Build Coastguard Worker if (c == '/')
645*f6dc9357SAndroid Build Coastguard Worker c = WCHAR_PATH_SEPARATOR;
646*f6dc9357SAndroid Build Coastguard Worker *s = c;
647*f6dc9357SAndroid Build Coastguard Worker }
648*f6dc9357SAndroid Build Coastguard Worker
649*f6dc9357SAndroid Build Coastguard Worker const CFileItem &file = Files[cur];
650*f6dc9357SAndroid Build Coastguard Worker cur = file.Parent;
651*f6dc9357SAndroid Build Coastguard Worker if (cur < 0)
652*f6dc9357SAndroid Build Coastguard Worker return S_OK;
653*f6dc9357SAndroid Build Coastguard Worker *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR);
654*f6dc9357SAndroid Build Coastguard Worker }
655*f6dc9357SAndroid Build Coastguard Worker */
656*f6dc9357SAndroid Build Coastguard Worker }
657*f6dc9357SAndroid Build Coastguard Worker
WaitId(UInt64 id)658*f6dc9357SAndroid Build Coastguard Worker void CInArchive::WaitId(UInt64 id)
659*f6dc9357SAndroid Build Coastguard Worker {
660*f6dc9357SAndroid Build Coastguard Worker for (;;)
661*f6dc9357SAndroid Build Coastguard Worker {
662*f6dc9357SAndroid Build Coastguard Worker const UInt64 type = ReadID();
663*f6dc9357SAndroid Build Coastguard Worker if (type == id)
664*f6dc9357SAndroid Build Coastguard Worker return;
665*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kEnd)
666*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
667*f6dc9357SAndroid Build Coastguard Worker SkipData();
668*f6dc9357SAndroid Build Coastguard Worker }
669*f6dc9357SAndroid Build Coastguard Worker }
670*f6dc9357SAndroid Build Coastguard Worker
671*f6dc9357SAndroid Build Coastguard Worker
Read_UInt32_Vector(CUInt32DefVector & v)672*f6dc9357SAndroid Build Coastguard Worker void CInArchive::Read_UInt32_Vector(CUInt32DefVector &v)
673*f6dc9357SAndroid Build Coastguard Worker {
674*f6dc9357SAndroid Build Coastguard Worker const unsigned numItems = v.Defs.Size();
675*f6dc9357SAndroid Build Coastguard Worker v.Vals.ClearAndSetSize(numItems);
676*f6dc9357SAndroid Build Coastguard Worker UInt32 *p = &v.Vals[0];
677*f6dc9357SAndroid Build Coastguard Worker const bool *defs = &v.Defs[0];
678*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numItems; i++)
679*f6dc9357SAndroid Build Coastguard Worker {
680*f6dc9357SAndroid Build Coastguard Worker UInt32 a = 0;
681*f6dc9357SAndroid Build Coastguard Worker if (defs[i])
682*f6dc9357SAndroid Build Coastguard Worker a = ReadUInt32();
683*f6dc9357SAndroid Build Coastguard Worker p[i] = a;
684*f6dc9357SAndroid Build Coastguard Worker }
685*f6dc9357SAndroid Build Coastguard Worker }
686*f6dc9357SAndroid Build Coastguard Worker
687*f6dc9357SAndroid Build Coastguard Worker
ReadHashDigests(unsigned numItems,CUInt32DefVector & crcs)688*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
689*f6dc9357SAndroid Build Coastguard Worker {
690*f6dc9357SAndroid Build Coastguard Worker ReadBoolVector2(numItems, crcs.Defs);
691*f6dc9357SAndroid Build Coastguard Worker Read_UInt32_Vector(crcs);
692*f6dc9357SAndroid Build Coastguard Worker }
693*f6dc9357SAndroid Build Coastguard Worker
694*f6dc9357SAndroid Build Coastguard Worker
ReadPackInfo(CFolders & f)695*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadPackInfo(CFolders &f)
696*f6dc9357SAndroid Build Coastguard Worker {
697*f6dc9357SAndroid Build Coastguard Worker const CNum numPackStreams = ReadNum();
698*f6dc9357SAndroid Build Coastguard Worker
699*f6dc9357SAndroid Build Coastguard Worker WaitId(NID::kSize);
700*f6dc9357SAndroid Build Coastguard Worker f.PackPositions.Alloc(numPackStreams + 1);
701*f6dc9357SAndroid Build Coastguard Worker f.NumPackStreams = numPackStreams;
702*f6dc9357SAndroid Build Coastguard Worker UInt64 sum = 0;
703*f6dc9357SAndroid Build Coastguard Worker for (CNum i = 0; i < numPackStreams; i++)
704*f6dc9357SAndroid Build Coastguard Worker {
705*f6dc9357SAndroid Build Coastguard Worker f.PackPositions[i] = sum;
706*f6dc9357SAndroid Build Coastguard Worker const UInt64 packSize = ReadNumber();
707*f6dc9357SAndroid Build Coastguard Worker sum += packSize;
708*f6dc9357SAndroid Build Coastguard Worker if (sum < packSize)
709*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
710*f6dc9357SAndroid Build Coastguard Worker }
711*f6dc9357SAndroid Build Coastguard Worker f.PackPositions[numPackStreams] = sum;
712*f6dc9357SAndroid Build Coastguard Worker
713*f6dc9357SAndroid Build Coastguard Worker UInt64 type;
714*f6dc9357SAndroid Build Coastguard Worker for (;;)
715*f6dc9357SAndroid Build Coastguard Worker {
716*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
717*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kEnd)
718*f6dc9357SAndroid Build Coastguard Worker return;
719*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kCRC)
720*f6dc9357SAndroid Build Coastguard Worker {
721*f6dc9357SAndroid Build Coastguard Worker CUInt32DefVector PackCRCs;
722*f6dc9357SAndroid Build Coastguard Worker ReadHashDigests(numPackStreams, PackCRCs);
723*f6dc9357SAndroid Build Coastguard Worker continue;
724*f6dc9357SAndroid Build Coastguard Worker }
725*f6dc9357SAndroid Build Coastguard Worker SkipData();
726*f6dc9357SAndroid Build Coastguard Worker }
727*f6dc9357SAndroid Build Coastguard Worker }
728*f6dc9357SAndroid Build Coastguard Worker
ReadUnpackInfo(const CObjectVector<CByteBuffer> * dataVector,CFolders & folders)729*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadUnpackInfo(
730*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CByteBuffer> *dataVector,
731*f6dc9357SAndroid Build Coastguard Worker CFolders &folders)
732*f6dc9357SAndroid Build Coastguard Worker {
733*f6dc9357SAndroid Build Coastguard Worker WaitId(NID::kFolder);
734*f6dc9357SAndroid Build Coastguard Worker const CNum numFolders = ReadNum();
735*f6dc9357SAndroid Build Coastguard Worker
736*f6dc9357SAndroid Build Coastguard Worker CNum numCodersOutStreams = 0;
737*f6dc9357SAndroid Build Coastguard Worker {
738*f6dc9357SAndroid Build Coastguard Worker CStreamSwitch streamSwitch;
739*f6dc9357SAndroid Build Coastguard Worker streamSwitch.Set(this, dataVector);
740*f6dc9357SAndroid Build Coastguard Worker const Byte *startBufPtr = _inByteBack->GetPtr();
741*f6dc9357SAndroid Build Coastguard Worker folders.NumFolders = numFolders;
742*f6dc9357SAndroid Build Coastguard Worker
743*f6dc9357SAndroid Build Coastguard Worker folders.FoStartPackStreamIndex.Alloc(numFolders + 1);
744*f6dc9357SAndroid Build Coastguard Worker folders.FoToMainUnpackSizeIndex.Alloc(numFolders);
745*f6dc9357SAndroid Build Coastguard Worker folders.FoCodersDataOffset.Alloc(numFolders + 1);
746*f6dc9357SAndroid Build Coastguard Worker folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
747*f6dc9357SAndroid Build Coastguard Worker
748*f6dc9357SAndroid Build Coastguard Worker CBoolVector StreamUsed;
749*f6dc9357SAndroid Build Coastguard Worker CBoolVector CoderUsed;
750*f6dc9357SAndroid Build Coastguard Worker
751*f6dc9357SAndroid Build Coastguard Worker CNum packStreamIndex = 0;
752*f6dc9357SAndroid Build Coastguard Worker CNum fo;
753*f6dc9357SAndroid Build Coastguard Worker CInByte2 *inByte = _inByteBack;
754*f6dc9357SAndroid Build Coastguard Worker
755*f6dc9357SAndroid Build Coastguard Worker for (fo = 0; fo < numFolders; fo++)
756*f6dc9357SAndroid Build Coastguard Worker {
757*f6dc9357SAndroid Build Coastguard Worker UInt32 indexOfMainStream = 0;
758*f6dc9357SAndroid Build Coastguard Worker UInt32 numPackStreams = 0;
759*f6dc9357SAndroid Build Coastguard Worker folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr);
760*f6dc9357SAndroid Build Coastguard Worker
761*f6dc9357SAndroid Build Coastguard Worker CNum numInStreams = 0;
762*f6dc9357SAndroid Build Coastguard Worker const CNum numCoders = inByte->ReadNum();
763*f6dc9357SAndroid Build Coastguard Worker
764*f6dc9357SAndroid Build Coastguard Worker if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
765*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
766*f6dc9357SAndroid Build Coastguard Worker
767*f6dc9357SAndroid Build Coastguard Worker for (CNum ci = 0; ci < numCoders; ci++)
768*f6dc9357SAndroid Build Coastguard Worker {
769*f6dc9357SAndroid Build Coastguard Worker const Byte mainByte = inByte->ReadByte();
770*f6dc9357SAndroid Build Coastguard Worker if ((mainByte & 0xC0) != 0)
771*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
772*f6dc9357SAndroid Build Coastguard Worker
773*f6dc9357SAndroid Build Coastguard Worker const unsigned idSize = (mainByte & 0xF);
774*f6dc9357SAndroid Build Coastguard Worker if (idSize > 8)
775*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
776*f6dc9357SAndroid Build Coastguard Worker if (idSize > inByte->GetRem())
777*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
778*f6dc9357SAndroid Build Coastguard Worker const Byte *longID = inByte->GetPtr();
779*f6dc9357SAndroid Build Coastguard Worker UInt64 id = 0;
780*f6dc9357SAndroid Build Coastguard Worker for (unsigned j = 0; j < idSize; j++)
781*f6dc9357SAndroid Build Coastguard Worker id = ((id << 8) | longID[j]);
782*f6dc9357SAndroid Build Coastguard Worker inByte->SkipDataNoCheck(idSize);
783*f6dc9357SAndroid Build Coastguard Worker if (folders.ParsedMethods.IDs.Size() < 128)
784*f6dc9357SAndroid Build Coastguard Worker folders.ParsedMethods.IDs.AddToUniqueSorted(id);
785*f6dc9357SAndroid Build Coastguard Worker
786*f6dc9357SAndroid Build Coastguard Worker CNum coderInStreams = 1;
787*f6dc9357SAndroid Build Coastguard Worker if ((mainByte & 0x10) != 0)
788*f6dc9357SAndroid Build Coastguard Worker {
789*f6dc9357SAndroid Build Coastguard Worker coderInStreams = inByte->ReadNum();
790*f6dc9357SAndroid Build Coastguard Worker if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
791*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
792*f6dc9357SAndroid Build Coastguard Worker if (inByte->ReadNum() != 1)
793*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
794*f6dc9357SAndroid Build Coastguard Worker }
795*f6dc9357SAndroid Build Coastguard Worker
796*f6dc9357SAndroid Build Coastguard Worker numInStreams += coderInStreams;
797*f6dc9357SAndroid Build Coastguard Worker if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
798*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
799*f6dc9357SAndroid Build Coastguard Worker
800*f6dc9357SAndroid Build Coastguard Worker if ((mainByte & 0x20) != 0)
801*f6dc9357SAndroid Build Coastguard Worker {
802*f6dc9357SAndroid Build Coastguard Worker const CNum propsSize = inByte->ReadNum();
803*f6dc9357SAndroid Build Coastguard Worker if (propsSize > inByte->GetRem())
804*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
805*f6dc9357SAndroid Build Coastguard Worker if (id == k_LZMA2 && propsSize == 1)
806*f6dc9357SAndroid Build Coastguard Worker {
807*f6dc9357SAndroid Build Coastguard Worker const Byte v = *_inByteBack->GetPtr();
808*f6dc9357SAndroid Build Coastguard Worker if (folders.ParsedMethods.Lzma2Prop < v)
809*f6dc9357SAndroid Build Coastguard Worker folders.ParsedMethods.Lzma2Prop = v;
810*f6dc9357SAndroid Build Coastguard Worker }
811*f6dc9357SAndroid Build Coastguard Worker else if (id == k_LZMA && propsSize == 5)
812*f6dc9357SAndroid Build Coastguard Worker {
813*f6dc9357SAndroid Build Coastguard Worker const UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1);
814*f6dc9357SAndroid Build Coastguard Worker if (folders.ParsedMethods.LzmaDic < dicSize)
815*f6dc9357SAndroid Build Coastguard Worker folders.ParsedMethods.LzmaDic = dicSize;
816*f6dc9357SAndroid Build Coastguard Worker }
817*f6dc9357SAndroid Build Coastguard Worker inByte->SkipDataNoCheck((size_t)propsSize);
818*f6dc9357SAndroid Build Coastguard Worker }
819*f6dc9357SAndroid Build Coastguard Worker }
820*f6dc9357SAndroid Build Coastguard Worker
821*f6dc9357SAndroid Build Coastguard Worker if (numCoders == 1 && numInStreams == 1)
822*f6dc9357SAndroid Build Coastguard Worker {
823*f6dc9357SAndroid Build Coastguard Worker indexOfMainStream = 0;
824*f6dc9357SAndroid Build Coastguard Worker numPackStreams = 1;
825*f6dc9357SAndroid Build Coastguard Worker }
826*f6dc9357SAndroid Build Coastguard Worker else
827*f6dc9357SAndroid Build Coastguard Worker {
828*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
829*f6dc9357SAndroid Build Coastguard Worker const CNum numBonds = numCoders - 1;
830*f6dc9357SAndroid Build Coastguard Worker if (numInStreams < numBonds)
831*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
832*f6dc9357SAndroid Build Coastguard Worker
833*f6dc9357SAndroid Build Coastguard Worker BoolVector_Fill_False(StreamUsed, numInStreams);
834*f6dc9357SAndroid Build Coastguard Worker BoolVector_Fill_False(CoderUsed, numCoders);
835*f6dc9357SAndroid Build Coastguard Worker
836*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numBonds; i++)
837*f6dc9357SAndroid Build Coastguard Worker {
838*f6dc9357SAndroid Build Coastguard Worker CNum index = ReadNum();
839*f6dc9357SAndroid Build Coastguard Worker if (index >= numInStreams || StreamUsed[index])
840*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
841*f6dc9357SAndroid Build Coastguard Worker StreamUsed[index] = true;
842*f6dc9357SAndroid Build Coastguard Worker
843*f6dc9357SAndroid Build Coastguard Worker index = ReadNum();
844*f6dc9357SAndroid Build Coastguard Worker if (index >= numCoders || CoderUsed[index])
845*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
846*f6dc9357SAndroid Build Coastguard Worker CoderUsed[index] = true;
847*f6dc9357SAndroid Build Coastguard Worker }
848*f6dc9357SAndroid Build Coastguard Worker
849*f6dc9357SAndroid Build Coastguard Worker numPackStreams = numInStreams - numBonds;
850*f6dc9357SAndroid Build Coastguard Worker
851*f6dc9357SAndroid Build Coastguard Worker if (numPackStreams != 1)
852*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numPackStreams; i++)
853*f6dc9357SAndroid Build Coastguard Worker {
854*f6dc9357SAndroid Build Coastguard Worker const CNum index = inByte->ReadNum(); // PackStreams
855*f6dc9357SAndroid Build Coastguard Worker if (index >= numInStreams || StreamUsed[index])
856*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
857*f6dc9357SAndroid Build Coastguard Worker StreamUsed[index] = true;
858*f6dc9357SAndroid Build Coastguard Worker }
859*f6dc9357SAndroid Build Coastguard Worker
860*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numCoders; i++)
861*f6dc9357SAndroid Build Coastguard Worker if (!CoderUsed[i])
862*f6dc9357SAndroid Build Coastguard Worker {
863*f6dc9357SAndroid Build Coastguard Worker indexOfMainStream = i;
864*f6dc9357SAndroid Build Coastguard Worker break;
865*f6dc9357SAndroid Build Coastguard Worker }
866*f6dc9357SAndroid Build Coastguard Worker
867*f6dc9357SAndroid Build Coastguard Worker if (i == numCoders)
868*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
869*f6dc9357SAndroid Build Coastguard Worker }
870*f6dc9357SAndroid Build Coastguard Worker
871*f6dc9357SAndroid Build Coastguard Worker folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
872*f6dc9357SAndroid Build Coastguard Worker numCodersOutStreams += numCoders;
873*f6dc9357SAndroid Build Coastguard Worker folders.FoStartPackStreamIndex[fo] = packStreamIndex;
874*f6dc9357SAndroid Build Coastguard Worker if (numPackStreams > folders.NumPackStreams - packStreamIndex)
875*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
876*f6dc9357SAndroid Build Coastguard Worker packStreamIndex += numPackStreams;
877*f6dc9357SAndroid Build Coastguard Worker folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
878*f6dc9357SAndroid Build Coastguard Worker }
879*f6dc9357SAndroid Build Coastguard Worker
880*f6dc9357SAndroid Build Coastguard Worker const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr);
881*f6dc9357SAndroid Build Coastguard Worker folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
882*f6dc9357SAndroid Build Coastguard Worker folders.FoStartPackStreamIndex[fo] = packStreamIndex;
883*f6dc9357SAndroid Build Coastguard Worker folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr);
884*f6dc9357SAndroid Build Coastguard Worker folders.CodersData.CopyFrom(startBufPtr, dataSize);
885*f6dc9357SAndroid Build Coastguard Worker
886*f6dc9357SAndroid Build Coastguard Worker // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();
887*f6dc9357SAndroid Build Coastguard Worker }
888*f6dc9357SAndroid Build Coastguard Worker
889*f6dc9357SAndroid Build Coastguard Worker WaitId(NID::kCodersUnpackSize);
890*f6dc9357SAndroid Build Coastguard Worker folders.CoderUnpackSizes.Alloc(numCodersOutStreams);
891*f6dc9357SAndroid Build Coastguard Worker for (CNum i = 0; i < numCodersOutStreams; i++)
892*f6dc9357SAndroid Build Coastguard Worker folders.CoderUnpackSizes[i] = ReadNumber();
893*f6dc9357SAndroid Build Coastguard Worker
894*f6dc9357SAndroid Build Coastguard Worker for (;;)
895*f6dc9357SAndroid Build Coastguard Worker {
896*f6dc9357SAndroid Build Coastguard Worker const UInt64 type = ReadID();
897*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kEnd)
898*f6dc9357SAndroid Build Coastguard Worker return;
899*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kCRC)
900*f6dc9357SAndroid Build Coastguard Worker {
901*f6dc9357SAndroid Build Coastguard Worker ReadHashDigests(numFolders, folders.FolderCRCs);
902*f6dc9357SAndroid Build Coastguard Worker continue;
903*f6dc9357SAndroid Build Coastguard Worker }
904*f6dc9357SAndroid Build Coastguard Worker SkipData();
905*f6dc9357SAndroid Build Coastguard Worker }
906*f6dc9357SAndroid Build Coastguard Worker }
907*f6dc9357SAndroid Build Coastguard Worker
ReadSubStreamsInfo(CFolders & folders,CRecordVector<UInt64> & unpackSizes,CUInt32DefVector & digests)908*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadSubStreamsInfo(
909*f6dc9357SAndroid Build Coastguard Worker CFolders &folders,
910*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> &unpackSizes,
911*f6dc9357SAndroid Build Coastguard Worker CUInt32DefVector &digests)
912*f6dc9357SAndroid Build Coastguard Worker {
913*f6dc9357SAndroid Build Coastguard Worker folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);
914*f6dc9357SAndroid Build Coastguard Worker CNum i;
915*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folders.NumFolders; i++)
916*f6dc9357SAndroid Build Coastguard Worker folders.NumUnpackStreamsVector[i] = 1;
917*f6dc9357SAndroid Build Coastguard Worker
918*f6dc9357SAndroid Build Coastguard Worker UInt64 type;
919*f6dc9357SAndroid Build Coastguard Worker
920*f6dc9357SAndroid Build Coastguard Worker for (;;)
921*f6dc9357SAndroid Build Coastguard Worker {
922*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
923*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kNumUnpackStream)
924*f6dc9357SAndroid Build Coastguard Worker {
925*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folders.NumFolders; i++)
926*f6dc9357SAndroid Build Coastguard Worker folders.NumUnpackStreamsVector[i] = ReadNum();
927*f6dc9357SAndroid Build Coastguard Worker continue;
928*f6dc9357SAndroid Build Coastguard Worker }
929*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd)
930*f6dc9357SAndroid Build Coastguard Worker break;
931*f6dc9357SAndroid Build Coastguard Worker SkipData();
932*f6dc9357SAndroid Build Coastguard Worker }
933*f6dc9357SAndroid Build Coastguard Worker
934*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kSize)
935*f6dc9357SAndroid Build Coastguard Worker {
936*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folders.NumFolders; i++)
937*f6dc9357SAndroid Build Coastguard Worker {
938*f6dc9357SAndroid Build Coastguard Worker // v3.13 incorrectly worked with empty folders
939*f6dc9357SAndroid Build Coastguard Worker // v4.07: we check that folder is empty
940*f6dc9357SAndroid Build Coastguard Worker const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
941*f6dc9357SAndroid Build Coastguard Worker if (numSubstreams == 0)
942*f6dc9357SAndroid Build Coastguard Worker continue;
943*f6dc9357SAndroid Build Coastguard Worker UInt64 sum = 0;
944*f6dc9357SAndroid Build Coastguard Worker for (CNum j = 1; j < numSubstreams; j++)
945*f6dc9357SAndroid Build Coastguard Worker {
946*f6dc9357SAndroid Build Coastguard Worker const UInt64 size = ReadNumber();
947*f6dc9357SAndroid Build Coastguard Worker unpackSizes.Add(size);
948*f6dc9357SAndroid Build Coastguard Worker sum += size;
949*f6dc9357SAndroid Build Coastguard Worker if (sum < size)
950*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
951*f6dc9357SAndroid Build Coastguard Worker }
952*f6dc9357SAndroid Build Coastguard Worker const UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i);
953*f6dc9357SAndroid Build Coastguard Worker if (folderUnpackSize < sum)
954*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
955*f6dc9357SAndroid Build Coastguard Worker unpackSizes.Add(folderUnpackSize - sum);
956*f6dc9357SAndroid Build Coastguard Worker }
957*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
958*f6dc9357SAndroid Build Coastguard Worker }
959*f6dc9357SAndroid Build Coastguard Worker else
960*f6dc9357SAndroid Build Coastguard Worker {
961*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folders.NumFolders; i++)
962*f6dc9357SAndroid Build Coastguard Worker {
963*f6dc9357SAndroid Build Coastguard Worker /* v9.26 - v9.29 incorrectly worked:
964*f6dc9357SAndroid Build Coastguard Worker if (folders.NumUnpackStreamsVector[i] == 0), it threw error */
965*f6dc9357SAndroid Build Coastguard Worker const CNum val = folders.NumUnpackStreamsVector[i];
966*f6dc9357SAndroid Build Coastguard Worker if (val > 1)
967*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
968*f6dc9357SAndroid Build Coastguard Worker if (val == 1)
969*f6dc9357SAndroid Build Coastguard Worker unpackSizes.Add(folders.GetFolderUnpackSize(i));
970*f6dc9357SAndroid Build Coastguard Worker }
971*f6dc9357SAndroid Build Coastguard Worker }
972*f6dc9357SAndroid Build Coastguard Worker
973*f6dc9357SAndroid Build Coastguard Worker unsigned numDigests = 0;
974*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folders.NumFolders; i++)
975*f6dc9357SAndroid Build Coastguard Worker {
976*f6dc9357SAndroid Build Coastguard Worker const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
977*f6dc9357SAndroid Build Coastguard Worker if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i))
978*f6dc9357SAndroid Build Coastguard Worker numDigests += numSubstreams;
979*f6dc9357SAndroid Build Coastguard Worker }
980*f6dc9357SAndroid Build Coastguard Worker
981*f6dc9357SAndroid Build Coastguard Worker for (;;)
982*f6dc9357SAndroid Build Coastguard Worker {
983*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kEnd)
984*f6dc9357SAndroid Build Coastguard Worker break;
985*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kCRC)
986*f6dc9357SAndroid Build Coastguard Worker {
987*f6dc9357SAndroid Build Coastguard Worker // CUInt32DefVector digests2;
988*f6dc9357SAndroid Build Coastguard Worker // ReadHashDigests(numDigests, digests2);
989*f6dc9357SAndroid Build Coastguard Worker CBoolVector digests2;
990*f6dc9357SAndroid Build Coastguard Worker ReadBoolVector2(numDigests, digests2);
991*f6dc9357SAndroid Build Coastguard Worker
992*f6dc9357SAndroid Build Coastguard Worker digests.ClearAndSetSize(unpackSizes.Size());
993*f6dc9357SAndroid Build Coastguard Worker
994*f6dc9357SAndroid Build Coastguard Worker unsigned k = 0;
995*f6dc9357SAndroid Build Coastguard Worker unsigned k2 = 0;
996*f6dc9357SAndroid Build Coastguard Worker
997*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folders.NumFolders; i++)
998*f6dc9357SAndroid Build Coastguard Worker {
999*f6dc9357SAndroid Build Coastguard Worker const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
1000*f6dc9357SAndroid Build Coastguard Worker if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
1001*f6dc9357SAndroid Build Coastguard Worker {
1002*f6dc9357SAndroid Build Coastguard Worker digests.Defs[k] = true;
1003*f6dc9357SAndroid Build Coastguard Worker digests.Vals[k] = folders.FolderCRCs.Vals[i];
1004*f6dc9357SAndroid Build Coastguard Worker k++;
1005*f6dc9357SAndroid Build Coastguard Worker }
1006*f6dc9357SAndroid Build Coastguard Worker else for (CNum j = 0; j < numSubstreams; j++)
1007*f6dc9357SAndroid Build Coastguard Worker {
1008*f6dc9357SAndroid Build Coastguard Worker bool defined = digests2[k2++];
1009*f6dc9357SAndroid Build Coastguard Worker digests.Defs[k] = defined;
1010*f6dc9357SAndroid Build Coastguard Worker UInt32 crc = 0;
1011*f6dc9357SAndroid Build Coastguard Worker if (defined)
1012*f6dc9357SAndroid Build Coastguard Worker crc = ReadUInt32();
1013*f6dc9357SAndroid Build Coastguard Worker digests.Vals[k] = crc;
1014*f6dc9357SAndroid Build Coastguard Worker k++;
1015*f6dc9357SAndroid Build Coastguard Worker }
1016*f6dc9357SAndroid Build Coastguard Worker }
1017*f6dc9357SAndroid Build Coastguard Worker // if (k != unpackSizes.Size()) throw 1234567;
1018*f6dc9357SAndroid Build Coastguard Worker }
1019*f6dc9357SAndroid Build Coastguard Worker else
1020*f6dc9357SAndroid Build Coastguard Worker SkipData();
1021*f6dc9357SAndroid Build Coastguard Worker
1022*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
1023*f6dc9357SAndroid Build Coastguard Worker }
1024*f6dc9357SAndroid Build Coastguard Worker
1025*f6dc9357SAndroid Build Coastguard Worker if (digests.Defs.Size() != unpackSizes.Size())
1026*f6dc9357SAndroid Build Coastguard Worker {
1027*f6dc9357SAndroid Build Coastguard Worker digests.ClearAndSetSize(unpackSizes.Size());
1028*f6dc9357SAndroid Build Coastguard Worker unsigned k = 0;
1029*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folders.NumFolders; i++)
1030*f6dc9357SAndroid Build Coastguard Worker {
1031*f6dc9357SAndroid Build Coastguard Worker const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
1032*f6dc9357SAndroid Build Coastguard Worker if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
1033*f6dc9357SAndroid Build Coastguard Worker {
1034*f6dc9357SAndroid Build Coastguard Worker digests.Defs[k] = true;
1035*f6dc9357SAndroid Build Coastguard Worker digests.Vals[k] = folders.FolderCRCs.Vals[i];
1036*f6dc9357SAndroid Build Coastguard Worker k++;
1037*f6dc9357SAndroid Build Coastguard Worker }
1038*f6dc9357SAndroid Build Coastguard Worker else for (CNum j = 0; j < numSubstreams; j++)
1039*f6dc9357SAndroid Build Coastguard Worker {
1040*f6dc9357SAndroid Build Coastguard Worker digests.Defs[k] = false;
1041*f6dc9357SAndroid Build Coastguard Worker digests.Vals[k] = 0;
1042*f6dc9357SAndroid Build Coastguard Worker k++;
1043*f6dc9357SAndroid Build Coastguard Worker }
1044*f6dc9357SAndroid Build Coastguard Worker }
1045*f6dc9357SAndroid Build Coastguard Worker }
1046*f6dc9357SAndroid Build Coastguard Worker }
1047*f6dc9357SAndroid Build Coastguard Worker
1048*f6dc9357SAndroid Build Coastguard Worker
1049*f6dc9357SAndroid Build Coastguard Worker
ReadStreamsInfo(const CObjectVector<CByteBuffer> * dataVector,UInt64 & dataOffset,CFolders & folders,CRecordVector<UInt64> & unpackSizes,CUInt32DefVector & digests)1050*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadStreamsInfo(
1051*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CByteBuffer> *dataVector,
1052*f6dc9357SAndroid Build Coastguard Worker UInt64 &dataOffset,
1053*f6dc9357SAndroid Build Coastguard Worker CFolders &folders,
1054*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> &unpackSizes,
1055*f6dc9357SAndroid Build Coastguard Worker CUInt32DefVector &digests)
1056*f6dc9357SAndroid Build Coastguard Worker {
1057*f6dc9357SAndroid Build Coastguard Worker UInt64 type = ReadID();
1058*f6dc9357SAndroid Build Coastguard Worker
1059*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kPackInfo)
1060*f6dc9357SAndroid Build Coastguard Worker {
1061*f6dc9357SAndroid Build Coastguard Worker dataOffset = ReadNumber();
1062*f6dc9357SAndroid Build Coastguard Worker if (dataOffset > _rangeLimit)
1063*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1064*f6dc9357SAndroid Build Coastguard Worker ReadPackInfo(folders);
1065*f6dc9357SAndroid Build Coastguard Worker if (folders.PackPositions[folders.NumPackStreams] > _rangeLimit - dataOffset)
1066*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1067*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
1068*f6dc9357SAndroid Build Coastguard Worker }
1069*f6dc9357SAndroid Build Coastguard Worker
1070*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kUnpackInfo)
1071*f6dc9357SAndroid Build Coastguard Worker {
1072*f6dc9357SAndroid Build Coastguard Worker ReadUnpackInfo(dataVector, folders);
1073*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
1074*f6dc9357SAndroid Build Coastguard Worker }
1075*f6dc9357SAndroid Build Coastguard Worker
1076*f6dc9357SAndroid Build Coastguard Worker if (folders.NumFolders != 0 && !folders.PackPositions)
1077*f6dc9357SAndroid Build Coastguard Worker {
1078*f6dc9357SAndroid Build Coastguard Worker // if there are folders, we need PackPositions also
1079*f6dc9357SAndroid Build Coastguard Worker folders.PackPositions.Alloc(1);
1080*f6dc9357SAndroid Build Coastguard Worker folders.PackPositions[0] = 0;
1081*f6dc9357SAndroid Build Coastguard Worker }
1082*f6dc9357SAndroid Build Coastguard Worker
1083*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kSubStreamsInfo)
1084*f6dc9357SAndroid Build Coastguard Worker {
1085*f6dc9357SAndroid Build Coastguard Worker ReadSubStreamsInfo(folders, unpackSizes, digests);
1086*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
1087*f6dc9357SAndroid Build Coastguard Worker }
1088*f6dc9357SAndroid Build Coastguard Worker else
1089*f6dc9357SAndroid Build Coastguard Worker {
1090*f6dc9357SAndroid Build Coastguard Worker folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);
1091*f6dc9357SAndroid Build Coastguard Worker /* If digests.Defs.Size() == 0, it means that there are no crcs.
1092*f6dc9357SAndroid Build Coastguard Worker So we don't need to fill digests with values. */
1093*f6dc9357SAndroid Build Coastguard Worker // digests.Vals.ClearAndSetSize(folders.NumFolders);
1094*f6dc9357SAndroid Build Coastguard Worker // BoolVector_Fill_False(digests.Defs, folders.NumFolders);
1095*f6dc9357SAndroid Build Coastguard Worker for (CNum i = 0; i < folders.NumFolders; i++)
1096*f6dc9357SAndroid Build Coastguard Worker {
1097*f6dc9357SAndroid Build Coastguard Worker folders.NumUnpackStreamsVector[i] = 1;
1098*f6dc9357SAndroid Build Coastguard Worker unpackSizes.Add(folders.GetFolderUnpackSize(i));
1099*f6dc9357SAndroid Build Coastguard Worker // digests.Vals[i] = 0;
1100*f6dc9357SAndroid Build Coastguard Worker }
1101*f6dc9357SAndroid Build Coastguard Worker }
1102*f6dc9357SAndroid Build Coastguard Worker
1103*f6dc9357SAndroid Build Coastguard Worker if (type != NID::kEnd)
1104*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1105*f6dc9357SAndroid Build Coastguard Worker }
1106*f6dc9357SAndroid Build Coastguard Worker
ReadBoolVector(unsigned numItems,CBoolVector & v)1107*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v)
1108*f6dc9357SAndroid Build Coastguard Worker {
1109*f6dc9357SAndroid Build Coastguard Worker v.ClearAndSetSize(numItems);
1110*f6dc9357SAndroid Build Coastguard Worker Byte b = 0;
1111*f6dc9357SAndroid Build Coastguard Worker Byte mask = 0;
1112*f6dc9357SAndroid Build Coastguard Worker bool *p = &v[0];
1113*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numItems; i++)
1114*f6dc9357SAndroid Build Coastguard Worker {
1115*f6dc9357SAndroid Build Coastguard Worker if (mask == 0)
1116*f6dc9357SAndroid Build Coastguard Worker {
1117*f6dc9357SAndroid Build Coastguard Worker b = ReadByte();
1118*f6dc9357SAndroid Build Coastguard Worker mask = 0x80;
1119*f6dc9357SAndroid Build Coastguard Worker }
1120*f6dc9357SAndroid Build Coastguard Worker p[i] = ((b & mask) != 0);
1121*f6dc9357SAndroid Build Coastguard Worker mask = (Byte)(mask >> 1);
1122*f6dc9357SAndroid Build Coastguard Worker }
1123*f6dc9357SAndroid Build Coastguard Worker }
1124*f6dc9357SAndroid Build Coastguard Worker
ReadBoolVector2(unsigned numItems,CBoolVector & v)1125*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v)
1126*f6dc9357SAndroid Build Coastguard Worker {
1127*f6dc9357SAndroid Build Coastguard Worker const Byte allAreDefined = ReadByte();
1128*f6dc9357SAndroid Build Coastguard Worker if (allAreDefined == 0)
1129*f6dc9357SAndroid Build Coastguard Worker {
1130*f6dc9357SAndroid Build Coastguard Worker ReadBoolVector(numItems, v);
1131*f6dc9357SAndroid Build Coastguard Worker return;
1132*f6dc9357SAndroid Build Coastguard Worker }
1133*f6dc9357SAndroid Build Coastguard Worker v.ClearAndSetSize(numItems);
1134*f6dc9357SAndroid Build Coastguard Worker bool *p = &v[0];
1135*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numItems; i++)
1136*f6dc9357SAndroid Build Coastguard Worker p[i] = true;
1137*f6dc9357SAndroid Build Coastguard Worker }
1138*f6dc9357SAndroid Build Coastguard Worker
ReadUInt64DefVector(const CObjectVector<CByteBuffer> & dataVector,CUInt64DefVector & v,unsigned numItems)1139*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
1140*f6dc9357SAndroid Build Coastguard Worker CUInt64DefVector &v, unsigned numItems)
1141*f6dc9357SAndroid Build Coastguard Worker {
1142*f6dc9357SAndroid Build Coastguard Worker ReadBoolVector2(numItems, v.Defs);
1143*f6dc9357SAndroid Build Coastguard Worker
1144*f6dc9357SAndroid Build Coastguard Worker CStreamSwitch streamSwitch;
1145*f6dc9357SAndroid Build Coastguard Worker streamSwitch.Set(this, &dataVector);
1146*f6dc9357SAndroid Build Coastguard Worker
1147*f6dc9357SAndroid Build Coastguard Worker v.Vals.ClearAndSetSize(numItems);
1148*f6dc9357SAndroid Build Coastguard Worker UInt64 *p = &v.Vals[0];
1149*f6dc9357SAndroid Build Coastguard Worker const bool *defs = &v.Defs[0];
1150*f6dc9357SAndroid Build Coastguard Worker
1151*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numItems; i++)
1152*f6dc9357SAndroid Build Coastguard Worker {
1153*f6dc9357SAndroid Build Coastguard Worker UInt64 t = 0;
1154*f6dc9357SAndroid Build Coastguard Worker if (defs[i])
1155*f6dc9357SAndroid Build Coastguard Worker t = ReadUInt64();
1156*f6dc9357SAndroid Build Coastguard Worker p[i] = t;
1157*f6dc9357SAndroid Build Coastguard Worker }
1158*f6dc9357SAndroid Build Coastguard Worker }
1159*f6dc9357SAndroid Build Coastguard Worker
ReadAndDecodePackedStreams(DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset,UInt64 & dataOffset,CObjectVector<CByteBuffer> & dataVector Z7_7Z_DECODER_CRYPRO_VARS_DECL)1160*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadAndDecodePackedStreams(
1161*f6dc9357SAndroid Build Coastguard Worker DECL_EXTERNAL_CODECS_LOC_VARS
1162*f6dc9357SAndroid Build Coastguard Worker UInt64 baseOffset,
1163*f6dc9357SAndroid Build Coastguard Worker UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector
1164*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS_DECL
1165*f6dc9357SAndroid Build Coastguard Worker )
1166*f6dc9357SAndroid Build Coastguard Worker {
1167*f6dc9357SAndroid Build Coastguard Worker CFolders folders;
1168*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> unpackSizes;
1169*f6dc9357SAndroid Build Coastguard Worker CUInt32DefVector digests;
1170*f6dc9357SAndroid Build Coastguard Worker
1171*f6dc9357SAndroid Build Coastguard Worker ReadStreamsInfo(NULL,
1172*f6dc9357SAndroid Build Coastguard Worker dataOffset,
1173*f6dc9357SAndroid Build Coastguard Worker folders,
1174*f6dc9357SAndroid Build Coastguard Worker unpackSizes,
1175*f6dc9357SAndroid Build Coastguard Worker digests);
1176*f6dc9357SAndroid Build Coastguard Worker
1177*f6dc9357SAndroid Build Coastguard Worker CDecoder decoder(_useMixerMT);
1178*f6dc9357SAndroid Build Coastguard Worker
1179*f6dc9357SAndroid Build Coastguard Worker for (CNum i = 0; i < folders.NumFolders; i++)
1180*f6dc9357SAndroid Build Coastguard Worker {
1181*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &data = dataVector.AddNew();
1182*f6dc9357SAndroid Build Coastguard Worker const UInt64 unpackSize64 = folders.GetFolderUnpackSize(i);
1183*f6dc9357SAndroid Build Coastguard Worker const size_t unpackSize = (size_t)unpackSize64;
1184*f6dc9357SAndroid Build Coastguard Worker if (unpackSize != unpackSize64)
1185*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
1186*f6dc9357SAndroid Build Coastguard Worker data.Alloc(unpackSize);
1187*f6dc9357SAndroid Build Coastguard Worker
1188*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStreamSpec;
1189*f6dc9357SAndroid Build Coastguard Worker outStreamSpec->Init(data, unpackSize);
1190*f6dc9357SAndroid Build Coastguard Worker
1191*f6dc9357SAndroid Build Coastguard Worker bool dataAfterEnd_Error = false;
1192*f6dc9357SAndroid Build Coastguard Worker
1193*f6dc9357SAndroid Build Coastguard Worker HRESULT result = decoder.Decode(
1194*f6dc9357SAndroid Build Coastguard Worker EXTERNAL_CODECS_LOC_VARS
1195*f6dc9357SAndroid Build Coastguard Worker _stream, baseOffset + dataOffset,
1196*f6dc9357SAndroid Build Coastguard Worker folders, i,
1197*f6dc9357SAndroid Build Coastguard Worker NULL, // &unpackSize64
1198*f6dc9357SAndroid Build Coastguard Worker
1199*f6dc9357SAndroid Build Coastguard Worker outStreamSpec,
1200*f6dc9357SAndroid Build Coastguard Worker NULL, // *compressProgress
1201*f6dc9357SAndroid Build Coastguard Worker
1202*f6dc9357SAndroid Build Coastguard Worker NULL // **inStreamMainRes
1203*f6dc9357SAndroid Build Coastguard Worker , dataAfterEnd_Error
1204*f6dc9357SAndroid Build Coastguard Worker
1205*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS
1206*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_ST)
1207*f6dc9357SAndroid Build Coastguard Worker , false // mtMode
1208*f6dc9357SAndroid Build Coastguard Worker , 1 // numThreads
1209*f6dc9357SAndroid Build Coastguard Worker , 0 // memUsage
1210*f6dc9357SAndroid Build Coastguard Worker #endif
1211*f6dc9357SAndroid Build Coastguard Worker );
1212*f6dc9357SAndroid Build Coastguard Worker
1213*f6dc9357SAndroid Build Coastguard Worker RINOK(result)
1214*f6dc9357SAndroid Build Coastguard Worker
1215*f6dc9357SAndroid Build Coastguard Worker if (dataAfterEnd_Error)
1216*f6dc9357SAndroid Build Coastguard Worker ThereIsHeaderError = true;
1217*f6dc9357SAndroid Build Coastguard Worker
1218*f6dc9357SAndroid Build Coastguard Worker if (unpackSize != outStreamSpec->GetPos())
1219*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1220*f6dc9357SAndroid Build Coastguard Worker
1221*f6dc9357SAndroid Build Coastguard Worker if (folders.FolderCRCs.ValidAndDefined(i))
1222*f6dc9357SAndroid Build Coastguard Worker if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
1223*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1224*f6dc9357SAndroid Build Coastguard Worker }
1225*f6dc9357SAndroid Build Coastguard Worker
1226*f6dc9357SAndroid Build Coastguard Worker if (folders.PackPositions)
1227*f6dc9357SAndroid Build Coastguard Worker HeadersSize += folders.PackPositions[folders.NumPackStreams];
1228*f6dc9357SAndroid Build Coastguard Worker
1229*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1230*f6dc9357SAndroid Build Coastguard Worker }
1231*f6dc9357SAndroid Build Coastguard Worker
ReadHeader(DECL_EXTERNAL_CODECS_LOC_VARS CDbEx & db Z7_7Z_DECODER_CRYPRO_VARS_DECL)1232*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadHeader(
1233*f6dc9357SAndroid Build Coastguard Worker DECL_EXTERNAL_CODECS_LOC_VARS
1234*f6dc9357SAndroid Build Coastguard Worker CDbEx &db
1235*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS_DECL
1236*f6dc9357SAndroid Build Coastguard Worker )
1237*f6dc9357SAndroid Build Coastguard Worker {
1238*f6dc9357SAndroid Build Coastguard Worker UInt64 type = ReadID();
1239*f6dc9357SAndroid Build Coastguard Worker
1240*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kArchiveProperties)
1241*f6dc9357SAndroid Build Coastguard Worker {
1242*f6dc9357SAndroid Build Coastguard Worker ReadArchiveProperties(db.ArcInfo);
1243*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
1244*f6dc9357SAndroid Build Coastguard Worker }
1245*f6dc9357SAndroid Build Coastguard Worker
1246*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CByteBuffer> dataVector;
1247*f6dc9357SAndroid Build Coastguard Worker
1248*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kAdditionalStreamsInfo)
1249*f6dc9357SAndroid Build Coastguard Worker {
1250*f6dc9357SAndroid Build Coastguard Worker const HRESULT result = ReadAndDecodePackedStreams(
1251*f6dc9357SAndroid Build Coastguard Worker EXTERNAL_CODECS_LOC_VARS
1252*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.StartPositionAfterHeader,
1253*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.DataStartPosition2,
1254*f6dc9357SAndroid Build Coastguard Worker dataVector
1255*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS
1256*f6dc9357SAndroid Build Coastguard Worker );
1257*f6dc9357SAndroid Build Coastguard Worker RINOK(result)
1258*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader;
1259*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
1260*f6dc9357SAndroid Build Coastguard Worker }
1261*f6dc9357SAndroid Build Coastguard Worker
1262*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> unpackSizes;
1263*f6dc9357SAndroid Build Coastguard Worker CUInt32DefVector digests;
1264*f6dc9357SAndroid Build Coastguard Worker
1265*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kMainStreamsInfo)
1266*f6dc9357SAndroid Build Coastguard Worker {
1267*f6dc9357SAndroid Build Coastguard Worker ReadStreamsInfo(&dataVector,
1268*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.DataStartPosition,
1269*f6dc9357SAndroid Build Coastguard Worker (CFolders &)db,
1270*f6dc9357SAndroid Build Coastguard Worker unpackSizes,
1271*f6dc9357SAndroid Build Coastguard Worker digests);
1272*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader;
1273*f6dc9357SAndroid Build Coastguard Worker type = ReadID();
1274*f6dc9357SAndroid Build Coastguard Worker }
1275*f6dc9357SAndroid Build Coastguard Worker
1276*f6dc9357SAndroid Build Coastguard Worker if (type == NID::kFilesInfo)
1277*f6dc9357SAndroid Build Coastguard Worker {
1278*f6dc9357SAndroid Build Coastguard Worker
1279*f6dc9357SAndroid Build Coastguard Worker const CNum numFiles = ReadNum();
1280*f6dc9357SAndroid Build Coastguard Worker
1281*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
1282*f6dc9357SAndroid Build Coastguard Worker // if (!db.PackSizes.IsEmpty())
1283*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
1284*f6dc9357SAndroid Build Coastguard Worker if (numFiles > 0 && !digests.Defs.IsEmpty())
1285*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
1286*f6dc9357SAndroid Build Coastguard Worker
1287*f6dc9357SAndroid Build Coastguard Worker CBoolVector emptyStreamVector;
1288*f6dc9357SAndroid Build Coastguard Worker CBoolVector emptyFileVector;
1289*f6dc9357SAndroid Build Coastguard Worker CBoolVector antiFileVector;
1290*f6dc9357SAndroid Build Coastguard Worker unsigned numEmptyStreams = 0;
1291*f6dc9357SAndroid Build Coastguard Worker
1292*f6dc9357SAndroid Build Coastguard Worker for (;;)
1293*f6dc9357SAndroid Build Coastguard Worker {
1294*f6dc9357SAndroid Build Coastguard Worker const UInt64 type2 = ReadID();
1295*f6dc9357SAndroid Build Coastguard Worker if (type2 == NID::kEnd)
1296*f6dc9357SAndroid Build Coastguard Worker break;
1297*f6dc9357SAndroid Build Coastguard Worker const UInt64 size = ReadNumber();
1298*f6dc9357SAndroid Build Coastguard Worker if (size > _inByteBack->GetRem())
1299*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1300*f6dc9357SAndroid Build Coastguard Worker CStreamSwitch switchProp;
1301*f6dc9357SAndroid Build Coastguard Worker switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);
1302*f6dc9357SAndroid Build Coastguard Worker bool addPropIdToList = true;
1303*f6dc9357SAndroid Build Coastguard Worker bool isKnownType = true;
1304*f6dc9357SAndroid Build Coastguard Worker if (type2 > ((UInt32)1 << 30))
1305*f6dc9357SAndroid Build Coastguard Worker isKnownType = false;
1306*f6dc9357SAndroid Build Coastguard Worker else switch ((UInt32)type2)
1307*f6dc9357SAndroid Build Coastguard Worker {
1308*f6dc9357SAndroid Build Coastguard Worker case NID::kName:
1309*f6dc9357SAndroid Build Coastguard Worker {
1310*f6dc9357SAndroid Build Coastguard Worker CStreamSwitch streamSwitch;
1311*f6dc9357SAndroid Build Coastguard Worker streamSwitch.Set(this, &dataVector);
1312*f6dc9357SAndroid Build Coastguard Worker const size_t rem = _inByteBack->GetRem();
1313*f6dc9357SAndroid Build Coastguard Worker db.NamesBuf.Alloc(rem);
1314*f6dc9357SAndroid Build Coastguard Worker ReadBytes(db.NamesBuf, rem);
1315*f6dc9357SAndroid Build Coastguard Worker db.NameOffsets.Alloc(numFiles + 1);
1316*f6dc9357SAndroid Build Coastguard Worker size_t pos = 0;
1317*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1318*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numFiles; i++)
1319*f6dc9357SAndroid Build Coastguard Worker {
1320*f6dc9357SAndroid Build Coastguard Worker const size_t curRem = (rem - pos) / 2;
1321*f6dc9357SAndroid Build Coastguard Worker const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf.ConstData() + pos);
1322*f6dc9357SAndroid Build Coastguard Worker size_t j;
1323*f6dc9357SAndroid Build Coastguard Worker for (j = 0; j < curRem && buf[j] != 0; j++);
1324*f6dc9357SAndroid Build Coastguard Worker if (j == curRem)
1325*f6dc9357SAndroid Build Coastguard Worker ThrowEndOfData();
1326*f6dc9357SAndroid Build Coastguard Worker db.NameOffsets[i] = pos / 2;
1327*f6dc9357SAndroid Build Coastguard Worker pos += j * 2 + 2;
1328*f6dc9357SAndroid Build Coastguard Worker }
1329*f6dc9357SAndroid Build Coastguard Worker db.NameOffsets[i] = pos / 2;
1330*f6dc9357SAndroid Build Coastguard Worker if (pos != rem)
1331*f6dc9357SAndroid Build Coastguard Worker ThereIsHeaderError = true;
1332*f6dc9357SAndroid Build Coastguard Worker break;
1333*f6dc9357SAndroid Build Coastguard Worker }
1334*f6dc9357SAndroid Build Coastguard Worker
1335*f6dc9357SAndroid Build Coastguard Worker case NID::kWinAttrib:
1336*f6dc9357SAndroid Build Coastguard Worker {
1337*f6dc9357SAndroid Build Coastguard Worker ReadBoolVector2(numFiles, db.Attrib.Defs);
1338*f6dc9357SAndroid Build Coastguard Worker CStreamSwitch streamSwitch;
1339*f6dc9357SAndroid Build Coastguard Worker streamSwitch.Set(this, &dataVector);
1340*f6dc9357SAndroid Build Coastguard Worker Read_UInt32_Vector(db.Attrib);
1341*f6dc9357SAndroid Build Coastguard Worker break;
1342*f6dc9357SAndroid Build Coastguard Worker }
1343*f6dc9357SAndroid Build Coastguard Worker
1344*f6dc9357SAndroid Build Coastguard Worker /*
1345*f6dc9357SAndroid Build Coastguard Worker case NID::kIsAux:
1346*f6dc9357SAndroid Build Coastguard Worker {
1347*f6dc9357SAndroid Build Coastguard Worker ReadBoolVector(numFiles, db.IsAux);
1348*f6dc9357SAndroid Build Coastguard Worker break;
1349*f6dc9357SAndroid Build Coastguard Worker }
1350*f6dc9357SAndroid Build Coastguard Worker case NID::kParent:
1351*f6dc9357SAndroid Build Coastguard Worker {
1352*f6dc9357SAndroid Build Coastguard Worker db.IsTree = true;
1353*f6dc9357SAndroid Build Coastguard Worker // CBoolVector boolVector;
1354*f6dc9357SAndroid Build Coastguard Worker // ReadBoolVector2(numFiles, boolVector);
1355*f6dc9357SAndroid Build Coastguard Worker // CStreamSwitch streamSwitch;
1356*f6dc9357SAndroid Build Coastguard Worker // streamSwitch.Set(this, &dataVector);
1357*f6dc9357SAndroid Build Coastguard Worker CBoolVector boolVector;
1358*f6dc9357SAndroid Build Coastguard Worker ReadBoolVector2(numFiles, boolVector);
1359*f6dc9357SAndroid Build Coastguard Worker
1360*f6dc9357SAndroid Build Coastguard Worker db.ThereAreAltStreams = false;
1361*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numFiles; i++)
1362*f6dc9357SAndroid Build Coastguard Worker {
1363*f6dc9357SAndroid Build Coastguard Worker CFileItem &file = db.Files[i];
1364*f6dc9357SAndroid Build Coastguard Worker // file.Parent = -1;
1365*f6dc9357SAndroid Build Coastguard Worker // if (boolVector[i])
1366*f6dc9357SAndroid Build Coastguard Worker file.Parent = (int)ReadUInt32();
1367*f6dc9357SAndroid Build Coastguard Worker file.IsAltStream = !boolVector[i];
1368*f6dc9357SAndroid Build Coastguard Worker if (file.IsAltStream)
1369*f6dc9357SAndroid Build Coastguard Worker db.ThereAreAltStreams = true;
1370*f6dc9357SAndroid Build Coastguard Worker }
1371*f6dc9357SAndroid Build Coastguard Worker break;
1372*f6dc9357SAndroid Build Coastguard Worker }
1373*f6dc9357SAndroid Build Coastguard Worker */
1374*f6dc9357SAndroid Build Coastguard Worker case NID::kEmptyStream:
1375*f6dc9357SAndroid Build Coastguard Worker {
1376*f6dc9357SAndroid Build Coastguard Worker ReadBoolVector(numFiles, emptyStreamVector);
1377*f6dc9357SAndroid Build Coastguard Worker numEmptyStreams = BoolVector_CountSum(emptyStreamVector);
1378*f6dc9357SAndroid Build Coastguard Worker emptyFileVector.Clear();
1379*f6dc9357SAndroid Build Coastguard Worker antiFileVector.Clear();
1380*f6dc9357SAndroid Build Coastguard Worker break;
1381*f6dc9357SAndroid Build Coastguard Worker }
1382*f6dc9357SAndroid Build Coastguard Worker case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break;
1383*f6dc9357SAndroid Build Coastguard Worker case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break;
1384*f6dc9357SAndroid Build Coastguard Worker case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break;
1385*f6dc9357SAndroid Build Coastguard Worker case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break;
1386*f6dc9357SAndroid Build Coastguard Worker case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break;
1387*f6dc9357SAndroid Build Coastguard Worker case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break;
1388*f6dc9357SAndroid Build Coastguard Worker case NID::kDummy:
1389*f6dc9357SAndroid Build Coastguard Worker {
1390*f6dc9357SAndroid Build Coastguard Worker for (UInt64 j = 0; j < size; j++)
1391*f6dc9357SAndroid Build Coastguard Worker if (ReadByte() != 0)
1392*f6dc9357SAndroid Build Coastguard Worker ThereIsHeaderError = true;
1393*f6dc9357SAndroid Build Coastguard Worker addPropIdToList = false;
1394*f6dc9357SAndroid Build Coastguard Worker break;
1395*f6dc9357SAndroid Build Coastguard Worker }
1396*f6dc9357SAndroid Build Coastguard Worker /*
1397*f6dc9357SAndroid Build Coastguard Worker case NID::kNtSecure:
1398*f6dc9357SAndroid Build Coastguard Worker {
1399*f6dc9357SAndroid Build Coastguard Worker try
1400*f6dc9357SAndroid Build Coastguard Worker {
1401*f6dc9357SAndroid Build Coastguard Worker {
1402*f6dc9357SAndroid Build Coastguard Worker CStreamSwitch streamSwitch;
1403*f6dc9357SAndroid Build Coastguard Worker streamSwitch.Set(this, &dataVector);
1404*f6dc9357SAndroid Build Coastguard Worker UInt32 numDescriptors = ReadUInt32();
1405*f6dc9357SAndroid Build Coastguard Worker size_t offset = 0;
1406*f6dc9357SAndroid Build Coastguard Worker db.SecureOffsets.Clear();
1407*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numDescriptors; i++)
1408*f6dc9357SAndroid Build Coastguard Worker {
1409*f6dc9357SAndroid Build Coastguard Worker UInt32 size = ReadUInt32();
1410*f6dc9357SAndroid Build Coastguard Worker db.SecureOffsets.Add(offset);
1411*f6dc9357SAndroid Build Coastguard Worker offset += size;
1412*f6dc9357SAndroid Build Coastguard Worker }
1413*f6dc9357SAndroid Build Coastguard Worker // ThrowIncorrect();;
1414*f6dc9357SAndroid Build Coastguard Worker db.SecureOffsets.Add(offset);
1415*f6dc9357SAndroid Build Coastguard Worker db.SecureBuf.SetCapacity(offset);
1416*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numDescriptors; i++)
1417*f6dc9357SAndroid Build Coastguard Worker {
1418*f6dc9357SAndroid Build Coastguard Worker offset = db.SecureOffsets[i];
1419*f6dc9357SAndroid Build Coastguard Worker ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);
1420*f6dc9357SAndroid Build Coastguard Worker }
1421*f6dc9357SAndroid Build Coastguard Worker db.SecureIDs.Clear();
1422*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numFiles; i++)
1423*f6dc9357SAndroid Build Coastguard Worker {
1424*f6dc9357SAndroid Build Coastguard Worker db.SecureIDs.Add(ReadNum());
1425*f6dc9357SAndroid Build Coastguard Worker // db.SecureIDs.Add(ReadUInt32());
1426*f6dc9357SAndroid Build Coastguard Worker }
1427*f6dc9357SAndroid Build Coastguard Worker // ReadUInt32();
1428*f6dc9357SAndroid Build Coastguard Worker if (_inByteBack->GetRem() != 0)
1429*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();;
1430*f6dc9357SAndroid Build Coastguard Worker }
1431*f6dc9357SAndroid Build Coastguard Worker }
1432*f6dc9357SAndroid Build Coastguard Worker catch(CInArchiveException &)
1433*f6dc9357SAndroid Build Coastguard Worker {
1434*f6dc9357SAndroid Build Coastguard Worker ThereIsHeaderError = true;
1435*f6dc9357SAndroid Build Coastguard Worker addPropIdToList = isKnownType = false;
1436*f6dc9357SAndroid Build Coastguard Worker db.ClearSecure();
1437*f6dc9357SAndroid Build Coastguard Worker }
1438*f6dc9357SAndroid Build Coastguard Worker break;
1439*f6dc9357SAndroid Build Coastguard Worker }
1440*f6dc9357SAndroid Build Coastguard Worker */
1441*f6dc9357SAndroid Build Coastguard Worker default:
1442*f6dc9357SAndroid Build Coastguard Worker addPropIdToList = isKnownType = false;
1443*f6dc9357SAndroid Build Coastguard Worker }
1444*f6dc9357SAndroid Build Coastguard Worker if (isKnownType)
1445*f6dc9357SAndroid Build Coastguard Worker {
1446*f6dc9357SAndroid Build Coastguard Worker if (addPropIdToList)
1447*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.FileInfoPopIDs.Add(type2);
1448*f6dc9357SAndroid Build Coastguard Worker }
1449*f6dc9357SAndroid Build Coastguard Worker else
1450*f6dc9357SAndroid Build Coastguard Worker {
1451*f6dc9357SAndroid Build Coastguard Worker db.UnsupportedFeatureWarning = true;
1452*f6dc9357SAndroid Build Coastguard Worker _inByteBack->SkipRem();
1453*f6dc9357SAndroid Build Coastguard Worker }
1454*f6dc9357SAndroid Build Coastguard Worker // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02)
1455*f6dc9357SAndroid Build Coastguard Worker if (_inByteBack->GetRem() != 0)
1456*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1457*f6dc9357SAndroid Build Coastguard Worker }
1458*f6dc9357SAndroid Build Coastguard Worker
1459*f6dc9357SAndroid Build Coastguard Worker type = ReadID(); // Read (NID::kEnd) end of headers
1460*f6dc9357SAndroid Build Coastguard Worker
1461*f6dc9357SAndroid Build Coastguard Worker if (numFiles - numEmptyStreams != unpackSizes.Size())
1462*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
1463*f6dc9357SAndroid Build Coastguard Worker
1464*f6dc9357SAndroid Build Coastguard Worker CNum emptyFileIndex = 0;
1465*f6dc9357SAndroid Build Coastguard Worker CNum sizeIndex = 0;
1466*f6dc9357SAndroid Build Coastguard Worker
1467*f6dc9357SAndroid Build Coastguard Worker const unsigned numAntiItems = BoolVector_CountSum(antiFileVector);
1468*f6dc9357SAndroid Build Coastguard Worker
1469*f6dc9357SAndroid Build Coastguard Worker if (numAntiItems != 0)
1470*f6dc9357SAndroid Build Coastguard Worker db.IsAnti.ClearAndSetSize(numFiles);
1471*f6dc9357SAndroid Build Coastguard Worker
1472*f6dc9357SAndroid Build Coastguard Worker db.Files.ClearAndSetSize(numFiles);
1473*f6dc9357SAndroid Build Coastguard Worker
1474*f6dc9357SAndroid Build Coastguard Worker for (CNum i = 0; i < numFiles; i++)
1475*f6dc9357SAndroid Build Coastguard Worker {
1476*f6dc9357SAndroid Build Coastguard Worker CFileItem &file = db.Files[i];
1477*f6dc9357SAndroid Build Coastguard Worker bool isAnti;
1478*f6dc9357SAndroid Build Coastguard Worker file.Crc = 0;
1479*f6dc9357SAndroid Build Coastguard Worker if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i))
1480*f6dc9357SAndroid Build Coastguard Worker {
1481*f6dc9357SAndroid Build Coastguard Worker file.HasStream = true;
1482*f6dc9357SAndroid Build Coastguard Worker file.IsDir = false;
1483*f6dc9357SAndroid Build Coastguard Worker isAnti = false;
1484*f6dc9357SAndroid Build Coastguard Worker file.Size = unpackSizes[sizeIndex];
1485*f6dc9357SAndroid Build Coastguard Worker file.CrcDefined = digests.ValidAndDefined(sizeIndex);
1486*f6dc9357SAndroid Build Coastguard Worker if (file.CrcDefined)
1487*f6dc9357SAndroid Build Coastguard Worker file.Crc = digests.Vals[sizeIndex];
1488*f6dc9357SAndroid Build Coastguard Worker sizeIndex++;
1489*f6dc9357SAndroid Build Coastguard Worker }
1490*f6dc9357SAndroid Build Coastguard Worker else
1491*f6dc9357SAndroid Build Coastguard Worker {
1492*f6dc9357SAndroid Build Coastguard Worker file.HasStream = false;
1493*f6dc9357SAndroid Build Coastguard Worker file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex);
1494*f6dc9357SAndroid Build Coastguard Worker isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex);
1495*f6dc9357SAndroid Build Coastguard Worker emptyFileIndex++;
1496*f6dc9357SAndroid Build Coastguard Worker file.Size = 0;
1497*f6dc9357SAndroid Build Coastguard Worker file.CrcDefined = false;
1498*f6dc9357SAndroid Build Coastguard Worker }
1499*f6dc9357SAndroid Build Coastguard Worker if (numAntiItems != 0)
1500*f6dc9357SAndroid Build Coastguard Worker db.IsAnti[i] = isAnti;
1501*f6dc9357SAndroid Build Coastguard Worker }
1502*f6dc9357SAndroid Build Coastguard Worker
1503*f6dc9357SAndroid Build Coastguard Worker }
1504*f6dc9357SAndroid Build Coastguard Worker
1505*f6dc9357SAndroid Build Coastguard Worker db.FillLinks();
1506*f6dc9357SAndroid Build Coastguard Worker
1507*f6dc9357SAndroid Build Coastguard Worker if (type != NID::kEnd || _inByteBack->GetRem() != 0)
1508*f6dc9357SAndroid Build Coastguard Worker {
1509*f6dc9357SAndroid Build Coastguard Worker db.UnsupportedFeatureWarning = true;
1510*f6dc9357SAndroid Build Coastguard Worker // ThrowIncorrect();
1511*f6dc9357SAndroid Build Coastguard Worker }
1512*f6dc9357SAndroid Build Coastguard Worker
1513*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1514*f6dc9357SAndroid Build Coastguard Worker }
1515*f6dc9357SAndroid Build Coastguard Worker
1516*f6dc9357SAndroid Build Coastguard Worker
FillLinks()1517*f6dc9357SAndroid Build Coastguard Worker void CDbEx::FillLinks()
1518*f6dc9357SAndroid Build Coastguard Worker {
1519*f6dc9357SAndroid Build Coastguard Worker FolderStartFileIndex.Alloc(NumFolders);
1520*f6dc9357SAndroid Build Coastguard Worker FileIndexToFolderIndexMap.Alloc(Files.Size());
1521*f6dc9357SAndroid Build Coastguard Worker
1522*f6dc9357SAndroid Build Coastguard Worker CNum folderIndex = 0;
1523*f6dc9357SAndroid Build Coastguard Worker CNum indexInFolder = 0;
1524*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1525*f6dc9357SAndroid Build Coastguard Worker
1526*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Files.Size(); i++)
1527*f6dc9357SAndroid Build Coastguard Worker {
1528*f6dc9357SAndroid Build Coastguard Worker const bool emptyStream = !Files[i].HasStream;
1529*f6dc9357SAndroid Build Coastguard Worker if (indexInFolder == 0)
1530*f6dc9357SAndroid Build Coastguard Worker {
1531*f6dc9357SAndroid Build Coastguard Worker if (emptyStream)
1532*f6dc9357SAndroid Build Coastguard Worker {
1533*f6dc9357SAndroid Build Coastguard Worker FileIndexToFolderIndexMap[i] = kNumNoIndex;
1534*f6dc9357SAndroid Build Coastguard Worker continue;
1535*f6dc9357SAndroid Build Coastguard Worker }
1536*f6dc9357SAndroid Build Coastguard Worker // v3.13 incorrectly worked with empty folders
1537*f6dc9357SAndroid Build Coastguard Worker // v4.07: we skip empty folders
1538*f6dc9357SAndroid Build Coastguard Worker for (;;)
1539*f6dc9357SAndroid Build Coastguard Worker {
1540*f6dc9357SAndroid Build Coastguard Worker if (folderIndex >= NumFolders)
1541*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1542*f6dc9357SAndroid Build Coastguard Worker FolderStartFileIndex[folderIndex] = i;
1543*f6dc9357SAndroid Build Coastguard Worker if (NumUnpackStreamsVector[folderIndex] != 0)
1544*f6dc9357SAndroid Build Coastguard Worker break;
1545*f6dc9357SAndroid Build Coastguard Worker folderIndex++;
1546*f6dc9357SAndroid Build Coastguard Worker }
1547*f6dc9357SAndroid Build Coastguard Worker }
1548*f6dc9357SAndroid Build Coastguard Worker FileIndexToFolderIndexMap[i] = folderIndex;
1549*f6dc9357SAndroid Build Coastguard Worker if (emptyStream)
1550*f6dc9357SAndroid Build Coastguard Worker continue;
1551*f6dc9357SAndroid Build Coastguard Worker if (++indexInFolder >= NumUnpackStreamsVector[folderIndex])
1552*f6dc9357SAndroid Build Coastguard Worker {
1553*f6dc9357SAndroid Build Coastguard Worker folderIndex++;
1554*f6dc9357SAndroid Build Coastguard Worker indexInFolder = 0;
1555*f6dc9357SAndroid Build Coastguard Worker }
1556*f6dc9357SAndroid Build Coastguard Worker }
1557*f6dc9357SAndroid Build Coastguard Worker
1558*f6dc9357SAndroid Build Coastguard Worker if (indexInFolder != 0)
1559*f6dc9357SAndroid Build Coastguard Worker {
1560*f6dc9357SAndroid Build Coastguard Worker folderIndex++;
1561*f6dc9357SAndroid Build Coastguard Worker // 18.06
1562*f6dc9357SAndroid Build Coastguard Worker ThereIsHeaderError = true;
1563*f6dc9357SAndroid Build Coastguard Worker // ThrowIncorrect();
1564*f6dc9357SAndroid Build Coastguard Worker }
1565*f6dc9357SAndroid Build Coastguard Worker
1566*f6dc9357SAndroid Build Coastguard Worker for (;;)
1567*f6dc9357SAndroid Build Coastguard Worker {
1568*f6dc9357SAndroid Build Coastguard Worker if (folderIndex >= NumFolders)
1569*f6dc9357SAndroid Build Coastguard Worker return;
1570*f6dc9357SAndroid Build Coastguard Worker FolderStartFileIndex[folderIndex] = i;
1571*f6dc9357SAndroid Build Coastguard Worker if (NumUnpackStreamsVector[folderIndex] != 0)
1572*f6dc9357SAndroid Build Coastguard Worker {
1573*f6dc9357SAndroid Build Coastguard Worker // 18.06
1574*f6dc9357SAndroid Build Coastguard Worker ThereIsHeaderError = true;
1575*f6dc9357SAndroid Build Coastguard Worker // ThrowIncorrect();
1576*f6dc9357SAndroid Build Coastguard Worker }
1577*f6dc9357SAndroid Build Coastguard Worker folderIndex++;
1578*f6dc9357SAndroid Build Coastguard Worker }
1579*f6dc9357SAndroid Build Coastguard Worker }
1580*f6dc9357SAndroid Build Coastguard Worker
1581*f6dc9357SAndroid Build Coastguard Worker
ReadDatabase2(DECL_EXTERNAL_CODECS_LOC_VARS CDbEx & db Z7_7Z_DECODER_CRYPRO_VARS_DECL)1582*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadDatabase2(
1583*f6dc9357SAndroid Build Coastguard Worker DECL_EXTERNAL_CODECS_LOC_VARS
1584*f6dc9357SAndroid Build Coastguard Worker CDbEx &db
1585*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS_DECL
1586*f6dc9357SAndroid Build Coastguard Worker )
1587*f6dc9357SAndroid Build Coastguard Worker {
1588*f6dc9357SAndroid Build Coastguard Worker db.Clear();
1589*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.StartPosition = _arhiveBeginStreamPosition;
1590*f6dc9357SAndroid Build Coastguard Worker
1591*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.Version.Major = _header[6];
1592*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.Version.Minor = _header[7];
1593*f6dc9357SAndroid Build Coastguard Worker
1594*f6dc9357SAndroid Build Coastguard Worker if (db.ArcInfo.Version.Major != kMajorVersion)
1595*f6dc9357SAndroid Build Coastguard Worker {
1596*f6dc9357SAndroid Build Coastguard Worker // db.UnsupportedVersion = true;
1597*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1598*f6dc9357SAndroid Build Coastguard Worker }
1599*f6dc9357SAndroid Build Coastguard Worker
1600*f6dc9357SAndroid Build Coastguard Worker UInt64 nextHeaderOffset = Get64(_header + 12);
1601*f6dc9357SAndroid Build Coastguard Worker UInt64 nextHeaderSize = Get64(_header + 20);
1602*f6dc9357SAndroid Build Coastguard Worker UInt32 nextHeaderCRC = Get32(_header + 28);
1603*f6dc9357SAndroid Build Coastguard Worker
1604*f6dc9357SAndroid Build Coastguard Worker #ifdef FORMAT_7Z_RECOVERY
1605*f6dc9357SAndroid Build Coastguard Worker const UInt32 crcFromArc = Get32(_header + 8);
1606*f6dc9357SAndroid Build Coastguard Worker if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
1607*f6dc9357SAndroid Build Coastguard Worker {
1608*f6dc9357SAndroid Build Coastguard Worker UInt64 cur, fileSize;
1609*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetPos(_stream, cur))
1610*f6dc9357SAndroid Build Coastguard Worker const unsigned kCheckSize = 512;
1611*f6dc9357SAndroid Build Coastguard Worker Byte buf[kCheckSize];
1612*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(_stream, fileSize))
1613*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = fileSize - cur;
1614*f6dc9357SAndroid Build Coastguard Worker unsigned checkSize = kCheckSize;
1615*f6dc9357SAndroid Build Coastguard Worker if (rem < kCheckSize)
1616*f6dc9357SAndroid Build Coastguard Worker checkSize = (unsigned)(rem);
1617*f6dc9357SAndroid Build Coastguard Worker if (checkSize < 3)
1618*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1619*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_stream, fileSize - checkSize))
1620*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize))
1621*f6dc9357SAndroid Build Coastguard Worker
1622*f6dc9357SAndroid Build Coastguard Worker if (buf[checkSize - 1] != 0)
1623*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1624*f6dc9357SAndroid Build Coastguard Worker
1625*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1626*f6dc9357SAndroid Build Coastguard Worker for (i = checkSize - 2;; i--)
1627*f6dc9357SAndroid Build Coastguard Worker {
1628*f6dc9357SAndroid Build Coastguard Worker if ((buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo) ||
1629*f6dc9357SAndroid Build Coastguard Worker (buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo))
1630*f6dc9357SAndroid Build Coastguard Worker break;
1631*f6dc9357SAndroid Build Coastguard Worker if (i == 0)
1632*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1633*f6dc9357SAndroid Build Coastguard Worker }
1634*f6dc9357SAndroid Build Coastguard Worker nextHeaderSize = checkSize - i;
1635*f6dc9357SAndroid Build Coastguard Worker nextHeaderOffset = rem - nextHeaderSize;
1636*f6dc9357SAndroid Build Coastguard Worker nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
1637*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_stream, cur))
1638*f6dc9357SAndroid Build Coastguard Worker db.StartHeaderWasRecovered = true;
1639*f6dc9357SAndroid Build Coastguard Worker }
1640*f6dc9357SAndroid Build Coastguard Worker else
1641*f6dc9357SAndroid Build Coastguard Worker #endif
1642*f6dc9357SAndroid Build Coastguard Worker {
1643*f6dc9357SAndroid Build Coastguard Worker // Crc was tested already at signature check
1644*f6dc9357SAndroid Build Coastguard Worker // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect();
1645*f6dc9357SAndroid Build Coastguard Worker }
1646*f6dc9357SAndroid Build Coastguard Worker
1647*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;
1648*f6dc9357SAndroid Build Coastguard Worker db.PhySize = kHeaderSize;
1649*f6dc9357SAndroid Build Coastguard Worker
1650*f6dc9357SAndroid Build Coastguard Worker db.IsArc = false;
1651*f6dc9357SAndroid Build Coastguard Worker if ((Int64)nextHeaderOffset < 0 ||
1652*f6dc9357SAndroid Build Coastguard Worker nextHeaderSize > ((UInt64)1 << 62))
1653*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1654*f6dc9357SAndroid Build Coastguard Worker
1655*f6dc9357SAndroid Build Coastguard Worker HeadersSize = kHeaderSize;
1656*f6dc9357SAndroid Build Coastguard Worker
1657*f6dc9357SAndroid Build Coastguard Worker if (nextHeaderSize == 0)
1658*f6dc9357SAndroid Build Coastguard Worker {
1659*f6dc9357SAndroid Build Coastguard Worker if (nextHeaderOffset != 0 || nextHeaderCRC != 0)
1660*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1661*f6dc9357SAndroid Build Coastguard Worker db.IsArc = true;
1662*f6dc9357SAndroid Build Coastguard Worker db.HeadersSize = HeadersSize;
1663*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1664*f6dc9357SAndroid Build Coastguard Worker }
1665*f6dc9357SAndroid Build Coastguard Worker
1666*f6dc9357SAndroid Build Coastguard Worker if (!db.StartHeaderWasRecovered)
1667*f6dc9357SAndroid Build Coastguard Worker db.IsArc = true;
1668*f6dc9357SAndroid Build Coastguard Worker
1669*f6dc9357SAndroid Build Coastguard Worker HeadersSize += nextHeaderSize;
1670*f6dc9357SAndroid Build Coastguard Worker // db.EndHeaderOffset = nextHeaderOffset;
1671*f6dc9357SAndroid Build Coastguard Worker _rangeLimit = nextHeaderOffset;
1672*f6dc9357SAndroid Build Coastguard Worker
1673*f6dc9357SAndroid Build Coastguard Worker db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;
1674*f6dc9357SAndroid Build Coastguard Worker if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize)
1675*f6dc9357SAndroid Build Coastguard Worker {
1676*f6dc9357SAndroid Build Coastguard Worker db.UnexpectedEnd = true;
1677*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1678*f6dc9357SAndroid Build Coastguard Worker }
1679*f6dc9357SAndroid Build Coastguard Worker RINOK(_stream->Seek((Int64)nextHeaderOffset, STREAM_SEEK_CUR, NULL))
1680*f6dc9357SAndroid Build Coastguard Worker
1681*f6dc9357SAndroid Build Coastguard Worker const size_t nextHeaderSize_t = (size_t)nextHeaderSize;
1682*f6dc9357SAndroid Build Coastguard Worker if (nextHeaderSize_t != nextHeaderSize)
1683*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
1684*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buffer2(nextHeaderSize_t);
1685*f6dc9357SAndroid Build Coastguard Worker
1686*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t))
1687*f6dc9357SAndroid Build Coastguard Worker
1688*f6dc9357SAndroid Build Coastguard Worker if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC)
1689*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1690*f6dc9357SAndroid Build Coastguard Worker
1691*f6dc9357SAndroid Build Coastguard Worker if (!db.StartHeaderWasRecovered)
1692*f6dc9357SAndroid Build Coastguard Worker db.PhySizeWasConfirmed = true;
1693*f6dc9357SAndroid Build Coastguard Worker
1694*f6dc9357SAndroid Build Coastguard Worker CStreamSwitch streamSwitch;
1695*f6dc9357SAndroid Build Coastguard Worker streamSwitch.Set(this, buffer2);
1696*f6dc9357SAndroid Build Coastguard Worker
1697*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CByteBuffer> dataVector;
1698*f6dc9357SAndroid Build Coastguard Worker
1699*f6dc9357SAndroid Build Coastguard Worker const UInt64 type = ReadID();
1700*f6dc9357SAndroid Build Coastguard Worker if (type != NID::kHeader)
1701*f6dc9357SAndroid Build Coastguard Worker {
1702*f6dc9357SAndroid Build Coastguard Worker if (type != NID::kEncodedHeader)
1703*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1704*f6dc9357SAndroid Build Coastguard Worker const HRESULT result = ReadAndDecodePackedStreams(
1705*f6dc9357SAndroid Build Coastguard Worker EXTERNAL_CODECS_LOC_VARS
1706*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.StartPositionAfterHeader,
1707*f6dc9357SAndroid Build Coastguard Worker db.ArcInfo.DataStartPosition2,
1708*f6dc9357SAndroid Build Coastguard Worker dataVector
1709*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS
1710*f6dc9357SAndroid Build Coastguard Worker );
1711*f6dc9357SAndroid Build Coastguard Worker RINOK(result)
1712*f6dc9357SAndroid Build Coastguard Worker if (dataVector.Size() == 0)
1713*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1714*f6dc9357SAndroid Build Coastguard Worker if (dataVector.Size() > 1)
1715*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1716*f6dc9357SAndroid Build Coastguard Worker streamSwitch.Remove();
1717*f6dc9357SAndroid Build Coastguard Worker streamSwitch.Set(this, dataVector.Front());
1718*f6dc9357SAndroid Build Coastguard Worker if (ReadID() != NID::kHeader)
1719*f6dc9357SAndroid Build Coastguard Worker ThrowIncorrect();
1720*f6dc9357SAndroid Build Coastguard Worker }
1721*f6dc9357SAndroid Build Coastguard Worker
1722*f6dc9357SAndroid Build Coastguard Worker db.IsArc = true;
1723*f6dc9357SAndroid Build Coastguard Worker
1724*f6dc9357SAndroid Build Coastguard Worker db.HeadersSize = HeadersSize;
1725*f6dc9357SAndroid Build Coastguard Worker
1726*f6dc9357SAndroid Build Coastguard Worker return ReadHeader(
1727*f6dc9357SAndroid Build Coastguard Worker EXTERNAL_CODECS_LOC_VARS
1728*f6dc9357SAndroid Build Coastguard Worker db
1729*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS
1730*f6dc9357SAndroid Build Coastguard Worker );
1731*f6dc9357SAndroid Build Coastguard Worker }
1732*f6dc9357SAndroid Build Coastguard Worker
1733*f6dc9357SAndroid Build Coastguard Worker
ReadDatabase(DECL_EXTERNAL_CODECS_LOC_VARS CDbEx & db Z7_7Z_DECODER_CRYPRO_VARS_DECL)1734*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadDatabase(
1735*f6dc9357SAndroid Build Coastguard Worker DECL_EXTERNAL_CODECS_LOC_VARS
1736*f6dc9357SAndroid Build Coastguard Worker CDbEx &db
1737*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS_DECL
1738*f6dc9357SAndroid Build Coastguard Worker )
1739*f6dc9357SAndroid Build Coastguard Worker {
1740*f6dc9357SAndroid Build Coastguard Worker try
1741*f6dc9357SAndroid Build Coastguard Worker {
1742*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = ReadDatabase2(
1743*f6dc9357SAndroid Build Coastguard Worker EXTERNAL_CODECS_LOC_VARS db
1744*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS
1745*f6dc9357SAndroid Build Coastguard Worker );
1746*f6dc9357SAndroid Build Coastguard Worker if (ThereIsHeaderError)
1747*f6dc9357SAndroid Build Coastguard Worker db.ThereIsHeaderError = true;
1748*f6dc9357SAndroid Build Coastguard Worker if (res == E_NOTIMPL)
1749*f6dc9357SAndroid Build Coastguard Worker ThrowUnsupported();
1750*f6dc9357SAndroid Build Coastguard Worker return res;
1751*f6dc9357SAndroid Build Coastguard Worker }
1752*f6dc9357SAndroid Build Coastguard Worker catch(CUnsupportedFeatureException &)
1753*f6dc9357SAndroid Build Coastguard Worker {
1754*f6dc9357SAndroid Build Coastguard Worker db.UnsupportedFeatureError = true;
1755*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1756*f6dc9357SAndroid Build Coastguard Worker }
1757*f6dc9357SAndroid Build Coastguard Worker catch(CInArchiveException &)
1758*f6dc9357SAndroid Build Coastguard Worker {
1759*f6dc9357SAndroid Build Coastguard Worker db.ThereIsHeaderError = true;
1760*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1761*f6dc9357SAndroid Build Coastguard Worker }
1762*f6dc9357SAndroid Build Coastguard Worker }
1763*f6dc9357SAndroid Build Coastguard Worker
1764*f6dc9357SAndroid Build Coastguard Worker }}
1765