Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Archive/7z/7zIn.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/7z/7zIn.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,1260 @@ 1.4 +// 7zIn.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +extern "C" 1.9 +{ 1.10 + #include "../../../../C/7zCrc.h" 1.11 + #include "../../../../C/CpuArch.h" 1.12 +} 1.13 + 1.14 +#include "../../Common/StreamObjects.h" 1.15 +#include "../../Common/StreamUtils.h" 1.16 + 1.17 +#include "7zDecode.h" 1.18 +#include "7zIn.h" 1.19 + 1.20 +#define Get16(p) GetUi16(p) 1.21 +#define Get32(p) GetUi32(p) 1.22 +#define Get64(p) GetUi64(p) 1.23 + 1.24 +// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader 1.25 +#ifndef _SFX 1.26 +#define FORMAT_7Z_RECOVERY 1.27 +#endif 1.28 + 1.29 +namespace NArchive { 1.30 +namespace N7z { 1.31 + 1.32 +static void BoolVector_Fill_False(CBoolVector &v, int size) 1.33 +{ 1.34 + v.Clear(); 1.35 + v.Reserve(size); 1.36 + for (int i = 0; i < size; i++) 1.37 + v.Add(false); 1.38 +} 1.39 + 1.40 +static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) 1.41 +{ 1.42 + if (index >= (UInt32)v.Size()) 1.43 + return true; 1.44 + bool res = v[index]; 1.45 + v[index] = true; 1.46 + return res; 1.47 +} 1.48 + 1.49 +bool CFolder::CheckStructure() const 1.50 +{ 1.51 + const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it 1.52 + const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax 1.53 + const int kNumBindsMax = 32; 1.54 + 1.55 + if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) 1.56 + return false; 1.57 + 1.58 + { 1.59 + CBoolVector v; 1.60 + BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); 1.61 + 1.62 + int i; 1.63 + for (i = 0; i < BindPairs.Size(); i++) 1.64 + if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) 1.65 + return false; 1.66 + for (i = 0; i < PackStreams.Size(); i++) 1.67 + if (BoolVector_GetAndSet(v, PackStreams[i])) 1.68 + return false; 1.69 + 1.70 + BoolVector_Fill_False(v, UnpackSizes.Size()); 1.71 + for (i = 0; i < BindPairs.Size(); i++) 1.72 + if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) 1.73 + return false; 1.74 + } 1.75 + 1.76 + UInt32 mask[kMaskSize]; 1.77 + int i; 1.78 + for (i = 0; i < kMaskSize; i++) 1.79 + mask[i] = 0; 1.80 + 1.81 + { 1.82 + CIntVector inStreamToCoder, outStreamToCoder; 1.83 + for (i = 0; i < Coders.Size(); i++) 1.84 + { 1.85 + CNum j; 1.86 + const CCoderInfo &coder = Coders[i]; 1.87 + for (j = 0; j < coder.NumInStreams; j++) 1.88 + inStreamToCoder.Add(i); 1.89 + for (j = 0; j < coder.NumOutStreams; j++) 1.90 + outStreamToCoder.Add(i); 1.91 + } 1.92 + 1.93 + for (i = 0; i < BindPairs.Size(); i++) 1.94 + { 1.95 + const CBindPair &bp = BindPairs[i]; 1.96 + mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); 1.97 + } 1.98 + } 1.99 + 1.100 + for (i = 0; i < kMaskSize; i++) 1.101 + for (int j = 0; j < kMaskSize; j++) 1.102 + if (((1 << j) & mask[i]) != 0) 1.103 + mask[i] |= mask[j]; 1.104 + 1.105 + for (i = 0; i < kMaskSize; i++) 1.106 + if (((1 << i) & mask[i]) != 0) 1.107 + return false; 1.108 + 1.109 + return true; 1.110 +} 1.111 + 1.112 +class CInArchiveException {}; 1.113 + 1.114 +static void ThrowException() { throw CInArchiveException(); } 1.115 +static inline void ThrowEndOfData() { ThrowException(); } 1.116 +static inline void ThrowUnsupported() { ThrowException(); } 1.117 +static inline void ThrowIncorrect() { ThrowException(); } 1.118 +static inline void ThrowUnsupportedVersion() { ThrowException(); } 1.119 + 1.120 +/* 1.121 +class CInArchiveException 1.122 +{ 1.123 +public: 1.124 + enum CCauseType 1.125 + { 1.126 + kUnsupportedVersion = 0, 1.127 + kUnsupported, 1.128 + kIncorrect, 1.129 + kEndOfData, 1.130 + } Cause; 1.131 + CInArchiveException(CCauseType cause): Cause(cause) {}; 1.132 +}; 1.133 + 1.134 +static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } 1.135 +static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } 1.136 +static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } 1.137 +static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } 1.138 +static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } 1.139 +*/ 1.140 + 1.141 +class CStreamSwitch 1.142 +{ 1.143 + CInArchive *_archive; 1.144 + bool _needRemove; 1.145 +public: 1.146 + CStreamSwitch(): _needRemove(false) {} 1.147 + ~CStreamSwitch() { Remove(); } 1.148 + void Remove(); 1.149 + void Set(CInArchive *archive, const Byte *data, size_t size); 1.150 + void Set(CInArchive *archive, const CByteBuffer &byteBuffer); 1.151 + void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); 1.152 +}; 1.153 + 1.154 +void CStreamSwitch::Remove() 1.155 +{ 1.156 + if (_needRemove) 1.157 + { 1.158 + _archive->DeleteByteStream(); 1.159 + _needRemove = false; 1.160 + } 1.161 +} 1.162 + 1.163 +void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) 1.164 +{ 1.165 + Remove(); 1.166 + _archive = archive; 1.167 + _archive->AddByteStream(data, size); 1.168 + _needRemove = true; 1.169 +} 1.170 + 1.171 +void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) 1.172 +{ 1.173 + Set(archive, byteBuffer, byteBuffer.GetCapacity()); 1.174 +} 1.175 + 1.176 +void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) 1.177 +{ 1.178 + Remove(); 1.179 + Byte external = archive->ReadByte(); 1.180 + if (external != 0) 1.181 + { 1.182 + int dataIndex = (int)archive->ReadNum(); 1.183 + if (dataIndex < 0 || dataIndex >= dataVector->Size()) 1.184 + ThrowIncorrect(); 1.185 + Set(archive, (*dataVector)[dataIndex]); 1.186 + } 1.187 +} 1.188 + 1.189 +Byte CInByte2::ReadByte() 1.190 +{ 1.191 + if (_pos >= _size) 1.192 + ThrowEndOfData(); 1.193 + return _buffer[_pos++]; 1.194 +} 1.195 + 1.196 +void CInByte2::ReadBytes(Byte *data, size_t size) 1.197 +{ 1.198 + if (size > _size - _pos) 1.199 + ThrowEndOfData(); 1.200 + for (size_t i = 0; i < size; i++) 1.201 + data[i] = _buffer[_pos++]; 1.202 +} 1.203 + 1.204 +void CInByte2::SkeepData(UInt64 size) 1.205 +{ 1.206 + if (size > _size - _pos) 1.207 + ThrowEndOfData(); 1.208 + _pos += (size_t)size; 1.209 +} 1.210 + 1.211 +void CInByte2::SkeepData() 1.212 +{ 1.213 + SkeepData(ReadNumber()); 1.214 +} 1.215 + 1.216 +UInt64 CInByte2::ReadNumber() 1.217 +{ 1.218 + if (_pos >= _size) 1.219 + ThrowEndOfData(); 1.220 + Byte firstByte = _buffer[_pos++]; 1.221 + Byte mask = 0x80; 1.222 + UInt64 value = 0; 1.223 + for (int i = 0; i < 8; i++) 1.224 + { 1.225 + if ((firstByte & mask) == 0) 1.226 + { 1.227 + UInt64 highPart = firstByte & (mask - 1); 1.228 + value += (highPart << (i * 8)); 1.229 + return value; 1.230 + } 1.231 + if (_pos >= _size) 1.232 + ThrowEndOfData(); 1.233 + value |= ((UInt64)_buffer[_pos++] << (8 * i)); 1.234 + mask >>= 1; 1.235 + } 1.236 + return value; 1.237 +} 1.238 + 1.239 +CNum CInByte2::ReadNum() 1.240 +{ 1.241 + UInt64 value = ReadNumber(); 1.242 + if (value > kNumMax) 1.243 + ThrowUnsupported(); 1.244 + return (CNum)value; 1.245 +} 1.246 + 1.247 +UInt32 CInByte2::ReadUInt32() 1.248 +{ 1.249 + if (_pos + 4 > _size) 1.250 + ThrowEndOfData(); 1.251 + UInt32 res = Get32(_buffer + _pos); 1.252 + _pos += 4; 1.253 + return res; 1.254 +} 1.255 + 1.256 +UInt64 CInByte2::ReadUInt64() 1.257 +{ 1.258 + if (_pos + 8 > _size) 1.259 + ThrowEndOfData(); 1.260 + UInt64 res = Get64(_buffer + _pos); 1.261 + _pos += 8; 1.262 + return res; 1.263 +} 1.264 + 1.265 +void CInByte2::ReadString(UString &s) 1.266 +{ 1.267 + const Byte *buf = _buffer + _pos; 1.268 + size_t rem = (_size - _pos) / 2 * 2; 1.269 + { 1.270 + size_t i; 1.271 + for (i = 0; i < rem; i += 2) 1.272 + if (buf[i] == 0 && buf[i + 1] == 0) 1.273 + break; 1.274 + if (i == rem) 1.275 + ThrowEndOfData(); 1.276 + rem = i; 1.277 + } 1.278 + int len = (int)(rem / 2); 1.279 + if (len < 0 || (size_t)len * 2 != rem) 1.280 + ThrowUnsupported(); 1.281 + wchar_t *p = s.GetBuffer(len); 1.282 + int i; 1.283 + for (i = 0; i < len; i++, buf += 2) 1.284 + p[i] = (wchar_t)Get16(buf); 1.285 + s.ReleaseBuffer(len); 1.286 + _pos += rem + 2; 1.287 +} 1.288 + 1.289 +static inline bool TestSignatureCandidate(const Byte *p) 1.290 +{ 1.291 + for (int i = 0; i < kSignatureSize; i++) 1.292 + if (p[i] != kSignature[i]) 1.293 + return false; 1.294 + return (p[0x1A] == 0 && p[0x1B] == 0); 1.295 +} 1.296 + 1.297 +HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) 1.298 +{ 1.299 + RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); 1.300 + 1.301 + if (TestSignatureCandidate(_header)) 1.302 + return S_OK; 1.303 + 1.304 + CByteBuffer byteBuffer; 1.305 + const UInt32 kBufferSize = (1 << 16); 1.306 + byteBuffer.SetCapacity(kBufferSize); 1.307 + Byte *buffer = byteBuffer; 1.308 + UInt32 numPrevBytes = kHeaderSize - 1; 1.309 + memcpy(buffer, _header + 1, numPrevBytes); 1.310 + UInt64 curTestPos = _arhiveBeginStreamPosition + 1; 1.311 + for (;;) 1.312 + { 1.313 + if (searchHeaderSizeLimit != NULL) 1.314 + if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) 1.315 + break; 1.316 + do 1.317 + { 1.318 + UInt32 numReadBytes = kBufferSize - numPrevBytes; 1.319 + UInt32 processedSize; 1.320 + RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); 1.321 + numPrevBytes += processedSize; 1.322 + if (processedSize == 0) 1.323 + return S_FALSE; 1.324 + } 1.325 + while (numPrevBytes < kHeaderSize); 1.326 + UInt32 numTests = numPrevBytes - kHeaderSize + 1; 1.327 + for (UInt32 pos = 0; pos < numTests; pos++) 1.328 + { 1.329 + for (; buffer[pos] != '7' && pos < numTests; pos++); 1.330 + if (pos == numTests) 1.331 + break; 1.332 + if (TestSignatureCandidate(buffer + pos)) 1.333 + { 1.334 + memcpy(_header, buffer + pos, kHeaderSize); 1.335 + curTestPos += pos; 1.336 + _arhiveBeginStreamPosition = curTestPos; 1.337 + return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); 1.338 + } 1.339 + } 1.340 + curTestPos += numTests; 1.341 + numPrevBytes -= numTests; 1.342 + memmove(buffer, buffer + numTests, numPrevBytes); 1.343 + } 1.344 + return S_FALSE; 1.345 +} 1.346 + 1.347 +// S_FALSE means that file is not archive 1.348 +HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) 1.349 +{ 1.350 + HeadersSize = 0; 1.351 + Close(); 1.352 + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) 1.353 + RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); 1.354 + _stream = stream; 1.355 + return S_OK; 1.356 +} 1.357 + 1.358 +void CInArchive::Close() 1.359 +{ 1.360 + _stream.Release(); 1.361 +} 1.362 + 1.363 +void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) 1.364 +{ 1.365 + for (;;) 1.366 + { 1.367 + if (ReadID() == NID::kEnd) 1.368 + break; 1.369 + SkeepData(); 1.370 + } 1.371 +} 1.372 + 1.373 +void CInArchive::GetNextFolderItem(CFolder &folder) 1.374 +{ 1.375 + CNum numCoders = ReadNum(); 1.376 + 1.377 + folder.Coders.Clear(); 1.378 + folder.Coders.Reserve((int)numCoders); 1.379 + CNum numInStreams = 0; 1.380 + CNum numOutStreams = 0; 1.381 + CNum i; 1.382 + for (i = 0; i < numCoders; i++) 1.383 + { 1.384 + folder.Coders.Add(CCoderInfo()); 1.385 + CCoderInfo &coder = folder.Coders.Back(); 1.386 + 1.387 + { 1.388 + Byte mainByte = ReadByte(); 1.389 + int idSize = (mainByte & 0xF); 1.390 + Byte longID[15]; 1.391 + ReadBytes(longID, idSize); 1.392 + if (idSize > 8) 1.393 + ThrowUnsupported(); 1.394 + UInt64 id = 0; 1.395 + for (int j = 0; j < idSize; j++) 1.396 + id |= (UInt64)longID[idSize - 1 - j] << (8 * j); 1.397 + coder.MethodID = id; 1.398 + 1.399 + if ((mainByte & 0x10) != 0) 1.400 + { 1.401 + coder.NumInStreams = ReadNum(); 1.402 + coder.NumOutStreams = ReadNum(); 1.403 + } 1.404 + else 1.405 + { 1.406 + coder.NumInStreams = 1; 1.407 + coder.NumOutStreams = 1; 1.408 + } 1.409 + if ((mainByte & 0x20) != 0) 1.410 + { 1.411 + CNum propsSize = ReadNum(); 1.412 + coder.Props.SetCapacity((size_t)propsSize); 1.413 + ReadBytes((Byte *)coder.Props, (size_t)propsSize); 1.414 + } 1.415 + if ((mainByte & 0x80) != 0) 1.416 + ThrowUnsupported(); 1.417 + } 1.418 + numInStreams += coder.NumInStreams; 1.419 + numOutStreams += coder.NumOutStreams; 1.420 + } 1.421 + 1.422 + CNum numBindPairs = numOutStreams - 1; 1.423 + folder.BindPairs.Clear(); 1.424 + folder.BindPairs.Reserve(numBindPairs); 1.425 + for (i = 0; i < numBindPairs; i++) 1.426 + { 1.427 + CBindPair bp; 1.428 + bp.InIndex = ReadNum(); 1.429 + bp.OutIndex = ReadNum(); 1.430 + folder.BindPairs.Add(bp); 1.431 + } 1.432 + 1.433 + if (numInStreams < numBindPairs) 1.434 + ThrowUnsupported(); 1.435 + CNum numPackStreams = numInStreams - numBindPairs; 1.436 + folder.PackStreams.Reserve(numPackStreams); 1.437 + if (numPackStreams == 1) 1.438 + { 1.439 + for (i = 0; i < numInStreams; i++) 1.440 + if (folder.FindBindPairForInStream(i) < 0) 1.441 + { 1.442 + folder.PackStreams.Add(i); 1.443 + break; 1.444 + } 1.445 + if (folder.PackStreams.Size() != 1) 1.446 + ThrowUnsupported(); 1.447 + } 1.448 + else 1.449 + for (i = 0; i < numPackStreams; i++) 1.450 + folder.PackStreams.Add(ReadNum()); 1.451 +} 1.452 + 1.453 +void CInArchive::WaitAttribute(UInt64 attribute) 1.454 +{ 1.455 + for (;;) 1.456 + { 1.457 + UInt64 type = ReadID(); 1.458 + if (type == attribute) 1.459 + return; 1.460 + if (type == NID::kEnd) 1.461 + ThrowIncorrect(); 1.462 + SkeepData(); 1.463 + } 1.464 +} 1.465 + 1.466 +void CInArchive::ReadHashDigests(int numItems, 1.467 + CBoolVector &digestsDefined, 1.468 + CRecordVector<UInt32> &digests) 1.469 +{ 1.470 + ReadBoolVector2(numItems, digestsDefined); 1.471 + digests.Clear(); 1.472 + digests.Reserve(numItems); 1.473 + for (int i = 0; i < numItems; i++) 1.474 + { 1.475 + UInt32 crc = 0; 1.476 + if (digestsDefined[i]) 1.477 + crc = ReadUInt32(); 1.478 + digests.Add(crc); 1.479 + } 1.480 +} 1.481 + 1.482 +void CInArchive::ReadPackInfo( 1.483 + UInt64 &dataOffset, 1.484 + CRecordVector<UInt64> &packSizes, 1.485 + CBoolVector &packCRCsDefined, 1.486 + CRecordVector<UInt32> &packCRCs) 1.487 +{ 1.488 + dataOffset = ReadNumber(); 1.489 + CNum numPackStreams = ReadNum(); 1.490 + 1.491 + WaitAttribute(NID::kSize); 1.492 + packSizes.Clear(); 1.493 + packSizes.Reserve(numPackStreams); 1.494 + for (CNum i = 0; i < numPackStreams; i++) 1.495 + packSizes.Add(ReadNumber()); 1.496 + 1.497 + UInt64 type; 1.498 + for (;;) 1.499 + { 1.500 + type = ReadID(); 1.501 + if (type == NID::kEnd) 1.502 + break; 1.503 + if (type == NID::kCRC) 1.504 + { 1.505 + ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); 1.506 + continue; 1.507 + } 1.508 + SkeepData(); 1.509 + } 1.510 + if (packCRCsDefined.IsEmpty()) 1.511 + { 1.512 + BoolVector_Fill_False(packCRCsDefined, numPackStreams); 1.513 + packCRCs.Reserve(numPackStreams); 1.514 + packCRCs.Clear(); 1.515 + for (CNum i = 0; i < numPackStreams; i++) 1.516 + packCRCs.Add(0); 1.517 + } 1.518 +} 1.519 + 1.520 +void CInArchive::ReadUnpackInfo( 1.521 + const CObjectVector<CByteBuffer> *dataVector, 1.522 + CObjectVector<CFolder> &folders) 1.523 +{ 1.524 + WaitAttribute(NID::kFolder); 1.525 + CNum numFolders = ReadNum(); 1.526 + 1.527 + { 1.528 + CStreamSwitch streamSwitch; 1.529 + streamSwitch.Set(this, dataVector); 1.530 + folders.Clear(); 1.531 + folders.Reserve(numFolders); 1.532 + for (CNum i = 0; i < numFolders; i++) 1.533 + { 1.534 + folders.Add(CFolder()); 1.535 + GetNextFolderItem(folders.Back()); 1.536 + } 1.537 + } 1.538 + 1.539 + WaitAttribute(NID::kCodersUnpackSize); 1.540 + 1.541 + CNum i; 1.542 + for (i = 0; i < numFolders; i++) 1.543 + { 1.544 + CFolder &folder = folders[i]; 1.545 + CNum numOutStreams = folder.GetNumOutStreams(); 1.546 + folder.UnpackSizes.Reserve(numOutStreams); 1.547 + for (CNum j = 0; j < numOutStreams; j++) 1.548 + folder.UnpackSizes.Add(ReadNumber()); 1.549 + } 1.550 + 1.551 + for (;;) 1.552 + { 1.553 + UInt64 type = ReadID(); 1.554 + if (type == NID::kEnd) 1.555 + return; 1.556 + if (type == NID::kCRC) 1.557 + { 1.558 + CBoolVector crcsDefined; 1.559 + CRecordVector<UInt32> crcs; 1.560 + ReadHashDigests(numFolders, crcsDefined, crcs); 1.561 + for (i = 0; i < numFolders; i++) 1.562 + { 1.563 + CFolder &folder = folders[i]; 1.564 + folder.UnpackCRCDefined = crcsDefined[i]; 1.565 + folder.UnpackCRC = crcs[i]; 1.566 + } 1.567 + continue; 1.568 + } 1.569 + SkeepData(); 1.570 + } 1.571 +} 1.572 + 1.573 +void CInArchive::ReadSubStreamsInfo( 1.574 + const CObjectVector<CFolder> &folders, 1.575 + CRecordVector<CNum> &numUnpackStreamsInFolders, 1.576 + CRecordVector<UInt64> &unpackSizes, 1.577 + CBoolVector &digestsDefined, 1.578 + CRecordVector<UInt32> &digests) 1.579 +{ 1.580 + numUnpackStreamsInFolders.Clear(); 1.581 + numUnpackStreamsInFolders.Reserve(folders.Size()); 1.582 + UInt64 type; 1.583 + for (;;) 1.584 + { 1.585 + type = ReadID(); 1.586 + if (type == NID::kNumUnpackStream) 1.587 + { 1.588 + for (int i = 0; i < folders.Size(); i++) 1.589 + numUnpackStreamsInFolders.Add(ReadNum()); 1.590 + continue; 1.591 + } 1.592 + if (type == NID::kCRC || type == NID::kSize) 1.593 + break; 1.594 + if (type == NID::kEnd) 1.595 + break; 1.596 + SkeepData(); 1.597 + } 1.598 + 1.599 + if (numUnpackStreamsInFolders.IsEmpty()) 1.600 + for (int i = 0; i < folders.Size(); i++) 1.601 + numUnpackStreamsInFolders.Add(1); 1.602 + 1.603 + int i; 1.604 + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) 1.605 + { 1.606 + // v3.13 incorrectly worked with empty folders 1.607 + // v4.07: we check that folder is empty 1.608 + CNum numSubstreams = numUnpackStreamsInFolders[i]; 1.609 + if (numSubstreams == 0) 1.610 + continue; 1.611 + UInt64 sum = 0; 1.612 + for (CNum j = 1; j < numSubstreams; j++) 1.613 + if (type == NID::kSize) 1.614 + { 1.615 + UInt64 size = ReadNumber(); 1.616 + unpackSizes.Add(size); 1.617 + sum += size; 1.618 + } 1.619 + unpackSizes.Add(folders[i].GetUnpackSize() - sum); 1.620 + } 1.621 + if (type == NID::kSize) 1.622 + type = ReadID(); 1.623 + 1.624 + int numDigests = 0; 1.625 + int numDigestsTotal = 0; 1.626 + for (i = 0; i < folders.Size(); i++) 1.627 + { 1.628 + CNum numSubstreams = numUnpackStreamsInFolders[i]; 1.629 + if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) 1.630 + numDigests += numSubstreams; 1.631 + numDigestsTotal += numSubstreams; 1.632 + } 1.633 + 1.634 + for (;;) 1.635 + { 1.636 + if (type == NID::kCRC) 1.637 + { 1.638 + CBoolVector digestsDefined2; 1.639 + CRecordVector<UInt32> digests2; 1.640 + ReadHashDigests(numDigests, digestsDefined2, digests2); 1.641 + int digestIndex = 0; 1.642 + for (i = 0; i < folders.Size(); i++) 1.643 + { 1.644 + CNum numSubstreams = numUnpackStreamsInFolders[i]; 1.645 + const CFolder &folder = folders[i]; 1.646 + if (numSubstreams == 1 && folder.UnpackCRCDefined) 1.647 + { 1.648 + digestsDefined.Add(true); 1.649 + digests.Add(folder.UnpackCRC); 1.650 + } 1.651 + else 1.652 + for (CNum j = 0; j < numSubstreams; j++, digestIndex++) 1.653 + { 1.654 + digestsDefined.Add(digestsDefined2[digestIndex]); 1.655 + digests.Add(digests2[digestIndex]); 1.656 + } 1.657 + } 1.658 + } 1.659 + else if (type == NID::kEnd) 1.660 + { 1.661 + if (digestsDefined.IsEmpty()) 1.662 + { 1.663 + BoolVector_Fill_False(digestsDefined, numDigestsTotal); 1.664 + digests.Clear(); 1.665 + for (int i = 0; i < numDigestsTotal; i++) 1.666 + digests.Add(0); 1.667 + } 1.668 + return; 1.669 + } 1.670 + else 1.671 + SkeepData(); 1.672 + type = ReadID(); 1.673 + } 1.674 +} 1.675 + 1.676 +void CInArchive::ReadStreamsInfo( 1.677 + const CObjectVector<CByteBuffer> *dataVector, 1.678 + UInt64 &dataOffset, 1.679 + CRecordVector<UInt64> &packSizes, 1.680 + CBoolVector &packCRCsDefined, 1.681 + CRecordVector<UInt32> &packCRCs, 1.682 + CObjectVector<CFolder> &folders, 1.683 + CRecordVector<CNum> &numUnpackStreamsInFolders, 1.684 + CRecordVector<UInt64> &unpackSizes, 1.685 + CBoolVector &digestsDefined, 1.686 + CRecordVector<UInt32> &digests) 1.687 +{ 1.688 + for (;;) 1.689 + { 1.690 + UInt64 type = ReadID(); 1.691 + if (type > ((UInt32)1 << 30)) 1.692 + ThrowIncorrect(); 1.693 + switch((UInt32)type) 1.694 + { 1.695 + case NID::kEnd: 1.696 + return; 1.697 + case NID::kPackInfo: 1.698 + { 1.699 + ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); 1.700 + break; 1.701 + } 1.702 + case NID::kUnpackInfo: 1.703 + { 1.704 + ReadUnpackInfo(dataVector, folders); 1.705 + break; 1.706 + } 1.707 + case NID::kSubStreamsInfo: 1.708 + { 1.709 + ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, 1.710 + unpackSizes, digestsDefined, digests); 1.711 + break; 1.712 + } 1.713 + default: 1.714 + ThrowIncorrect(); 1.715 + } 1.716 + } 1.717 +} 1.718 + 1.719 +void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) 1.720 +{ 1.721 + v.Clear(); 1.722 + v.Reserve(numItems); 1.723 + Byte b = 0; 1.724 + Byte mask = 0; 1.725 + for (int i = 0; i < numItems; i++) 1.726 + { 1.727 + if (mask == 0) 1.728 + { 1.729 + b = ReadByte(); 1.730 + mask = 0x80; 1.731 + } 1.732 + v.Add((b & mask) != 0); 1.733 + mask >>= 1; 1.734 + } 1.735 +} 1.736 + 1.737 +void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) 1.738 +{ 1.739 + Byte allAreDefined = ReadByte(); 1.740 + if (allAreDefined == 0) 1.741 + { 1.742 + ReadBoolVector(numItems, v); 1.743 + return; 1.744 + } 1.745 + v.Clear(); 1.746 + v.Reserve(numItems); 1.747 + for (int i = 0; i < numItems; i++) 1.748 + v.Add(true); 1.749 +} 1.750 + 1.751 +void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, 1.752 + CUInt64DefVector &v, int numFiles) 1.753 +{ 1.754 + ReadBoolVector2(numFiles, v.Defined); 1.755 + 1.756 + CStreamSwitch streamSwitch; 1.757 + streamSwitch.Set(this, &dataVector); 1.758 + v.Values.Reserve(numFiles); 1.759 + 1.760 + for (int i = 0; i < numFiles; i++) 1.761 + { 1.762 + UInt64 t = 0; 1.763 + if (v.Defined[i]) 1.764 + t = ReadUInt64(); 1.765 + v.Values.Add(t); 1.766 + } 1.767 +} 1.768 + 1.769 +HRESULT CInArchive::ReadAndDecodePackedStreams( 1.770 + DECL_EXTERNAL_CODECS_LOC_VARS 1.771 + UInt64 baseOffset, 1.772 + UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector 1.773 + #ifndef _NO_CRYPTO 1.774 + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined 1.775 + #endif 1.776 + ) 1.777 +{ 1.778 + CRecordVector<UInt64> packSizes; 1.779 + CBoolVector packCRCsDefined; 1.780 + CRecordVector<UInt32> packCRCs; 1.781 + CObjectVector<CFolder> folders; 1.782 + 1.783 + CRecordVector<CNum> numUnpackStreamsInFolders; 1.784 + CRecordVector<UInt64> unpackSizes; 1.785 + CBoolVector digestsDefined; 1.786 + CRecordVector<UInt32> digests; 1.787 + 1.788 + ReadStreamsInfo(NULL, 1.789 + dataOffset, 1.790 + packSizes, 1.791 + packCRCsDefined, 1.792 + packCRCs, 1.793 + folders, 1.794 + numUnpackStreamsInFolders, 1.795 + unpackSizes, 1.796 + digestsDefined, 1.797 + digests); 1.798 + 1.799 + // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; 1.800 + 1.801 + CNum packIndex = 0; 1.802 + CDecoder decoder( 1.803 + #ifdef _ST_MODE 1.804 + false 1.805 + #else 1.806 + true 1.807 + #endif 1.808 + ); 1.809 + UInt64 dataStartPos = baseOffset + dataOffset; 1.810 + for (int i = 0; i < folders.Size(); i++) 1.811 + { 1.812 + const CFolder &folder = folders[i]; 1.813 + dataVector.Add(CByteBuffer()); 1.814 + CByteBuffer &data = dataVector.Back(); 1.815 + UInt64 unpackSize64 = folder.GetUnpackSize(); 1.816 + size_t unpackSize = (size_t)unpackSize64; 1.817 + if (unpackSize != unpackSize64) 1.818 + ThrowUnsupported(); 1.819 + data.SetCapacity(unpackSize); 1.820 + 1.821 + CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; 1.822 + CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; 1.823 + outStreamSpec->Init(data, unpackSize); 1.824 + 1.825 + HRESULT result = decoder.Decode( 1.826 + EXTERNAL_CODECS_LOC_VARS 1.827 + _stream, dataStartPos, 1.828 + &packSizes[packIndex], folder, outStream, NULL 1.829 + #ifndef _NO_CRYPTO 1.830 + , getTextPassword, passwordIsDefined 1.831 + #endif 1.832 + #ifdef COMPRESS_MT 1.833 + , false, 1 1.834 + #endif 1.835 + ); 1.836 + RINOK(result); 1.837 + 1.838 + if (folder.UnpackCRCDefined) 1.839 + if (CrcCalc(data, unpackSize) != folder.UnpackCRC) 1.840 + ThrowIncorrect(); 1.841 + for (int j = 0; j < folder.PackStreams.Size(); j++) 1.842 + { 1.843 + UInt64 packSize = packSizes[packIndex++]; 1.844 + dataStartPos += packSize; 1.845 + HeadersSize += packSize; 1.846 + } 1.847 + } 1.848 + return S_OK; 1.849 +} 1.850 + 1.851 +HRESULT CInArchive::ReadHeader( 1.852 + DECL_EXTERNAL_CODECS_LOC_VARS 1.853 + CArchiveDatabaseEx &db 1.854 + #ifndef _NO_CRYPTO 1.855 + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined 1.856 + #endif 1.857 + ) 1.858 +{ 1.859 + UInt64 type = ReadID(); 1.860 + 1.861 + if (type == NID::kArchiveProperties) 1.862 + { 1.863 + ReadArchiveProperties(db.ArchiveInfo); 1.864 + type = ReadID(); 1.865 + } 1.866 + 1.867 + CObjectVector<CByteBuffer> dataVector; 1.868 + 1.869 + if (type == NID::kAdditionalStreamsInfo) 1.870 + { 1.871 + HRESULT result = ReadAndDecodePackedStreams( 1.872 + EXTERNAL_CODECS_LOC_VARS 1.873 + db.ArchiveInfo.StartPositionAfterHeader, 1.874 + db.ArchiveInfo.DataStartPosition2, 1.875 + dataVector 1.876 + #ifndef _NO_CRYPTO 1.877 + , getTextPassword, passwordIsDefined 1.878 + #endif 1.879 + ); 1.880 + RINOK(result); 1.881 + db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; 1.882 + type = ReadID(); 1.883 + } 1.884 + 1.885 + CRecordVector<UInt64> unpackSizes; 1.886 + CBoolVector digestsDefined; 1.887 + CRecordVector<UInt32> digests; 1.888 + 1.889 + if (type == NID::kMainStreamsInfo) 1.890 + { 1.891 + ReadStreamsInfo(&dataVector, 1.892 + db.ArchiveInfo.DataStartPosition, 1.893 + db.PackSizes, 1.894 + db.PackCRCsDefined, 1.895 + db.PackCRCs, 1.896 + db.Folders, 1.897 + db.NumUnpackStreamsVector, 1.898 + unpackSizes, 1.899 + digestsDefined, 1.900 + digests); 1.901 + db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; 1.902 + type = ReadID(); 1.903 + } 1.904 + else 1.905 + { 1.906 + for (int i = 0; i < db.Folders.Size(); i++) 1.907 + { 1.908 + db.NumUnpackStreamsVector.Add(1); 1.909 + CFolder &folder = db.Folders[i]; 1.910 + unpackSizes.Add(folder.GetUnpackSize()); 1.911 + digestsDefined.Add(folder.UnpackCRCDefined); 1.912 + digests.Add(folder.UnpackCRC); 1.913 + } 1.914 + } 1.915 + 1.916 + db.Files.Clear(); 1.917 + 1.918 + if (type == NID::kEnd) 1.919 + return S_OK; 1.920 + if (type != NID::kFilesInfo) 1.921 + ThrowIncorrect(); 1.922 + 1.923 + CNum numFiles = ReadNum(); 1.924 + db.Files.Reserve(numFiles); 1.925 + CNum i; 1.926 + for (i = 0; i < numFiles; i++) 1.927 + db.Files.Add(CFileItem()); 1.928 + 1.929 + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); 1.930 + if (!db.PackSizes.IsEmpty()) 1.931 + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); 1.932 + if (numFiles > 0 && !digests.IsEmpty()) 1.933 + db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); 1.934 + 1.935 + CBoolVector emptyStreamVector; 1.936 + BoolVector_Fill_False(emptyStreamVector, (int)numFiles); 1.937 + CBoolVector emptyFileVector; 1.938 + CBoolVector antiFileVector; 1.939 + CNum numEmptyStreams = 0; 1.940 + 1.941 + for (;;) 1.942 + { 1.943 + UInt64 type = ReadID(); 1.944 + if (type == NID::kEnd) 1.945 + break; 1.946 + UInt64 size = ReadNumber(); 1.947 + size_t ppp = _inByteBack->_pos; 1.948 + bool addPropIdToList = true; 1.949 + bool isKnownType = true; 1.950 + if (type > ((UInt32)1 << 30)) 1.951 + isKnownType = false; 1.952 + else switch((UInt32)type) 1.953 + { 1.954 + case NID::kName: 1.955 + { 1.956 + CStreamSwitch streamSwitch; 1.957 + streamSwitch.Set(this, &dataVector); 1.958 + for (int i = 0; i < db.Files.Size(); i++) 1.959 + _inByteBack->ReadString(db.Files[i].Name); 1.960 + break; 1.961 + } 1.962 + case NID::kWinAttributes: 1.963 + { 1.964 + CBoolVector boolVector; 1.965 + ReadBoolVector2(db.Files.Size(), boolVector); 1.966 + CStreamSwitch streamSwitch; 1.967 + streamSwitch.Set(this, &dataVector); 1.968 + for (i = 0; i < numFiles; i++) 1.969 + { 1.970 + CFileItem &file = db.Files[i]; 1.971 + file.AttribDefined = boolVector[i]; 1.972 + if (file.AttribDefined) 1.973 + file.Attrib = ReadUInt32(); 1.974 + } 1.975 + break; 1.976 + } 1.977 + case NID::kEmptyStream: 1.978 + { 1.979 + ReadBoolVector(numFiles, emptyStreamVector); 1.980 + for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) 1.981 + if (emptyStreamVector[i]) 1.982 + numEmptyStreams++; 1.983 + 1.984 + BoolVector_Fill_False(emptyFileVector, numEmptyStreams); 1.985 + BoolVector_Fill_False(antiFileVector, numEmptyStreams); 1.986 + 1.987 + break; 1.988 + } 1.989 + case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; 1.990 + case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; 1.991 + case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; 1.992 + case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; 1.993 + case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; 1.994 + case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; 1.995 + case NID::kDummy: 1.996 + { 1.997 + for (UInt64 j = 0; j < size; j++) 1.998 + if (ReadByte() != 0) 1.999 + ThrowIncorrect(); 1.1000 + addPropIdToList = false; 1.1001 + break; 1.1002 + } 1.1003 + default: 1.1004 + addPropIdToList = isKnownType = false; 1.1005 + } 1.1006 + if (isKnownType) 1.1007 + { 1.1008 + if(addPropIdToList) 1.1009 + db.ArchiveInfo.FileInfoPopIDs.Add(type); 1.1010 + } 1.1011 + else 1.1012 + SkeepData(size); 1.1013 + bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || 1.1014 + db.ArchiveInfo.Version.Minor > 2); 1.1015 + if (checkRecordsSize && _inByteBack->_pos - ppp != size) 1.1016 + ThrowIncorrect(); 1.1017 + } 1.1018 + 1.1019 + CNum emptyFileIndex = 0; 1.1020 + CNum sizeIndex = 0; 1.1021 + 1.1022 + CNum numAntiItems = 0; 1.1023 + for (i = 0; i < numEmptyStreams; i++) 1.1024 + if (antiFileVector[i]) 1.1025 + numAntiItems++; 1.1026 + 1.1027 + for (i = 0; i < numFiles; i++) 1.1028 + { 1.1029 + CFileItem &file = db.Files[i]; 1.1030 + bool isAnti; 1.1031 + file.HasStream = !emptyStreamVector[i]; 1.1032 + if (file.HasStream) 1.1033 + { 1.1034 + file.IsDir = false; 1.1035 + isAnti = false; 1.1036 + file.Size = unpackSizes[sizeIndex]; 1.1037 + file.Crc = digests[sizeIndex]; 1.1038 + file.CrcDefined = digestsDefined[sizeIndex]; 1.1039 + sizeIndex++; 1.1040 + } 1.1041 + else 1.1042 + { 1.1043 + file.IsDir = !emptyFileVector[emptyFileIndex]; 1.1044 + isAnti = antiFileVector[emptyFileIndex]; 1.1045 + emptyFileIndex++; 1.1046 + file.Size = 0; 1.1047 + file.CrcDefined = false; 1.1048 + } 1.1049 + if (numAntiItems != 0) 1.1050 + db.IsAnti.Add(isAnti); 1.1051 + } 1.1052 + return S_OK; 1.1053 +} 1.1054 + 1.1055 + 1.1056 +void CArchiveDatabaseEx::FillFolderStartPackStream() 1.1057 +{ 1.1058 + FolderStartPackStreamIndex.Clear(); 1.1059 + FolderStartPackStreamIndex.Reserve(Folders.Size()); 1.1060 + CNum startPos = 0; 1.1061 + for (int i = 0; i < Folders.Size(); i++) 1.1062 + { 1.1063 + FolderStartPackStreamIndex.Add(startPos); 1.1064 + startPos += (CNum)Folders[i].PackStreams.Size(); 1.1065 + } 1.1066 +} 1.1067 + 1.1068 +void CArchiveDatabaseEx::FillStartPos() 1.1069 +{ 1.1070 + PackStreamStartPositions.Clear(); 1.1071 + PackStreamStartPositions.Reserve(PackSizes.Size()); 1.1072 + UInt64 startPos = 0; 1.1073 + for (int i = 0; i < PackSizes.Size(); i++) 1.1074 + { 1.1075 + PackStreamStartPositions.Add(startPos); 1.1076 + startPos += PackSizes[i]; 1.1077 + } 1.1078 +} 1.1079 + 1.1080 +void CArchiveDatabaseEx::FillFolderStartFileIndex() 1.1081 +{ 1.1082 + FolderStartFileIndex.Clear(); 1.1083 + FolderStartFileIndex.Reserve(Folders.Size()); 1.1084 + FileIndexToFolderIndexMap.Clear(); 1.1085 + FileIndexToFolderIndexMap.Reserve(Files.Size()); 1.1086 + 1.1087 + int folderIndex = 0; 1.1088 + CNum indexInFolder = 0; 1.1089 + for (int i = 0; i < Files.Size(); i++) 1.1090 + { 1.1091 + const CFileItem &file = Files[i]; 1.1092 + bool emptyStream = !file.HasStream; 1.1093 + if (emptyStream && indexInFolder == 0) 1.1094 + { 1.1095 + FileIndexToFolderIndexMap.Add(kNumNoIndex); 1.1096 + continue; 1.1097 + } 1.1098 + if (indexInFolder == 0) 1.1099 + { 1.1100 + // v3.13 incorrectly worked with empty folders 1.1101 + // v4.07: Loop for skipping empty folders 1.1102 + for (;;) 1.1103 + { 1.1104 + if (folderIndex >= Folders.Size()) 1.1105 + ThrowIncorrect(); 1.1106 + FolderStartFileIndex.Add(i); // check it 1.1107 + if (NumUnpackStreamsVector[folderIndex] != 0) 1.1108 + break; 1.1109 + folderIndex++; 1.1110 + } 1.1111 + } 1.1112 + FileIndexToFolderIndexMap.Add(folderIndex); 1.1113 + if (emptyStream) 1.1114 + continue; 1.1115 + indexInFolder++; 1.1116 + if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) 1.1117 + { 1.1118 + folderIndex++; 1.1119 + indexInFolder = 0; 1.1120 + } 1.1121 + } 1.1122 +} 1.1123 + 1.1124 +HRESULT CInArchive::ReadDatabase2( 1.1125 + DECL_EXTERNAL_CODECS_LOC_VARS 1.1126 + CArchiveDatabaseEx &db 1.1127 + #ifndef _NO_CRYPTO 1.1128 + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined 1.1129 + #endif 1.1130 + ) 1.1131 +{ 1.1132 + db.Clear(); 1.1133 + db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; 1.1134 + 1.1135 + db.ArchiveInfo.Version.Major = _header[6]; 1.1136 + db.ArchiveInfo.Version.Minor = _header[7]; 1.1137 + 1.1138 + if (db.ArchiveInfo.Version.Major != kMajorVersion) 1.1139 + ThrowUnsupportedVersion(); 1.1140 + 1.1141 + UInt32 crcFromArchive = Get32(_header + 8); 1.1142 + UInt64 nextHeaderOffset = Get64(_header + 0xC); 1.1143 + UInt64 nextHeaderSize = Get64(_header + 0x14); 1.1144 + UInt32 nextHeaderCRC = Get32(_header + 0x1C); 1.1145 + UInt32 crc = CrcCalc(_header + 0xC, 20); 1.1146 + 1.1147 + #ifdef FORMAT_7Z_RECOVERY 1.1148 + if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) 1.1149 + { 1.1150 + UInt64 cur, cur2; 1.1151 + RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); 1.1152 + const int kCheckSize = 500; 1.1153 + Byte buf[kCheckSize]; 1.1154 + RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); 1.1155 + int checkSize = kCheckSize; 1.1156 + if (cur2 - cur < kCheckSize) 1.1157 + checkSize = (int)(cur2 - cur); 1.1158 + RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); 1.1159 + 1.1160 + RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); 1.1161 + 1.1162 + int i; 1.1163 + for (i = (int)checkSize - 2; i >= 0; i--) 1.1164 + if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) 1.1165 + break; 1.1166 + if (i < 0) 1.1167 + return S_FALSE; 1.1168 + nextHeaderSize = checkSize - i; 1.1169 + nextHeaderOffset = cur2 - cur + i; 1.1170 + nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); 1.1171 + RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); 1.1172 + } 1.1173 + #endif 1.1174 + 1.1175 + #ifdef FORMAT_7Z_RECOVERY 1.1176 + crcFromArchive = crc; 1.1177 + #endif 1.1178 + 1.1179 + db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; 1.1180 + 1.1181 + if (crc != crcFromArchive) 1.1182 + ThrowIncorrect(); 1.1183 + 1.1184 + if (nextHeaderSize == 0) 1.1185 + return S_OK; 1.1186 + 1.1187 + if (nextHeaderSize > (UInt64)0xFFFFFFFF) 1.1188 + return S_FALSE; 1.1189 + 1.1190 + RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); 1.1191 + 1.1192 + CByteBuffer buffer2; 1.1193 + buffer2.SetCapacity((size_t)nextHeaderSize); 1.1194 + 1.1195 + RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); 1.1196 + HeadersSize += kHeaderSize + nextHeaderSize; 1.1197 + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; 1.1198 + 1.1199 + if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) 1.1200 + ThrowIncorrect(); 1.1201 + 1.1202 + CStreamSwitch streamSwitch; 1.1203 + streamSwitch.Set(this, buffer2); 1.1204 + 1.1205 + CObjectVector<CByteBuffer> dataVector; 1.1206 + 1.1207 + UInt64 type = ReadID(); 1.1208 + if (type != NID::kHeader) 1.1209 + { 1.1210 + if (type != NID::kEncodedHeader) 1.1211 + ThrowIncorrect(); 1.1212 + HRESULT result = ReadAndDecodePackedStreams( 1.1213 + EXTERNAL_CODECS_LOC_VARS 1.1214 + db.ArchiveInfo.StartPositionAfterHeader, 1.1215 + db.ArchiveInfo.DataStartPosition2, 1.1216 + dataVector 1.1217 + #ifndef _NO_CRYPTO 1.1218 + , getTextPassword, passwordIsDefined 1.1219 + #endif 1.1220 + ); 1.1221 + RINOK(result); 1.1222 + if (dataVector.Size() == 0) 1.1223 + return S_OK; 1.1224 + if (dataVector.Size() > 1) 1.1225 + ThrowIncorrect(); 1.1226 + streamSwitch.Remove(); 1.1227 + streamSwitch.Set(this, dataVector.Front()); 1.1228 + if (ReadID() != NID::kHeader) 1.1229 + ThrowIncorrect(); 1.1230 + } 1.1231 + 1.1232 + db.HeadersSize = HeadersSize; 1.1233 + 1.1234 + return ReadHeader( 1.1235 + EXTERNAL_CODECS_LOC_VARS 1.1236 + db 1.1237 + #ifndef _NO_CRYPTO 1.1238 + , getTextPassword, passwordIsDefined 1.1239 + #endif 1.1240 + ); 1.1241 +} 1.1242 + 1.1243 +HRESULT CInArchive::ReadDatabase( 1.1244 + DECL_EXTERNAL_CODECS_LOC_VARS 1.1245 + CArchiveDatabaseEx &db 1.1246 + #ifndef _NO_CRYPTO 1.1247 + , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined 1.1248 + #endif 1.1249 + ) 1.1250 +{ 1.1251 + try 1.1252 + { 1.1253 + return ReadDatabase2( 1.1254 + EXTERNAL_CODECS_LOC_VARS db 1.1255 + #ifndef _NO_CRYPTO 1.1256 + , getTextPassword, passwordIsDefined 1.1257 + #endif 1.1258 + ); 1.1259 + } 1.1260 + catch(CInArchiveException &) { return S_FALSE; } 1.1261 +} 1.1262 + 1.1263 +}}