summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp')
-rw-r--r--src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp1679
1 files changed, 0 insertions, 1679 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp
deleted file mode 100644
index 28ec5e083..000000000
--- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp
+++ /dev/null
@@ -1,1679 +0,0 @@
-// 7zIn.cpp
-
-#include "StdAfx.h"
-
-#ifdef _WIN32
-#include <wchar.h>
-#else
-#include <ctype.h>
-#endif
-
-#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
-
-using namespace NWindows;
-using namespace NCOM;
-
-namespace NArchive {
-namespace N7z {
-
-static const UInt32 k_LZMA2 = 0x21;
-static const UInt32 k_LZMA = 0x030101;
-
-static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
-{
- v.ClearAndSetSize(size);
- bool *p = &v[0];
- for (unsigned i = 0; i < size; i++)
- p[i] = 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(unsigned numUnpackSizes) const
-{
- const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it
- const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax
- const unsigned kNumBindsMax = 32;
-
- if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)
- return false;
-
- {
- CBoolVector v;
- BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());
-
- unsigned 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, numUnpackSizes);
- for (i = 0; i < BindPairs.Size(); i++)
- if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))
- return false;
- }
-
- UInt32 mask[kMaskSize];
- unsigned i;
- for (i = 0; i < kMaskSize; i++)
- mask[i] = 0;
-
- {
- CUIntVector 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 (unsigned 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 {};
-class CUnsupportedFeatureException: public CInArchiveException {};
-
-static void ThrowException() { throw CInArchiveException(); }
-static inline void ThrowEndOfData() { ThrowException(); }
-static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); }
-static inline void ThrowIncorrect() { ThrowException(); }
-
-class CStreamSwitch
-{
- CInArchive *_archive;
- bool _needRemove;
- bool _needUpdatePos;
-public:
- CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {}
- ~CStreamSwitch() { Remove(); }
- void Remove();
- void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos);
- void Set(CInArchive *archive, const CByteBuffer &byteBuffer);
- void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);
-};
-
-void CStreamSwitch::Remove()
-{
- if (_needRemove)
- {
- if (_archive->_inByteBack->GetRem() != 0)
- _archive->ThereIsHeaderError = true;
- _archive->DeleteByteStream(_needUpdatePos);
- _needRemove = false;
- }
-}
-
-void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos)
-{
- Remove();
- _archive = archive;
- _archive->AddByteStream(data, size);
- _needRemove = true;
- _needUpdatePos = needUpdatePos;
-}
-
-void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)
-{
- Set(archive, byteBuffer, byteBuffer.Size(), false);
-}
-
-void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)
-{
- Remove();
- Byte external = archive->ReadByte();
- if (external != 0)
- {
- CNum dataIndex = archive->ReadNum();
- if (dataIndex >= dataVector->Size())
- ThrowIncorrect();
- Set(archive, (*dataVector)[dataIndex]);
- }
-}
-
-void CInArchive::AddByteStream(const Byte *buf, size_t size)
-{
- if (_numInByteBufs == kNumBufLevelsMax)
- ThrowIncorrect();
- _inByteBack = &_inByteVector[_numInByteBufs++];
- _inByteBack->Init(buf, size);
-}
-
-
-Byte CInByte2::ReadByte()
-{
- if (_pos >= _size)
- ThrowEndOfData();
- return _buffer[_pos++];
-}
-
-void CInByte2::ReadBytes(Byte *data, size_t size)
-{
- if (size > _size - _pos)
- ThrowEndOfData();
- memcpy(data, _buffer + _pos, size);
- _pos += size;
-}
-
-void CInByte2::SkipData(UInt64 size)
-{
- if (size > _size - _pos)
- ThrowEndOfData();
- _pos += (size_t)size;
-}
-
-void CInByte2::SkipData()
-{
- SkipData(ReadNumber());
-}
-
-static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
-{
- if (size == 0)
- {
- processed = 0;
- return 0;
- }
- Byte firstByte = *p++;
- size--;
- if ((firstByte & 0x80) == 0)
- {
- processed = 1;
- return firstByte;
- }
- Byte mask = 0x40;
- if (size == 0)
- {
- processed = 0;
- return 0;
- }
- UInt64 value = (UInt64)*p;
- p++;
- size--;
- for (unsigned i = 1; i < 8; i++)
- {
- if ((firstByte & mask) == 0)
- {
- UInt64 highPart = firstByte & (mask - 1);
- value += (highPart << (i * 8));
- processed = i + 1;
- return value;
- }
- if (size == 0)
- {
- processed = 0;
- return 0;
- }
- value |= ((UInt64)*p << (i * 8));
- p++;
- size--;
- mask >>= 1;
- }
- processed = 9;
- return value;
-}
-
-UInt64 CInByte2::ReadNumber()
-{
- size_t processed;
- UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed);
- if (processed == 0)
- ThrowEndOfData();
- _pos += processed;
- return res;
-}
-
-CNum CInByte2::ReadNum()
-{
- /*
- if (_pos < _size)
- {
- Byte val = _buffer[_pos];
- if ((unsigned)val < 0x80)
- {
- _pos++;
- return (unsigned)val;
- }
- }
- */
- 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;
-}
-
-#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false;
-
-static inline bool TestSignature(const Byte *p)
-{
- CHECK_SIGNATURE
- return CrcCalc(p + 12, 20) == Get32(p + 8);
-}
-
-#ifdef FORMAT_7Z_RECOVERY
-static inline bool TestSignature2(const Byte *p)
-{
- CHECK_SIGNATURE;
- if (CrcCalc(p + 12, 20) == Get32(p + 8))
- return true;
- for (unsigned i = 8; i < kHeaderSize; i++)
- if (p[i] != 0)
- return false;
- return (p[6] != 0 || p[7] != 0);
-}
-#else
-#define TestSignature2(p) TestSignature(p)
-#endif
-
-HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
-{
- RINOK(ReadStream_FALSE(stream, _header, kHeaderSize));
-
- if (TestSignature2(_header))
- return S_OK;
- if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
- return S_FALSE;
-
- const UInt32 kBufSize = 1 << 15;
- CByteArr buf(kBufSize);
- memcpy(buf, _header, kHeaderSize);
- UInt64 offset = 0;
-
- for (;;)
- {
- UInt32 readSize = kBufSize - kHeaderSize;
- {
- UInt64 rem = *searchHeaderSizeLimit - offset;
- if (readSize > rem)
- readSize = (UInt32)rem;
- if (readSize == 0)
- return S_FALSE;
- }
- UInt32 processed = 0;
- RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));
- if (processed == 0)
- return S_FALSE;
- for (UInt32 pos = 0;;)
- {
- const Byte *p = buf + pos + 1;
- const Byte *lim = buf + processed;
- for (; p <= lim; p += 4)
- {
- if (p[0] == '7') break;
- if (p[1] == '7') { p += 1; break; }
- if (p[2] == '7') { p += 2; break; }
- if (p[3] == '7') { p += 3; break; }
- };
- if (p > lim)
- break;
- pos = (UInt32)(p - buf);
- if (TestSignature(p))
- {
- memcpy(_header, p, kHeaderSize);
- _arhiveBeginStreamPosition += offset + pos;
- return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
- }
- }
- offset += processed;
- memmove(buf, buf + processed, kHeaderSize);
- }
-}
-
-// 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(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition))
- RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL))
- RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
- _stream = stream;
- return S_OK;
-}
-
-void CInArchive::Close()
-{
- _numInByteBufs = 0;
- _stream.Release();
- ThereIsHeaderError = false;
-}
-
-void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
-{
- for (;;)
- {
- if (ReadID() == NID::kEnd)
- break;
- SkipData();
- }
-}
-
-// CFolder &folder can be non empty. So we must set all fields
-
-void CInByte2::ParseFolder(CFolder &folder)
-{
- CNum numCoders = ReadNum();
-
- folder.Coders.SetSize(numCoders);
-
- CNum numInStreams = 0;
- CNum numOutStreams = 0;
- CNum i;
- for (i = 0; i < numCoders; i++)
- {
- CCoderInfo &coder = folder.Coders[i];
- {
- Byte mainByte = ReadByte();
- if ((mainByte & 0xC0) != 0)
- ThrowUnsupported();
- unsigned idSize = (mainByte & 0xF);
- if (idSize > 8 || idSize > GetRem())
- ThrowUnsupported();
- const Byte *longID = GetPtr();
- UInt64 id = 0;
- for (unsigned j = 0; j < idSize; j++)
- id = ((id << 8) | longID[j]);
- SkipDataNoCheck(idSize);
- 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.Alloc((size_t)propsSize);
- ReadBytes((Byte *)coder.Props, (size_t)propsSize);
- }
- else
- coder.Props.Free();
- }
- numInStreams += coder.NumInStreams;
- numOutStreams += coder.NumOutStreams;
- }
-
- CNum numBindPairs = numOutStreams - 1;
- folder.BindPairs.SetSize(numBindPairs);
- for (i = 0; i < numBindPairs; i++)
- {
- CBindPair &bp = folder.BindPairs[i];
- bp.InIndex = ReadNum();
- bp.OutIndex = ReadNum();
- }
-
- if (numInStreams < numBindPairs)
- ThrowUnsupported();
- CNum numPackStreams = numInStreams - numBindPairs;
- folder.PackStreams.SetSize(numPackStreams);
- if (numPackStreams == 1)
- {
- for (i = 0; i < numInStreams; i++)
- if (folder.FindBindPairForInStream(i) < 0)
- {
- folder.PackStreams[0] = i;
- break;
- }
- if (i == numInStreams)
- ThrowUnsupported();
- }
- else
- for (i = 0; i < numPackStreams; i++)
- folder.PackStreams[i] = ReadNum();
-}
-
-void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const
-{
- size_t startPos = FoCodersDataOffset[folderIndex];
- CInByte2 inByte;
- inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);
- inByte.ParseFolder(folder);
- if (inByte.GetRem() != 0)
- throw 20120424;
-}
-
-
-void CDatabase::GetPath(unsigned index, UString &path) const
-{
- path.Empty();
- if (!NameOffsets || !NamesBuf)
- return;
-
- size_t offset = NameOffsets[index];
- size_t size = NameOffsets[index + 1] - offset - 1;
-
- if (size >= (1 << 20))
- return;
-
- wchar_t *s = path.GetBuffer((unsigned)size);
-
- const Byte *p = ((const Byte *)NamesBuf + offset * 2);
-
- #if defined(_WIN32) && defined(MY_CPU_LE)
-
- wmemcpy(s, (const wchar_t *)p, size);
-
- #else
-
- for (size_t i = 0; i < size; i++)
- {
- *s = Get16(p);
- p += 2;
- s++;
- }
-
- #endif
-
- path.ReleaseBuffer((unsigned)size);
-}
-
-HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
-{
- PropVariant_Clear(path);
- if (!NameOffsets || !NamesBuf)
- return S_OK;
-
- size_t offset = NameOffsets[index];
- size_t size = NameOffsets[index + 1] - offset;
-
- if (size >= (1 << 14))
- return S_OK;
-
- RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1));
- wchar_t *s = path->bstrVal;
-
- const Byte *p = ((const Byte *)NamesBuf + offset * 2);
-
- for (size_t i = 0; i < size; i++)
- {
- wchar_t c = Get16(p);
- p += 2;
- #if WCHAR_PATH_SEPARATOR != L'/'
- if (c == L'/')
- c = WCHAR_PATH_SEPARATOR;
- #endif
- *s++ = c;
- }
-
- return S_OK;
-
- /*
- unsigned cur = index;
- unsigned size = 0;
-
- for (int i = 0;; i++)
- {
- size_t len = NameOffsets[cur + 1] - NameOffsets[cur];
- size += (unsigned)len;
- if (i > 256 || len > (1 << 14) || size > (1 << 14))
- return PropVarEm_Set_Str(path, "[TOO-LONG]");
- cur = Files[cur].Parent;
- if (cur < 0)
- break;
- }
- size--;
-
- RINOK(PropVarEm_Alloc_Bstr(path, size));
- wchar_t *s = path->bstrVal;
- s += size;
- *s = 0;
- cur = index;
-
- for (;;)
- {
- unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
- const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
- do
- {
- p -= 2;
- --s;
- wchar_t c = Get16(p);
- if (c == '/')
- c = WCHAR_PATH_SEPARATOR;
- *s = c;
- }
- while (--len);
- const CFileItem &file = Files[cur];
- cur = file.Parent;
- if (cur < 0)
- return S_OK;
- *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR);
- }
- */
-}
-
-void CInArchive::WaitId(UInt64 id)
-{
- for (;;)
- {
- UInt64 type = ReadID();
- if (type == id)
- return;
- if (type == NID::kEnd)
- ThrowIncorrect();
- SkipData();
- }
-}
-
-void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
-{
- ReadBoolVector2(numItems, crcs.Defs);
- crcs.Vals.ClearAndSetSize(numItems);
- UInt32 *p = &crcs.Vals[0];
- const bool *defs = &crcs.Defs[0];
- for (unsigned i = 0; i < numItems; i++)
- {
- UInt32 crc = 0;
- if (defs[i])
- crc = ReadUInt32();
- p[i] = crc;
- }
-}
-
-void CInArchive::ReadPackInfo(CFolders &f)
-{
- CNum numPackStreams = ReadNum();
-
- WaitId(NID::kSize);
- f.PackPositions.Alloc(numPackStreams + 1);
- f.NumPackStreams = numPackStreams;
- UInt64 sum = 0;
- for (CNum i = 0; i < numPackStreams; i++)
- {
- f.PackPositions[i] = sum;
- UInt64 packSize = ReadNumber();
- sum += packSize;
- if (sum < packSize)
- ThrowIncorrect();
- }
- f.PackPositions[numPackStreams] = sum;
-
- UInt64 type;
- for (;;)
- {
- type = ReadID();
- if (type == NID::kEnd)
- return;
- if (type == NID::kCRC)
- {
- CUInt32DefVector PackCRCs;
- ReadHashDigests(numPackStreams, PackCRCs);
- continue;
- }
- SkipData();
- }
-}
-
-void CInArchive::ReadUnpackInfo(
- const CObjectVector<CByteBuffer> *dataVector,
- CFolders &folders)
-{
- WaitId(NID::kFolder);
- CNum numFolders = ReadNum();
-
- CNum numCodersOutStreams = 0;
- {
- CStreamSwitch streamSwitch;
- streamSwitch.Set(this, dataVector);
- const Byte *startBufPtr = _inByteBack->GetPtr();
- folders.NumFolders = numFolders;
-
- folders.FoStartPackStreamIndex.Alloc(numFolders + 1);
- folders.FoToMainUnpackSizeIndex.Alloc(numFolders);
- folders.FoCodersDataOffset.Alloc(numFolders + 1);
- folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
-
- CRecordVector<bool> InStreamUsed;
- CRecordVector<bool> OutStreamUsed;
-
- CNum packStreamIndex = 0;
- CNum fo;
- CInByte2 *inByte = _inByteBack;
- for (fo = 0; fo < numFolders; fo++)
- {
- UInt32 numOutStreams = 0;
- UInt32 indexOfMainStream = 0;
- UInt32 numPackStreams = 0;
- folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
-
- numOutStreams = 0;
- CNum numInStreams = 0;
- CNum numCoders = inByte->ReadNum();
- for (CNum ci = 0; ci < numCoders; ci++)
- {
- Byte mainByte = inByte->ReadByte();
- if ((mainByte & 0xC0) != 0)
- ThrowUnsupported();
- unsigned idSize = (mainByte & 0xF);
- if (idSize > 8)
- ThrowUnsupported();
- if (idSize > inByte->GetRem())
- ThrowEndOfData();
- const Byte *longID = inByte->GetPtr();
- UInt64 id = 0;
- for (unsigned j = 0; j < idSize; j++)
- id = ((id << 8) | longID[j]);
- inByte->SkipDataNoCheck(idSize);
- if (folders.ParsedMethods.IDs.Size() < 128)
- folders.ParsedMethods.IDs.AddToUniqueSorted(id);
- CNum coderInStreams = 1;
- CNum coderOutStreams = 1;
- if ((mainByte & 0x10) != 0)
- {
- coderInStreams = inByte->ReadNum();
- coderOutStreams = inByte->ReadNum();
- }
- numInStreams += coderInStreams;
- if (numInStreams < coderInStreams)
- ThrowUnsupported();
- numOutStreams += coderOutStreams;
- if (numOutStreams < coderOutStreams)
- ThrowUnsupported();
- if ((mainByte & 0x20) != 0)
- {
- CNum propsSize = inByte->ReadNum();
- if (propsSize > inByte->GetRem())
- ThrowEndOfData();
- if (id == k_LZMA2 && propsSize == 1)
- {
- Byte v = *_inByteBack->GetPtr();
- if (folders.ParsedMethods.Lzma2Prop < v)
- folders.ParsedMethods.Lzma2Prop = v;
- }
- else if (id == k_LZMA && propsSize == 5)
- {
- UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1);
- if (folders.ParsedMethods.LzmaDic < dicSize)
- folders.ParsedMethods.LzmaDic = dicSize;
- }
- inByte->SkipDataNoCheck((size_t)propsSize);
- }
- }
-
- if (numOutStreams == 1 && numInStreams == 1)
- {
- indexOfMainStream = 0;
- numPackStreams = 1;
- }
- else
- {
- UInt32 i;
- if (numOutStreams == 0)
- ThrowUnsupported();
- CNum numBindPairs = numOutStreams - 1;
- if (numInStreams < numBindPairs)
- ThrowUnsupported();
- if (numInStreams >= 256 || numOutStreams >= 256)
- ThrowUnsupported();
-
- InStreamUsed.ClearAndSetSize(numInStreams);
- for (i = 0; i < numInStreams; i++)
- InStreamUsed[i] = false;
-
- OutStreamUsed.ClearAndSetSize(numOutStreams);
- for (i = 0; i < numOutStreams; i++)
- OutStreamUsed[i] = false;
-
- for (i = 0; i < numBindPairs; i++)
- {
- CNum index = ReadNum();
- if (index >= numInStreams || InStreamUsed[index])
- ThrowUnsupported();
- InStreamUsed[index] = true;
- index = ReadNum();
- if (index >= numOutStreams || OutStreamUsed[index])
- ThrowUnsupported();
- OutStreamUsed[index] = true;
- }
-
- numPackStreams = numInStreams - numBindPairs;
-
- if (numPackStreams != 1)
- for (i = 0; i < numPackStreams; i++)
- inByte->ReadNum(); // PackStreams
-
- for (i = 0; i < numOutStreams; i++)
- if (!OutStreamUsed[i])
- {
- indexOfMainStream = i;
- break;
- }
- if (i == numOutStreams)
- ThrowUnsupported();
- }
- folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
- numCodersOutStreams += numOutStreams;
- folders.FoStartPackStreamIndex[fo] = packStreamIndex;
- packStreamIndex += numPackStreams;
- folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
- }
- size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
- folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
- folders.FoStartPackStreamIndex[fo] = packStreamIndex;
- folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
- folders.CodersData.CopyFrom(startBufPtr, dataSize);
- }
-
- WaitId(NID::kCodersUnpackSize);
- folders.CoderUnpackSizes.Alloc(numCodersOutStreams);
- for (CNum i = 0; i < numCodersOutStreams; i++)
- folders.CoderUnpackSizes[i] = ReadNumber();
-
- for (;;)
- {
- UInt64 type = ReadID();
- if (type == NID::kEnd)
- return;
- if (type == NID::kCRC)
- {
- ReadHashDigests(numFolders, folders.FolderCRCs);
- continue;
- }
- SkipData();
- }
-}
-
-void CInArchive::ReadSubStreamsInfo(
- CFolders &folders,
- CRecordVector<UInt64> &unpackSizes,
- CUInt32DefVector &digests)
-{
- folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);
- CNum i;
- for (i = 0; i < folders.NumFolders; i++)
- folders.NumUnpackStreamsVector[i] = 1;
-
- UInt64 type;
-
- for (;;)
- {
- type = ReadID();
- if (type == NID::kNumUnpackStream)
- {
- for (i = 0; i < folders.NumFolders; i++)
- folders.NumUnpackStreamsVector[i] = ReadNum();
- continue;
- }
- if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd)
- break;
- SkipData();
- }
-
- if (type == NID::kSize)
- {
- for (i = 0; i < folders.NumFolders; i++)
- {
- // v3.13 incorrectly worked with empty folders
- // v4.07: we check that folder is empty
- CNum numSubstreams = folders.NumUnpackStreamsVector[i];
- if (numSubstreams == 0)
- continue;
- UInt64 sum = 0;
- for (CNum j = 1; j < numSubstreams; j++)
- {
- UInt64 size = ReadNumber();
- unpackSizes.Add(size);
- sum += size;
- if (sum < size)
- ThrowIncorrect();
- }
- UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i);
- if (folderUnpackSize < sum)
- ThrowIncorrect();
- unpackSizes.Add(folderUnpackSize - sum);
- }
- type = ReadID();
- }
- else
- {
- for (i = 0; i < folders.NumFolders; i++)
- {
- /* v9.26 - v9.29 incorrectly worked:
- if (folders.NumUnpackStreamsVector[i] == 0), it threw error */
- CNum val = folders.NumUnpackStreamsVector[i];
- if (val > 1)
- ThrowIncorrect();
- if (val == 1)
- unpackSizes.Add(folders.GetFolderUnpackSize(i));
- }
- }
-
- unsigned numDigests = 0;
- for (i = 0; i < folders.NumFolders; i++)
- {
- CNum numSubstreams = folders.NumUnpackStreamsVector[i];
- if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i))
- numDigests += numSubstreams;
- }
-
- for (;;)
- {
- if (type == NID::kEnd)
- break;
- if (type == NID::kCRC)
- {
- // CUInt32DefVector digests2;
- // ReadHashDigests(numDigests, digests2);
- CBoolVector digests2;
- ReadBoolVector2(numDigests, digests2);
-
- digests.ClearAndSetSize(unpackSizes.Size());
-
- unsigned k = 0;
- unsigned k2 = 0;
-
- for (i = 0; i < folders.NumFolders; i++)
- {
- CNum numSubstreams = folders.NumUnpackStreamsVector[i];
- if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
- {
- digests.Defs[k] = true;
- digests.Vals[k] = folders.FolderCRCs.Vals[i];
- k++;
- }
- else for (CNum j = 0; j < numSubstreams; j++)
- {
- bool defined = digests2[k2++];
- digests.Defs[k] = defined;
- UInt32 crc = 0;
- if (defined)
- crc = ReadUInt32();
- digests.Vals[k] = crc;
- k++;
- }
- }
- // if (k != unpackSizes.Size()) throw 1234567;
- }
- else
- SkipData();
-
- type = ReadID();
- }
-
- if (digests.Defs.Size() != unpackSizes.Size())
- {
- digests.ClearAndSetSize(unpackSizes.Size());
- unsigned k = 0;
- for (i = 0; i < folders.NumFolders; i++)
- {
- CNum numSubstreams = folders.NumUnpackStreamsVector[i];
- if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
- {
- digests.Defs[k] = true;
- digests.Vals[k] = folders.FolderCRCs.Vals[i];
- k++;
- }
- else for (CNum j = 0; j < numSubstreams; j++)
- {
- digests.Defs[k] = false;
- digests.Vals[k] = 0;
- k++;
- }
- }
- }
-}
-
-void CInArchive::ReadStreamsInfo(
- const CObjectVector<CByteBuffer> *dataVector,
- UInt64 &dataOffset,
- CFolders &folders,
- CRecordVector<UInt64> &unpackSizes,
- CUInt32DefVector &digests)
-{
- UInt64 type = ReadID();
-
- if (type == NID::kPackInfo)
- {
- dataOffset = ReadNumber();
- ReadPackInfo(folders);
- type = ReadID();
- }
-
- if (type == NID::kUnpackInfo)
- {
- ReadUnpackInfo(dataVector, folders);
- type = ReadID();
- }
-
- if (folders.NumFolders != 0 && !folders.PackPositions)
- {
- // if there are folders, we need PackPositions also
- folders.PackPositions.Alloc(1);
- folders.PackPositions[0] = 0;
- }
-
- if (type == NID::kSubStreamsInfo)
- {
- ReadSubStreamsInfo(folders, unpackSizes, digests);
- type = ReadID();
- }
- else
- {
- folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);
- /* If digests.Defs.Size() == 0, it means that there are no crcs.
- So we don't need to fill digests with values. */
- // digests.Vals.ClearAndSetSize(folders.NumFolders);
- // BoolVector_Fill_False(digests.Defs, folders.NumFolders);
- for (CNum i = 0; i < folders.NumFolders; i++)
- {
- folders.NumUnpackStreamsVector[i] = 1;
- unpackSizes.Add(folders.GetFolderUnpackSize(i));
- // digests.Vals[i] = 0;
- }
- }
-
- if (type != NID::kEnd)
- ThrowIncorrect();
-}
-
-void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v)
-{
- v.ClearAndSetSize(numItems);
- Byte b = 0;
- Byte mask = 0;
- bool *p = &v[0];
- for (unsigned i = 0; i < numItems; i++)
- {
- if (mask == 0)
- {
- b = ReadByte();
- mask = 0x80;
- }
- p[i] = ((b & mask) != 0);
- mask >>= 1;
- }
-}
-
-void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v)
-{
- Byte allAreDefined = ReadByte();
- if (allAreDefined == 0)
- {
- ReadBoolVector(numItems, v);
- return;
- }
- v.ClearAndSetSize(numItems);
- bool *p = &v[0];
- for (unsigned i = 0; i < numItems; i++)
- p[i] = true;
-}
-
-void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
- CUInt64DefVector &v, unsigned numItems)
-{
- ReadBoolVector2(numItems, v.Defs);
-
- CStreamSwitch streamSwitch;
- streamSwitch.Set(this, &dataVector);
-
- v.Vals.ClearAndSetSize(numItems);
- UInt64 *p = &v.Vals[0];
- const bool *defs = &v.Defs[0];
-
- for (unsigned i = 0; i < numItems; i++)
- {
- UInt64 t = 0;
- if (defs[i])
- t = ReadUInt64();
- p[i] = t;
- }
-}
-
-HRESULT CInArchive::ReadAndDecodePackedStreams(
- DECL_EXTERNAL_CODECS_LOC_VARS
- UInt64 baseOffset,
- UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector
- _7Z_DECODER_CRYPRO_VARS_DECL
- )
-{
- CFolders folders;
- CRecordVector<UInt64> unpackSizes;
- CUInt32DefVector digests;
-
- ReadStreamsInfo(NULL,
- dataOffset,
- folders,
- unpackSizes,
- digests);
-
- CDecoder decoder(
- #ifdef _ST_MODE
- false
- #else
- true
- #endif
- );
-
- for (CNum i = 0; i < folders.NumFolders; i++)
- {
- CByteBuffer &data = dataVector.AddNew();
- UInt64 unpackSize64 = folders.GetFolderUnpackSize(i);
- size_t unpackSize = (size_t)unpackSize64;
- if (unpackSize != unpackSize64)
- ThrowUnsupported();
- data.Alloc(unpackSize);
-
- CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
- CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
- outStreamSpec->Init(data, unpackSize);
-
- HRESULT result = decoder.Decode(
- EXTERNAL_CODECS_LOC_VARS
- _stream, baseOffset + dataOffset,
- folders, i,
- outStream, NULL
- _7Z_DECODER_CRYPRO_VARS
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- , false, 1
- #endif
- );
- RINOK(result);
-
- if (folders.FolderCRCs.ValidAndDefined(i))
- if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
- ThrowIncorrect();
- }
- HeadersSize += folders.PackPositions[folders.NumPackStreams];
- return S_OK;
-}
-
-HRESULT CInArchive::ReadHeader(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CDbEx &db
- _7Z_DECODER_CRYPRO_VARS_DECL
- )
-{
- UInt64 type = ReadID();
-
- if (type == NID::kArchiveProperties)
- {
- ReadArchiveProperties(db.ArcInfo);
- type = ReadID();
- }
-
- CObjectVector<CByteBuffer> dataVector;
-
- if (type == NID::kAdditionalStreamsInfo)
- {
- HRESULT result = ReadAndDecodePackedStreams(
- EXTERNAL_CODECS_LOC_VARS
- db.ArcInfo.StartPositionAfterHeader,
- db.ArcInfo.DataStartPosition2,
- dataVector
- _7Z_DECODER_CRYPRO_VARS
- );
- RINOK(result);
- db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader;
- type = ReadID();
- }
-
- CRecordVector<UInt64> unpackSizes;
- CUInt32DefVector digests;
-
- if (type == NID::kMainStreamsInfo)
- {
- ReadStreamsInfo(&dataVector,
- db.ArcInfo.DataStartPosition,
- (CFolders &)db,
- unpackSizes,
- digests);
- db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader;
- type = ReadID();
- }
-
- db.Files.Clear();
-
- if (type == NID::kFilesInfo)
- {
-
- CNum numFiles = ReadNum();
- db.Files.ClearAndSetSize(numFiles);
- CNum i;
- /*
- db.Files.Reserve(numFiles);
- CNum i;
- for (i = 0; i < numFiles; i++)
- db.Files.Add(CFileItem());
- */
-
- db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
- // if (!db.PackSizes.IsEmpty())
- db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
- if (numFiles > 0 && !digests.Defs.IsEmpty())
- db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
-
- CBoolVector emptyStreamVector;
- BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles);
- CBoolVector emptyFileVector;
- CBoolVector antiFileVector;
- CNum numEmptyStreams = 0;
-
- for (;;)
- {
- UInt64 type = ReadID();
- if (type == NID::kEnd)
- break;
- UInt64 size = ReadNumber();
- if (size > _inByteBack->GetRem())
- ThrowIncorrect();
- CStreamSwitch switchProp;
- switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);
- 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);
- size_t rem = _inByteBack->GetRem();
- db.NamesBuf.Alloc(rem);
- ReadBytes(db.NamesBuf, rem);
- db.NameOffsets.Alloc(db.Files.Size() + 1);
- size_t pos = 0;
- unsigned i;
- for (i = 0; i < db.Files.Size(); i++)
- {
- size_t curRem = (rem - pos) / 2;
- const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos);
- size_t j;
- for (j = 0; j < curRem && buf[j] != 0; j++);
- if (j == curRem)
- ThrowEndOfData();
- db.NameOffsets[i] = pos / 2;
- pos += j * 2 + 2;
- }
- db.NameOffsets[i] = pos / 2;
- if (pos != rem)
- ThereIsHeaderError = true;
- break;
- }
- case NID::kWinAttrib:
- {
- 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::kIsAux:
- {
- ReadBoolVector(db.Files.Size(), db.IsAux);
- break;
- }
- case NID::kParent:
- {
- db.IsTree = true;
- // CBoolVector boolVector;
- // ReadBoolVector2(db.Files.Size(), boolVector);
- // CStreamSwitch streamSwitch;
- // streamSwitch.Set(this, &dataVector);
- CBoolVector boolVector;
- ReadBoolVector2(db.Files.Size(), boolVector);
-
- db.ThereAreAltStreams = false;
- for (i = 0; i < numFiles; i++)
- {
- CFileItem &file = db.Files[i];
- // file.Parent = -1;
- // if (boolVector[i])
- file.Parent = (int)ReadUInt32();
- file.IsAltStream = !boolVector[i];
- if (file.IsAltStream)
- db.ThereAreAltStreams = true;
- }
- break;
- }
- */
- case NID::kEmptyStream:
- {
- ReadBoolVector(numFiles, emptyStreamVector);
- numEmptyStreams = 0;
- 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, (unsigned)numFiles); break;
- case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break;
- case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break;
- case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break;
- case NID::kDummy:
- {
- for (UInt64 j = 0; j < size; j++)
- if (ReadByte() != 0)
- ThereIsHeaderError = true;
- addPropIdToList = false;
- break;
- }
- /*
- case NID::kNtSecure:
- {
- try
- {
- {
- CStreamSwitch streamSwitch;
- streamSwitch.Set(this, &dataVector);
- UInt32 numDescriptors = ReadUInt32();
- size_t offset = 0;
- db.SecureOffsets.Clear();
- for (i = 0; i < numDescriptors; i++)
- {
- UInt32 size = ReadUInt32();
- db.SecureOffsets.Add(offset);
- offset += size;
- }
- // ThrowIncorrect();;
- db.SecureOffsets.Add(offset);
- db.SecureBuf.SetCapacity(offset);
- for (i = 0; i < numDescriptors; i++)
- {
- offset = db.SecureOffsets[i];
- ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);
- }
- db.SecureIDs.Clear();
- for (unsigned i = 0; i < db.Files.Size(); i++)
- {
- db.SecureIDs.Add(ReadNum());
- // db.SecureIDs.Add(ReadUInt32());
- }
- // ReadUInt32();
- if (_inByteBack->GetRem() != 0)
- ThrowIncorrect();;
- }
- }
- catch(CInArchiveException &)
- {
- ThereIsHeaderError = true;
- addPropIdToList = isKnownType = false;
- db.ClearSecure();
- }
- break;
- }
- */
- default:
- addPropIdToList = isKnownType = false;
- }
- if (isKnownType)
- {
- if (addPropIdToList)
- db.ArcInfo.FileInfoPopIDs.Add(type);
- }
- else
- {
- db.UnsupportedFeatureWarning = true;
- _inByteBack->SkipRem();
- }
- // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02)
- if (_inByteBack->GetRem() != 0)
- ThrowIncorrect();
- }
-
- type = ReadID(); // Read (NID::kEnd) end of headers
-
- 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];
- file.Crc = 0;
- if (file.HasStream)
- {
- file.IsDir = false;
- isAnti = false;
- file.Size = unpackSizes[sizeIndex];
- file.CrcDefined = digests.ValidAndDefined(sizeIndex);
- if (file.CrcDefined)
- file.Crc = digests.Vals[sizeIndex];
- sizeIndex++;
- }
- else
- {
- file.IsDir = !emptyFileVector[emptyFileIndex];
- isAnti = antiFileVector[emptyFileIndex];
- emptyFileIndex++;
- file.Size = 0;
- file.CrcDefined = false;
- }
- if (numAntiItems != 0)
- db.IsAnti.Add(isAnti);
- }
- }
- db.FillLinks();
- /*
- if (type != NID::kEnd)
- ThrowIncorrect();
- if (_inByteBack->GetRem() != 0)
- ThrowIncorrect();
- */
- return S_OK;
-}
-
-void CDbEx::FillLinks()
-{
- FolderStartFileIndex.ClearAndSetSize(NumFolders);
-
- FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size());
-
- CNum folderIndex = 0;
- CNum indexInFolder = 0;
- unsigned i;
- for (i = 0; i < Files.Size(); i++)
- {
- bool emptyStream = !Files[i].HasStream;
- if (indexInFolder == 0)
- {
- if (emptyStream)
- {
- FileIndexToFolderIndexMap[i] = kNumNoIndex;
- continue;
- }
- // v3.13 incorrectly worked with empty folders
- // v4.07: we skip empty folders
- for (;;)
- {
- if (folderIndex >= NumFolders)
- ThrowIncorrect();
- FolderStartFileIndex[folderIndex] = i;
- if (NumUnpackStreamsVector[folderIndex] != 0)
- break;
- folderIndex++;
- }
- }
- FileIndexToFolderIndexMap[i] = folderIndex;
- if (emptyStream)
- continue;
- if (++indexInFolder >= NumUnpackStreamsVector[folderIndex])
- {
- folderIndex++;
- indexInFolder = 0;
- }
- }
-
- if (indexInFolder != 0)
- folderIndex++;
- /*
- if (indexInFolder != 0)
- ThrowIncorrect();
- */
- for (;;)
- {
- if (folderIndex >= NumFolders)
- return;
- FolderStartFileIndex[folderIndex] = i;
- /*
- if (NumUnpackStreamsVector[folderIndex] != 0)
- ThrowIncorrect();;
- */
- folderIndex++;
- }
-}
-
-HRESULT CInArchive::ReadDatabase2(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CDbEx &db
- _7Z_DECODER_CRYPRO_VARS_DECL
- )
-{
- db.Clear();
- db.ArcInfo.StartPosition = _arhiveBeginStreamPosition;
-
- db.ArcInfo.Version.Major = _header[6];
- db.ArcInfo.Version.Minor = _header[7];
-
- if (db.ArcInfo.Version.Major != kMajorVersion)
- {
- // db.UnsupportedVersion = true;
- return S_FALSE;
- }
-
- UInt64 nextHeaderOffset = Get64(_header + 12);
- UInt64 nextHeaderSize = Get64(_header + 20);
- UInt32 nextHeaderCRC = Get32(_header + 28);
-
- #ifdef FORMAT_7Z_RECOVERY
- UInt32 crcFromArc = Get32(_header + 8);
- if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
- {
- UInt64 cur, fileSize;
- RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));
- const unsigned kCheckSize = 512;
- Byte buf[kCheckSize];
- RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));
- UInt64 rem = fileSize - cur;
- unsigned checkSize = kCheckSize;
- if (rem < kCheckSize)
- checkSize = (unsigned)(rem);
- if (checkSize < 3)
- return S_FALSE;
- RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL));
- RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize));
-
- if (buf[checkSize - 1] != 0)
- return S_FALSE;
-
- unsigned i;
- for (i = checkSize - 2;; i--)
- {
- if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo ||
- buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo)
- break;
- if (i == 0)
- return S_FALSE;
- }
- nextHeaderSize = checkSize - i;
- nextHeaderOffset = rem - nextHeaderSize;
- nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
- RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));
- db.StartHeaderWasRecovered = true;
- }
- else
- #endif
- {
- // Crc was tested already at signature check
- // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect();
- }
-
- db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;
- db.PhySize = kHeaderSize;
-
- db.IsArc = false;
- if ((Int64)nextHeaderOffset < 0 ||
- nextHeaderSize > ((UInt64)1 << 62))
- return S_FALSE;
- if (nextHeaderSize == 0)
- {
- if (nextHeaderOffset != 0)
- return S_FALSE;
- db.IsArc = true;
- return S_OK;
- }
-
- if (!db.StartHeaderWasRecovered)
- db.IsArc = true;
-
- HeadersSize += kHeaderSize + nextHeaderSize;
- db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;
- if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize)
- {
- db.UnexpectedEnd = true;
- return S_FALSE;
- }
- RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
-
- size_t nextHeaderSize_t = (size_t)nextHeaderSize;
- if (nextHeaderSize_t != nextHeaderSize)
- return E_OUTOFMEMORY;
- CByteBuffer buffer2(nextHeaderSize_t);
-
- RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t));
-
- if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC)
- ThrowIncorrect();
-
- if (!db.StartHeaderWasRecovered)
- db.PhySizeWasConfirmed = true;
-
- 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.ArcInfo.StartPositionAfterHeader,
- db.ArcInfo.DataStartPosition2,
- dataVector
- _7Z_DECODER_CRYPRO_VARS
- );
- 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.IsArc = true;
-
- db.HeadersSize = HeadersSize;
-
- return ReadHeader(
- EXTERNAL_CODECS_LOC_VARS
- db
- _7Z_DECODER_CRYPRO_VARS
- );
-}
-
-HRESULT CInArchive::ReadDatabase(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CDbEx &db
- _7Z_DECODER_CRYPRO_VARS_DECL
- )
-{
- try
- {
- HRESULT res = ReadDatabase2(
- EXTERNAL_CODECS_LOC_VARS db
- _7Z_DECODER_CRYPRO_VARS
- );
- if (ThereIsHeaderError)
- db.ThereIsHeaderError = true;
- if (res == E_NOTIMPL)
- ThrowUnsupported();
- return res;
- }
- catch(CUnsupportedFeatureException &)
- {
- db.UnsupportedFeatureError = true;
- return S_FALSE;
- }
- catch(CInArchiveException &)
- {
- db.ThereIsHeaderError = true;
- return S_FALSE;
- }
-}
-
-}}