Esempio n. 1
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));
  }
  else
  #endif
  {
    if (crc != crcFromArchive)
      ThrowIncorrect();
  }

  db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;

  if (nextHeaderSize == 0)
    return S_OK;

  if (nextHeaderSize > (UInt64)0xFFFFFFFF)
    return S_FALSE;

  if ((Int64)nextHeaderOffset < 0)
    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
    );
}
Esempio n. 2
0
STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
      const UInt64 **inSizes,
      UInt32 numInStreams,
      ISequentialOutStream **outStreams,
      const UInt64 **outSizes,
      UInt32 numOutStreams,
      ICompressProgressInfo *progress)
{
  if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
      numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
    return E_INVALIDARG;

  // Find main coder
  int _mainCoderIndex = -1;
  int i;
  for (i = 0; i < _coders.Size(); i++)
    if (_coders[i].IsMain)
    {
      _mainCoderIndex = i;
      break;
    }
  if (_mainCoderIndex < 0)
  for (i = 0; i < _coders.Size(); i++)
    if (_coders[i].NumInStreams > 1)
    {
      if (_mainCoderIndex >= 0)
        return E_NOTIMPL;
      _mainCoderIndex = i;
    }
  if (_mainCoderIndex < 0)
    _mainCoderIndex = 0;
 
  // _mainCoderIndex = 0;
  // _mainCoderIndex = _coders.Size() - 1;
  CCoderInfo &mainCoder = _coders[_mainCoderIndex];

  CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
  CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
  UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex);
  UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex);
  for (i = 0; i < (int)mainCoder.NumInStreams; i++)
  {
    CMyComPtr<ISequentialInStream> seqInStream;
    RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream));
    seqInStreams.Add(seqInStream);
  }
  for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
  {
    CMyComPtr<ISequentialOutStream> seqOutStream;
    RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream));
    seqOutStreams.Add(seqOutStream);
  }
  CRecordVector< ISequentialInStream * > seqInStreamsSpec;
  CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
  for (i = 0; i < (int)mainCoder.NumInStreams; i++)
    seqInStreamsSpec.Add(seqInStreams[i]);
  for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
    seqOutStreamsSpec.Add(seqOutStreams[i]);

  for (i = 0; i < _coders.Size(); i++)
  {
    if (i == _mainCoderIndex)
      continue;
    CCoderInfo &coder = _coders[i];
    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
    coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
    if (setOutStreamSize)
    {
      RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0]));
    }
  }
  if (mainCoder.Coder)
  {
    RINOK(mainCoder.Coder->Code(
        seqInStreamsSpec[0], seqOutStreamsSpec[0],
        mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0],
        progress));
  }
  else
  {
    RINOK(mainCoder.Coder2->Code(
        &seqInStreamsSpec.Front(),
        &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams,
        &seqOutStreamsSpec.Front(),
        &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams,
        progress));
  }
  CMyComPtr<IOutStreamFlush> flush;
  seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush);
  if (flush)
    return flush->Flush();
  return S_OK;
}