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

📄 7zhandler.cpp

📁 一个7ZIP的解压源码。比较详细。里面含有四种语言的实现代码。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 7zHandler.cpp

#include "StdAfx.h"

#include "7zHandler.h"
#include "7zProperties.h"

#include "../../../Common/IntToString.h"
#include "../../../Common/ComTry.h"
#include "../../../Windows/Defs.h"

#include "../Common/ItemNameUtils.h"
#ifdef _7Z_VOL
#include "../Common/MultiStream.h"
#endif

#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
#include "../Common/ParseProperties.h"
#endif
#endif

#ifdef COMPRESS_MT
#include "../../../Windows/System.h"
#endif

using namespace NWindows;

extern UString ConvertMethodIdToString(UInt64 id);

namespace NArchive {
namespace N7z {

CHandler::CHandler()
{
  _crcSize = 4;

  #ifdef EXTRACT_ONLY
  #ifdef COMPRESS_MT
  _numThreads = NWindows::NSystem::GetNumberOfProcessors();
  #endif
  #else
  Init();
  #endif
}

STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
  *numItems = 
  #ifdef _7Z_VOL
  _refs.Size();
  #else
  *numItems = _database.Files.Size();
  #endif
  return S_OK;
}

#ifdef _SFX

IMP_IInArchive_ArcProps_NO

STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
{
  return E_NOTIMPL;
}

STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,     
      BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
{
  return E_NOTIMPL;
}


#else

STATPROPSTG kArcProps[] = 
{
  { NULL, kpidMethod, VT_BSTR},
  { NULL, kpidSolid, VT_BOOL},
  { NULL, kpidNumBlocks, VT_UI4}
};

STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
  COM_TRY_BEGIN
  NWindows::NCOM::CPropVariant prop;
  switch(propID)
  {
    case kpidMethod:
    {
      UString resString;
      CRecordVector<UInt64> ids;
      int i;
      for (i = 0; i < _database.Folders.Size(); i++)
      {
        const CFolder &f = _database.Folders[i];
        for (int j = f.Coders.Size() - 1; j >= 0; j--)
          ids.AddToUniqueSorted(f.Coders[j].MethodID);
      }

      for (i = 0; i < ids.Size(); i++)
      {
        UInt64 id = ids[i];
        UString methodName;
        /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
        if (methodName.IsEmpty())
          methodName = ConvertMethodIdToString(id);
        if (!resString.IsEmpty())
          resString += L' ';
        resString += methodName;
      }
      prop = resString; 
      break;
    }
    case kpidSolid: prop = _database.IsSolid(); break;
    case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break;
  }
  prop.Detach(value);
  return S_OK;
  COM_TRY_END
}

IMP_IInArchive_ArcProps

#endif

static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop)
{
  if (timeDefined)
    prop = unixTime;
}

#ifndef _SFX

static UString ConvertUInt32ToString(UInt32 value)
{
  wchar_t buffer[32];
  ConvertUInt64ToString(value, buffer);
  return buffer;
}

static UString GetStringForSizeValue(UInt32 value)
{
  for (int i = 31; i >= 0; i--)
    if ((UInt32(1) << i) == value)
      return ConvertUInt32ToString(i);
  UString result;
  if (value % (1 << 20) == 0)
  {
    result += ConvertUInt32ToString(value >> 20);
    result += L"m";
  }
  else if (value % (1 << 10) == 0)
  {
    result += ConvertUInt32ToString(value >> 10);
    result += L"k";
  }
  else
  {
    result += ConvertUInt32ToString(value);
    result += L"b";
  }
  return result;
}

static const UInt64 k_Copy = 0x0;
static const UInt64 k_LZMA  = 0x030101;
static const UInt64 k_PPMD  = 0x030401;

static wchar_t GetHex(Byte value)
{
  return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
}
static inline UString GetHex2(Byte value)
{
  UString result;
  result += GetHex((Byte)(value >> 4));
  result += GetHex((Byte)(value & 0xF));
  return result;
}

#endif

static const UInt64 k_AES  = 0x06F10701;

#ifndef _SFX
static inline UInt32 GetUInt32FromMemLE(const Byte *p)
{
  return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
}
#endif

bool CHandler::IsEncrypted(UInt32 index2) const
{
  CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
  if (folderIndex != kNumNoIndex)
  {
    const CFolder &folderInfo = _database.Folders[folderIndex];
    for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
      if (folderInfo.Coders[i].MethodID == k_AES)
        return true;
  }
  return false;
}

STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)
{
  COM_TRY_BEGIN
  NWindows::NCOM::CPropVariant prop;
  
  /*
  const CRef2 &ref2 = _refs[index];
  if (ref2.Refs.IsEmpty())
    return E_FAIL;
  const CRef &ref = ref2.Refs.Front();
  */
  
  #ifdef _7Z_VOL
  const CRef &ref = _refs[index];
  const CVolume &volume = _volumes[ref.VolumeIndex];
  const CArchiveDatabaseEx &_database = volume.Database;
  UInt32 index2 = ref.ItemIndex;
  const CFileItem &item = _database.Files[index2];
  #else
  const CFileItem &item = _database.Files[index];
  UInt32 index2 = index;
  #endif

  switch(propID)
  {
    case kpidPath:
    {
      if (!item.Name.IsEmpty())
        prop = NItemName::GetOSName(item.Name);
      break;
    }
    case kpidIsFolder:
      prop = item.IsDirectory;
      break;
    case kpidSize:
    {
      prop = item.UnPackSize;
      // prop = ref2.UnPackSize;
      break;
    }
    case kpidPosition:
    {
      /*
      if (ref2.Refs.Size() > 1)
        prop = ref2.StartPos;
      else
      */
        if (item.IsStartPosDefined)
          prop = item.StartPos;
      break;
    }
    case kpidPackedSize:
    {
      // prop = ref2.PackSize;
      {
        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
        if (folderIndex != kNumNoIndex)
        {
          if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2)
            prop = _database.GetFolderFullPackSize(folderIndex);
          /*
          else
            prop = (UInt64)0;
          */
        }
        else
          prop = (UInt64)0;
      }
      break;
    }
    case kpidLastAccessTime:
      MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop);
      break;
    case kpidCreationTime:
      MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop);
      break;
    case kpidLastWriteTime:
      MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop);
      break;
    case kpidAttributes:
      if (item.AreAttributesDefined)
        prop = item.Attributes;
      break;
    case kpidCRC:
      if (item.IsFileCRCDefined)
        prop = item.FileCRC;
      break;
    case kpidEncrypted:
    {
      prop = IsEncrypted(index2);
      break;
    }
    #ifndef _SFX
    case kpidMethod:
      {
        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
        if (folderIndex != kNumNoIndex)
        {
          const CFolder &folderInfo = _database.Folders[folderIndex];
          UString methodsString;
          for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
          {
            const CCoderInfo &coderInfo = folderInfo.Coders[i];
            if (!methodsString.IsEmpty())
              methodsString += L' ';

            {
              UString methodName;
              bool methodIsKnown = FindMethod(
                  EXTERNAL_CODECS_VARS 
                  coderInfo.MethodID, methodName);

              if (methodIsKnown)
              {
                methodsString += methodName;
                if (coderInfo.MethodID == k_LZMA)
                {
                  if (coderInfo.Properties.GetCapacity() >= 5)
                  {
                    methodsString += L":";
                    UInt32 dicSize = GetUInt32FromMemLE(
                      ((const Byte *)coderInfo.Properties + 1));
                    methodsString += GetStringForSizeValue(dicSize);
                  }
                }
                else if (coderInfo.MethodID == k_PPMD)
                {
                  if (coderInfo.Properties.GetCapacity() >= 5)
                  {
                    Byte order = *(const Byte *)coderInfo.Properties;
                    methodsString += L":o";
                    methodsString += ConvertUInt32ToString(order);
                    methodsString += L":mem";
                    UInt32 dicSize = GetUInt32FromMemLE(
                      ((const Byte *)coderInfo.Properties + 1));
                    methodsString += GetStringForSizeValue(dicSize);
                  }
                }
                else if (coderInfo.MethodID == k_AES)
                {
                  if (coderInfo.Properties.GetCapacity() >= 1)
                  {
                    methodsString += L":";
                    const Byte *data = (const Byte *)coderInfo.Properties;
                    Byte firstByte = *data++;
                    UInt32 numCyclesPower = firstByte & 0x3F;
                    methodsString += ConvertUInt32ToString(numCyclesPower);
                    /*
                    if ((firstByte & 0xC0) != 0)
                    {
                      methodsString += L":";
                      return S_OK;
                      UInt32 saltSize = (firstByte >> 7) & 1;
                      UInt32 ivSize = (firstByte >> 6) & 1;
                      if (coderInfo.Properties.GetCapacity() >= 2)
                      {
                        Byte secondByte = *data++;
                        saltSize += (secondByte >> 4);
                        ivSize += (secondByte & 0x0F);
                      }
                    }
                    */
                  }
                }
                else
                {
                  if (coderInfo.Properties.GetCapacity() > 0)
                  {
                    methodsString += L":[";
                    for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++)
                    {
                      if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity())
                      {
                        methodsString += L"..";
                        break;
                      }
                      else
                        methodsString += GetHex2(coderInfo.Properties[bi]);
                    }
                    methodsString += L"]";
                  }
                }
              }
              else
              {
                methodsString += ConvertMethodIdToString(coderInfo.MethodID);
              }
            }
          }
          prop = methodsString;
        }
      }

⌨️ 快捷键说明

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