1370b324cSopenharmony_ci// 7zIn.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#ifdef _WIN32
6370b324cSopenharmony_ci#include <wchar.h>
7370b324cSopenharmony_ci#else
8370b324cSopenharmony_ci#include <ctype.h>
9370b324cSopenharmony_ci#endif
10370b324cSopenharmony_ci
11370b324cSopenharmony_ci#include "../../../../C/7zCrc.h"
12370b324cSopenharmony_ci#include "../../../../C/CpuArch.h"
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci#include "../../../Common/MyBuffer2.h"
15370b324cSopenharmony_ci// #include "../../../Common/UTFConvert.h"
16370b324cSopenharmony_ci
17370b324cSopenharmony_ci#include "../../Common/StreamObjects.h"
18370b324cSopenharmony_ci#include "../../Common/StreamUtils.h"
19370b324cSopenharmony_ci
20370b324cSopenharmony_ci#include "7zDecode.h"
21370b324cSopenharmony_ci#include "7zIn.h"
22370b324cSopenharmony_ci
23370b324cSopenharmony_ci#define Get16(p) GetUi16(p)
24370b324cSopenharmony_ci#define Get32(p) GetUi32(p)
25370b324cSopenharmony_ci#define Get64(p) GetUi64(p)
26370b324cSopenharmony_ci
27370b324cSopenharmony_ci// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader
28370b324cSopenharmony_ci#ifndef Z7_SFX
29370b324cSopenharmony_ci#define FORMAT_7Z_RECOVERY
30370b324cSopenharmony_ci#endif
31370b324cSopenharmony_ci
32370b324cSopenharmony_ciusing namespace NWindows;
33370b324cSopenharmony_ciusing namespace NCOM;
34370b324cSopenharmony_ci
35370b324cSopenharmony_cinamespace NArchive {
36370b324cSopenharmony_cinamespace N7z {
37370b324cSopenharmony_ci
38370b324cSopenharmony_ci#define k_Scan_NumCoders_MAX 64
39370b324cSopenharmony_ci#define k_Scan_NumCodersStreams_in_Folder_MAX 64
40370b324cSopenharmony_ci
41370b324cSopenharmony_ciunsigned BoolVector_CountSum(const CBoolVector &v);
42370b324cSopenharmony_ciunsigned BoolVector_CountSum(const CBoolVector &v)
43370b324cSopenharmony_ci{
44370b324cSopenharmony_ci  unsigned sum = 0;
45370b324cSopenharmony_ci  const unsigned size = v.Size();
46370b324cSopenharmony_ci  for (unsigned i = 0; i < size; i++)
47370b324cSopenharmony_ci    if (v[i])
48370b324cSopenharmony_ci      sum++;
49370b324cSopenharmony_ci  return sum;
50370b324cSopenharmony_ci}
51370b324cSopenharmony_ci
52370b324cSopenharmony_cistatic inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)
53370b324cSopenharmony_ci{
54370b324cSopenharmony_ci  return (i < v.Size() ? v[i] : false);
55370b324cSopenharmony_ci}
56370b324cSopenharmony_ci
57370b324cSopenharmony_cistatic void BoolVector_Fill_False(CBoolVector &v, unsigned size)
58370b324cSopenharmony_ci{
59370b324cSopenharmony_ci  v.ClearAndSetSize(size);
60370b324cSopenharmony_ci  bool *p = &v[0];
61370b324cSopenharmony_ci  for (unsigned i = 0; i < size; i++)
62370b324cSopenharmony_ci    p[i] = false;
63370b324cSopenharmony_ci}
64370b324cSopenharmony_ci
65370b324cSopenharmony_ci
66370b324cSopenharmony_ciclass CInArchiveException {};
67370b324cSopenharmony_ciclass CUnsupportedFeatureException: public CInArchiveException {};
68370b324cSopenharmony_ci
69370b324cSopenharmony_ciZ7_ATTR_NORETURN
70370b324cSopenharmony_cistatic void ThrowException() { throw CInArchiveException(); }
71370b324cSopenharmony_ciZ7_ATTR_NORETURN
72370b324cSopenharmony_cistatic inline void ThrowEndOfData()   { ThrowException(); }
73370b324cSopenharmony_ciZ7_ATTR_NORETURN
74370b324cSopenharmony_cistatic inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); }
75370b324cSopenharmony_ciZ7_ATTR_NORETURN
76370b324cSopenharmony_cistatic inline void ThrowIncorrect()   { ThrowException(); }
77370b324cSopenharmony_ci
78370b324cSopenharmony_ciclass CStreamSwitch
79370b324cSopenharmony_ci{
80370b324cSopenharmony_ci  CInArchive *_archive;
81370b324cSopenharmony_ci  bool _needRemove;
82370b324cSopenharmony_ci  bool _needUpdatePos;
83370b324cSopenharmony_cipublic:
84370b324cSopenharmony_ci  CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {}
85370b324cSopenharmony_ci  ~CStreamSwitch() { Remove(); }
86370b324cSopenharmony_ci  void Remove();
87370b324cSopenharmony_ci  void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos);
88370b324cSopenharmony_ci  void Set(CInArchive *archive, const CByteBuffer &byteBuffer);
89370b324cSopenharmony_ci  void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);
90370b324cSopenharmony_ci};
91370b324cSopenharmony_ci
92370b324cSopenharmony_civoid CStreamSwitch::Remove()
93370b324cSopenharmony_ci{
94370b324cSopenharmony_ci  if (_needRemove)
95370b324cSopenharmony_ci  {
96370b324cSopenharmony_ci    if (_archive->_inByteBack->GetRem() != 0)
97370b324cSopenharmony_ci      _archive->ThereIsHeaderError = true;
98370b324cSopenharmony_ci    _archive->DeleteByteStream(_needUpdatePos);
99370b324cSopenharmony_ci    _needRemove = false;
100370b324cSopenharmony_ci  }
101370b324cSopenharmony_ci}
102370b324cSopenharmony_ci
103370b324cSopenharmony_civoid CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos)
104370b324cSopenharmony_ci{
105370b324cSopenharmony_ci  Remove();
106370b324cSopenharmony_ci  _archive = archive;
107370b324cSopenharmony_ci  _archive->AddByteStream(data, size);
108370b324cSopenharmony_ci  _needRemove = true;
109370b324cSopenharmony_ci  _needUpdatePos = needUpdatePos;
110370b324cSopenharmony_ci}
111370b324cSopenharmony_ci
112370b324cSopenharmony_civoid CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)
113370b324cSopenharmony_ci{
114370b324cSopenharmony_ci  Set(archive, byteBuffer, byteBuffer.Size(), false);
115370b324cSopenharmony_ci}
116370b324cSopenharmony_ci
117370b324cSopenharmony_civoid CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)
118370b324cSopenharmony_ci{
119370b324cSopenharmony_ci  Remove();
120370b324cSopenharmony_ci  const Byte external = archive->ReadByte();
121370b324cSopenharmony_ci  if (external != 0)
122370b324cSopenharmony_ci  {
123370b324cSopenharmony_ci    if (!dataVector)
124370b324cSopenharmony_ci      ThrowIncorrect();
125370b324cSopenharmony_ci    const CNum dataIndex = archive->ReadNum();
126370b324cSopenharmony_ci    if (dataIndex >= dataVector->Size())
127370b324cSopenharmony_ci      ThrowIncorrect();
128370b324cSopenharmony_ci    Set(archive, (*dataVector)[dataIndex]);
129370b324cSopenharmony_ci  }
130370b324cSopenharmony_ci}
131370b324cSopenharmony_ci
132370b324cSopenharmony_civoid CInArchive::AddByteStream(const Byte *buf, size_t size)
133370b324cSopenharmony_ci{
134370b324cSopenharmony_ci  if (_numInByteBufs == kNumBufLevelsMax)
135370b324cSopenharmony_ci    ThrowIncorrect();
136370b324cSopenharmony_ci  _inByteBack = &_inByteVector[_numInByteBufs++];
137370b324cSopenharmony_ci  _inByteBack->Init(buf, size);
138370b324cSopenharmony_ci}
139370b324cSopenharmony_ci
140370b324cSopenharmony_ci
141370b324cSopenharmony_ciByte CInByte2::ReadByte()
142370b324cSopenharmony_ci{
143370b324cSopenharmony_ci  if (_pos >= _size)
144370b324cSopenharmony_ci    ThrowEndOfData();
145370b324cSopenharmony_ci  return _buffer[_pos++];
146370b324cSopenharmony_ci}
147370b324cSopenharmony_ci
148370b324cSopenharmony_civoid CInByte2::ReadBytes(Byte *data, size_t size)
149370b324cSopenharmony_ci{
150370b324cSopenharmony_ci  if (size == 0)
151370b324cSopenharmony_ci    return;
152370b324cSopenharmony_ci  if (size > _size - _pos)
153370b324cSopenharmony_ci    ThrowEndOfData();
154370b324cSopenharmony_ci  memcpy(data, _buffer + _pos, size);
155370b324cSopenharmony_ci  _pos += size;
156370b324cSopenharmony_ci}
157370b324cSopenharmony_ci
158370b324cSopenharmony_civoid CInByte2::SkipData(UInt64 size)
159370b324cSopenharmony_ci{
160370b324cSopenharmony_ci  if (size > _size - _pos)
161370b324cSopenharmony_ci    ThrowEndOfData();
162370b324cSopenharmony_ci  _pos += (size_t)size;
163370b324cSopenharmony_ci}
164370b324cSopenharmony_ci
165370b324cSopenharmony_civoid CInByte2::SkipData()
166370b324cSopenharmony_ci{
167370b324cSopenharmony_ci  SkipData(ReadNumber());
168370b324cSopenharmony_ci}
169370b324cSopenharmony_ci
170370b324cSopenharmony_cistatic UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
171370b324cSopenharmony_ci{
172370b324cSopenharmony_ci  if (size == 0)
173370b324cSopenharmony_ci  {
174370b324cSopenharmony_ci    processed = 0;
175370b324cSopenharmony_ci    return 0;
176370b324cSopenharmony_ci  }
177370b324cSopenharmony_ci
178370b324cSopenharmony_ci  const unsigned b = *p++;
179370b324cSopenharmony_ci  size--;
180370b324cSopenharmony_ci
181370b324cSopenharmony_ci  if ((b & 0x80) == 0)
182370b324cSopenharmony_ci  {
183370b324cSopenharmony_ci    processed = 1;
184370b324cSopenharmony_ci    return b;
185370b324cSopenharmony_ci  }
186370b324cSopenharmony_ci
187370b324cSopenharmony_ci  if (size == 0)
188370b324cSopenharmony_ci  {
189370b324cSopenharmony_ci    processed = 0;
190370b324cSopenharmony_ci    return 0;
191370b324cSopenharmony_ci  }
192370b324cSopenharmony_ci
193370b324cSopenharmony_ci  UInt64 value = (UInt64)*p;
194370b324cSopenharmony_ci  p++;
195370b324cSopenharmony_ci  size--;
196370b324cSopenharmony_ci
197370b324cSopenharmony_ci  for (unsigned i = 1; i < 8; i++)
198370b324cSopenharmony_ci  {
199370b324cSopenharmony_ci    const unsigned mask = (unsigned)0x80 >> i;
200370b324cSopenharmony_ci    if ((b & mask) == 0)
201370b324cSopenharmony_ci    {
202370b324cSopenharmony_ci      const UInt64 high = b & (mask - 1);
203370b324cSopenharmony_ci      value |= (high << (i * 8));
204370b324cSopenharmony_ci      processed = i + 1;
205370b324cSopenharmony_ci      return value;
206370b324cSopenharmony_ci    }
207370b324cSopenharmony_ci
208370b324cSopenharmony_ci    if (size == 0)
209370b324cSopenharmony_ci    {
210370b324cSopenharmony_ci      processed = 0;
211370b324cSopenharmony_ci      return 0;
212370b324cSopenharmony_ci    }
213370b324cSopenharmony_ci
214370b324cSopenharmony_ci    value |= ((UInt64)*p << (i * 8));
215370b324cSopenharmony_ci    p++;
216370b324cSopenharmony_ci    size--;
217370b324cSopenharmony_ci  }
218370b324cSopenharmony_ci
219370b324cSopenharmony_ci  processed = 9;
220370b324cSopenharmony_ci  return value;
221370b324cSopenharmony_ci}
222370b324cSopenharmony_ci
223370b324cSopenharmony_ciUInt64 CInByte2::ReadNumber()
224370b324cSopenharmony_ci{
225370b324cSopenharmony_ci  size_t processed;
226370b324cSopenharmony_ci  const UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed);
227370b324cSopenharmony_ci  if (processed == 0)
228370b324cSopenharmony_ci    ThrowEndOfData();
229370b324cSopenharmony_ci  _pos += processed;
230370b324cSopenharmony_ci  return res;
231370b324cSopenharmony_ci}
232370b324cSopenharmony_ci
233370b324cSopenharmony_ciCNum CInByte2::ReadNum()
234370b324cSopenharmony_ci{
235370b324cSopenharmony_ci  /*
236370b324cSopenharmony_ci  if (_pos < _size)
237370b324cSopenharmony_ci  {
238370b324cSopenharmony_ci    Byte val = _buffer[_pos];
239370b324cSopenharmony_ci    if ((unsigned)val < 0x80)
240370b324cSopenharmony_ci    {
241370b324cSopenharmony_ci      _pos++;
242370b324cSopenharmony_ci      return (unsigned)val;
243370b324cSopenharmony_ci    }
244370b324cSopenharmony_ci  }
245370b324cSopenharmony_ci  */
246370b324cSopenharmony_ci  const UInt64 value = ReadNumber();
247370b324cSopenharmony_ci  if (value > kNumMax)
248370b324cSopenharmony_ci    ThrowUnsupported();
249370b324cSopenharmony_ci  return (CNum)value;
250370b324cSopenharmony_ci}
251370b324cSopenharmony_ci
252370b324cSopenharmony_ciUInt32 CInByte2::ReadUInt32()
253370b324cSopenharmony_ci{
254370b324cSopenharmony_ci  if (_pos + 4 > _size)
255370b324cSopenharmony_ci    ThrowEndOfData();
256370b324cSopenharmony_ci  const UInt32 res = Get32(_buffer + _pos);
257370b324cSopenharmony_ci  _pos += 4;
258370b324cSopenharmony_ci  return res;
259370b324cSopenharmony_ci}
260370b324cSopenharmony_ci
261370b324cSopenharmony_ciUInt64 CInByte2::ReadUInt64()
262370b324cSopenharmony_ci{
263370b324cSopenharmony_ci  if (_pos + 8 > _size)
264370b324cSopenharmony_ci    ThrowEndOfData();
265370b324cSopenharmony_ci  const UInt64 res = Get64(_buffer + _pos);
266370b324cSopenharmony_ci  _pos += 8;
267370b324cSopenharmony_ci  return res;
268370b324cSopenharmony_ci}
269370b324cSopenharmony_ci
270370b324cSopenharmony_ci#define Y0  '7'
271370b324cSopenharmony_ci#define Y1  'z'
272370b324cSopenharmony_ci#define Y2  0xBC
273370b324cSopenharmony_ci#define Y3  0xAF
274370b324cSopenharmony_ci#define Y4  0x27
275370b324cSopenharmony_ci#define Y5  0x1C
276370b324cSopenharmony_ci
277370b324cSopenharmony_ci#define IS_SIGNATURE(p)( \
278370b324cSopenharmony_ci        (p)[2] == Y2 &&  \
279370b324cSopenharmony_ci        (p)[3] == Y3 &&  \
280370b324cSopenharmony_ci        (p)[5] == Y5 &&  \
281370b324cSopenharmony_ci        (p)[4] == Y4 &&  \
282370b324cSopenharmony_ci        (p)[1] == Y1 &&  \
283370b324cSopenharmony_ci        (p)[0] == Y0)
284370b324cSopenharmony_ci
285370b324cSopenharmony_ci/* FindSignature_10() is allowed to access data up to and including &limit[9].
286370b324cSopenharmony_ci   limit[10] access is not allowed.
287370b324cSopenharmony_ci  return:
288370b324cSopenharmony_ci    (return_ptr <  limit) : signature was found at (return_ptr)
289370b324cSopenharmony_ci    (return_ptr >= limit) : limit was reached or crossed. So no signature found before limit
290370b324cSopenharmony_ci*/
291370b324cSopenharmony_ciZ7_NO_INLINE
292370b324cSopenharmony_cistatic const Byte *FindSignature_10(const Byte *p, const Byte *limit)
293370b324cSopenharmony_ci{
294370b324cSopenharmony_ci  for (;;)
295370b324cSopenharmony_ci  {
296370b324cSopenharmony_ci    for (;;)
297370b324cSopenharmony_ci    {
298370b324cSopenharmony_ci      if (p >= limit)
299370b324cSopenharmony_ci        return limit;
300370b324cSopenharmony_ci      const Byte b = p[5];
301370b324cSopenharmony_ci      p += 6;
302370b324cSopenharmony_ci      if (b == Y0) {         break; }
303370b324cSopenharmony_ci      if (b == Y1) { p -= 1; break; }
304370b324cSopenharmony_ci      if (b == Y2) { p -= 2; break; }
305370b324cSopenharmony_ci      if (b == Y3) { p -= 3; break; }
306370b324cSopenharmony_ci      if (b == Y4) { p -= 4; break; }
307370b324cSopenharmony_ci      if (b == Y5) { p -= 5; break; }
308370b324cSopenharmony_ci    }
309370b324cSopenharmony_ci    if (IS_SIGNATURE(p - 1))
310370b324cSopenharmony_ci      return p - 1;
311370b324cSopenharmony_ci  }
312370b324cSopenharmony_ci}
313370b324cSopenharmony_ci
314370b324cSopenharmony_ci
315370b324cSopenharmony_cistatic inline bool TestStartCrc(const Byte *p)
316370b324cSopenharmony_ci{
317370b324cSopenharmony_ci  return CrcCalc(p + 12, 20) == Get32(p + 8);
318370b324cSopenharmony_ci}
319370b324cSopenharmony_ci
320370b324cSopenharmony_cistatic inline bool TestSignature2(const Byte *p)
321370b324cSopenharmony_ci{
322370b324cSopenharmony_ci  if (!IS_SIGNATURE(p))
323370b324cSopenharmony_ci    return false;
324370b324cSopenharmony_ci #ifdef FORMAT_7Z_RECOVERY
325370b324cSopenharmony_ci  if (TestStartCrc(p))
326370b324cSopenharmony_ci    return true;
327370b324cSopenharmony_ci  for (unsigned i = 8; i < kHeaderSize; i++)
328370b324cSopenharmony_ci    if (p[i] != 0)
329370b324cSopenharmony_ci      return false;
330370b324cSopenharmony_ci  return (p[6] != 0 || p[7] != 0);
331370b324cSopenharmony_ci #else
332370b324cSopenharmony_ci  return TestStartCrc(p);
333370b324cSopenharmony_ci #endif
334370b324cSopenharmony_ci}
335370b324cSopenharmony_ci
336370b324cSopenharmony_ci
337370b324cSopenharmony_ciHRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
338370b324cSopenharmony_ci{
339370b324cSopenharmony_ci  RINOK(ReadStream_FALSE(stream, _header, kHeaderSize))
340370b324cSopenharmony_ci
341370b324cSopenharmony_ci  if (TestSignature2(_header))
342370b324cSopenharmony_ci    return S_OK;
343370b324cSopenharmony_ci  if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
344370b324cSopenharmony_ci    return S_FALSE;
345370b324cSopenharmony_ci
346370b324cSopenharmony_ci  const UInt32 kBufSize = (1 << 15) + kHeaderSize;  // must be > (kHeaderSize * 2)
347370b324cSopenharmony_ci  CAlignedBuffer1 buf(kBufSize);
348370b324cSopenharmony_ci  memcpy(buf, _header, kHeaderSize);
349370b324cSopenharmony_ci  UInt64 offset = 0;
350370b324cSopenharmony_ci
351370b324cSopenharmony_ci  for (;;)
352370b324cSopenharmony_ci  {
353370b324cSopenharmony_ci    UInt32 readSize =
354370b324cSopenharmony_ci        (offset == 0) ?
355370b324cSopenharmony_ci          kBufSize - kHeaderSize - kHeaderSize :
356370b324cSopenharmony_ci          kBufSize - kHeaderSize;
357370b324cSopenharmony_ci    if (searchHeaderSizeLimit)
358370b324cSopenharmony_ci    {
359370b324cSopenharmony_ci      const UInt64 rem = *searchHeaderSizeLimit - offset;
360370b324cSopenharmony_ci      if (readSize > rem)
361370b324cSopenharmony_ci        readSize = (UInt32)rem;
362370b324cSopenharmony_ci      if (readSize == 0)
363370b324cSopenharmony_ci        return S_FALSE;
364370b324cSopenharmony_ci    }
365370b324cSopenharmony_ci
366370b324cSopenharmony_ci    UInt32 processed = 0;
367370b324cSopenharmony_ci    RINOK(stream->Read(buf + kHeaderSize, readSize, &processed))
368370b324cSopenharmony_ci    if (processed == 0)
369370b324cSopenharmony_ci      return S_FALSE;
370370b324cSopenharmony_ci
371370b324cSopenharmony_ci    /* &buf[0] was already tested for signature before.
372370b324cSopenharmony_ci       So first search here will be for &buf[1] */
373370b324cSopenharmony_ci
374370b324cSopenharmony_ci    for (UInt32 pos = 0;;)
375370b324cSopenharmony_ci    {
376370b324cSopenharmony_ci      const Byte *p = buf + pos + 1;
377370b324cSopenharmony_ci      const Byte *lim = buf + processed + 1;
378370b324cSopenharmony_ci      /* we have (kHeaderSize - 1 = 31) filled bytes starting from (lim),
379370b324cSopenharmony_ci         and it's safe to access just 10 bytes in that reserved area */
380370b324cSopenharmony_ci      p = FindSignature_10(p, lim);
381370b324cSopenharmony_ci      if (p >= lim)
382370b324cSopenharmony_ci        break;
383370b324cSopenharmony_ci      pos = (UInt32)(p - buf);
384370b324cSopenharmony_ci      if (TestStartCrc(p))
385370b324cSopenharmony_ci      {
386370b324cSopenharmony_ci        memcpy(_header, p, kHeaderSize);
387370b324cSopenharmony_ci        _arhiveBeginStreamPosition += offset + pos;
388370b324cSopenharmony_ci        return InStream_SeekSet(stream, _arhiveBeginStreamPosition + kHeaderSize);
389370b324cSopenharmony_ci      }
390370b324cSopenharmony_ci    }
391370b324cSopenharmony_ci
392370b324cSopenharmony_ci    offset += processed;
393370b324cSopenharmony_ci    memmove(buf, buf + processed, kHeaderSize);
394370b324cSopenharmony_ci  }
395370b324cSopenharmony_ci}
396370b324cSopenharmony_ci
397370b324cSopenharmony_ci// S_FALSE means that file is not archive
398370b324cSopenharmony_ciHRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
399370b324cSopenharmony_ci{
400370b324cSopenharmony_ci  HeadersSize = 0;
401370b324cSopenharmony_ci  Close();
402370b324cSopenharmony_ci  RINOK(InStream_GetPos_GetSize(stream, _arhiveBeginStreamPosition, _fileEndPosition))
403370b324cSopenharmony_ci  RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit))
404370b324cSopenharmony_ci  _stream = stream;
405370b324cSopenharmony_ci  return S_OK;
406370b324cSopenharmony_ci}
407370b324cSopenharmony_ci
408370b324cSopenharmony_civoid CInArchive::Close()
409370b324cSopenharmony_ci{
410370b324cSopenharmony_ci  _numInByteBufs = 0;
411370b324cSopenharmony_ci  _stream.Release();
412370b324cSopenharmony_ci  ThereIsHeaderError = false;
413370b324cSopenharmony_ci}
414370b324cSopenharmony_ci
415370b324cSopenharmony_civoid CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
416370b324cSopenharmony_ci{
417370b324cSopenharmony_ci  for (;;)
418370b324cSopenharmony_ci  {
419370b324cSopenharmony_ci    if (ReadID() == NID::kEnd)
420370b324cSopenharmony_ci      break;
421370b324cSopenharmony_ci    SkipData();
422370b324cSopenharmony_ci  }
423370b324cSopenharmony_ci}
424370b324cSopenharmony_ci
425370b324cSopenharmony_ci// CFolder &folder can be non empty. So we must set all fields
426370b324cSopenharmony_ci
427370b324cSopenharmony_civoid CInByte2::ParseFolder(CFolder &folder)
428370b324cSopenharmony_ci{
429370b324cSopenharmony_ci  const UInt32 numCoders = ReadNum();
430370b324cSopenharmony_ci
431370b324cSopenharmony_ci  if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
432370b324cSopenharmony_ci    ThrowUnsupported();
433370b324cSopenharmony_ci
434370b324cSopenharmony_ci  folder.Coders.SetSize(numCoders);
435370b324cSopenharmony_ci
436370b324cSopenharmony_ci  UInt32 numInStreams = 0;
437370b324cSopenharmony_ci  UInt32 i;
438370b324cSopenharmony_ci  for (i = 0; i < numCoders; i++)
439370b324cSopenharmony_ci  {
440370b324cSopenharmony_ci    CCoderInfo &coder = folder.Coders[i];
441370b324cSopenharmony_ci    {
442370b324cSopenharmony_ci      const Byte mainByte = ReadByte();
443370b324cSopenharmony_ci      if ((mainByte & 0xC0) != 0)
444370b324cSopenharmony_ci        ThrowUnsupported();
445370b324cSopenharmony_ci      const unsigned idSize = (mainByte & 0xF);
446370b324cSopenharmony_ci      if (idSize > 8 || idSize > GetRem())
447370b324cSopenharmony_ci        ThrowUnsupported();
448370b324cSopenharmony_ci      const Byte *longID = GetPtr();
449370b324cSopenharmony_ci      UInt64 id = 0;
450370b324cSopenharmony_ci      for (unsigned j = 0; j < idSize; j++)
451370b324cSopenharmony_ci        id = ((id << 8) | longID[j]);
452370b324cSopenharmony_ci      SkipDataNoCheck(idSize);
453370b324cSopenharmony_ci      coder.MethodID = id;
454370b324cSopenharmony_ci
455370b324cSopenharmony_ci      if ((mainByte & 0x10) != 0)
456370b324cSopenharmony_ci      {
457370b324cSopenharmony_ci        coder.NumStreams = ReadNum();
458370b324cSopenharmony_ci        // if (coder.NumStreams > k_Scan_NumCodersStreams_in_Folder_MAX) ThrowUnsupported();
459370b324cSopenharmony_ci        /* numOutStreams = */ ReadNum();
460370b324cSopenharmony_ci        // if (ReadNum() != 1) // numOutStreams ThrowUnsupported();
461370b324cSopenharmony_ci      }
462370b324cSopenharmony_ci      else
463370b324cSopenharmony_ci      {
464370b324cSopenharmony_ci        coder.NumStreams = 1;
465370b324cSopenharmony_ci      }
466370b324cSopenharmony_ci
467370b324cSopenharmony_ci      if ((mainByte & 0x20) != 0)
468370b324cSopenharmony_ci      {
469370b324cSopenharmony_ci        const CNum propsSize = ReadNum();
470370b324cSopenharmony_ci        coder.Props.Alloc((size_t)propsSize);
471370b324cSopenharmony_ci        ReadBytes((Byte *)coder.Props, (size_t)propsSize);
472370b324cSopenharmony_ci      }
473370b324cSopenharmony_ci      else
474370b324cSopenharmony_ci        coder.Props.Free();
475370b324cSopenharmony_ci    }
476370b324cSopenharmony_ci    numInStreams += coder.NumStreams;
477370b324cSopenharmony_ci  }
478370b324cSopenharmony_ci
479370b324cSopenharmony_ci  const UInt32 numBonds = numCoders - 1;
480370b324cSopenharmony_ci  folder.Bonds.SetSize(numBonds);
481370b324cSopenharmony_ci  for (i = 0; i < numBonds; i++)
482370b324cSopenharmony_ci  {
483370b324cSopenharmony_ci    CBond &bp = folder.Bonds[i];
484370b324cSopenharmony_ci    bp.PackIndex = ReadNum();
485370b324cSopenharmony_ci    bp.UnpackIndex = ReadNum();
486370b324cSopenharmony_ci  }
487370b324cSopenharmony_ci
488370b324cSopenharmony_ci  if (numInStreams < numBonds)
489370b324cSopenharmony_ci    ThrowUnsupported();
490370b324cSopenharmony_ci  const UInt32 numPackStreams = numInStreams - numBonds;
491370b324cSopenharmony_ci  folder.PackStreams.SetSize(numPackStreams);
492370b324cSopenharmony_ci
493370b324cSopenharmony_ci  if (numPackStreams == 1)
494370b324cSopenharmony_ci  {
495370b324cSopenharmony_ci    for (i = 0; i < numInStreams; i++)
496370b324cSopenharmony_ci      if (folder.FindBond_for_PackStream(i) < 0)
497370b324cSopenharmony_ci      {
498370b324cSopenharmony_ci        folder.PackStreams[0] = i;
499370b324cSopenharmony_ci        break;
500370b324cSopenharmony_ci      }
501370b324cSopenharmony_ci    if (i == numInStreams)
502370b324cSopenharmony_ci      ThrowUnsupported();
503370b324cSopenharmony_ci  }
504370b324cSopenharmony_ci  else
505370b324cSopenharmony_ci    for (i = 0; i < numPackStreams; i++)
506370b324cSopenharmony_ci      folder.PackStreams[i] = ReadNum();
507370b324cSopenharmony_ci}
508370b324cSopenharmony_ci
509370b324cSopenharmony_civoid CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const
510370b324cSopenharmony_ci{
511370b324cSopenharmony_ci  const size_t startPos = FoCodersDataOffset[folderIndex];
512370b324cSopenharmony_ci  CInByte2 inByte;
513370b324cSopenharmony_ci  inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);
514370b324cSopenharmony_ci  inByte.ParseFolder(folder);
515370b324cSopenharmony_ci  if (inByte.GetRem() != 0)
516370b324cSopenharmony_ci    throw 20120424;
517370b324cSopenharmony_ci}
518370b324cSopenharmony_ci
519370b324cSopenharmony_ci
520370b324cSopenharmony_civoid CDatabase::GetPath(unsigned index, UString &path) const
521370b324cSopenharmony_ci{
522370b324cSopenharmony_ci  path.Empty();
523370b324cSopenharmony_ci  if (!NameOffsets || !NamesBuf)
524370b324cSopenharmony_ci    return;
525370b324cSopenharmony_ci
526370b324cSopenharmony_ci  const size_t offset = NameOffsets[index];
527370b324cSopenharmony_ci  const size_t size = NameOffsets[index + 1] - offset;
528370b324cSopenharmony_ci
529370b324cSopenharmony_ci  if (size >= (1 << 28))
530370b324cSopenharmony_ci    return;
531370b324cSopenharmony_ci
532370b324cSopenharmony_ci  wchar_t *s = path.GetBuf((unsigned)size - 1);
533370b324cSopenharmony_ci
534370b324cSopenharmony_ci  const Byte *p = ((const Byte *)NamesBuf + offset * 2);
535370b324cSopenharmony_ci
536370b324cSopenharmony_ci  #if defined(_WIN32) && defined(MY_CPU_LE)
537370b324cSopenharmony_ci
538370b324cSopenharmony_ci  wmemcpy(s, (const wchar_t *)(const void *)p, size);
539370b324cSopenharmony_ci
540370b324cSopenharmony_ci  #else
541370b324cSopenharmony_ci
542370b324cSopenharmony_ci  for (size_t i = 0; i < size; i++)
543370b324cSopenharmony_ci  {
544370b324cSopenharmony_ci    *s = Get16(p);
545370b324cSopenharmony_ci    p += 2;
546370b324cSopenharmony_ci    s++;
547370b324cSopenharmony_ci  }
548370b324cSopenharmony_ci
549370b324cSopenharmony_ci  #endif
550370b324cSopenharmony_ci
551370b324cSopenharmony_ci  path.ReleaseBuf_SetLen((unsigned)size - 1);
552370b324cSopenharmony_ci}
553370b324cSopenharmony_ci
554370b324cSopenharmony_ciHRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
555370b324cSopenharmony_ci{
556370b324cSopenharmony_ci  PropVariant_Clear(path);
557370b324cSopenharmony_ci  if (!NameOffsets || !NamesBuf)
558370b324cSopenharmony_ci    return S_OK;
559370b324cSopenharmony_ci
560370b324cSopenharmony_ci  const size_t offset = NameOffsets[index];
561370b324cSopenharmony_ci  const size_t size = NameOffsets[index + 1] - offset;
562370b324cSopenharmony_ci
563370b324cSopenharmony_ci  if (size >= (1 << 14))
564370b324cSopenharmony_ci    return S_OK;
565370b324cSopenharmony_ci
566370b324cSopenharmony_ci  // (size) includes null terminator
567370b324cSopenharmony_ci
568370b324cSopenharmony_ci  /*
569370b324cSopenharmony_ci  #if WCHAR_MAX > 0xffff
570370b324cSopenharmony_ci
571370b324cSopenharmony_ci  const Byte *p = ((const Byte *)NamesBuf + offset * 2);
572370b324cSopenharmony_ci  size = Utf16LE__Get_Num_WCHARs(p, size - 1);
573370b324cSopenharmony_ci  // (size) doesn't include null terminator
574370b324cSopenharmony_ci  RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size));
575370b324cSopenharmony_ci  wchar_t *s = path->bstrVal;
576370b324cSopenharmony_ci  wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, size, s);
577370b324cSopenharmony_ci  *sEnd = 0;
578370b324cSopenharmony_ci  if (s + size != sEnd) return E_FAIL;
579370b324cSopenharmony_ci
580370b324cSopenharmony_ci  #else
581370b324cSopenharmony_ci  */
582370b324cSopenharmony_ci
583370b324cSopenharmony_ci  RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1))
584370b324cSopenharmony_ci  wchar_t *s = path->bstrVal;
585370b324cSopenharmony_ci  const Byte *p = ((const Byte *)NamesBuf + offset * 2);
586370b324cSopenharmony_ci  // Utf16LE__To_WCHARs_Sep(p, size, s);
587370b324cSopenharmony_ci
588370b324cSopenharmony_ci  for (size_t i = 0; i < size; i++)
589370b324cSopenharmony_ci  {
590370b324cSopenharmony_ci    wchar_t c = Get16(p);
591370b324cSopenharmony_ci    p += 2;
592370b324cSopenharmony_ci    #if WCHAR_PATH_SEPARATOR != L'/'
593370b324cSopenharmony_ci    if (c == L'/')
594370b324cSopenharmony_ci      c = WCHAR_PATH_SEPARATOR;
595370b324cSopenharmony_ci    else if (c == L'\\')
596370b324cSopenharmony_ci      c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme
597370b324cSopenharmony_ci    #endif
598370b324cSopenharmony_ci    *s++ = c;
599370b324cSopenharmony_ci  }
600370b324cSopenharmony_ci
601370b324cSopenharmony_ci  // #endif
602370b324cSopenharmony_ci
603370b324cSopenharmony_ci  return S_OK;
604370b324cSopenharmony_ci
605370b324cSopenharmony_ci  /*
606370b324cSopenharmony_ci  unsigned cur = index;
607370b324cSopenharmony_ci  unsigned size = 0;
608370b324cSopenharmony_ci
609370b324cSopenharmony_ci  for (int i = 0;; i++)
610370b324cSopenharmony_ci  {
611370b324cSopenharmony_ci    size_t len = NameOffsets[cur + 1] - NameOffsets[cur];
612370b324cSopenharmony_ci    size += (unsigned)len;
613370b324cSopenharmony_ci    if (i > 256 || len > (1 << 14) || size > (1 << 14))
614370b324cSopenharmony_ci      return PropVarEm_Set_Str(path, "[TOO-LONG]");
615370b324cSopenharmony_ci    cur = Files[cur].Parent;
616370b324cSopenharmony_ci    if (cur < 0)
617370b324cSopenharmony_ci      break;
618370b324cSopenharmony_ci  }
619370b324cSopenharmony_ci  size--;
620370b324cSopenharmony_ci
621370b324cSopenharmony_ci  RINOK(PropVarEm_Alloc_Bstr(path, size));
622370b324cSopenharmony_ci  wchar_t *s = path->bstrVal;
623370b324cSopenharmony_ci  s += size;
624370b324cSopenharmony_ci  *s = 0;
625370b324cSopenharmony_ci  cur = index;
626370b324cSopenharmony_ci
627370b324cSopenharmony_ci  for (;;)
628370b324cSopenharmony_ci  {
629370b324cSopenharmony_ci    unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
630370b324cSopenharmony_ci    const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
631370b324cSopenharmony_ci    for (; len != 0; len--)
632370b324cSopenharmony_ci    {
633370b324cSopenharmony_ci      p -= 2;
634370b324cSopenharmony_ci      --s;
635370b324cSopenharmony_ci      wchar_t c = Get16(p);
636370b324cSopenharmony_ci      if (c == '/')
637370b324cSopenharmony_ci        c = WCHAR_PATH_SEPARATOR;
638370b324cSopenharmony_ci      *s = c;
639370b324cSopenharmony_ci    }
640370b324cSopenharmony_ci
641370b324cSopenharmony_ci    const CFileItem &file = Files[cur];
642370b324cSopenharmony_ci    cur = file.Parent;
643370b324cSopenharmony_ci    if (cur < 0)
644370b324cSopenharmony_ci      return S_OK;
645370b324cSopenharmony_ci    *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR);
646370b324cSopenharmony_ci  }
647370b324cSopenharmony_ci  */
648370b324cSopenharmony_ci}
649370b324cSopenharmony_ci
650370b324cSopenharmony_civoid CInArchive::WaitId(UInt64 id)
651370b324cSopenharmony_ci{
652370b324cSopenharmony_ci  for (;;)
653370b324cSopenharmony_ci  {
654370b324cSopenharmony_ci    const UInt64 type = ReadID();
655370b324cSopenharmony_ci    if (type == id)
656370b324cSopenharmony_ci      return;
657370b324cSopenharmony_ci    if (type == NID::kEnd)
658370b324cSopenharmony_ci      ThrowIncorrect();
659370b324cSopenharmony_ci    SkipData();
660370b324cSopenharmony_ci  }
661370b324cSopenharmony_ci}
662370b324cSopenharmony_ci
663370b324cSopenharmony_ci
664370b324cSopenharmony_civoid CInArchive::Read_UInt32_Vector(CUInt32DefVector &v)
665370b324cSopenharmony_ci{
666370b324cSopenharmony_ci  const unsigned numItems = v.Defs.Size();
667370b324cSopenharmony_ci  v.Vals.ClearAndSetSize(numItems);
668370b324cSopenharmony_ci  UInt32 *p = &v.Vals[0];
669370b324cSopenharmony_ci  const bool *defs = &v.Defs[0];
670370b324cSopenharmony_ci  for (unsigned i = 0; i < numItems; i++)
671370b324cSopenharmony_ci  {
672370b324cSopenharmony_ci    UInt32 a = 0;
673370b324cSopenharmony_ci    if (defs[i])
674370b324cSopenharmony_ci      a = ReadUInt32();
675370b324cSopenharmony_ci    p[i] = a;
676370b324cSopenharmony_ci  }
677370b324cSopenharmony_ci}
678370b324cSopenharmony_ci
679370b324cSopenharmony_ci
680370b324cSopenharmony_civoid CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
681370b324cSopenharmony_ci{
682370b324cSopenharmony_ci  ReadBoolVector2(numItems, crcs.Defs);
683370b324cSopenharmony_ci  Read_UInt32_Vector(crcs);
684370b324cSopenharmony_ci}
685370b324cSopenharmony_ci
686370b324cSopenharmony_ci
687370b324cSopenharmony_civoid CInArchive::ReadPackInfo(CFolders &f)
688370b324cSopenharmony_ci{
689370b324cSopenharmony_ci  const CNum numPackStreams = ReadNum();
690370b324cSopenharmony_ci
691370b324cSopenharmony_ci  WaitId(NID::kSize);
692370b324cSopenharmony_ci  f.PackPositions.Alloc(numPackStreams + 1);
693370b324cSopenharmony_ci  f.NumPackStreams = numPackStreams;
694370b324cSopenharmony_ci  UInt64 sum = 0;
695370b324cSopenharmony_ci  for (CNum i = 0; i < numPackStreams; i++)
696370b324cSopenharmony_ci  {
697370b324cSopenharmony_ci    f.PackPositions[i] = sum;
698370b324cSopenharmony_ci    const UInt64 packSize = ReadNumber();
699370b324cSopenharmony_ci    sum += packSize;
700370b324cSopenharmony_ci    if (sum < packSize)
701370b324cSopenharmony_ci      ThrowIncorrect();
702370b324cSopenharmony_ci  }
703370b324cSopenharmony_ci  f.PackPositions[numPackStreams] = sum;
704370b324cSopenharmony_ci
705370b324cSopenharmony_ci  UInt64 type;
706370b324cSopenharmony_ci  for (;;)
707370b324cSopenharmony_ci  {
708370b324cSopenharmony_ci    type = ReadID();
709370b324cSopenharmony_ci    if (type == NID::kEnd)
710370b324cSopenharmony_ci      return;
711370b324cSopenharmony_ci    if (type == NID::kCRC)
712370b324cSopenharmony_ci    {
713370b324cSopenharmony_ci      CUInt32DefVector PackCRCs;
714370b324cSopenharmony_ci      ReadHashDigests(numPackStreams, PackCRCs);
715370b324cSopenharmony_ci      continue;
716370b324cSopenharmony_ci    }
717370b324cSopenharmony_ci    SkipData();
718370b324cSopenharmony_ci  }
719370b324cSopenharmony_ci}
720370b324cSopenharmony_ci
721370b324cSopenharmony_civoid CInArchive::ReadUnpackInfo(
722370b324cSopenharmony_ci    const CObjectVector<CByteBuffer> *dataVector,
723370b324cSopenharmony_ci    CFolders &folders)
724370b324cSopenharmony_ci{
725370b324cSopenharmony_ci  WaitId(NID::kFolder);
726370b324cSopenharmony_ci  const CNum numFolders = ReadNum();
727370b324cSopenharmony_ci
728370b324cSopenharmony_ci  CNum numCodersOutStreams = 0;
729370b324cSopenharmony_ci  {
730370b324cSopenharmony_ci    CStreamSwitch streamSwitch;
731370b324cSopenharmony_ci    streamSwitch.Set(this, dataVector);
732370b324cSopenharmony_ci    const Byte *startBufPtr = _inByteBack->GetPtr();
733370b324cSopenharmony_ci    folders.NumFolders = numFolders;
734370b324cSopenharmony_ci
735370b324cSopenharmony_ci    folders.FoStartPackStreamIndex.Alloc(numFolders + 1);
736370b324cSopenharmony_ci    folders.FoToMainUnpackSizeIndex.Alloc(numFolders);
737370b324cSopenharmony_ci    folders.FoCodersDataOffset.Alloc(numFolders + 1);
738370b324cSopenharmony_ci    folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
739370b324cSopenharmony_ci
740370b324cSopenharmony_ci    CBoolVector StreamUsed;
741370b324cSopenharmony_ci    CBoolVector CoderUsed;
742370b324cSopenharmony_ci
743370b324cSopenharmony_ci    CNum packStreamIndex = 0;
744370b324cSopenharmony_ci    CNum fo;
745370b324cSopenharmony_ci    CInByte2 *inByte = _inByteBack;
746370b324cSopenharmony_ci
747370b324cSopenharmony_ci    for (fo = 0; fo < numFolders; fo++)
748370b324cSopenharmony_ci    {
749370b324cSopenharmony_ci      UInt32 indexOfMainStream = 0;
750370b324cSopenharmony_ci      UInt32 numPackStreams = 0;
751370b324cSopenharmony_ci      folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr);
752370b324cSopenharmony_ci
753370b324cSopenharmony_ci      CNum numInStreams = 0;
754370b324cSopenharmony_ci      const CNum numCoders = inByte->ReadNum();
755370b324cSopenharmony_ci
756370b324cSopenharmony_ci      if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
757370b324cSopenharmony_ci        ThrowUnsupported();
758370b324cSopenharmony_ci
759370b324cSopenharmony_ci      for (CNum ci = 0; ci < numCoders; ci++)
760370b324cSopenharmony_ci      {
761370b324cSopenharmony_ci        const Byte mainByte = inByte->ReadByte();
762370b324cSopenharmony_ci        if ((mainByte & 0xC0) != 0)
763370b324cSopenharmony_ci          ThrowUnsupported();
764370b324cSopenharmony_ci
765370b324cSopenharmony_ci        const unsigned idSize = (mainByte & 0xF);
766370b324cSopenharmony_ci        if (idSize > 8)
767370b324cSopenharmony_ci          ThrowUnsupported();
768370b324cSopenharmony_ci        if (idSize > inByte->GetRem())
769370b324cSopenharmony_ci          ThrowEndOfData();
770370b324cSopenharmony_ci        const Byte *longID = inByte->GetPtr();
771370b324cSopenharmony_ci        UInt64 id = 0;
772370b324cSopenharmony_ci        for (unsigned j = 0; j < idSize; j++)
773370b324cSopenharmony_ci          id = ((id << 8) | longID[j]);
774370b324cSopenharmony_ci        inByte->SkipDataNoCheck(idSize);
775370b324cSopenharmony_ci        if (folders.ParsedMethods.IDs.Size() < 128)
776370b324cSopenharmony_ci          folders.ParsedMethods.IDs.AddToUniqueSorted(id);
777370b324cSopenharmony_ci
778370b324cSopenharmony_ci        CNum coderInStreams = 1;
779370b324cSopenharmony_ci        if ((mainByte & 0x10) != 0)
780370b324cSopenharmony_ci        {
781370b324cSopenharmony_ci          coderInStreams = inByte->ReadNum();
782370b324cSopenharmony_ci          if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
783370b324cSopenharmony_ci            ThrowUnsupported();
784370b324cSopenharmony_ci          if (inByte->ReadNum() != 1)
785370b324cSopenharmony_ci            ThrowUnsupported();
786370b324cSopenharmony_ci        }
787370b324cSopenharmony_ci
788370b324cSopenharmony_ci        numInStreams += coderInStreams;
789370b324cSopenharmony_ci        if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
790370b324cSopenharmony_ci          ThrowUnsupported();
791370b324cSopenharmony_ci
792370b324cSopenharmony_ci        if ((mainByte & 0x20) != 0)
793370b324cSopenharmony_ci        {
794370b324cSopenharmony_ci          const CNum propsSize = inByte->ReadNum();
795370b324cSopenharmony_ci          if (propsSize > inByte->GetRem())
796370b324cSopenharmony_ci            ThrowEndOfData();
797370b324cSopenharmony_ci          if (id == k_LZMA2 && propsSize == 1)
798370b324cSopenharmony_ci          {
799370b324cSopenharmony_ci            const Byte v = *_inByteBack->GetPtr();
800370b324cSopenharmony_ci            if (folders.ParsedMethods.Lzma2Prop < v)
801370b324cSopenharmony_ci              folders.ParsedMethods.Lzma2Prop = v;
802370b324cSopenharmony_ci          }
803370b324cSopenharmony_ci          else if (id == k_LZMA && propsSize == 5)
804370b324cSopenharmony_ci          {
805370b324cSopenharmony_ci            const UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1);
806370b324cSopenharmony_ci            if (folders.ParsedMethods.LzmaDic < dicSize)
807370b324cSopenharmony_ci              folders.ParsedMethods.LzmaDic = dicSize;
808370b324cSopenharmony_ci          }
809370b324cSopenharmony_ci          inByte->SkipDataNoCheck((size_t)propsSize);
810370b324cSopenharmony_ci        }
811370b324cSopenharmony_ci      }
812370b324cSopenharmony_ci
813370b324cSopenharmony_ci      if (numCoders == 1 && numInStreams == 1)
814370b324cSopenharmony_ci      {
815370b324cSopenharmony_ci        indexOfMainStream = 0;
816370b324cSopenharmony_ci        numPackStreams = 1;
817370b324cSopenharmony_ci      }
818370b324cSopenharmony_ci      else
819370b324cSopenharmony_ci      {
820370b324cSopenharmony_ci        UInt32 i;
821370b324cSopenharmony_ci        const CNum numBonds = numCoders - 1;
822370b324cSopenharmony_ci        if (numInStreams < numBonds)
823370b324cSopenharmony_ci          ThrowUnsupported();
824370b324cSopenharmony_ci
825370b324cSopenharmony_ci        BoolVector_Fill_False(StreamUsed, numInStreams);
826370b324cSopenharmony_ci        BoolVector_Fill_False(CoderUsed, numCoders);
827370b324cSopenharmony_ci
828370b324cSopenharmony_ci        for (i = 0; i < numBonds; i++)
829370b324cSopenharmony_ci        {
830370b324cSopenharmony_ci          CNum index = ReadNum();
831370b324cSopenharmony_ci          if (index >= numInStreams || StreamUsed[index])
832370b324cSopenharmony_ci            ThrowUnsupported();
833370b324cSopenharmony_ci          StreamUsed[index] = true;
834370b324cSopenharmony_ci
835370b324cSopenharmony_ci          index = ReadNum();
836370b324cSopenharmony_ci          if (index >= numCoders || CoderUsed[index])
837370b324cSopenharmony_ci            ThrowUnsupported();
838370b324cSopenharmony_ci          CoderUsed[index] = true;
839370b324cSopenharmony_ci        }
840370b324cSopenharmony_ci
841370b324cSopenharmony_ci        numPackStreams = numInStreams - numBonds;
842370b324cSopenharmony_ci
843370b324cSopenharmony_ci        if (numPackStreams != 1)
844370b324cSopenharmony_ci          for (i = 0; i < numPackStreams; i++)
845370b324cSopenharmony_ci          {
846370b324cSopenharmony_ci            const CNum index = inByte->ReadNum(); // PackStreams
847370b324cSopenharmony_ci            if (index >= numInStreams || StreamUsed[index])
848370b324cSopenharmony_ci              ThrowUnsupported();
849370b324cSopenharmony_ci            StreamUsed[index] = true;
850370b324cSopenharmony_ci          }
851370b324cSopenharmony_ci
852370b324cSopenharmony_ci        for (i = 0; i < numCoders; i++)
853370b324cSopenharmony_ci          if (!CoderUsed[i])
854370b324cSopenharmony_ci          {
855370b324cSopenharmony_ci            indexOfMainStream = i;
856370b324cSopenharmony_ci            break;
857370b324cSopenharmony_ci          }
858370b324cSopenharmony_ci
859370b324cSopenharmony_ci        if (i == numCoders)
860370b324cSopenharmony_ci          ThrowUnsupported();
861370b324cSopenharmony_ci      }
862370b324cSopenharmony_ci
863370b324cSopenharmony_ci      folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
864370b324cSopenharmony_ci      numCodersOutStreams += numCoders;
865370b324cSopenharmony_ci      folders.FoStartPackStreamIndex[fo] = packStreamIndex;
866370b324cSopenharmony_ci      if (numPackStreams > folders.NumPackStreams - packStreamIndex)
867370b324cSopenharmony_ci        ThrowIncorrect();
868370b324cSopenharmony_ci      packStreamIndex += numPackStreams;
869370b324cSopenharmony_ci      folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
870370b324cSopenharmony_ci    }
871370b324cSopenharmony_ci
872370b324cSopenharmony_ci    const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr);
873370b324cSopenharmony_ci    folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
874370b324cSopenharmony_ci    folders.FoStartPackStreamIndex[fo] = packStreamIndex;
875370b324cSopenharmony_ci    folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr);
876370b324cSopenharmony_ci    folders.CodersData.CopyFrom(startBufPtr, dataSize);
877370b324cSopenharmony_ci
878370b324cSopenharmony_ci    // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();
879370b324cSopenharmony_ci  }
880370b324cSopenharmony_ci
881370b324cSopenharmony_ci  WaitId(NID::kCodersUnpackSize);
882370b324cSopenharmony_ci  folders.CoderUnpackSizes.Alloc(numCodersOutStreams);
883370b324cSopenharmony_ci  for (CNum i = 0; i < numCodersOutStreams; i++)
884370b324cSopenharmony_ci    folders.CoderUnpackSizes[i] = ReadNumber();
885370b324cSopenharmony_ci
886370b324cSopenharmony_ci  for (;;)
887370b324cSopenharmony_ci  {
888370b324cSopenharmony_ci    const UInt64 type = ReadID();
889370b324cSopenharmony_ci    if (type == NID::kEnd)
890370b324cSopenharmony_ci      return;
891370b324cSopenharmony_ci    if (type == NID::kCRC)
892370b324cSopenharmony_ci    {
893370b324cSopenharmony_ci      ReadHashDigests(numFolders, folders.FolderCRCs);
894370b324cSopenharmony_ci      continue;
895370b324cSopenharmony_ci    }
896370b324cSopenharmony_ci    SkipData();
897370b324cSopenharmony_ci  }
898370b324cSopenharmony_ci}
899370b324cSopenharmony_ci
900370b324cSopenharmony_civoid CInArchive::ReadSubStreamsInfo(
901370b324cSopenharmony_ci    CFolders &folders,
902370b324cSopenharmony_ci    CRecordVector<UInt64> &unpackSizes,
903370b324cSopenharmony_ci    CUInt32DefVector &digests)
904370b324cSopenharmony_ci{
905370b324cSopenharmony_ci  folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);
906370b324cSopenharmony_ci  CNum i;
907370b324cSopenharmony_ci  for (i = 0; i < folders.NumFolders; i++)
908370b324cSopenharmony_ci    folders.NumUnpackStreamsVector[i] = 1;
909370b324cSopenharmony_ci
910370b324cSopenharmony_ci  UInt64 type;
911370b324cSopenharmony_ci
912370b324cSopenharmony_ci  for (;;)
913370b324cSopenharmony_ci  {
914370b324cSopenharmony_ci    type = ReadID();
915370b324cSopenharmony_ci    if (type == NID::kNumUnpackStream)
916370b324cSopenharmony_ci    {
917370b324cSopenharmony_ci      for (i = 0; i < folders.NumFolders; i++)
918370b324cSopenharmony_ci        folders.NumUnpackStreamsVector[i] = ReadNum();
919370b324cSopenharmony_ci      continue;
920370b324cSopenharmony_ci    }
921370b324cSopenharmony_ci    if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd)
922370b324cSopenharmony_ci      break;
923370b324cSopenharmony_ci    SkipData();
924370b324cSopenharmony_ci  }
925370b324cSopenharmony_ci
926370b324cSopenharmony_ci  if (type == NID::kSize)
927370b324cSopenharmony_ci  {
928370b324cSopenharmony_ci    for (i = 0; i < folders.NumFolders; i++)
929370b324cSopenharmony_ci    {
930370b324cSopenharmony_ci      // v3.13 incorrectly worked with empty folders
931370b324cSopenharmony_ci      // v4.07: we check that folder is empty
932370b324cSopenharmony_ci      const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
933370b324cSopenharmony_ci      if (numSubstreams == 0)
934370b324cSopenharmony_ci        continue;
935370b324cSopenharmony_ci      UInt64 sum = 0;
936370b324cSopenharmony_ci      for (CNum j = 1; j < numSubstreams; j++)
937370b324cSopenharmony_ci      {
938370b324cSopenharmony_ci        const UInt64 size = ReadNumber();
939370b324cSopenharmony_ci        unpackSizes.Add(size);
940370b324cSopenharmony_ci        sum += size;
941370b324cSopenharmony_ci        if (sum < size)
942370b324cSopenharmony_ci          ThrowIncorrect();
943370b324cSopenharmony_ci      }
944370b324cSopenharmony_ci      const UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i);
945370b324cSopenharmony_ci      if (folderUnpackSize < sum)
946370b324cSopenharmony_ci        ThrowIncorrect();
947370b324cSopenharmony_ci      unpackSizes.Add(folderUnpackSize - sum);
948370b324cSopenharmony_ci    }
949370b324cSopenharmony_ci    type = ReadID();
950370b324cSopenharmony_ci  }
951370b324cSopenharmony_ci  else
952370b324cSopenharmony_ci  {
953370b324cSopenharmony_ci    for (i = 0; i < folders.NumFolders; i++)
954370b324cSopenharmony_ci    {
955370b324cSopenharmony_ci      /* v9.26 - v9.29 incorrectly worked:
956370b324cSopenharmony_ci         if (folders.NumUnpackStreamsVector[i] == 0), it threw error */
957370b324cSopenharmony_ci      const CNum val = folders.NumUnpackStreamsVector[i];
958370b324cSopenharmony_ci      if (val > 1)
959370b324cSopenharmony_ci        ThrowIncorrect();
960370b324cSopenharmony_ci      if (val == 1)
961370b324cSopenharmony_ci        unpackSizes.Add(folders.GetFolderUnpackSize(i));
962370b324cSopenharmony_ci    }
963370b324cSopenharmony_ci  }
964370b324cSopenharmony_ci
965370b324cSopenharmony_ci  unsigned numDigests = 0;
966370b324cSopenharmony_ci  for (i = 0; i < folders.NumFolders; i++)
967370b324cSopenharmony_ci  {
968370b324cSopenharmony_ci    const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
969370b324cSopenharmony_ci    if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i))
970370b324cSopenharmony_ci      numDigests += numSubstreams;
971370b324cSopenharmony_ci  }
972370b324cSopenharmony_ci
973370b324cSopenharmony_ci  for (;;)
974370b324cSopenharmony_ci  {
975370b324cSopenharmony_ci    if (type == NID::kEnd)
976370b324cSopenharmony_ci      break;
977370b324cSopenharmony_ci    if (type == NID::kCRC)
978370b324cSopenharmony_ci    {
979370b324cSopenharmony_ci      // CUInt32DefVector digests2;
980370b324cSopenharmony_ci      // ReadHashDigests(numDigests, digests2);
981370b324cSopenharmony_ci      CBoolVector digests2;
982370b324cSopenharmony_ci      ReadBoolVector2(numDigests, digests2);
983370b324cSopenharmony_ci
984370b324cSopenharmony_ci      digests.ClearAndSetSize(unpackSizes.Size());
985370b324cSopenharmony_ci
986370b324cSopenharmony_ci      unsigned k = 0;
987370b324cSopenharmony_ci      unsigned k2 = 0;
988370b324cSopenharmony_ci
989370b324cSopenharmony_ci      for (i = 0; i < folders.NumFolders; i++)
990370b324cSopenharmony_ci      {
991370b324cSopenharmony_ci        const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
992370b324cSopenharmony_ci        if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
993370b324cSopenharmony_ci        {
994370b324cSopenharmony_ci          digests.Defs[k] = true;
995370b324cSopenharmony_ci          digests.Vals[k] = folders.FolderCRCs.Vals[i];
996370b324cSopenharmony_ci          k++;
997370b324cSopenharmony_ci        }
998370b324cSopenharmony_ci        else for (CNum j = 0; j < numSubstreams; j++)
999370b324cSopenharmony_ci        {
1000370b324cSopenharmony_ci          bool defined = digests2[k2++];
1001370b324cSopenharmony_ci          digests.Defs[k] = defined;
1002370b324cSopenharmony_ci          UInt32 crc = 0;
1003370b324cSopenharmony_ci          if (defined)
1004370b324cSopenharmony_ci            crc = ReadUInt32();
1005370b324cSopenharmony_ci          digests.Vals[k] = crc;
1006370b324cSopenharmony_ci          k++;
1007370b324cSopenharmony_ci        }
1008370b324cSopenharmony_ci      }
1009370b324cSopenharmony_ci      // if (k != unpackSizes.Size()) throw 1234567;
1010370b324cSopenharmony_ci    }
1011370b324cSopenharmony_ci    else
1012370b324cSopenharmony_ci      SkipData();
1013370b324cSopenharmony_ci
1014370b324cSopenharmony_ci    type = ReadID();
1015370b324cSopenharmony_ci  }
1016370b324cSopenharmony_ci
1017370b324cSopenharmony_ci  if (digests.Defs.Size() != unpackSizes.Size())
1018370b324cSopenharmony_ci  {
1019370b324cSopenharmony_ci    digests.ClearAndSetSize(unpackSizes.Size());
1020370b324cSopenharmony_ci    unsigned k = 0;
1021370b324cSopenharmony_ci    for (i = 0; i < folders.NumFolders; i++)
1022370b324cSopenharmony_ci    {
1023370b324cSopenharmony_ci      const CNum numSubstreams = folders.NumUnpackStreamsVector[i];
1024370b324cSopenharmony_ci      if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
1025370b324cSopenharmony_ci      {
1026370b324cSopenharmony_ci        digests.Defs[k] = true;
1027370b324cSopenharmony_ci        digests.Vals[k] = folders.FolderCRCs.Vals[i];
1028370b324cSopenharmony_ci        k++;
1029370b324cSopenharmony_ci      }
1030370b324cSopenharmony_ci      else for (CNum j = 0; j < numSubstreams; j++)
1031370b324cSopenharmony_ci      {
1032370b324cSopenharmony_ci        digests.Defs[k] = false;
1033370b324cSopenharmony_ci        digests.Vals[k] = 0;
1034370b324cSopenharmony_ci        k++;
1035370b324cSopenharmony_ci      }
1036370b324cSopenharmony_ci    }
1037370b324cSopenharmony_ci  }
1038370b324cSopenharmony_ci}
1039370b324cSopenharmony_ci
1040370b324cSopenharmony_ci
1041370b324cSopenharmony_ci
1042370b324cSopenharmony_civoid CInArchive::ReadStreamsInfo(
1043370b324cSopenharmony_ci    const CObjectVector<CByteBuffer> *dataVector,
1044370b324cSopenharmony_ci    UInt64 &dataOffset,
1045370b324cSopenharmony_ci    CFolders &folders,
1046370b324cSopenharmony_ci    CRecordVector<UInt64> &unpackSizes,
1047370b324cSopenharmony_ci    CUInt32DefVector &digests)
1048370b324cSopenharmony_ci{
1049370b324cSopenharmony_ci  UInt64 type = ReadID();
1050370b324cSopenharmony_ci
1051370b324cSopenharmony_ci  if (type == NID::kPackInfo)
1052370b324cSopenharmony_ci  {
1053370b324cSopenharmony_ci    dataOffset = ReadNumber();
1054370b324cSopenharmony_ci    if (dataOffset > _rangeLimit)
1055370b324cSopenharmony_ci      ThrowIncorrect();
1056370b324cSopenharmony_ci    ReadPackInfo(folders);
1057370b324cSopenharmony_ci    if (folders.PackPositions[folders.NumPackStreams] > _rangeLimit - dataOffset)
1058370b324cSopenharmony_ci      ThrowIncorrect();
1059370b324cSopenharmony_ci    type = ReadID();
1060370b324cSopenharmony_ci  }
1061370b324cSopenharmony_ci
1062370b324cSopenharmony_ci  if (type == NID::kUnpackInfo)
1063370b324cSopenharmony_ci  {
1064370b324cSopenharmony_ci    ReadUnpackInfo(dataVector, folders);
1065370b324cSopenharmony_ci    type = ReadID();
1066370b324cSopenharmony_ci  }
1067370b324cSopenharmony_ci
1068370b324cSopenharmony_ci  if (folders.NumFolders != 0 && !folders.PackPositions)
1069370b324cSopenharmony_ci  {
1070370b324cSopenharmony_ci    // if there are folders, we need PackPositions also
1071370b324cSopenharmony_ci    folders.PackPositions.Alloc(1);
1072370b324cSopenharmony_ci    folders.PackPositions[0] = 0;
1073370b324cSopenharmony_ci  }
1074370b324cSopenharmony_ci
1075370b324cSopenharmony_ci  if (type == NID::kSubStreamsInfo)
1076370b324cSopenharmony_ci  {
1077370b324cSopenharmony_ci    ReadSubStreamsInfo(folders, unpackSizes, digests);
1078370b324cSopenharmony_ci    type = ReadID();
1079370b324cSopenharmony_ci  }
1080370b324cSopenharmony_ci  else
1081370b324cSopenharmony_ci  {
1082370b324cSopenharmony_ci    folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);
1083370b324cSopenharmony_ci    /* If digests.Defs.Size() == 0, it means that there are no crcs.
1084370b324cSopenharmony_ci       So we don't need to fill digests with values. */
1085370b324cSopenharmony_ci    // digests.Vals.ClearAndSetSize(folders.NumFolders);
1086370b324cSopenharmony_ci    // BoolVector_Fill_False(digests.Defs, folders.NumFolders);
1087370b324cSopenharmony_ci    for (CNum i = 0; i < folders.NumFolders; i++)
1088370b324cSopenharmony_ci    {
1089370b324cSopenharmony_ci      folders.NumUnpackStreamsVector[i] = 1;
1090370b324cSopenharmony_ci      unpackSizes.Add(folders.GetFolderUnpackSize(i));
1091370b324cSopenharmony_ci      // digests.Vals[i] = 0;
1092370b324cSopenharmony_ci    }
1093370b324cSopenharmony_ci  }
1094370b324cSopenharmony_ci
1095370b324cSopenharmony_ci  if (type != NID::kEnd)
1096370b324cSopenharmony_ci    ThrowIncorrect();
1097370b324cSopenharmony_ci}
1098370b324cSopenharmony_ci
1099370b324cSopenharmony_civoid CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v)
1100370b324cSopenharmony_ci{
1101370b324cSopenharmony_ci  v.ClearAndSetSize(numItems);
1102370b324cSopenharmony_ci  Byte b = 0;
1103370b324cSopenharmony_ci  Byte mask = 0;
1104370b324cSopenharmony_ci  bool *p = &v[0];
1105370b324cSopenharmony_ci  for (unsigned i = 0; i < numItems; i++)
1106370b324cSopenharmony_ci  {
1107370b324cSopenharmony_ci    if (mask == 0)
1108370b324cSopenharmony_ci    {
1109370b324cSopenharmony_ci      b = ReadByte();
1110370b324cSopenharmony_ci      mask = 0x80;
1111370b324cSopenharmony_ci    }
1112370b324cSopenharmony_ci    p[i] = ((b & mask) != 0);
1113370b324cSopenharmony_ci    mask = (Byte)(mask >> 1);
1114370b324cSopenharmony_ci  }
1115370b324cSopenharmony_ci}
1116370b324cSopenharmony_ci
1117370b324cSopenharmony_civoid CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v)
1118370b324cSopenharmony_ci{
1119370b324cSopenharmony_ci  const Byte allAreDefined = ReadByte();
1120370b324cSopenharmony_ci  if (allAreDefined == 0)
1121370b324cSopenharmony_ci  {
1122370b324cSopenharmony_ci    ReadBoolVector(numItems, v);
1123370b324cSopenharmony_ci    return;
1124370b324cSopenharmony_ci  }
1125370b324cSopenharmony_ci  v.ClearAndSetSize(numItems);
1126370b324cSopenharmony_ci  bool *p = &v[0];
1127370b324cSopenharmony_ci  for (unsigned i = 0; i < numItems; i++)
1128370b324cSopenharmony_ci    p[i] = true;
1129370b324cSopenharmony_ci}
1130370b324cSopenharmony_ci
1131370b324cSopenharmony_civoid CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
1132370b324cSopenharmony_ci    CUInt64DefVector &v, unsigned numItems)
1133370b324cSopenharmony_ci{
1134370b324cSopenharmony_ci  ReadBoolVector2(numItems, v.Defs);
1135370b324cSopenharmony_ci
1136370b324cSopenharmony_ci  CStreamSwitch streamSwitch;
1137370b324cSopenharmony_ci  streamSwitch.Set(this, &dataVector);
1138370b324cSopenharmony_ci
1139370b324cSopenharmony_ci  v.Vals.ClearAndSetSize(numItems);
1140370b324cSopenharmony_ci  UInt64 *p = &v.Vals[0];
1141370b324cSopenharmony_ci  const bool *defs = &v.Defs[0];
1142370b324cSopenharmony_ci
1143370b324cSopenharmony_ci  for (unsigned i = 0; i < numItems; i++)
1144370b324cSopenharmony_ci  {
1145370b324cSopenharmony_ci    UInt64 t = 0;
1146370b324cSopenharmony_ci    if (defs[i])
1147370b324cSopenharmony_ci      t = ReadUInt64();
1148370b324cSopenharmony_ci    p[i] = t;
1149370b324cSopenharmony_ci  }
1150370b324cSopenharmony_ci}
1151370b324cSopenharmony_ci
1152370b324cSopenharmony_ciHRESULT CInArchive::ReadAndDecodePackedStreams(
1153370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
1154370b324cSopenharmony_ci    UInt64 baseOffset,
1155370b324cSopenharmony_ci    UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector
1156370b324cSopenharmony_ci    Z7_7Z_DECODER_CRYPRO_VARS_DECL
1157370b324cSopenharmony_ci    )
1158370b324cSopenharmony_ci{
1159370b324cSopenharmony_ci  CFolders folders;
1160370b324cSopenharmony_ci  CRecordVector<UInt64> unpackSizes;
1161370b324cSopenharmony_ci  CUInt32DefVector  digests;
1162370b324cSopenharmony_ci
1163370b324cSopenharmony_ci  ReadStreamsInfo(NULL,
1164370b324cSopenharmony_ci    dataOffset,
1165370b324cSopenharmony_ci    folders,
1166370b324cSopenharmony_ci    unpackSizes,
1167370b324cSopenharmony_ci    digests);
1168370b324cSopenharmony_ci
1169370b324cSopenharmony_ci  CDecoder decoder(_useMixerMT);
1170370b324cSopenharmony_ci
1171370b324cSopenharmony_ci  for (CNum i = 0; i < folders.NumFolders; i++)
1172370b324cSopenharmony_ci  {
1173370b324cSopenharmony_ci    CByteBuffer &data = dataVector.AddNew();
1174370b324cSopenharmony_ci    const UInt64 unpackSize64 = folders.GetFolderUnpackSize(i);
1175370b324cSopenharmony_ci    const size_t unpackSize = (size_t)unpackSize64;
1176370b324cSopenharmony_ci    if (unpackSize != unpackSize64)
1177370b324cSopenharmony_ci      ThrowUnsupported();
1178370b324cSopenharmony_ci    data.Alloc(unpackSize);
1179370b324cSopenharmony_ci
1180370b324cSopenharmony_ci    CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
1181370b324cSopenharmony_ci    CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
1182370b324cSopenharmony_ci    outStreamSpec->Init(data, unpackSize);
1183370b324cSopenharmony_ci
1184370b324cSopenharmony_ci    bool dataAfterEnd_Error = false;
1185370b324cSopenharmony_ci
1186370b324cSopenharmony_ci    HRESULT result = decoder.Decode(
1187370b324cSopenharmony_ci        EXTERNAL_CODECS_LOC_VARS
1188370b324cSopenharmony_ci        _stream, baseOffset + dataOffset,
1189370b324cSopenharmony_ci        folders, i,
1190370b324cSopenharmony_ci        NULL, // &unpackSize64
1191370b324cSopenharmony_ci
1192370b324cSopenharmony_ci        outStream,
1193370b324cSopenharmony_ci        NULL, // *compressProgress
1194370b324cSopenharmony_ci
1195370b324cSopenharmony_ci        NULL  // **inStreamMainRes
1196370b324cSopenharmony_ci        , dataAfterEnd_Error
1197370b324cSopenharmony_ci
1198370b324cSopenharmony_ci        Z7_7Z_DECODER_CRYPRO_VARS
1199370b324cSopenharmony_ci        #if !defined(Z7_ST)
1200370b324cSopenharmony_ci          , false // mtMode
1201370b324cSopenharmony_ci          , 1     // numThreads
1202370b324cSopenharmony_ci          , 0     // memUsage
1203370b324cSopenharmony_ci        #endif
1204370b324cSopenharmony_ci      );
1205370b324cSopenharmony_ci
1206370b324cSopenharmony_ci    RINOK(result)
1207370b324cSopenharmony_ci
1208370b324cSopenharmony_ci    if (dataAfterEnd_Error)
1209370b324cSopenharmony_ci      ThereIsHeaderError = true;
1210370b324cSopenharmony_ci
1211370b324cSopenharmony_ci    if (unpackSize != outStreamSpec->GetPos())
1212370b324cSopenharmony_ci      ThrowIncorrect();
1213370b324cSopenharmony_ci
1214370b324cSopenharmony_ci    if (folders.FolderCRCs.ValidAndDefined(i))
1215370b324cSopenharmony_ci      if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
1216370b324cSopenharmony_ci        ThrowIncorrect();
1217370b324cSopenharmony_ci  }
1218370b324cSopenharmony_ci
1219370b324cSopenharmony_ci  if (folders.PackPositions)
1220370b324cSopenharmony_ci    HeadersSize += folders.PackPositions[folders.NumPackStreams];
1221370b324cSopenharmony_ci
1222370b324cSopenharmony_ci  return S_OK;
1223370b324cSopenharmony_ci}
1224370b324cSopenharmony_ci
1225370b324cSopenharmony_ciHRESULT CInArchive::ReadHeader(
1226370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
1227370b324cSopenharmony_ci    CDbEx &db
1228370b324cSopenharmony_ci    Z7_7Z_DECODER_CRYPRO_VARS_DECL
1229370b324cSopenharmony_ci    )
1230370b324cSopenharmony_ci{
1231370b324cSopenharmony_ci  UInt64 type = ReadID();
1232370b324cSopenharmony_ci
1233370b324cSopenharmony_ci  if (type == NID::kArchiveProperties)
1234370b324cSopenharmony_ci  {
1235370b324cSopenharmony_ci    ReadArchiveProperties(db.ArcInfo);
1236370b324cSopenharmony_ci    type = ReadID();
1237370b324cSopenharmony_ci  }
1238370b324cSopenharmony_ci
1239370b324cSopenharmony_ci  CObjectVector<CByteBuffer> dataVector;
1240370b324cSopenharmony_ci
1241370b324cSopenharmony_ci  if (type == NID::kAdditionalStreamsInfo)
1242370b324cSopenharmony_ci  {
1243370b324cSopenharmony_ci    const HRESULT result = ReadAndDecodePackedStreams(
1244370b324cSopenharmony_ci        EXTERNAL_CODECS_LOC_VARS
1245370b324cSopenharmony_ci        db.ArcInfo.StartPositionAfterHeader,
1246370b324cSopenharmony_ci        db.ArcInfo.DataStartPosition2,
1247370b324cSopenharmony_ci        dataVector
1248370b324cSopenharmony_ci        Z7_7Z_DECODER_CRYPRO_VARS
1249370b324cSopenharmony_ci        );
1250370b324cSopenharmony_ci    RINOK(result)
1251370b324cSopenharmony_ci    db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader;
1252370b324cSopenharmony_ci    type = ReadID();
1253370b324cSopenharmony_ci  }
1254370b324cSopenharmony_ci
1255370b324cSopenharmony_ci  CRecordVector<UInt64> unpackSizes;
1256370b324cSopenharmony_ci  CUInt32DefVector digests;
1257370b324cSopenharmony_ci
1258370b324cSopenharmony_ci  if (type == NID::kMainStreamsInfo)
1259370b324cSopenharmony_ci  {
1260370b324cSopenharmony_ci    ReadStreamsInfo(&dataVector,
1261370b324cSopenharmony_ci        db.ArcInfo.DataStartPosition,
1262370b324cSopenharmony_ci        (CFolders &)db,
1263370b324cSopenharmony_ci        unpackSizes,
1264370b324cSopenharmony_ci        digests);
1265370b324cSopenharmony_ci    db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader;
1266370b324cSopenharmony_ci    type = ReadID();
1267370b324cSopenharmony_ci  }
1268370b324cSopenharmony_ci
1269370b324cSopenharmony_ci  if (type == NID::kFilesInfo)
1270370b324cSopenharmony_ci  {
1271370b324cSopenharmony_ci
1272370b324cSopenharmony_ci  const CNum numFiles = ReadNum();
1273370b324cSopenharmony_ci
1274370b324cSopenharmony_ci  db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
1275370b324cSopenharmony_ci  // if (!db.PackSizes.IsEmpty())
1276370b324cSopenharmony_ci    db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
1277370b324cSopenharmony_ci  if (numFiles > 0 && !digests.Defs.IsEmpty())
1278370b324cSopenharmony_ci    db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
1279370b324cSopenharmony_ci
1280370b324cSopenharmony_ci  CBoolVector emptyStreamVector;
1281370b324cSopenharmony_ci  CBoolVector emptyFileVector;
1282370b324cSopenharmony_ci  CBoolVector antiFileVector;
1283370b324cSopenharmony_ci  CNum numEmptyStreams = 0;
1284370b324cSopenharmony_ci
1285370b324cSopenharmony_ci  for (;;)
1286370b324cSopenharmony_ci  {
1287370b324cSopenharmony_ci    const UInt64 type2 = ReadID();
1288370b324cSopenharmony_ci    if (type2 == NID::kEnd)
1289370b324cSopenharmony_ci      break;
1290370b324cSopenharmony_ci    const UInt64 size = ReadNumber();
1291370b324cSopenharmony_ci    if (size > _inByteBack->GetRem())
1292370b324cSopenharmony_ci      ThrowIncorrect();
1293370b324cSopenharmony_ci    CStreamSwitch switchProp;
1294370b324cSopenharmony_ci    switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);
1295370b324cSopenharmony_ci    bool addPropIdToList = true;
1296370b324cSopenharmony_ci    bool isKnownType = true;
1297370b324cSopenharmony_ci    if (type2 > ((UInt32)1 << 30))
1298370b324cSopenharmony_ci      isKnownType = false;
1299370b324cSopenharmony_ci    else switch ((UInt32)type2)
1300370b324cSopenharmony_ci    {
1301370b324cSopenharmony_ci      case NID::kName:
1302370b324cSopenharmony_ci      {
1303370b324cSopenharmony_ci        CStreamSwitch streamSwitch;
1304370b324cSopenharmony_ci        streamSwitch.Set(this, &dataVector);
1305370b324cSopenharmony_ci        const size_t rem = _inByteBack->GetRem();
1306370b324cSopenharmony_ci        db.NamesBuf.Alloc(rem);
1307370b324cSopenharmony_ci        ReadBytes(db.NamesBuf, rem);
1308370b324cSopenharmony_ci        db.NameOffsets.Alloc(numFiles + 1);
1309370b324cSopenharmony_ci        size_t pos = 0;
1310370b324cSopenharmony_ci        unsigned i;
1311370b324cSopenharmony_ci        for (i = 0; i < numFiles; i++)
1312370b324cSopenharmony_ci        {
1313370b324cSopenharmony_ci          const size_t curRem = (rem - pos) / 2;
1314370b324cSopenharmony_ci          const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf + pos);
1315370b324cSopenharmony_ci          size_t j;
1316370b324cSopenharmony_ci          for (j = 0; j < curRem && buf[j] != 0; j++);
1317370b324cSopenharmony_ci          if (j == curRem)
1318370b324cSopenharmony_ci            ThrowEndOfData();
1319370b324cSopenharmony_ci          db.NameOffsets[i] = pos / 2;
1320370b324cSopenharmony_ci          pos += j * 2 + 2;
1321370b324cSopenharmony_ci        }
1322370b324cSopenharmony_ci        db.NameOffsets[i] = pos / 2;
1323370b324cSopenharmony_ci        if (pos != rem)
1324370b324cSopenharmony_ci          ThereIsHeaderError = true;
1325370b324cSopenharmony_ci        break;
1326370b324cSopenharmony_ci      }
1327370b324cSopenharmony_ci
1328370b324cSopenharmony_ci      case NID::kWinAttrib:
1329370b324cSopenharmony_ci      {
1330370b324cSopenharmony_ci        ReadBoolVector2(numFiles, db.Attrib.Defs);
1331370b324cSopenharmony_ci        CStreamSwitch streamSwitch;
1332370b324cSopenharmony_ci        streamSwitch.Set(this, &dataVector);
1333370b324cSopenharmony_ci        Read_UInt32_Vector(db.Attrib);
1334370b324cSopenharmony_ci        break;
1335370b324cSopenharmony_ci      }
1336370b324cSopenharmony_ci
1337370b324cSopenharmony_ci      /*
1338370b324cSopenharmony_ci      case NID::kIsAux:
1339370b324cSopenharmony_ci      {
1340370b324cSopenharmony_ci        ReadBoolVector(numFiles, db.IsAux);
1341370b324cSopenharmony_ci        break;
1342370b324cSopenharmony_ci      }
1343370b324cSopenharmony_ci      case NID::kParent:
1344370b324cSopenharmony_ci      {
1345370b324cSopenharmony_ci        db.IsTree = true;
1346370b324cSopenharmony_ci        // CBoolVector boolVector;
1347370b324cSopenharmony_ci        // ReadBoolVector2(numFiles, boolVector);
1348370b324cSopenharmony_ci        // CStreamSwitch streamSwitch;
1349370b324cSopenharmony_ci        // streamSwitch.Set(this, &dataVector);
1350370b324cSopenharmony_ci        CBoolVector boolVector;
1351370b324cSopenharmony_ci        ReadBoolVector2(numFiles, boolVector);
1352370b324cSopenharmony_ci
1353370b324cSopenharmony_ci        db.ThereAreAltStreams = false;
1354370b324cSopenharmony_ci        for (i = 0; i < numFiles; i++)
1355370b324cSopenharmony_ci        {
1356370b324cSopenharmony_ci          CFileItem &file = db.Files[i];
1357370b324cSopenharmony_ci          // file.Parent = -1;
1358370b324cSopenharmony_ci          // if (boolVector[i])
1359370b324cSopenharmony_ci          file.Parent = (int)ReadUInt32();
1360370b324cSopenharmony_ci          file.IsAltStream = !boolVector[i];
1361370b324cSopenharmony_ci          if (file.IsAltStream)
1362370b324cSopenharmony_ci            db.ThereAreAltStreams = true;
1363370b324cSopenharmony_ci        }
1364370b324cSopenharmony_ci        break;
1365370b324cSopenharmony_ci      }
1366370b324cSopenharmony_ci      */
1367370b324cSopenharmony_ci      case NID::kEmptyStream:
1368370b324cSopenharmony_ci      {
1369370b324cSopenharmony_ci        ReadBoolVector(numFiles, emptyStreamVector);
1370370b324cSopenharmony_ci        numEmptyStreams = BoolVector_CountSum(emptyStreamVector);
1371370b324cSopenharmony_ci        emptyFileVector.Clear();
1372370b324cSopenharmony_ci        antiFileVector.Clear();
1373370b324cSopenharmony_ci        break;
1374370b324cSopenharmony_ci      }
1375370b324cSopenharmony_ci      case NID::kEmptyFile:  ReadBoolVector(numEmptyStreams, emptyFileVector); break;
1376370b324cSopenharmony_ci      case NID::kAnti:  ReadBoolVector(numEmptyStreams, antiFileVector); break;
1377370b324cSopenharmony_ci      case NID::kStartPos:  ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break;
1378370b324cSopenharmony_ci      case NID::kCTime:  ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break;
1379370b324cSopenharmony_ci      case NID::kATime:  ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break;
1380370b324cSopenharmony_ci      case NID::kMTime:  ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break;
1381370b324cSopenharmony_ci      case NID::kDummy:
1382370b324cSopenharmony_ci      {
1383370b324cSopenharmony_ci        for (UInt64 j = 0; j < size; j++)
1384370b324cSopenharmony_ci          if (ReadByte() != 0)
1385370b324cSopenharmony_ci            ThereIsHeaderError = true;
1386370b324cSopenharmony_ci        addPropIdToList = false;
1387370b324cSopenharmony_ci        break;
1388370b324cSopenharmony_ci      }
1389370b324cSopenharmony_ci      /*
1390370b324cSopenharmony_ci      case NID::kNtSecure:
1391370b324cSopenharmony_ci      {
1392370b324cSopenharmony_ci        try
1393370b324cSopenharmony_ci        {
1394370b324cSopenharmony_ci          {
1395370b324cSopenharmony_ci            CStreamSwitch streamSwitch;
1396370b324cSopenharmony_ci            streamSwitch.Set(this, &dataVector);
1397370b324cSopenharmony_ci            UInt32 numDescriptors = ReadUInt32();
1398370b324cSopenharmony_ci            size_t offset = 0;
1399370b324cSopenharmony_ci            db.SecureOffsets.Clear();
1400370b324cSopenharmony_ci            for (i = 0; i < numDescriptors; i++)
1401370b324cSopenharmony_ci            {
1402370b324cSopenharmony_ci              UInt32 size = ReadUInt32();
1403370b324cSopenharmony_ci              db.SecureOffsets.Add(offset);
1404370b324cSopenharmony_ci              offset += size;
1405370b324cSopenharmony_ci            }
1406370b324cSopenharmony_ci            // ThrowIncorrect();;
1407370b324cSopenharmony_ci            db.SecureOffsets.Add(offset);
1408370b324cSopenharmony_ci            db.SecureBuf.SetCapacity(offset);
1409370b324cSopenharmony_ci            for (i = 0; i < numDescriptors; i++)
1410370b324cSopenharmony_ci            {
1411370b324cSopenharmony_ci              offset = db.SecureOffsets[i];
1412370b324cSopenharmony_ci              ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);
1413370b324cSopenharmony_ci            }
1414370b324cSopenharmony_ci            db.SecureIDs.Clear();
1415370b324cSopenharmony_ci            for (unsigned i = 0; i < numFiles; i++)
1416370b324cSopenharmony_ci            {
1417370b324cSopenharmony_ci              db.SecureIDs.Add(ReadNum());
1418370b324cSopenharmony_ci              // db.SecureIDs.Add(ReadUInt32());
1419370b324cSopenharmony_ci            }
1420370b324cSopenharmony_ci            // ReadUInt32();
1421370b324cSopenharmony_ci            if (_inByteBack->GetRem() != 0)
1422370b324cSopenharmony_ci              ThrowIncorrect();;
1423370b324cSopenharmony_ci          }
1424370b324cSopenharmony_ci        }
1425370b324cSopenharmony_ci        catch(CInArchiveException &)
1426370b324cSopenharmony_ci        {
1427370b324cSopenharmony_ci          ThereIsHeaderError = true;
1428370b324cSopenharmony_ci          addPropIdToList = isKnownType = false;
1429370b324cSopenharmony_ci          db.ClearSecure();
1430370b324cSopenharmony_ci        }
1431370b324cSopenharmony_ci        break;
1432370b324cSopenharmony_ci      }
1433370b324cSopenharmony_ci      */
1434370b324cSopenharmony_ci      default:
1435370b324cSopenharmony_ci        addPropIdToList = isKnownType = false;
1436370b324cSopenharmony_ci    }
1437370b324cSopenharmony_ci    if (isKnownType)
1438370b324cSopenharmony_ci    {
1439370b324cSopenharmony_ci      if (addPropIdToList)
1440370b324cSopenharmony_ci        db.ArcInfo.FileInfoPopIDs.Add(type2);
1441370b324cSopenharmony_ci    }
1442370b324cSopenharmony_ci    else
1443370b324cSopenharmony_ci    {
1444370b324cSopenharmony_ci      db.UnsupportedFeatureWarning = true;
1445370b324cSopenharmony_ci      _inByteBack->SkipRem();
1446370b324cSopenharmony_ci    }
1447370b324cSopenharmony_ci    // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02)
1448370b324cSopenharmony_ci    if (_inByteBack->GetRem() != 0)
1449370b324cSopenharmony_ci      ThrowIncorrect();
1450370b324cSopenharmony_ci  }
1451370b324cSopenharmony_ci
1452370b324cSopenharmony_ci  type = ReadID(); // Read (NID::kEnd) end of headers
1453370b324cSopenharmony_ci
1454370b324cSopenharmony_ci  if (numFiles - numEmptyStreams != unpackSizes.Size())
1455370b324cSopenharmony_ci    ThrowUnsupported();
1456370b324cSopenharmony_ci
1457370b324cSopenharmony_ci  CNum emptyFileIndex = 0;
1458370b324cSopenharmony_ci  CNum sizeIndex = 0;
1459370b324cSopenharmony_ci
1460370b324cSopenharmony_ci  const CNum numAntiItems = BoolVector_CountSum(antiFileVector);
1461370b324cSopenharmony_ci
1462370b324cSopenharmony_ci  if (numAntiItems != 0)
1463370b324cSopenharmony_ci    db.IsAnti.ClearAndSetSize(numFiles);
1464370b324cSopenharmony_ci
1465370b324cSopenharmony_ci  db.Files.ClearAndSetSize(numFiles);
1466370b324cSopenharmony_ci
1467370b324cSopenharmony_ci  for (CNum i = 0; i < numFiles; i++)
1468370b324cSopenharmony_ci  {
1469370b324cSopenharmony_ci    CFileItem &file = db.Files[i];
1470370b324cSopenharmony_ci    bool isAnti;
1471370b324cSopenharmony_ci    file.Crc = 0;
1472370b324cSopenharmony_ci    if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i))
1473370b324cSopenharmony_ci    {
1474370b324cSopenharmony_ci      file.HasStream = true;
1475370b324cSopenharmony_ci      file.IsDir = false;
1476370b324cSopenharmony_ci      isAnti = false;
1477370b324cSopenharmony_ci      file.Size = unpackSizes[sizeIndex];
1478370b324cSopenharmony_ci      file.CrcDefined = digests.ValidAndDefined(sizeIndex);
1479370b324cSopenharmony_ci      if (file.CrcDefined)
1480370b324cSopenharmony_ci        file.Crc = digests.Vals[sizeIndex];
1481370b324cSopenharmony_ci      sizeIndex++;
1482370b324cSopenharmony_ci    }
1483370b324cSopenharmony_ci    else
1484370b324cSopenharmony_ci    {
1485370b324cSopenharmony_ci      file.HasStream = false;
1486370b324cSopenharmony_ci      file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex);
1487370b324cSopenharmony_ci      isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex);
1488370b324cSopenharmony_ci      emptyFileIndex++;
1489370b324cSopenharmony_ci      file.Size = 0;
1490370b324cSopenharmony_ci      file.CrcDefined = false;
1491370b324cSopenharmony_ci    }
1492370b324cSopenharmony_ci    if (numAntiItems != 0)
1493370b324cSopenharmony_ci      db.IsAnti[i] = isAnti;
1494370b324cSopenharmony_ci  }
1495370b324cSopenharmony_ci
1496370b324cSopenharmony_ci  }
1497370b324cSopenharmony_ci
1498370b324cSopenharmony_ci  db.FillLinks();
1499370b324cSopenharmony_ci
1500370b324cSopenharmony_ci  if (type != NID::kEnd || _inByteBack->GetRem() != 0)
1501370b324cSopenharmony_ci  {
1502370b324cSopenharmony_ci    db.UnsupportedFeatureWarning = true;
1503370b324cSopenharmony_ci    // ThrowIncorrect();
1504370b324cSopenharmony_ci  }
1505370b324cSopenharmony_ci
1506370b324cSopenharmony_ci  return S_OK;
1507370b324cSopenharmony_ci}
1508370b324cSopenharmony_ci
1509370b324cSopenharmony_ci
1510370b324cSopenharmony_civoid CDbEx::FillLinks()
1511370b324cSopenharmony_ci{
1512370b324cSopenharmony_ci  FolderStartFileIndex.Alloc(NumFolders);
1513370b324cSopenharmony_ci  FileIndexToFolderIndexMap.Alloc(Files.Size());
1514370b324cSopenharmony_ci
1515370b324cSopenharmony_ci  CNum folderIndex = 0;
1516370b324cSopenharmony_ci  CNum indexInFolder = 0;
1517370b324cSopenharmony_ci  unsigned i;
1518370b324cSopenharmony_ci
1519370b324cSopenharmony_ci  for (i = 0; i < Files.Size(); i++)
1520370b324cSopenharmony_ci  {
1521370b324cSopenharmony_ci    const bool emptyStream = !Files[i].HasStream;
1522370b324cSopenharmony_ci    if (indexInFolder == 0)
1523370b324cSopenharmony_ci    {
1524370b324cSopenharmony_ci      if (emptyStream)
1525370b324cSopenharmony_ci      {
1526370b324cSopenharmony_ci        FileIndexToFolderIndexMap[i] = kNumNoIndex;
1527370b324cSopenharmony_ci        continue;
1528370b324cSopenharmony_ci      }
1529370b324cSopenharmony_ci      // v3.13 incorrectly worked with empty folders
1530370b324cSopenharmony_ci      // v4.07: we skip empty folders
1531370b324cSopenharmony_ci      for (;;)
1532370b324cSopenharmony_ci      {
1533370b324cSopenharmony_ci        if (folderIndex >= NumFolders)
1534370b324cSopenharmony_ci          ThrowIncorrect();
1535370b324cSopenharmony_ci        FolderStartFileIndex[folderIndex] = i;
1536370b324cSopenharmony_ci        if (NumUnpackStreamsVector[folderIndex] != 0)
1537370b324cSopenharmony_ci          break;
1538370b324cSopenharmony_ci        folderIndex++;
1539370b324cSopenharmony_ci      }
1540370b324cSopenharmony_ci    }
1541370b324cSopenharmony_ci    FileIndexToFolderIndexMap[i] = folderIndex;
1542370b324cSopenharmony_ci    if (emptyStream)
1543370b324cSopenharmony_ci      continue;
1544370b324cSopenharmony_ci    if (++indexInFolder >= NumUnpackStreamsVector[folderIndex])
1545370b324cSopenharmony_ci    {
1546370b324cSopenharmony_ci      folderIndex++;
1547370b324cSopenharmony_ci      indexInFolder = 0;
1548370b324cSopenharmony_ci    }
1549370b324cSopenharmony_ci  }
1550370b324cSopenharmony_ci
1551370b324cSopenharmony_ci  if (indexInFolder != 0)
1552370b324cSopenharmony_ci  {
1553370b324cSopenharmony_ci    folderIndex++;
1554370b324cSopenharmony_ci    // 18.06
1555370b324cSopenharmony_ci    ThereIsHeaderError = true;
1556370b324cSopenharmony_ci    // ThrowIncorrect();
1557370b324cSopenharmony_ci  }
1558370b324cSopenharmony_ci
1559370b324cSopenharmony_ci  for (;;)
1560370b324cSopenharmony_ci  {
1561370b324cSopenharmony_ci    if (folderIndex >= NumFolders)
1562370b324cSopenharmony_ci      return;
1563370b324cSopenharmony_ci    FolderStartFileIndex[folderIndex] = i;
1564370b324cSopenharmony_ci    if (NumUnpackStreamsVector[folderIndex] != 0)
1565370b324cSopenharmony_ci    {
1566370b324cSopenharmony_ci      // 18.06
1567370b324cSopenharmony_ci      ThereIsHeaderError = true;
1568370b324cSopenharmony_ci      // ThrowIncorrect();
1569370b324cSopenharmony_ci    }
1570370b324cSopenharmony_ci    folderIndex++;
1571370b324cSopenharmony_ci  }
1572370b324cSopenharmony_ci}
1573370b324cSopenharmony_ci
1574370b324cSopenharmony_ci
1575370b324cSopenharmony_ciHRESULT CInArchive::ReadDatabase2(
1576370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
1577370b324cSopenharmony_ci    CDbEx &db
1578370b324cSopenharmony_ci    Z7_7Z_DECODER_CRYPRO_VARS_DECL
1579370b324cSopenharmony_ci    )
1580370b324cSopenharmony_ci{
1581370b324cSopenharmony_ci  db.Clear();
1582370b324cSopenharmony_ci  db.ArcInfo.StartPosition = _arhiveBeginStreamPosition;
1583370b324cSopenharmony_ci
1584370b324cSopenharmony_ci  db.ArcInfo.Version.Major = _header[6];
1585370b324cSopenharmony_ci  db.ArcInfo.Version.Minor = _header[7];
1586370b324cSopenharmony_ci
1587370b324cSopenharmony_ci  if (db.ArcInfo.Version.Major != kMajorVersion)
1588370b324cSopenharmony_ci  {
1589370b324cSopenharmony_ci    // db.UnsupportedVersion = true;
1590370b324cSopenharmony_ci    return S_FALSE;
1591370b324cSopenharmony_ci  }
1592370b324cSopenharmony_ci
1593370b324cSopenharmony_ci  UInt64 nextHeaderOffset = Get64(_header + 12);
1594370b324cSopenharmony_ci  UInt64 nextHeaderSize = Get64(_header + 20);
1595370b324cSopenharmony_ci  UInt32 nextHeaderCRC = Get32(_header + 28);
1596370b324cSopenharmony_ci
1597370b324cSopenharmony_ci  #ifdef FORMAT_7Z_RECOVERY
1598370b324cSopenharmony_ci  const UInt32 crcFromArc = Get32(_header + 8);
1599370b324cSopenharmony_ci  if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
1600370b324cSopenharmony_ci  {
1601370b324cSopenharmony_ci    UInt64 cur, fileSize;
1602370b324cSopenharmony_ci    RINOK(InStream_GetPos(_stream, cur))
1603370b324cSopenharmony_ci    const unsigned kCheckSize = 512;
1604370b324cSopenharmony_ci    Byte buf[kCheckSize];
1605370b324cSopenharmony_ci    RINOK(InStream_GetSize_SeekToEnd(_stream, fileSize))
1606370b324cSopenharmony_ci    const UInt64 rem = fileSize - cur;
1607370b324cSopenharmony_ci    unsigned checkSize = kCheckSize;
1608370b324cSopenharmony_ci    if (rem < kCheckSize)
1609370b324cSopenharmony_ci      checkSize = (unsigned)(rem);
1610370b324cSopenharmony_ci    if (checkSize < 3)
1611370b324cSopenharmony_ci      return S_FALSE;
1612370b324cSopenharmony_ci    RINOK(InStream_SeekSet(_stream, fileSize - checkSize))
1613370b324cSopenharmony_ci    RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize))
1614370b324cSopenharmony_ci
1615370b324cSopenharmony_ci    if (buf[checkSize - 1] != 0)
1616370b324cSopenharmony_ci      return S_FALSE;
1617370b324cSopenharmony_ci
1618370b324cSopenharmony_ci    unsigned i;
1619370b324cSopenharmony_ci    for (i = checkSize - 2;; i--)
1620370b324cSopenharmony_ci    {
1621370b324cSopenharmony_ci      if ((buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo) ||
1622370b324cSopenharmony_ci          (buf[i] == NID::kHeader        && buf[i + 1] == NID::kMainStreamsInfo))
1623370b324cSopenharmony_ci        break;
1624370b324cSopenharmony_ci      if (i == 0)
1625370b324cSopenharmony_ci        return S_FALSE;
1626370b324cSopenharmony_ci    }
1627370b324cSopenharmony_ci    nextHeaderSize = checkSize - i;
1628370b324cSopenharmony_ci    nextHeaderOffset = rem - nextHeaderSize;
1629370b324cSopenharmony_ci    nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
1630370b324cSopenharmony_ci    RINOK(InStream_SeekSet(_stream, cur))
1631370b324cSopenharmony_ci    db.StartHeaderWasRecovered = true;
1632370b324cSopenharmony_ci  }
1633370b324cSopenharmony_ci  else
1634370b324cSopenharmony_ci  #endif
1635370b324cSopenharmony_ci  {
1636370b324cSopenharmony_ci    // Crc was tested already at signature check
1637370b324cSopenharmony_ci    // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect();
1638370b324cSopenharmony_ci  }
1639370b324cSopenharmony_ci
1640370b324cSopenharmony_ci  db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;
1641370b324cSopenharmony_ci  db.PhySize = kHeaderSize;
1642370b324cSopenharmony_ci
1643370b324cSopenharmony_ci  db.IsArc = false;
1644370b324cSopenharmony_ci  if ((Int64)nextHeaderOffset < 0 ||
1645370b324cSopenharmony_ci      nextHeaderSize > ((UInt64)1 << 62))
1646370b324cSopenharmony_ci    return S_FALSE;
1647370b324cSopenharmony_ci
1648370b324cSopenharmony_ci  HeadersSize = kHeaderSize;
1649370b324cSopenharmony_ci
1650370b324cSopenharmony_ci  if (nextHeaderSize == 0)
1651370b324cSopenharmony_ci  {
1652370b324cSopenharmony_ci    if (nextHeaderOffset != 0)
1653370b324cSopenharmony_ci      return S_FALSE;
1654370b324cSopenharmony_ci    db.IsArc = true;
1655370b324cSopenharmony_ci    db.HeadersSize = HeadersSize;
1656370b324cSopenharmony_ci    return S_OK;
1657370b324cSopenharmony_ci  }
1658370b324cSopenharmony_ci
1659370b324cSopenharmony_ci  if (!db.StartHeaderWasRecovered)
1660370b324cSopenharmony_ci    db.IsArc = true;
1661370b324cSopenharmony_ci
1662370b324cSopenharmony_ci  HeadersSize += nextHeaderSize;
1663370b324cSopenharmony_ci  // db.EndHeaderOffset = nextHeaderOffset;
1664370b324cSopenharmony_ci  _rangeLimit = nextHeaderOffset;
1665370b324cSopenharmony_ci
1666370b324cSopenharmony_ci  db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;
1667370b324cSopenharmony_ci  if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize)
1668370b324cSopenharmony_ci  {
1669370b324cSopenharmony_ci    db.UnexpectedEnd = true;
1670370b324cSopenharmony_ci    return S_FALSE;
1671370b324cSopenharmony_ci  }
1672370b324cSopenharmony_ci  RINOK(_stream->Seek((Int64)nextHeaderOffset, STREAM_SEEK_CUR, NULL))
1673370b324cSopenharmony_ci
1674370b324cSopenharmony_ci  const size_t nextHeaderSize_t = (size_t)nextHeaderSize;
1675370b324cSopenharmony_ci  if (nextHeaderSize_t != nextHeaderSize)
1676370b324cSopenharmony_ci    return E_OUTOFMEMORY;
1677370b324cSopenharmony_ci  CByteBuffer buffer2(nextHeaderSize_t);
1678370b324cSopenharmony_ci
1679370b324cSopenharmony_ci  RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t))
1680370b324cSopenharmony_ci
1681370b324cSopenharmony_ci  if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC)
1682370b324cSopenharmony_ci    ThrowIncorrect();
1683370b324cSopenharmony_ci
1684370b324cSopenharmony_ci  if (!db.StartHeaderWasRecovered)
1685370b324cSopenharmony_ci    db.PhySizeWasConfirmed = true;
1686370b324cSopenharmony_ci
1687370b324cSopenharmony_ci  CStreamSwitch streamSwitch;
1688370b324cSopenharmony_ci  streamSwitch.Set(this, buffer2);
1689370b324cSopenharmony_ci
1690370b324cSopenharmony_ci  CObjectVector<CByteBuffer> dataVector;
1691370b324cSopenharmony_ci
1692370b324cSopenharmony_ci  const UInt64 type = ReadID();
1693370b324cSopenharmony_ci  if (type != NID::kHeader)
1694370b324cSopenharmony_ci  {
1695370b324cSopenharmony_ci    if (type != NID::kEncodedHeader)
1696370b324cSopenharmony_ci      ThrowIncorrect();
1697370b324cSopenharmony_ci    const HRESULT result = ReadAndDecodePackedStreams(
1698370b324cSopenharmony_ci        EXTERNAL_CODECS_LOC_VARS
1699370b324cSopenharmony_ci        db.ArcInfo.StartPositionAfterHeader,
1700370b324cSopenharmony_ci        db.ArcInfo.DataStartPosition2,
1701370b324cSopenharmony_ci        dataVector
1702370b324cSopenharmony_ci        Z7_7Z_DECODER_CRYPRO_VARS
1703370b324cSopenharmony_ci        );
1704370b324cSopenharmony_ci    RINOK(result)
1705370b324cSopenharmony_ci    if (dataVector.Size() == 0)
1706370b324cSopenharmony_ci      return S_OK;
1707370b324cSopenharmony_ci    if (dataVector.Size() > 1)
1708370b324cSopenharmony_ci      ThrowIncorrect();
1709370b324cSopenharmony_ci    streamSwitch.Remove();
1710370b324cSopenharmony_ci    streamSwitch.Set(this, dataVector.Front());
1711370b324cSopenharmony_ci    if (ReadID() != NID::kHeader)
1712370b324cSopenharmony_ci      ThrowIncorrect();
1713370b324cSopenharmony_ci  }
1714370b324cSopenharmony_ci
1715370b324cSopenharmony_ci  db.IsArc = true;
1716370b324cSopenharmony_ci
1717370b324cSopenharmony_ci  db.HeadersSize = HeadersSize;
1718370b324cSopenharmony_ci
1719370b324cSopenharmony_ci  return ReadHeader(
1720370b324cSopenharmony_ci    EXTERNAL_CODECS_LOC_VARS
1721370b324cSopenharmony_ci    db
1722370b324cSopenharmony_ci    Z7_7Z_DECODER_CRYPRO_VARS
1723370b324cSopenharmony_ci    );
1724370b324cSopenharmony_ci}
1725370b324cSopenharmony_ci
1726370b324cSopenharmony_ci
1727370b324cSopenharmony_ciHRESULT CInArchive::ReadDatabase(
1728370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
1729370b324cSopenharmony_ci    CDbEx &db
1730370b324cSopenharmony_ci    Z7_7Z_DECODER_CRYPRO_VARS_DECL
1731370b324cSopenharmony_ci    )
1732370b324cSopenharmony_ci{
1733370b324cSopenharmony_ci  try
1734370b324cSopenharmony_ci  {
1735370b324cSopenharmony_ci    const HRESULT res = ReadDatabase2(
1736370b324cSopenharmony_ci      EXTERNAL_CODECS_LOC_VARS db
1737370b324cSopenharmony_ci      Z7_7Z_DECODER_CRYPRO_VARS
1738370b324cSopenharmony_ci      );
1739370b324cSopenharmony_ci    if (ThereIsHeaderError)
1740370b324cSopenharmony_ci      db.ThereIsHeaderError = true;
1741370b324cSopenharmony_ci    if (res == E_NOTIMPL)
1742370b324cSopenharmony_ci      ThrowUnsupported();
1743370b324cSopenharmony_ci    return res;
1744370b324cSopenharmony_ci  }
1745370b324cSopenharmony_ci  catch(CUnsupportedFeatureException &)
1746370b324cSopenharmony_ci  {
1747370b324cSopenharmony_ci    db.UnsupportedFeatureError = true;
1748370b324cSopenharmony_ci    return S_FALSE;
1749370b324cSopenharmony_ci  }
1750370b324cSopenharmony_ci  catch(CInArchiveException &)
1751370b324cSopenharmony_ci  {
1752370b324cSopenharmony_ci    db.ThereIsHeaderError = true;
1753370b324cSopenharmony_ci    return S_FALSE;
1754370b324cSopenharmony_ci  }
1755370b324cSopenharmony_ci}
1756370b324cSopenharmony_ci
1757370b324cSopenharmony_ci}}
1758