Ejemplo n.º 1
0
//HRESULT wipeOutArchive(CInArchive *archive, CFileEnumeratorCallback *fileEnumeratorCallback) {
HRESULT wipeOutArchive(Client7zHandler *handler, fileItemInfo &v, CFileEnumeratorCallback *fileEnumeratorCallback) {
	CInArchive *archive;
	RINOK(handler->openArchive(v, &archive))
	boost::scoped_ptr<CInArchive> archiveGuard(archive);

	CMyComPtr<CArchiveExtractCallback> archiveExtractCallback = new CArchiveExtractCallback(NULL);
	//CInArchiveImpl *archive_ = dynamic_cast<CInArchiveImpl*>(archive);
	//CMyComPtr<IInArchive> archiveHandler;
	//RINOK(archive_->getArchiveHandler(&archiveHandler))

	std::wstring rootPath(v.path); rootPath += L"\\";
	archiveExtractCallback->Init(archive, fileEnumeratorCallback, rootPath);
	//RINOK(archiveHandler->Extract(NULL, (UInt32)(Int32)(-1), 0, archiveExtractCallback))
	RINOK(archive->Extract(NULL, (UInt32)(Int32)(-1), 0, archiveExtractCallback))

	return S_OK;
}
Ejemplo n.º 2
0
HRESULT CZipDecoder::Decode(
    CInArchive &archive, const CItemEx &item,
    ISequentialOutStream *realOutStream,
    IArchiveExtractCallback *_extractCallback,
    quint32 numThreads, qint32 &res)
{
    RefPtr<IArchiveExtractCallback> extractCallback(_extractCallback);

    res = NArchive::NExtract::NOperationResult::kDataError;
    CInStreamReleaser inStreamReleaser;

    bool needCRC = true;
    bool aesMode = false;
#ifdef ZIP_STRONG_SUPORT
    bool pkAesMode = false;
#endif
    quint16 methodId = item.CompressionMethod;
    if (item.IsEncrypted()) {
        if (item.IsStrongEncrypted()) {
#ifdef ZIP_STRONG_SUPORT
            CStrongCryptoField f;
            if (item.CentralExtra.GetStrongCryptoField(f)) {
                pkAesMode = true;
            }
            if (!pkAesMode)
#endif
            {
                res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
                return S_OK;
            }
        }
        if (methodId == NFileHeader::NCompressionMethod::kWzAES) {
            CWzAesExtraField aesField;
            if (item.CentralExtra.GetWzAesField(aesField)) {
                aesMode = true;
                needCRC = aesField.NeedCrc();
            }
        }
    }

    COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
    RefPtr<ISequentialOutStream> outStream = outStreamSpec;
    outStreamSpec->SetStream(realOutStream);
    outStreamSpec->Init(needCRC);

    quint64 authenticationPos;

    RefPtr<ISequentialInStream> inStream;
    {
        quint64 packSize = item.PackSize;
        if (aesMode) {
            if (packSize < NCrypto::NWzAES::kMacSize)
                return S_OK;
            packSize -= NCrypto::NWzAES::kMacSize;
        }
        quint64 dataPos = item.GetDataPosition();
        inStream = archive.CreateLimitedStream(dataPos, packSize);
        authenticationPos = dataPos + packSize;
    }

    RefPtr<ICompressFilter> cryptoFilter;
    if (item.IsEncrypted()) {
        if (aesMode) {
            CWzAesExtraField aesField;
            if (!item.CentralExtra.GetWzAesField(aesField))
                return S_OK;
            methodId = aesField.Method;
            if (!_aesDecoder) {
                _aesDecoderSpec = new NCrypto::NWzAES::CDecoder;
                _aesDecoder = _aesDecoderSpec;
            }
            cryptoFilter = _aesDecoder;
            quint8 properties = aesField.Strength;
            RINOK(_aesDecoderSpec->SetDecoderProperties2(&properties, 1));
        }
#ifdef ZIP_STRONG_SUPORT
        else if (pkAesMode) {
            if (!_zsDecoder) {
                _zsDecoderSpec = new NCrypto::NZipStrong::CDecoder;
                _zsDecoder = _zsDecoderSpec;
            }
            cryptoFilter = _zsDecoder;
        }
#endif
        else {
            if (!_zipCryptoDecoder) {
                _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder;
                _zipCryptoDecoder = _zipCryptoDecoderSpec;
            }
            cryptoFilter = _zipCryptoDecoder;
        }
        RefPtr<ICryptoSetPassword> cryptoSetPassword;
        RINOK(cryptoFilter.QueryInterface(&cryptoSetPassword));

        if (!getTextPassword)
            extractCallback.QueryInterface(&getTextPassword);

        if (getTextPassword) {
            QString password;
            RINOK(getTextPassword->CryptoGetTextPassword(&password));
            QByteArray charPassword;
            if (aesMode
#ifdef ZIP_STRONG_SUPORT
                    || pkAesMode
#endif
               ) {
                charPassword = password.toUtf8();
                /*
                for (int i = 0;; i++)
                {
                  wchar_t c = password[i];
                  if (c == 0)
                    break;
                  if (c >= 0x80)
                  {
                    res = NArchive::NExtract::NOperationResult::kDataError;
                    return S_OK;
                  }
                  charPassword += (char)c;
                }
                */
            } else {
                // we use OEM. WinZip/Windows probably use ANSI for some files
                charPassword = password.toLocal8Bit();
            }
            HRESULT res = cryptoSetPassword->CryptoSetPassword(
                              (const quint8 *)charPassword.constData(), charPassword.length());
            if (res != S_OK)
                return S_OK;
        } else {
            RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
        }
    }

    int m;
    for (m = 0; m < methodItems.size(); m++)
        if (methodItems[m]->ZipMethod == methodId)
            break;

    if (m == methodItems.size()) {
        CMethodItem mi;
        mi.ZipMethod = methodId;
        if (methodId == NFileHeader::NCompressionMethod::kStored)
            mi.Coder = new NCompress::CCopyCoder;
        else if (methodId == NFileHeader::NCompressionMethod::kShrunk)
            mi.Coder = new NCompress::NShrink::CDecoder;
        else if (methodId == NFileHeader::NCompressionMethod::kImploded)
            mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
        else {
            CMethodId szMethodID;
            if (methodId == NFileHeader::NCompressionMethod::kBZip2)
                szMethodID = kMethodId_BZip2;
            else {
                if (methodId > 0xFF) {
                    res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
                    return S_OK;
                }
                szMethodID = kMethodId_ZipBase + (quint8)methodId;
            }

            QObject *dec = CreateDecoderForId(szMethodID);
            if (dec)
                mi.Coder = qobject_cast<ICompressCoder *>(dec);

            if (mi.Coder == 0) {
                delete dec;
                res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
                return S_OK;
            }
        }
        methodItems.append(new CMethodItem(mi));
        m = methodItems.size() - 1;
    }
    RefPtr<ICompressCoder> coder(methodItems[m]->Coder);

    {
        RefPtr<ICompressSetDecoderProperties2> setDecoderProperties;
        coder.QueryInterface(&setDecoderProperties);
        if (setDecoderProperties) {
            quint8 properties = (quint8)item.Flags;
            RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));
        }
    }

#ifdef THREADED
    {
        RefPtr<ICompressSetCoderMt> setCoderMt;
        coder.QueryInterface(&setCoderMt);
        if (setCoderMt) {
            RINOK(setCoderMt->SetNumberOfThreads(numThreads));
        }
    }
#endif
    {
        HRESULT result;
        RefPtr<ISequentialInStream> inStreamNew;
        if (item.IsEncrypted()) {
            if (!filterStream) {
                filterStreamSpec = new CFilterCoder;
                filterStream = filterStreamSpec;
            }
            filterStreamSpec->setFilter(cryptoFilter);
            if (aesMode) {
                RINOK(_aesDecoderSpec->ReadHeader(inStream));
            }
#ifdef ZIP_STRONG_SUPORT
            else if (pkAesMode) {
                RINOK(_zsDecoderSpec->ReadHeader(inStream));
            }
#endif
            else {
                RINOK(_zipCryptoDecoderSpec->ReadHeader(inStream));
            }
            RINOK(filterStreamSpec->SetInStream(inStream));
            inStreamReleaser.FilterCoder = filterStreamSpec;
            inStreamNew = filterStream;

            if (aesMode) {
                if (!_aesDecoderSpec->CheckPasswordVerifyCode())
                    return S_OK;
            }
        } else
            inStreamNew = inStream;
        result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize);
        if (result == S_FALSE)
            return S_OK;
        RINOK(result);
    }
    bool crcOK = true;
    bool authOk = true;
    if (needCRC)
        crcOK = (outStreamSpec->GetCRC() == item.FileCRC);
    if (aesMode) {
        inStream = archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAES::kMacSize);
        if (_aesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
            authOk = false;
    }

    res = ((crcOK && authOk) ?
           NArchive::NExtract::NOperationResult::kOK :
           NArchive::NExtract::NOperationResult::kCRCError);
    return S_OK;
}
Ejemplo n.º 3
0
STDMETHODIMP CHandler::Open(IInStream *inStream,
    const UInt64 *maxCheckStartPosition,
    IArchiveOpenCallback *callback)
{
  COM_TRY_BEGIN
  Close();
  HRESULT res = S_FALSE;
  CInArchive archive;
  CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
  callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
  
  CMyComPtr<IInStream> nextStream = inStream;
  bool prevChecked = false;
  UInt64 numItems = 0;
  try
  {
    while (nextStream != 0)
    {
      CDatabaseEx db;
      db.Stream = nextStream;
      res = archive.Open(maxCheckStartPosition, db);
      if (res == S_OK)
      {
        if (!m_Database.Volumes.IsEmpty())
        {
          const CDatabaseEx &dbPrev = m_Database.Volumes[prevChecked ? m_Database.Volumes.Size() - 1 : 0];
          if (dbPrev.ArchiveInfo.SetID != db.ArchiveInfo.SetID ||
              dbPrev.ArchiveInfo.CabinetNumber + (prevChecked ? 1: - 1) !=
              db.ArchiveInfo.CabinetNumber)
            res = S_FALSE;
        }
      }
      if (res == S_OK)
        m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db);
      else if (res != S_FALSE)
        return res;
      else
      {
        if (m_Database.Volumes.IsEmpty())
          return S_FALSE;
        if (prevChecked)
          break;
        prevChecked = true;
      }

      numItems += db.Items.Size();
      RINOK(callback->SetCompleted(&numItems, NULL));
        
      nextStream = 0;
      for (;;)
      {
        const COtherArchive *otherArchive = 0;
        if (!prevChecked)
        {
          const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo;
          if (ai.IsTherePrev())
            otherArchive = &ai.PrevArc;
          else
            prevChecked = true;
        }
        if (otherArchive == 0)
        {
          const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo;
          if (ai.IsThereNext())
            otherArchive = &ai.NextArc;
        }
        if (!otherArchive)
          break;
        const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP);
        if (!openVolumeCallback)
          break;

        HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
        if (result == S_OK)
          break;
        if (result != S_FALSE)
          return result;
        if (prevChecked)
          break;
        prevChecked = true;
      }
    }
    if (res == S_OK)
    {
      m_Database.FillSortAndShrink();
      if (!m_Database.Check())
        res = S_FALSE;
    }
  }
  catch(...)
  {
    res = S_FALSE;
  }
  if (res != S_OK)
  {
    Close();
    return res;
  }
  COM_TRY_END
  return S_OK;
}
Ejemplo n.º 4
0
STDMETHODIMP CHandler::Open(IInStream *inStream,
    const UInt64 *maxCheckStartPosition,
    IArchiveOpenCallback *callback)
{
  COM_TRY_BEGIN
  Close();

  CInArchive archive;
  CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
  callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
  
  CMyComPtr<IInStream> nextStream = inStream;
  bool prevChecked = false;
  UInt64 numItems = 0;
  unsigned numTempVolumes = 0;
  // try
  {
    while (nextStream != NULL)
    {
      CDatabaseEx db;
      db.Stream = nextStream;
      HRESULT res = archive.Open(db, maxCheckStartPosition);
      _errorInHeaders |= archive.HeaderError;
      _errorInHeaders |= archive.ErrorInNames;
      _unexpectedEnd |= archive.UnexpectedEnd;
      
      if (res == S_OK && !m_Database.Volumes.IsEmpty())
      {
        const CArchInfo &lastArc = m_Database.Volumes.Back().ArcInfo;
        unsigned cabNumber = db.ArcInfo.CabinetNumber;
        if (lastArc.SetID != db.ArcInfo.SetID)
          res = S_FALSE;
        else if (prevChecked)
        {
          if (cabNumber != lastArc.CabinetNumber + 1)
            res = S_FALSE;
        }
        else if (cabNumber >= lastArc.CabinetNumber)
          res = S_FALSE;
        else if (numTempVolumes != 0)
        {
          const CArchInfo &prevArc = m_Database.Volumes[numTempVolumes - 1].ArcInfo;
          if (cabNumber != prevArc.CabinetNumber + 1)
            res = S_FALSE;
        }
      }
      
      if (archive.IsArc || res == S_OK)
      {
        _isArc = true;
        if (m_Database.Volumes.IsEmpty())
        {
          _offset = db.StartPosition;
          _phySize = db.ArcInfo.Size;
        }
      }
      
      if (res == S_OK)
      {
        numItems += db.Items.Size();
        m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : numTempVolumes, db);
        if (!prevChecked && m_Database.Volumes.Size() > 1)
        {
          numTempVolumes++;
          if (db.ArcInfo.CabinetNumber + 1 == m_Database.Volumes[numTempVolumes].ArcInfo.CabinetNumber)
            numTempVolumes = 0;
        }
      }
      else
      {
        if (res != S_FALSE)
          return res;
        if (m_Database.Volumes.IsEmpty())
          return S_FALSE;
        if (prevChecked)
          break;
        prevChecked = true;
        if (numTempVolumes != 0)
        {
          m_Database.Volumes.DeleteFrontal(numTempVolumes);
          numTempVolumes = 0;
        }
      }

      RINOK(callback->SetCompleted(&numItems, NULL));
        
      nextStream = NULL;
      
      for (;;)
      {
        const COtherArc *otherArc = NULL;
        if (!prevChecked)
        {
          if (numTempVolumes == 0)
          {
            const CInArcInfo &ai = m_Database.Volumes[0].ArcInfo;
            if (ai.IsTherePrev())
              otherArc = &ai.PrevArc;
            else
              prevChecked = true;
          }
          else
          {
            const CInArcInfo &ai = m_Database.Volumes[numTempVolumes - 1].ArcInfo;
            if (ai.IsThereNext())
              otherArc = &ai.NextArc;
            else
            {
              prevChecked = true;
              m_Database.Volumes.DeleteFrontal(numTempVolumes);
              numTempVolumes = 0;
            }
          }
        }
        if (!otherArc)
        {
          const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo;
          if (ai.IsThereNext())
            otherArc = &ai.NextArc;
        }
        if (!otherArc)
          break;
        if (!openVolumeCallback)
          break;
        // printf("\n%s", otherArc->FileName);
        const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP);
        HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
        if (result == S_OK)
          break;
        if (result != S_FALSE)
          return result;

        if (!_errorMessage.IsEmpty())
          _errorMessage.Add_LF();
        _errorMessage.AddAscii("Can't open volume: ");
        _errorMessage += fullName;
        
        if (prevChecked)
          break;
        prevChecked = true;
        if (numTempVolumes != 0)
        {
          m_Database.Volumes.DeleteFrontal(numTempVolumes);
          numTempVolumes = 0;
        }
      }

    } // read nextStream iteration

    if (numTempVolumes != 0)
    {
      m_Database.Volumes.DeleteFrontal(numTempVolumes);
      numTempVolumes = 0;
    }
    if (m_Database.Volumes.IsEmpty())
      return S_FALSE;
    else
    {
      m_Database.FillSortAndShrink();
      if (!m_Database.Check())
        return S_FALSE;
    }
  }
  COM_TRY_END
  return S_OK;
}