⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ziphandler.cpp

📁 版本4.32
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    {
      RINOK(openArchiveCallback->SetTotal(NULL, NULL));
    }
    CPropgressImp propgressImp;
    propgressImp.Init(openArchiveCallback);
    RINOK(m_Archive.ReadHeaders(m_Items, &propgressImp));
  }
  /*
  catch(...)
  {
    return S_FALSE;
  }
  */
  COM_TRY_END
  return S_OK;
}

STDMETHODIMP CHandler::Close()
{
  m_Items.Clear();
  m_Archive.Close();
  m_ArchiveIsOpen = false;
  return S_OK;
}

//////////////////////////////////////
// CHandler::DecompressItems

struct CMethodItem
{
  Byte ZipMethod;
  CMyComPtr<ICompressCoder> Coder;
};

STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
    Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback)
{
  COM_TRY_BEGIN
  CMyComPtr<ICryptoGetTextPassword> getTextPassword;
  bool testMode = (_aTestMode != 0);
  CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback;
  UInt64 totalUnPacked = 0, totalPacked = 0;
  bool allFilesMode = (numItems == UInt32(-1));
  if (allFilesMode)
    numItems = m_Items.Size();
  if(numItems == 0)
    return S_OK;
  UInt32 i;
  for(i = 0; i < numItems; i++)
  {
    const CItemEx &item = m_Items[allFilesMode ? i : indices[i]];
    totalUnPacked += item.UnPackSize;
    totalPacked += item.PackSize;
  }
  extractCallback->SetTotal(totalUnPacked);

  UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
  UInt64 currentItemUnPacked, currentItemPacked;
  
 
  #ifndef EXCLUDE_COM
  N7z::LoadMethodMap();
  CCoderLibraries libraries;
  #endif
  CObjectVector<CMethodItem> methodItems;
  /*
  CCoderLibraries _libraries;
  #ifndef COMPRESS_IMPLODE
  CCoderLibrary implodeLib;
  #endif
  

  CMyComPtr<ICompressCoder> implodeDecoder;
  CMyComPtr<ICompressCoder> deflateDecoder;
  CMyComPtr<ICompressCoder> deflate64Decoder;
  CMyComPtr<ICompressCoder> bzip2Decoder;

  #ifndef CRYPTO_ZIP
  CCoderLibrary cryptoLib;
  #endif
  */

  NCrypto::NZip::CDecoder *cryptoDecoderSpec;
  CMyComPtr<ICompressFilter> cryptoDecoder;
  CFilterCoder *filterStreamSpec;
  CMyComPtr<ISequentialInStream> filterStream;

  // UInt16 mixerCoderMethod;

  for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,
      currentTotalPacked += currentItemPacked)
  {
    currentItemUnPacked = 0;
    currentItemPacked = 0;

    RINOK(extractCallback->SetCompleted(&currentTotalUnPacked));
    CMyComPtr<ISequentialOutStream> realOutStream;
    Int32 askMode;
    askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
        NArchive::NExtract::NAskMode::kExtract;
    Int32 index = allFilesMode ? i : indices[i];
    const CItemEx &item = m_Items[index];
    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));

    if(item.IsDirectory() || item.IgnoreItem())
    {
      // if (!testMode)
      {
        RINOK(extractCallback->PrepareOperation(askMode));
        RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
      }
      continue;
    }

    if (!testMode && (!realOutStream)) 
      continue;

    RINOK(extractCallback->PrepareOperation(askMode));
    currentItemUnPacked = item.UnPackSize;
    currentItemPacked = item.PackSize;

    CInStreamReleaser inStreamReleaser;
    {
      COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
      outStreamSpec->Init(realOutStream);
      realOutStream.Release();
      
      CMyComPtr<ISequentialInStream> inStream;
      inStream.Attach(m_Archive.CreateLimitedStream(item.GetDataPosition(),
          item.PackSize));

      CLocalProgress *localProgressSpec = new CLocalProgress;
      CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
      localProgressSpec->Init(extractCallback, false);

      CLocalCompressProgressInfo *localCompressProgressSpec = 
          new CLocalCompressProgressInfo;
      CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
      localCompressProgressSpec->Init(progress, 
          &currentTotalPacked,
          &currentTotalUnPacked);

      if (item.IsEncrypted())
      {
        if (!cryptoDecoder)
        {
          cryptoDecoderSpec = new NCrypto::NZip::CDecoder;
          cryptoDecoder = cryptoDecoderSpec;
        }
        CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
        RINOK(cryptoDecoder.QueryInterface(
            IID_ICryptoSetPassword, &cryptoSetPassword));

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

        if (getTextPassword)
        {
          CMyComBSTR password;
          RINOK(getTextPassword->CryptoGetTextPassword(&password));
          AString anOemPassword = UnicodeStringToMultiByte(
              (const wchar_t *)password, CP_OEMCP);
          RINOK(cryptoSetPassword->CryptoSetPassword(
              (const Byte *)(const char *)anOemPassword, anOemPassword.Length()));
        }
        else
        {
          RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
        }
      }

      int m;
      for (m = 0; m < methodItems.Size(); m++)
        if (methodItems[m].ZipMethod == item.CompressionMethod)
          break;
      if (m == methodItems.Size())
      {
        CMethodItem mi;
        mi.ZipMethod = (Byte)item.CompressionMethod;
        if (item.CompressionMethod == NFileHeader::NCompressionMethod::kStored)
          mi.Coder = new NCompress::CCopyCoder;
        else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kShrunk)
          mi.Coder = new NCompress::NShrink::CDecoder;
        else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kImploded)
          mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
        else
        {
        #ifdef EXCLUDE_COM
        switch(item.CompressionMethod)
        {
          case NFileHeader::NCompressionMethod::kDeflated:
            mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder;
            break;
          case NFileHeader::NCompressionMethod::kDeflated64:
            mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder64;
            break;
          case NFileHeader::NCompressionMethod::kBZip2:
            mi.Coder = new NCompress::NBZip2::CDecoder;
            break;
          default:
            RINOK(extractCallback->SetOperationResult(
              NArchive::NExtract::NOperationResult::kUnSupportedMethod));
            continue;
        }
        #else
        N7z::CMethodID methodID = { { 0x04, 0x01 } , 3 };
        methodID.ID[2] = mi.ZipMethod;
        if (item.CompressionMethod == NFileHeader::NCompressionMethod::kStored)
        {
          methodID.ID[0] = 0;
          methodID.IDSize = 1;
        }
        else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kBZip2)
        {
          methodID.ID[1] = 0x02;
          methodID.ID[2] = 0x02;
        }
         
        N7z::CMethodInfo methodInfo;
        if (!N7z::GetMethodInfo(methodID, methodInfo))
        {
          RINOK(extractCallback->SetOperationResult(
              NArchive::NExtract::NOperationResult::kUnSupportedMethod));
          continue;
        }
        RINOK(libraries.CreateCoder(methodInfo.FilePath, 
              methodInfo.Decoder, &mi.Coder));
        #endif
        }
        m = methodItems.Add(mi);
      }
      ICompressCoder *coder = methodItems[m].Coder;

      CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
      if (coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&compressSetDecoderProperties) == S_OK)
      {
        Byte properties = (Byte)item.Flags;
        RINOK(compressSetDecoderProperties->SetDecoderProperties2(&properties, 1));
      }

      // case NFileHeader::NCompressionMethod::kImploded:
      // switch(item.CompressionMethod)
      try
      {
        HRESULT result;
        CMyComPtr<ISequentialInStream> inStreamNew;
        if (item.IsEncrypted())
        {
          if (!filterStream)
          {
            filterStreamSpec = new CFilterCoder;
            filterStream = filterStreamSpec;
            filterStreamSpec->Filter = cryptoDecoder;
          }
          RINOK(cryptoDecoderSpec->ReadHeader(inStream));
          RINOK(filterStreamSpec->SetInStream(inStream));
          inStreamReleaser.FilterCoder = filterStreamSpec;

          /*
          switch(item.CompressionMethod)
          {
            case NFileHeader::NCompressionMethod::kStored:
              mixerCoderSpec->SetCoderInfo(0, &currentItemPacked, 
                &currentItemUnPacked);
              mixerCoderSpec->SetCoderInfo(1, NULL, NULL);
              break;
            default:
              mixerCoderSpec->SetCoderInfo(0, &currentItemPacked, NULL);
              mixerCoderSpec->SetCoderInfo(1, NULL, &currentItemUnPacked);
              break;
          }
          */
          inStreamNew = filterStream; 
        }
        else
        {
          inStreamNew = inStream; 
        }
        result = coder->Code(inStreamNew, outStream,
          NULL, &currentItemUnPacked, compressProgress);
        if (result == S_FALSE)
          throw "data error";
        if (result != S_OK)
          return result;
      }
      catch(...)
      {
        outStream.Release();
        RINOK(extractCallback->SetOperationResult(
          NArchive::NExtract::NOperationResult::kDataError));
        continue;
      }
      bool crcOK = outStreamSpec->GetCRC() == item.FileCRC;
      outStream.Release();
      RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK :
          NArchive::NExtract::NOperationResult::kCRCError))
    }
  }
  return S_OK;
  COM_TRY_END
}

}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -