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

📄 ziphandlerout.cpp

📁 7-Zip 3.11的源码
💻 CPP
字号:
// Zip/HandlerOut.cpp

#include "StdAfx.h"

#include "ZipHandler.h"
#include "ZipUpdate.h"

#include "Common/StringConvert.h"
#include "Common/ComTry.h"
#include "Common/StringToInt.h"

#include "Windows/PropVariant.h"
#include "Windows/Time.h"

#include "../../IPassword.h"
#include "../Common/ItemNameUtils.h"

using namespace NWindows;
using namespace NCOM;
using namespace NTime;

namespace NArchive {
namespace NZip {

STDMETHODIMP CHandler::GetFileTimeType(UINT32 *timeType)
{
  *timeType = NFileTimeType::kDOS;
  return S_OK;
}

STDMETHODIMP CHandler::UpdateItems(IOutStream *outStream, UINT32 numItems,
    IArchiveUpdateCallback *updateCallback)
{
  COM_TRY_BEGIN
  CObjectVector<CUpdateItem> updateItems;
  for(int i = 0; i < numItems; i++)
  {
    CUpdateItem updateItem;
    INT32 newData;
    INT32 newProperties;
    UINT32 indexInArchive;
    if (!updateCallback)
      return E_FAIL;
    RINOK(updateCallback->GetUpdateItemInfo(i,
        &newData, // 1 - compress 0 - copy
        &newProperties,
        &indexInArchive));
    updateItem.NewProperties = IntToBool(newProperties);
    updateItem.NewData = IntToBool(newData);
    updateItem.IndexInArchive = indexInArchive;
    updateItem.IndexInClient = i;
    bool existInArchive = (indexInArchive != UINT32(-1));
    if (IntToBool(newProperties))
    {
      FILETIME utcFileTime;
      UString name;
      bool isDirectoryStatusDefined;
      {
        NCOM::CPropVariant propVariant;
        RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));
        if (propVariant.vt == VT_EMPTY)
          updateItem.Attributes = 0;
        else if (propVariant.vt != VT_UI4)
          return E_INVALIDARG;
        else
          updateItem.Attributes = propVariant.ulVal;
      }
      {
        NCOM::CPropVariant propVariant;
        RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &propVariant));
        if (propVariant.vt != VT_FILETIME)
          return E_INVALIDARG;
        utcFileTime = propVariant.filetime;
      }
      {
        NCOM::CPropVariant propVariant;
        RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant));
        if (propVariant.vt == VT_EMPTY)
          name.Empty();
        else if (propVariant.vt != VT_BSTR)
          return E_INVALIDARG;
        else
          name = propVariant.bstrVal;
      }
      {
        NCOM::CPropVariant propVariant;
        RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant));
        if (propVariant.vt == VT_EMPTY)
          isDirectoryStatusDefined = false;
        else if (propVariant.vt != VT_BOOL)
          return E_INVALIDARG;
        else
        {
          updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE);
          isDirectoryStatusDefined = true;
        }
      }
      FILETIME localFileTime;
      if(!FileTimeToLocalFileTime(&utcFileTime, &localFileTime))
        return E_INVALIDARG;
      if(!FileTimeToDosTime(localFileTime, updateItem.Time))
        return E_INVALIDARG;
      updateItem.Name = UnicodeStringToMultiByte(
          NItemName::MakeLegalName(name), CP_OEMCP);
      if (!isDirectoryStatusDefined)
        updateItem.IsDirectory = ((updateItem.Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
      if (updateItem.IsDirectory)
        updateItem.Name += '/';
      updateItem.IndexInClient = i;
      if(existInArchive)
      {
        const CItemEx &itemInfo = m_Items[indexInArchive];
        // updateItem.Commented = itemInfo.IsCommented();
        updateItem.Commented = false;
        if(updateItem.Commented)
        {
          updateItem.CommentRange.Position = itemInfo.GetCommentPosition();
          updateItem.CommentRange.Size  = itemInfo.CommentSize;
        }
      }
      else
        updateItem.Commented = false;
    }
    if (IntToBool(newData))
    {
      UINT64 size;
      {
        NCOM::CPropVariant propVariant;
        RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant));
        if (propVariant.vt != VT_UI8)
          return E_INVALIDARG;
        size = *(UINT64 *)(&propVariant.uhVal);
      }
      if(size > 0xFFFFFFFF)
        return E_NOTIMPL;
      updateItem.Size = size;
    }
    updateItems.Add(updateItem);
  }

  CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
  if (!getTextPassword)
  {
    CMyComPtr<IArchiveUpdateCallback> udateCallBack2(updateCallback);
    udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
  }
  if (getTextPassword)
  {
    CMyComBSTR password;
    INT32 passwordIsDefined;
    RINOK(getTextPassword->CryptoGetTextPassword2(
        &passwordIsDefined, &password));
    if (m_Method.PasswordIsDefined = IntToBool(passwordIsDefined))
      m_Method.Password = UnicodeStringToMultiByte(
          (const wchar_t *)password, CP_OEMCP);
  }
  else
    m_Method.PasswordIsDefined = false;

  return Update(m_Items, updateItems, outStream, 
      m_ArchiveIsOpen ? &m_Archive : NULL, &m_Method, updateCallback);
  COM_TRY_END
}

static const UINT32 kNumPassesNormal = 1;
static const UINT32 kNumPassesMX  = 3;

static const UINT32 kMatchFastLenNormal  = 32;
static const UINT32 kMatchFastLenMX  = 64;

STDMETHODIMP CHandler::SetProperties(const BSTR *names, const PROPVARIANT *values, INT32 numProperties)
{
  InitMethodProperties();
  BYTE mainMethod = NFileHeader::NCompressionMethod::kDeflated;
  for (int i = 0; i < numProperties; i++)
  {
    UString name = UString(names[i]);
    name.MakeUpper();
    const PROPVARIANT &value = values[i];

    if (name[0] == 'X')
    {
      name.Delete(0);
      UINT32 level = 9;
      if (value.vt == VT_UI4)
      {
        if (!name.IsEmpty())
          return E_INVALIDARG;
        level = value.ulVal;
      }
      else if (value.vt == VT_EMPTY)
      {
        if(!name.IsEmpty())
        {
          const wchar_t *start = name;
          const wchar_t *end;
          UINT64 v = ConvertStringToUINT64(start, &end);
          if (end - start != name.Length())
            return E_INVALIDARG;
          level = (UINT32)v;
        }
      }
      else
        return E_INVALIDARG;
      if (level == 0)
      {
        mainMethod = NFileHeader::NCompressionMethod::kStored;
      }
      else if (level < 7)
      {
        InitMethodProperties();
        if (mainMethod == NFileHeader::NCompressionMethod::kStored)
          mainMethod = NFileHeader::NCompressionMethod::kDeflated;
      }
      else
      {
        m_Method.NumPasses = kNumPassesMX;
        m_Method.NumFastBytes = kMatchFastLenMX;
        if (mainMethod == NFileHeader::NCompressionMethod::kStored)
          mainMethod = NFileHeader::NCompressionMethod::kDeflated;
      }
      continue;
    }
    else if (name == L"M")
    {
      if (value.vt == VT_BSTR)
      {
        UString valueString = value.bstrVal;
        valueString.MakeUpper();
        if (valueString == L"COPY")
          mainMethod = NFileHeader::NCompressionMethod::kStored;
        else if (valueString == L"DEFLATE")
          mainMethod = NFileHeader::NCompressionMethod::kDeflated;
        else if (valueString == L"DEFLATE64")
          mainMethod = NFileHeader::NCompressionMethod::kDeflated64;
        else if (valueString == L"BZIP2")
          mainMethod = NFileHeader::NCompressionMethod::kBZip2;
        else 
          return E_INVALIDARG;
      }
      else if (value.vt == VT_UI4)
      {
        switch(value.ulVal)
        {
          case NFileHeader::NCompressionMethod::kStored:
          case NFileHeader::NCompressionMethod::kDeflated:
          case NFileHeader::NCompressionMethod::kDeflated64:
          case NFileHeader::NCompressionMethod::kBZip2:
            mainMethod = value.ulVal;
            break;
          default:
            return E_INVALIDARG;
        }
      }
      else
        return E_INVALIDARG;
    }
    else if (name == L"PASS")
    {
      if (value.vt != VT_UI4)
        return E_INVALIDARG;
      m_Method.NumPasses = value.ulVal;
      if (m_Method.NumPasses < 1 || m_Method.NumPasses > 4)
        return E_INVALIDARG;
    }
    else if (name == L"FB")
    {
      if (value.vt != VT_UI4)
        return E_INVALIDARG;
      m_Method.NumFastBytes = value.ulVal;
      if (m_Method.NumFastBytes < 3 || m_Method.NumFastBytes > 255)
        return E_INVALIDARG;
    }
    else
      return E_INVALIDARG;
  }
  m_Method.MethodSequence.Clear();
  if (mainMethod != NFileHeader::NCompressionMethod::kStored)
    m_Method.MethodSequence.Add(mainMethod);
  m_Method.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
  return S_OK;
}  

}}

⌨️ 快捷键说明

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