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