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

📄 xarhandler.cpp

📁 7-Zip 是一款号称有着现今最高压缩比的压缩软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    const UInt64 * /* maxCheckStartPosition */,
    IArchiveOpenCallback * /* openArchiveCallback */)
{
  COM_TRY_BEGIN
  {
    Close();
    if (Open2(stream) != S_OK)
      return S_FALSE;
    _inStream = stream;
  }
  return S_OK;
  COM_TRY_END
}

STDMETHODIMP CHandler::Close()
{
  _inStream.Release();
  _files.Clear();
  _xml.Empty();
  return S_OK;
}

STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
  *numItems = _files.Size()
    #ifdef XAR_SHOW_RAW
    + 1
    #endif
  ;
  return S_OK;
}

static void TimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop)
{
  if (t != 0)
  {
    FILETIME ft;
    ft.dwLowDateTime = (UInt32)(t);
    ft.dwHighDateTime = (UInt32)(t >> 32);
    prop = ft;
  }
}

STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
  COM_TRY_BEGIN
  NWindows::NCOM::CPropVariant prop;
  
  #ifdef XAR_SHOW_RAW
  if ((int)index == _files.Size())
  {
    switch(propID)
    {
      case kpidPath: prop = L"[TOC].xml"; break;
      case kpidSize:
      case kpidPackSize: prop = (UInt64)_xml.Length(); break;
    }
  }
  else
  #endif
  {
    const CFile &item = _files[index];
    switch(propID)
    {
      case kpidMethod:
      {
        UString name;
        if (ConvertUTF8ToUnicode(item.Method, name))
          prop = name;
        break;
      }
      case kpidPath:
      {
        AString path;
        int cur = index;
        do
        {
          const CFile &item = _files[cur];
          AString s = item.Name;
          if (s.IsEmpty())
            s = "unknown";
          if (path.IsEmpty())
            path = s;
          else
            path = s + CHAR_PATH_SEPARATOR + path;
          cur = item.Parent;
        }
        while (cur >= 0);

        UString name;
        if (ConvertUTF8ToUnicode(path, name))
          prop = name;
        break;
      }
      
      case kpidIsDir:  prop = item.IsDir; break;
      case kpidSize:      if (!item.IsDir) prop = item.Size; break;
      case kpidPackSize:  if (!item.IsDir) prop = item.PackSize; break;
      
      case kpidMTime:  TimeToProp(item.MTime, prop); break;
      case kpidCTime:  TimeToProp(item.CTime, prop); break;
      case kpidATime:  TimeToProp(item.ATime, prop); break;
    }
  }
  prop.Detach(value);
  return S_OK;
  COM_TRY_END
}

STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
    Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
{
  COM_TRY_BEGIN
  bool testMode = (_aTestMode != 0);
  bool allFilesMode = (numItems == UInt32(-1));
  if (allFilesMode)
    numItems = _files.Size();
  if (numItems == 0)
    return S_OK;
  UInt64 totalSize = 0;
  UInt32 i;
  for (i = 0; i < numItems; i++)
  {
    int index = (int)(allFilesMode ? i : indices[i]);
    #ifdef XAR_SHOW_RAW
    if (index == _files.Size())
      totalSize += _xml.Length();
    else
    #endif
      totalSize += _files[index].Size;
  }
  extractCallback->SetTotal(totalSize);

  UInt64 currentPackTotal = 0;
  UInt64 currentUnpTotal = 0;
  UInt64 currentPackSize = 0;
  UInt64 currentUnpSize = 0;

  const UInt32 kZeroBufSize = (1 << 14);
  CByteBuffer zeroBuf;
  zeroBuf.SetCapacity(kZeroBufSize);
  memset(zeroBuf, 0, kZeroBufSize);
  
  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;

  NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();
  CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;
  
  NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder();
  CMyComPtr<ICompressCoder> bzip2Coder = bzip2CoderSpec;

  NCompress::NDeflate::NDecoder::CCOMCoder *deflateCoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder();
  CMyComPtr<ICompressCoder> deflateCoder = deflateCoderSpec;

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

  CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream;
  CMyComPtr<ISequentialInStream> inStream(inStreamSpec);
  inStreamSpec->SetStream(_inStream);

  
  CLimitedSequentialOutStream *outStreamLimSpec = new CLimitedSequentialOutStream;
  CMyComPtr<ISequentialOutStream> outStream(outStreamLimSpec);

  COutStreamWithSha1 *outStreamSha1Spec = new COutStreamWithSha1;
  {
    CMyComPtr<ISequentialOutStream> outStreamSha1(outStreamSha1Spec);
    outStreamLimSpec->SetStream(outStreamSha1);
  }

  for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize)
  {
    lps->InSize = currentPackTotal;
    lps->OutSize = currentUnpTotal;
    currentPackSize = 0;
    currentUnpSize = 0;
    RINOK(lps->SetCur());
    CMyComPtr<ISequentialOutStream> realOutStream;
    Int32 askMode = testMode ?
        NArchive::NExtract::NAskMode::kTest :
        NArchive::NExtract::NAskMode::kExtract;
    Int32 index = allFilesMode ? i : indices[i];
    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
    
    if (index < _files.Size())
    {
      const CFile &item = _files[index];
      if (item.IsDir)
      {
        RINOK(extractCallback->PrepareOperation(askMode));
        RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
        continue;
      }
    }

    if (!testMode && (!realOutStream))
      continue;
    RINOK(extractCallback->PrepareOperation(askMode));

    outStreamSha1Spec->SetStream(realOutStream);
    realOutStream.Release();

    Int32 opRes = NArchive::NExtract::NOperationResult::kOK;
    #ifdef XAR_SHOW_RAW
    if (index == _files.Size())
    {
      outStreamSha1Spec->Init(false);
      outStreamLimSpec->Init(_xml.Length());
      RINOK(WriteStream(outStream, (const char *)_xml, _xml.Length()));
      currentPackSize = currentUnpSize = _xml.Length();
    }
    else
    #endif
    {
      const CFile &item = _files[index];
      if (item.HasData)
      {
        currentPackSize = item.PackSize;
        currentUnpSize = item.Size;
        
        RINOK(_inStream->Seek(_dataStartPos + item.Offset, STREAM_SEEK_SET, NULL));
        inStreamSpec->Init(item.PackSize);
        outStreamSha1Spec->Init(item.Sha1IsDefined);
        outStreamLimSpec->Init(item.Size);
        HRESULT res = S_OK;
        
        ICompressCoder *coder = NULL;
        if (item.Method == "octet-stream")
          if (item.PackSize == item.Size)
            coder = copyCoder;
          else
            opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
        else if (item.Method == METHOD_NAME_ZLIB)
          coder = zlibCoder;
        else if (item.Method == "bzip2")
          coder = bzip2Coder;
        else
          opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
        
        if (coder)
          res = coder->Code(inStream, outStream, NULL, NULL, progress);
        
        if (res != S_OK)
        {
          if (!outStreamLimSpec->IsFinishedOK())
            opRes = NArchive::NExtract::NOperationResult::kDataError;
          else if (res != S_FALSE)
            return res;
          if (opRes == NArchive::NExtract::NOperationResult::kOK)
            opRes = NArchive::NExtract::NOperationResult::kDataError;
        }

        if (opRes == NArchive::NExtract::NOperationResult::kOK)
        {
          if (outStreamLimSpec->IsFinishedOK() &&
              outStreamSha1Spec->GetSize() == item.Size)
          {
            if (!outStreamLimSpec->IsFinishedOK())
            {
              opRes = NArchive::NExtract::NOperationResult::kDataError;
            }
            else if (item.Sha1IsDefined)
            {
              Byte digest[NCrypto::NSha1::kDigestSize];
              outStreamSha1Spec->Final(digest);
              if (memcmp(digest, item.Sha1, NCrypto::NSha1::kDigestSize) != 0)
                opRes = NArchive::NExtract::NOperationResult::kCRCError;
            }
          }
          else
            opRes = NArchive::NExtract::NOperationResult::kDataError;
        }
      }
    }
    outStreamSha1Spec->ReleaseStream();
    RINOK(extractCallback->SetOperationResult(opRes));
  }
  return S_OK;
  COM_TRY_END
}

static IInArchive *CreateArc() { return new NArchive::NXar::CHandler;  }

static CArcInfo g_ArcInfo =
  { L"Xar", L"xar", 0, 0xE1, { 'x', 'a', 'r', '!', 0, 0x1C }, 6, false, CreateArc, 0 };

REGISTER_ARC(Xar)

}}

⌨️ 快捷键说明

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