Index: third_party/lzma/v4_65/files/CPP/7zip/Archive/7z/7zIn.cpp |
diff --git a/third_party/lzma/v4_65/files/CPP/7zip/Archive/7z/7zIn.cpp b/third_party/lzma/v4_65/files/CPP/7zip/Archive/7z/7zIn.cpp |
deleted file mode 100644 |
index ab78eeaeec5da6a0e2e26c217aaa83f728cb104b..0000000000000000000000000000000000000000 |
--- a/third_party/lzma/v4_65/files/CPP/7zip/Archive/7z/7zIn.cpp |
+++ /dev/null |
@@ -1,1260 +0,0 @@ |
-// 7zIn.cpp |
- |
-#include "StdAfx.h" |
- |
-extern "C" |
-{ |
- #include "../../../../C/7zCrc.h" |
- #include "../../../../C/CpuArch.h" |
-} |
- |
-#include "../../Common/StreamObjects.h" |
-#include "../../Common/StreamUtils.h" |
- |
-#include "7zDecode.h" |
-#include "7zIn.h" |
- |
-#define Get16(p) GetUi16(p) |
-#define Get32(p) GetUi32(p) |
-#define Get64(p) GetUi64(p) |
- |
-// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader |
-#ifndef _SFX |
-#define FORMAT_7Z_RECOVERY |
-#endif |
- |
-namespace NArchive { |
-namespace N7z { |
- |
-static void BoolVector_Fill_False(CBoolVector &v, int size) |
-{ |
- v.Clear(); |
- v.Reserve(size); |
- for (int i = 0; i < size; i++) |
- v.Add(false); |
-} |
- |
-static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) |
-{ |
- if (index >= (UInt32)v.Size()) |
- return true; |
- bool res = v[index]; |
- v[index] = true; |
- return res; |
-} |
- |
-bool CFolder::CheckStructure() const |
-{ |
- const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it |
- const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax |
- const int kNumBindsMax = 32; |
- |
- if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) |
- return false; |
- |
- { |
- CBoolVector v; |
- BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); |
- |
- int i; |
- for (i = 0; i < BindPairs.Size(); i++) |
- if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) |
- return false; |
- for (i = 0; i < PackStreams.Size(); i++) |
- if (BoolVector_GetAndSet(v, PackStreams[i])) |
- return false; |
- |
- BoolVector_Fill_False(v, UnpackSizes.Size()); |
- for (i = 0; i < BindPairs.Size(); i++) |
- if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) |
- return false; |
- } |
- |
- UInt32 mask[kMaskSize]; |
- int i; |
- for (i = 0; i < kMaskSize; i++) |
- mask[i] = 0; |
- |
- { |
- CIntVector inStreamToCoder, outStreamToCoder; |
- for (i = 0; i < Coders.Size(); i++) |
- { |
- CNum j; |
- const CCoderInfo &coder = Coders[i]; |
- for (j = 0; j < coder.NumInStreams; j++) |
- inStreamToCoder.Add(i); |
- for (j = 0; j < coder.NumOutStreams; j++) |
- outStreamToCoder.Add(i); |
- } |
- |
- for (i = 0; i < BindPairs.Size(); i++) |
- { |
- const CBindPair &bp = BindPairs[i]; |
- mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); |
- } |
- } |
- |
- for (i = 0; i < kMaskSize; i++) |
- for (int j = 0; j < kMaskSize; j++) |
- if (((1 << j) & mask[i]) != 0) |
- mask[i] |= mask[j]; |
- |
- for (i = 0; i < kMaskSize; i++) |
- if (((1 << i) & mask[i]) != 0) |
- return false; |
- |
- return true; |
-} |
- |
-class CInArchiveException {}; |
- |
-static void ThrowException() { throw CInArchiveException(); } |
-static inline void ThrowEndOfData() { ThrowException(); } |
-static inline void ThrowUnsupported() { ThrowException(); } |
-static inline void ThrowIncorrect() { ThrowException(); } |
-static inline void ThrowUnsupportedVersion() { ThrowException(); } |
- |
-/* |
-class CInArchiveException |
-{ |
-public: |
- enum CCauseType |
- { |
- kUnsupportedVersion = 0, |
- kUnsupported, |
- kIncorrect, |
- kEndOfData, |
- } Cause; |
- CInArchiveException(CCauseType cause): Cause(cause) {}; |
-}; |
- |
-static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } |
-static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } |
-static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } |
-static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } |
-static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } |
-*/ |
- |
-class CStreamSwitch |
-{ |
- CInArchive *_archive; |
- bool _needRemove; |
-public: |
- CStreamSwitch(): _needRemove(false) {} |
- ~CStreamSwitch() { Remove(); } |
- void Remove(); |
- void Set(CInArchive *archive, const Byte *data, size_t size); |
- void Set(CInArchive *archive, const CByteBuffer &byteBuffer); |
- void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); |
-}; |
- |
-void CStreamSwitch::Remove() |
-{ |
- if (_needRemove) |
- { |
- _archive->DeleteByteStream(); |
- _needRemove = false; |
- } |
-} |
- |
-void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) |
-{ |
- Remove(); |
- _archive = archive; |
- _archive->AddByteStream(data, size); |
- _needRemove = true; |
-} |
- |
-void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) |
-{ |
- Set(archive, byteBuffer, byteBuffer.GetCapacity()); |
-} |
- |
-void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) |
-{ |
- Remove(); |
- Byte external = archive->ReadByte(); |
- if (external != 0) |
- { |
- int dataIndex = (int)archive->ReadNum(); |
- if (dataIndex < 0 || dataIndex >= dataVector->Size()) |
- ThrowIncorrect(); |
- Set(archive, (*dataVector)[dataIndex]); |
- } |
-} |
- |
-Byte CInByte2::ReadByte() |
-{ |
- if (_pos >= _size) |
- ThrowEndOfData(); |
- return _buffer[_pos++]; |
-} |
- |
-void CInByte2::ReadBytes(Byte *data, size_t size) |
-{ |
- if (size > _size - _pos) |
- ThrowEndOfData(); |
- for (size_t i = 0; i < size; i++) |
- data[i] = _buffer[_pos++]; |
-} |
- |
-void CInByte2::SkeepData(UInt64 size) |
-{ |
- if (size > _size - _pos) |
- ThrowEndOfData(); |
- _pos += (size_t)size; |
-} |
- |
-void CInByte2::SkeepData() |
-{ |
- SkeepData(ReadNumber()); |
-} |
- |
-UInt64 CInByte2::ReadNumber() |
-{ |
- if (_pos >= _size) |
- ThrowEndOfData(); |
- Byte firstByte = _buffer[_pos++]; |
- Byte mask = 0x80; |
- UInt64 value = 0; |
- for (int i = 0; i < 8; i++) |
- { |
- if ((firstByte & mask) == 0) |
- { |
- UInt64 highPart = firstByte & (mask - 1); |
- value += (highPart << (i * 8)); |
- return value; |
- } |
- if (_pos >= _size) |
- ThrowEndOfData(); |
- value |= ((UInt64)_buffer[_pos++] << (8 * i)); |
- mask >>= 1; |
- } |
- return value; |
-} |
- |
-CNum CInByte2::ReadNum() |
-{ |
- UInt64 value = ReadNumber(); |
- if (value > kNumMax) |
- ThrowUnsupported(); |
- return (CNum)value; |
-} |
- |
-UInt32 CInByte2::ReadUInt32() |
-{ |
- if (_pos + 4 > _size) |
- ThrowEndOfData(); |
- UInt32 res = Get32(_buffer + _pos); |
- _pos += 4; |
- return res; |
-} |
- |
-UInt64 CInByte2::ReadUInt64() |
-{ |
- if (_pos + 8 > _size) |
- ThrowEndOfData(); |
- UInt64 res = Get64(_buffer + _pos); |
- _pos += 8; |
- return res; |
-} |
- |
-void CInByte2::ReadString(UString &s) |
-{ |
- const Byte *buf = _buffer + _pos; |
- size_t rem = (_size - _pos) / 2 * 2; |
- { |
- size_t i; |
- for (i = 0; i < rem; i += 2) |
- if (buf[i] == 0 && buf[i + 1] == 0) |
- break; |
- if (i == rem) |
- ThrowEndOfData(); |
- rem = i; |
- } |
- int len = (int)(rem / 2); |
- if (len < 0 || (size_t)len * 2 != rem) |
- ThrowUnsupported(); |
- wchar_t *p = s.GetBuffer(len); |
- int i; |
- for (i = 0; i < len; i++, buf += 2) |
- p[i] = (wchar_t)Get16(buf); |
- s.ReleaseBuffer(len); |
- _pos += rem + 2; |
-} |
- |
-static inline bool TestSignatureCandidate(const Byte *p) |
-{ |
- for (int i = 0; i < kSignatureSize; i++) |
- if (p[i] != kSignature[i]) |
- return false; |
- return (p[0x1A] == 0 && p[0x1B] == 0); |
-} |
- |
-HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) |
-{ |
- RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); |
- |
- if (TestSignatureCandidate(_header)) |
- return S_OK; |
- |
- CByteBuffer byteBuffer; |
- const UInt32 kBufferSize = (1 << 16); |
- byteBuffer.SetCapacity(kBufferSize); |
- Byte *buffer = byteBuffer; |
- UInt32 numPrevBytes = kHeaderSize - 1; |
- memcpy(buffer, _header + 1, numPrevBytes); |
- UInt64 curTestPos = _arhiveBeginStreamPosition + 1; |
- for (;;) |
- { |
- if (searchHeaderSizeLimit != NULL) |
- if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) |
- break; |
- do |
- { |
- UInt32 numReadBytes = kBufferSize - numPrevBytes; |
- UInt32 processedSize; |
- RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); |
- numPrevBytes += processedSize; |
- if (processedSize == 0) |
- return S_FALSE; |
- } |
- while (numPrevBytes < kHeaderSize); |
- UInt32 numTests = numPrevBytes - kHeaderSize + 1; |
- for (UInt32 pos = 0; pos < numTests; pos++) |
- { |
- for (; buffer[pos] != '7' && pos < numTests; pos++); |
- if (pos == numTests) |
- break; |
- if (TestSignatureCandidate(buffer + pos)) |
- { |
- memcpy(_header, buffer + pos, kHeaderSize); |
- curTestPos += pos; |
- _arhiveBeginStreamPosition = curTestPos; |
- return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); |
- } |
- } |
- curTestPos += numTests; |
- numPrevBytes -= numTests; |
- memmove(buffer, buffer + numTests, numPrevBytes); |
- } |
- return S_FALSE; |
-} |
- |
-// S_FALSE means that file is not archive |
-HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) |
-{ |
- HeadersSize = 0; |
- Close(); |
- RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) |
- RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); |
- _stream = stream; |
- return S_OK; |
-} |
- |
-void CInArchive::Close() |
-{ |
- _stream.Release(); |
-} |
- |
-void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) |
-{ |
- for (;;) |
- { |
- if (ReadID() == NID::kEnd) |
- break; |
- SkeepData(); |
- } |
-} |
- |
-void CInArchive::GetNextFolderItem(CFolder &folder) |
-{ |
- CNum numCoders = ReadNum(); |
- |
- folder.Coders.Clear(); |
- folder.Coders.Reserve((int)numCoders); |
- CNum numInStreams = 0; |
- CNum numOutStreams = 0; |
- CNum i; |
- for (i = 0; i < numCoders; i++) |
- { |
- folder.Coders.Add(CCoderInfo()); |
- CCoderInfo &coder = folder.Coders.Back(); |
- |
- { |
- Byte mainByte = ReadByte(); |
- int idSize = (mainByte & 0xF); |
- Byte longID[15]; |
- ReadBytes(longID, idSize); |
- if (idSize > 8) |
- ThrowUnsupported(); |
- UInt64 id = 0; |
- for (int j = 0; j < idSize; j++) |
- id |= (UInt64)longID[idSize - 1 - j] << (8 * j); |
- coder.MethodID = id; |
- |
- if ((mainByte & 0x10) != 0) |
- { |
- coder.NumInStreams = ReadNum(); |
- coder.NumOutStreams = ReadNum(); |
- } |
- else |
- { |
- coder.NumInStreams = 1; |
- coder.NumOutStreams = 1; |
- } |
- if ((mainByte & 0x20) != 0) |
- { |
- CNum propsSize = ReadNum(); |
- coder.Props.SetCapacity((size_t)propsSize); |
- ReadBytes((Byte *)coder.Props, (size_t)propsSize); |
- } |
- if ((mainByte & 0x80) != 0) |
- ThrowUnsupported(); |
- } |
- numInStreams += coder.NumInStreams; |
- numOutStreams += coder.NumOutStreams; |
- } |
- |
- CNum numBindPairs = numOutStreams - 1; |
- folder.BindPairs.Clear(); |
- folder.BindPairs.Reserve(numBindPairs); |
- for (i = 0; i < numBindPairs; i++) |
- { |
- CBindPair bp; |
- bp.InIndex = ReadNum(); |
- bp.OutIndex = ReadNum(); |
- folder.BindPairs.Add(bp); |
- } |
- |
- if (numInStreams < numBindPairs) |
- ThrowUnsupported(); |
- CNum numPackStreams = numInStreams - numBindPairs; |
- folder.PackStreams.Reserve(numPackStreams); |
- if (numPackStreams == 1) |
- { |
- for (i = 0; i < numInStreams; i++) |
- if (folder.FindBindPairForInStream(i) < 0) |
- { |
- folder.PackStreams.Add(i); |
- break; |
- } |
- if (folder.PackStreams.Size() != 1) |
- ThrowUnsupported(); |
- } |
- else |
- for (i = 0; i < numPackStreams; i++) |
- folder.PackStreams.Add(ReadNum()); |
-} |
- |
-void CInArchive::WaitAttribute(UInt64 attribute) |
-{ |
- for (;;) |
- { |
- UInt64 type = ReadID(); |
- if (type == attribute) |
- return; |
- if (type == NID::kEnd) |
- ThrowIncorrect(); |
- SkeepData(); |
- } |
-} |
- |
-void CInArchive::ReadHashDigests(int numItems, |
- CBoolVector &digestsDefined, |
- CRecordVector<UInt32> &digests) |
-{ |
- ReadBoolVector2(numItems, digestsDefined); |
- digests.Clear(); |
- digests.Reserve(numItems); |
- for (int i = 0; i < numItems; i++) |
- { |
- UInt32 crc = 0; |
- if (digestsDefined[i]) |
- crc = ReadUInt32(); |
- digests.Add(crc); |
- } |
-} |
- |
-void CInArchive::ReadPackInfo( |
- UInt64 &dataOffset, |
- CRecordVector<UInt64> &packSizes, |
- CBoolVector &packCRCsDefined, |
- CRecordVector<UInt32> &packCRCs) |
-{ |
- dataOffset = ReadNumber(); |
- CNum numPackStreams = ReadNum(); |
- |
- WaitAttribute(NID::kSize); |
- packSizes.Clear(); |
- packSizes.Reserve(numPackStreams); |
- for (CNum i = 0; i < numPackStreams; i++) |
- packSizes.Add(ReadNumber()); |
- |
- UInt64 type; |
- for (;;) |
- { |
- type = ReadID(); |
- if (type == NID::kEnd) |
- break; |
- if (type == NID::kCRC) |
- { |
- ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); |
- continue; |
- } |
- SkeepData(); |
- } |
- if (packCRCsDefined.IsEmpty()) |
- { |
- BoolVector_Fill_False(packCRCsDefined, numPackStreams); |
- packCRCs.Reserve(numPackStreams); |
- packCRCs.Clear(); |
- for (CNum i = 0; i < numPackStreams; i++) |
- packCRCs.Add(0); |
- } |
-} |
- |
-void CInArchive::ReadUnpackInfo( |
- const CObjectVector<CByteBuffer> *dataVector, |
- CObjectVector<CFolder> &folders) |
-{ |
- WaitAttribute(NID::kFolder); |
- CNum numFolders = ReadNum(); |
- |
- { |
- CStreamSwitch streamSwitch; |
- streamSwitch.Set(this, dataVector); |
- folders.Clear(); |
- folders.Reserve(numFolders); |
- for (CNum i = 0; i < numFolders; i++) |
- { |
- folders.Add(CFolder()); |
- GetNextFolderItem(folders.Back()); |
- } |
- } |
- |
- WaitAttribute(NID::kCodersUnpackSize); |
- |
- CNum i; |
- for (i = 0; i < numFolders; i++) |
- { |
- CFolder &folder = folders[i]; |
- CNum numOutStreams = folder.GetNumOutStreams(); |
- folder.UnpackSizes.Reserve(numOutStreams); |
- for (CNum j = 0; j < numOutStreams; j++) |
- folder.UnpackSizes.Add(ReadNumber()); |
- } |
- |
- for (;;) |
- { |
- UInt64 type = ReadID(); |
- if (type == NID::kEnd) |
- return; |
- if (type == NID::kCRC) |
- { |
- CBoolVector crcsDefined; |
- CRecordVector<UInt32> crcs; |
- ReadHashDigests(numFolders, crcsDefined, crcs); |
- for (i = 0; i < numFolders; i++) |
- { |
- CFolder &folder = folders[i]; |
- folder.UnpackCRCDefined = crcsDefined[i]; |
- folder.UnpackCRC = crcs[i]; |
- } |
- continue; |
- } |
- SkeepData(); |
- } |
-} |
- |
-void CInArchive::ReadSubStreamsInfo( |
- const CObjectVector<CFolder> &folders, |
- CRecordVector<CNum> &numUnpackStreamsInFolders, |
- CRecordVector<UInt64> &unpackSizes, |
- CBoolVector &digestsDefined, |
- CRecordVector<UInt32> &digests) |
-{ |
- numUnpackStreamsInFolders.Clear(); |
- numUnpackStreamsInFolders.Reserve(folders.Size()); |
- UInt64 type; |
- for (;;) |
- { |
- type = ReadID(); |
- if (type == NID::kNumUnpackStream) |
- { |
- for (int i = 0; i < folders.Size(); i++) |
- numUnpackStreamsInFolders.Add(ReadNum()); |
- continue; |
- } |
- if (type == NID::kCRC || type == NID::kSize) |
- break; |
- if (type == NID::kEnd) |
- break; |
- SkeepData(); |
- } |
- |
- if (numUnpackStreamsInFolders.IsEmpty()) |
- for (int i = 0; i < folders.Size(); i++) |
- numUnpackStreamsInFolders.Add(1); |
- |
- int i; |
- for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) |
- { |
- // v3.13 incorrectly worked with empty folders |
- // v4.07: we check that folder is empty |
- CNum numSubstreams = numUnpackStreamsInFolders[i]; |
- if (numSubstreams == 0) |
- continue; |
- UInt64 sum = 0; |
- for (CNum j = 1; j < numSubstreams; j++) |
- if (type == NID::kSize) |
- { |
- UInt64 size = ReadNumber(); |
- unpackSizes.Add(size); |
- sum += size; |
- } |
- unpackSizes.Add(folders[i].GetUnpackSize() - sum); |
- } |
- if (type == NID::kSize) |
- type = ReadID(); |
- |
- int numDigests = 0; |
- int numDigestsTotal = 0; |
- for (i = 0; i < folders.Size(); i++) |
- { |
- CNum numSubstreams = numUnpackStreamsInFolders[i]; |
- if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) |
- numDigests += numSubstreams; |
- numDigestsTotal += numSubstreams; |
- } |
- |
- for (;;) |
- { |
- if (type == NID::kCRC) |
- { |
- CBoolVector digestsDefined2; |
- CRecordVector<UInt32> digests2; |
- ReadHashDigests(numDigests, digestsDefined2, digests2); |
- int digestIndex = 0; |
- for (i = 0; i < folders.Size(); i++) |
- { |
- CNum numSubstreams = numUnpackStreamsInFolders[i]; |
- const CFolder &folder = folders[i]; |
- if (numSubstreams == 1 && folder.UnpackCRCDefined) |
- { |
- digestsDefined.Add(true); |
- digests.Add(folder.UnpackCRC); |
- } |
- else |
- for (CNum j = 0; j < numSubstreams; j++, digestIndex++) |
- { |
- digestsDefined.Add(digestsDefined2[digestIndex]); |
- digests.Add(digests2[digestIndex]); |
- } |
- } |
- } |
- else if (type == NID::kEnd) |
- { |
- if (digestsDefined.IsEmpty()) |
- { |
- BoolVector_Fill_False(digestsDefined, numDigestsTotal); |
- digests.Clear(); |
- for (int i = 0; i < numDigestsTotal; i++) |
- digests.Add(0); |
- } |
- return; |
- } |
- else |
- SkeepData(); |
- type = ReadID(); |
- } |
-} |
- |
-void CInArchive::ReadStreamsInfo( |
- const CObjectVector<CByteBuffer> *dataVector, |
- UInt64 &dataOffset, |
- CRecordVector<UInt64> &packSizes, |
- CBoolVector &packCRCsDefined, |
- CRecordVector<UInt32> &packCRCs, |
- CObjectVector<CFolder> &folders, |
- CRecordVector<CNum> &numUnpackStreamsInFolders, |
- CRecordVector<UInt64> &unpackSizes, |
- CBoolVector &digestsDefined, |
- CRecordVector<UInt32> &digests) |
-{ |
- for (;;) |
- { |
- UInt64 type = ReadID(); |
- if (type > ((UInt32)1 << 30)) |
- ThrowIncorrect(); |
- switch((UInt32)type) |
- { |
- case NID::kEnd: |
- return; |
- case NID::kPackInfo: |
- { |
- ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); |
- break; |
- } |
- case NID::kUnpackInfo: |
- { |
- ReadUnpackInfo(dataVector, folders); |
- break; |
- } |
- case NID::kSubStreamsInfo: |
- { |
- ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, |
- unpackSizes, digestsDefined, digests); |
- break; |
- } |
- default: |
- ThrowIncorrect(); |
- } |
- } |
-} |
- |
-void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) |
-{ |
- v.Clear(); |
- v.Reserve(numItems); |
- Byte b = 0; |
- Byte mask = 0; |
- for (int i = 0; i < numItems; i++) |
- { |
- if (mask == 0) |
- { |
- b = ReadByte(); |
- mask = 0x80; |
- } |
- v.Add((b & mask) != 0); |
- mask >>= 1; |
- } |
-} |
- |
-void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) |
-{ |
- Byte allAreDefined = ReadByte(); |
- if (allAreDefined == 0) |
- { |
- ReadBoolVector(numItems, v); |
- return; |
- } |
- v.Clear(); |
- v.Reserve(numItems); |
- for (int i = 0; i < numItems; i++) |
- v.Add(true); |
-} |
- |
-void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, |
- CUInt64DefVector &v, int numFiles) |
-{ |
- ReadBoolVector2(numFiles, v.Defined); |
- |
- CStreamSwitch streamSwitch; |
- streamSwitch.Set(this, &dataVector); |
- v.Values.Reserve(numFiles); |
- |
- for (int i = 0; i < numFiles; i++) |
- { |
- UInt64 t = 0; |
- if (v.Defined[i]) |
- t = ReadUInt64(); |
- v.Values.Add(t); |
- } |
-} |
- |
-HRESULT CInArchive::ReadAndDecodePackedStreams( |
- DECL_EXTERNAL_CODECS_LOC_VARS |
- UInt64 baseOffset, |
- UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector |
- #ifndef _NO_CRYPTO |
- , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined |
- #endif |
- ) |
-{ |
- CRecordVector<UInt64> packSizes; |
- CBoolVector packCRCsDefined; |
- CRecordVector<UInt32> packCRCs; |
- CObjectVector<CFolder> folders; |
- |
- CRecordVector<CNum> numUnpackStreamsInFolders; |
- CRecordVector<UInt64> unpackSizes; |
- CBoolVector digestsDefined; |
- CRecordVector<UInt32> digests; |
- |
- ReadStreamsInfo(NULL, |
- dataOffset, |
- packSizes, |
- packCRCsDefined, |
- packCRCs, |
- folders, |
- numUnpackStreamsInFolders, |
- unpackSizes, |
- digestsDefined, |
- digests); |
- |
- // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; |
- |
- CNum packIndex = 0; |
- CDecoder decoder( |
- #ifdef _ST_MODE |
- false |
- #else |
- true |
- #endif |
- ); |
- UInt64 dataStartPos = baseOffset + dataOffset; |
- for (int i = 0; i < folders.Size(); i++) |
- { |
- const CFolder &folder = folders[i]; |
- dataVector.Add(CByteBuffer()); |
- CByteBuffer &data = dataVector.Back(); |
- UInt64 unpackSize64 = folder.GetUnpackSize(); |
- size_t unpackSize = (size_t)unpackSize64; |
- if (unpackSize != unpackSize64) |
- ThrowUnsupported(); |
- data.SetCapacity(unpackSize); |
- |
- CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; |
- CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; |
- outStreamSpec->Init(data, unpackSize); |
- |
- HRESULT result = decoder.Decode( |
- EXTERNAL_CODECS_LOC_VARS |
- _stream, dataStartPos, |
- &packSizes[packIndex], folder, outStream, NULL |
- #ifndef _NO_CRYPTO |
- , getTextPassword, passwordIsDefined |
- #endif |
- #ifdef COMPRESS_MT |
- , false, 1 |
- #endif |
- ); |
- RINOK(result); |
- |
- if (folder.UnpackCRCDefined) |
- if (CrcCalc(data, unpackSize) != folder.UnpackCRC) |
- ThrowIncorrect(); |
- for (int j = 0; j < folder.PackStreams.Size(); j++) |
- { |
- UInt64 packSize = packSizes[packIndex++]; |
- dataStartPos += packSize; |
- HeadersSize += packSize; |
- } |
- } |
- return S_OK; |
-} |
- |
-HRESULT CInArchive::ReadHeader( |
- DECL_EXTERNAL_CODECS_LOC_VARS |
- CArchiveDatabaseEx &db |
- #ifndef _NO_CRYPTO |
- , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined |
- #endif |
- ) |
-{ |
- UInt64 type = ReadID(); |
- |
- if (type == NID::kArchiveProperties) |
- { |
- ReadArchiveProperties(db.ArchiveInfo); |
- type = ReadID(); |
- } |
- |
- CObjectVector<CByteBuffer> dataVector; |
- |
- if (type == NID::kAdditionalStreamsInfo) |
- { |
- HRESULT result = ReadAndDecodePackedStreams( |
- EXTERNAL_CODECS_LOC_VARS |
- db.ArchiveInfo.StartPositionAfterHeader, |
- db.ArchiveInfo.DataStartPosition2, |
- dataVector |
- #ifndef _NO_CRYPTO |
- , getTextPassword, passwordIsDefined |
- #endif |
- ); |
- RINOK(result); |
- db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; |
- type = ReadID(); |
- } |
- |
- CRecordVector<UInt64> unpackSizes; |
- CBoolVector digestsDefined; |
- CRecordVector<UInt32> digests; |
- |
- if (type == NID::kMainStreamsInfo) |
- { |
- ReadStreamsInfo(&dataVector, |
- db.ArchiveInfo.DataStartPosition, |
- db.PackSizes, |
- db.PackCRCsDefined, |
- db.PackCRCs, |
- db.Folders, |
- db.NumUnpackStreamsVector, |
- unpackSizes, |
- digestsDefined, |
- digests); |
- db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; |
- type = ReadID(); |
- } |
- else |
- { |
- for (int i = 0; i < db.Folders.Size(); i++) |
- { |
- db.NumUnpackStreamsVector.Add(1); |
- CFolder &folder = db.Folders[i]; |
- unpackSizes.Add(folder.GetUnpackSize()); |
- digestsDefined.Add(folder.UnpackCRCDefined); |
- digests.Add(folder.UnpackCRC); |
- } |
- } |
- |
- db.Files.Clear(); |
- |
- if (type == NID::kEnd) |
- return S_OK; |
- if (type != NID::kFilesInfo) |
- ThrowIncorrect(); |
- |
- CNum numFiles = ReadNum(); |
- db.Files.Reserve(numFiles); |
- CNum i; |
- for (i = 0; i < numFiles; i++) |
- db.Files.Add(CFileItem()); |
- |
- db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); |
- if (!db.PackSizes.IsEmpty()) |
- db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); |
- if (numFiles > 0 && !digests.IsEmpty()) |
- db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); |
- |
- CBoolVector emptyStreamVector; |
- BoolVector_Fill_False(emptyStreamVector, (int)numFiles); |
- CBoolVector emptyFileVector; |
- CBoolVector antiFileVector; |
- CNum numEmptyStreams = 0; |
- |
- for (;;) |
- { |
- UInt64 type = ReadID(); |
- if (type == NID::kEnd) |
- break; |
- UInt64 size = ReadNumber(); |
- size_t ppp = _inByteBack->_pos; |
- bool addPropIdToList = true; |
- bool isKnownType = true; |
- if (type > ((UInt32)1 << 30)) |
- isKnownType = false; |
- else switch((UInt32)type) |
- { |
- case NID::kName: |
- { |
- CStreamSwitch streamSwitch; |
- streamSwitch.Set(this, &dataVector); |
- for (int i = 0; i < db.Files.Size(); i++) |
- _inByteBack->ReadString(db.Files[i].Name); |
- break; |
- } |
- case NID::kWinAttributes: |
- { |
- CBoolVector boolVector; |
- ReadBoolVector2(db.Files.Size(), boolVector); |
- CStreamSwitch streamSwitch; |
- streamSwitch.Set(this, &dataVector); |
- for (i = 0; i < numFiles; i++) |
- { |
- CFileItem &file = db.Files[i]; |
- file.AttribDefined = boolVector[i]; |
- if (file.AttribDefined) |
- file.Attrib = ReadUInt32(); |
- } |
- break; |
- } |
- case NID::kEmptyStream: |
- { |
- ReadBoolVector(numFiles, emptyStreamVector); |
- for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) |
- if (emptyStreamVector[i]) |
- numEmptyStreams++; |
- |
- BoolVector_Fill_False(emptyFileVector, numEmptyStreams); |
- BoolVector_Fill_False(antiFileVector, numEmptyStreams); |
- |
- break; |
- } |
- case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; |
- case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; |
- case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; |
- case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; |
- case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; |
- case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; |
- case NID::kDummy: |
- { |
- for (UInt64 j = 0; j < size; j++) |
- if (ReadByte() != 0) |
- ThrowIncorrect(); |
- addPropIdToList = false; |
- break; |
- } |
- default: |
- addPropIdToList = isKnownType = false; |
- } |
- if (isKnownType) |
- { |
- if(addPropIdToList) |
- db.ArchiveInfo.FileInfoPopIDs.Add(type); |
- } |
- else |
- SkeepData(size); |
- bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || |
- db.ArchiveInfo.Version.Minor > 2); |
- if (checkRecordsSize && _inByteBack->_pos - ppp != size) |
- ThrowIncorrect(); |
- } |
- |
- CNum emptyFileIndex = 0; |
- CNum sizeIndex = 0; |
- |
- CNum numAntiItems = 0; |
- for (i = 0; i < numEmptyStreams; i++) |
- if (antiFileVector[i]) |
- numAntiItems++; |
- |
- for (i = 0; i < numFiles; i++) |
- { |
- CFileItem &file = db.Files[i]; |
- bool isAnti; |
- file.HasStream = !emptyStreamVector[i]; |
- if (file.HasStream) |
- { |
- file.IsDir = false; |
- isAnti = false; |
- file.Size = unpackSizes[sizeIndex]; |
- file.Crc = digests[sizeIndex]; |
- file.CrcDefined = digestsDefined[sizeIndex]; |
- sizeIndex++; |
- } |
- else |
- { |
- file.IsDir = !emptyFileVector[emptyFileIndex]; |
- isAnti = antiFileVector[emptyFileIndex]; |
- emptyFileIndex++; |
- file.Size = 0; |
- file.CrcDefined = false; |
- } |
- if (numAntiItems != 0) |
- db.IsAnti.Add(isAnti); |
- } |
- return S_OK; |
-} |
- |
- |
-void CArchiveDatabaseEx::FillFolderStartPackStream() |
-{ |
- FolderStartPackStreamIndex.Clear(); |
- FolderStartPackStreamIndex.Reserve(Folders.Size()); |
- CNum startPos = 0; |
- for (int i = 0; i < Folders.Size(); i++) |
- { |
- FolderStartPackStreamIndex.Add(startPos); |
- startPos += (CNum)Folders[i].PackStreams.Size(); |
- } |
-} |
- |
-void CArchiveDatabaseEx::FillStartPos() |
-{ |
- PackStreamStartPositions.Clear(); |
- PackStreamStartPositions.Reserve(PackSizes.Size()); |
- UInt64 startPos = 0; |
- for (int i = 0; i < PackSizes.Size(); i++) |
- { |
- PackStreamStartPositions.Add(startPos); |
- startPos += PackSizes[i]; |
- } |
-} |
- |
-void CArchiveDatabaseEx::FillFolderStartFileIndex() |
-{ |
- FolderStartFileIndex.Clear(); |
- FolderStartFileIndex.Reserve(Folders.Size()); |
- FileIndexToFolderIndexMap.Clear(); |
- FileIndexToFolderIndexMap.Reserve(Files.Size()); |
- |
- int folderIndex = 0; |
- CNum indexInFolder = 0; |
- for (int i = 0; i < Files.Size(); i++) |
- { |
- const CFileItem &file = Files[i]; |
- bool emptyStream = !file.HasStream; |
- if (emptyStream && indexInFolder == 0) |
- { |
- FileIndexToFolderIndexMap.Add(kNumNoIndex); |
- continue; |
- } |
- if (indexInFolder == 0) |
- { |
- // v3.13 incorrectly worked with empty folders |
- // v4.07: Loop for skipping empty folders |
- for (;;) |
- { |
- if (folderIndex >= Folders.Size()) |
- ThrowIncorrect(); |
- FolderStartFileIndex.Add(i); // check it |
- if (NumUnpackStreamsVector[folderIndex] != 0) |
- break; |
- folderIndex++; |
- } |
- } |
- FileIndexToFolderIndexMap.Add(folderIndex); |
- if (emptyStream) |
- continue; |
- indexInFolder++; |
- if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) |
- { |
- folderIndex++; |
- indexInFolder = 0; |
- } |
- } |
-} |
- |
-HRESULT CInArchive::ReadDatabase2( |
- DECL_EXTERNAL_CODECS_LOC_VARS |
- CArchiveDatabaseEx &db |
- #ifndef _NO_CRYPTO |
- , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined |
- #endif |
- ) |
-{ |
- db.Clear(); |
- db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; |
- |
- db.ArchiveInfo.Version.Major = _header[6]; |
- db.ArchiveInfo.Version.Minor = _header[7]; |
- |
- if (db.ArchiveInfo.Version.Major != kMajorVersion) |
- ThrowUnsupportedVersion(); |
- |
- UInt32 crcFromArchive = Get32(_header + 8); |
- UInt64 nextHeaderOffset = Get64(_header + 0xC); |
- UInt64 nextHeaderSize = Get64(_header + 0x14); |
- UInt32 nextHeaderCRC = Get32(_header + 0x1C); |
- UInt32 crc = CrcCalc(_header + 0xC, 20); |
- |
- #ifdef FORMAT_7Z_RECOVERY |
- if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) |
- { |
- UInt64 cur, cur2; |
- RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); |
- const int kCheckSize = 500; |
- Byte buf[kCheckSize]; |
- RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); |
- int checkSize = kCheckSize; |
- if (cur2 - cur < kCheckSize) |
- checkSize = (int)(cur2 - cur); |
- RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); |
- |
- RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); |
- |
- int i; |
- for (i = (int)checkSize - 2; i >= 0; i--) |
- if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) |
- break; |
- if (i < 0) |
- return S_FALSE; |
- nextHeaderSize = checkSize - i; |
- nextHeaderOffset = cur2 - cur + i; |
- nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); |
- RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); |
- } |
- #endif |
- |
- #ifdef FORMAT_7Z_RECOVERY |
- crcFromArchive = crc; |
- #endif |
- |
- db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; |
- |
- if (crc != crcFromArchive) |
- ThrowIncorrect(); |
- |
- if (nextHeaderSize == 0) |
- return S_OK; |
- |
- if (nextHeaderSize > (UInt64)0xFFFFFFFF) |
- return S_FALSE; |
- |
- RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); |
- |
- CByteBuffer buffer2; |
- buffer2.SetCapacity((size_t)nextHeaderSize); |
- |
- RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); |
- HeadersSize += kHeaderSize + nextHeaderSize; |
- db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; |
- |
- if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) |
- ThrowIncorrect(); |
- |
- CStreamSwitch streamSwitch; |
- streamSwitch.Set(this, buffer2); |
- |
- CObjectVector<CByteBuffer> dataVector; |
- |
- UInt64 type = ReadID(); |
- if (type != NID::kHeader) |
- { |
- if (type != NID::kEncodedHeader) |
- ThrowIncorrect(); |
- HRESULT result = ReadAndDecodePackedStreams( |
- EXTERNAL_CODECS_LOC_VARS |
- db.ArchiveInfo.StartPositionAfterHeader, |
- db.ArchiveInfo.DataStartPosition2, |
- dataVector |
- #ifndef _NO_CRYPTO |
- , getTextPassword, passwordIsDefined |
- #endif |
- ); |
- RINOK(result); |
- if (dataVector.Size() == 0) |
- return S_OK; |
- if (dataVector.Size() > 1) |
- ThrowIncorrect(); |
- streamSwitch.Remove(); |
- streamSwitch.Set(this, dataVector.Front()); |
- if (ReadID() != NID::kHeader) |
- ThrowIncorrect(); |
- } |
- |
- db.HeadersSize = HeadersSize; |
- |
- return ReadHeader( |
- EXTERNAL_CODECS_LOC_VARS |
- db |
- #ifndef _NO_CRYPTO |
- , getTextPassword, passwordIsDefined |
- #endif |
- ); |
-} |
- |
-HRESULT CInArchive::ReadDatabase( |
- DECL_EXTERNAL_CODECS_LOC_VARS |
- CArchiveDatabaseEx &db |
- #ifndef _NO_CRYPTO |
- , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined |
- #endif |
- ) |
-{ |
- try |
- { |
- return ReadDatabase2( |
- EXTERNAL_CODECS_LOC_VARS db |
- #ifndef _NO_CRYPTO |
- , getTextPassword, passwordIsDefined |
- #endif |
- ); |
- } |
- catch(CInArchiveException &) { return S_FALSE; } |
-} |
- |
-}} |