ziphandler.cpp
来自「seven zip源代码」· C++ 代码 · 共 772 行 · 第 1/2 页
CPP
772 行
// ZipHandler.cpp
#include "StdAfx.h"
#include "ZipHandler.h"
#include "Common/Defs.h"
#include "Common/StringConvert.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "Windows/Time.h"
#include "Windows/PropVariant.h"
#include "../../IPassword.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../Common/ItemNameUtils.h"
#include "../Common/OutStreamWithCRC.h"
#include "../../Compress/Shrink/ShrinkDecoder.h"
#include "../../Compress/Implode/ImplodeDecoder.h"
#include "../../Crypto/Zip/ZipCipher.h"
#include "../../Crypto/WzAES/WzAES.h"
#ifdef ZIP_STRONG_SUPORT
#include "../../Crypto/ZipStrong/ZipStrong.h"
#endif
using namespace NWindows;
using namespace NTime;
namespace NArchive {
namespace NZip {
// static const CMethodId kMethodId_Store = 0;
static const CMethodId kMethodId_ZipBase = 0x040100;
static const CMethodId kMethodId_BZip2 = 0x040202;
const wchar_t *kHostOS[] =
{
L"FAT",
L"AMIGA",
L"VMS",
L"Unix",
L"VM/CMS",
L"Atari",
L"HPFS",
L"Macintosh",
L"Z-System",
L"CP/M",
L"TOPS-20",
L"NTFS",
L"SMS/QDOS",
L"Acorn",
L"VFAT",
L"MVS",
L"BeOS",
L"Tandem",
L"OS/400",
L"OS/X"
};
static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
static const wchar_t *kUnknownOS = L"Unknown";
STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsFolder, VT_BOOL},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackedSize, VT_UI8},
{ NULL, kpidLastWriteTime, VT_FILETIME},
{ NULL, kpidAttributes, VT_UI4},
{ NULL, kpidEncrypted, VT_BOOL},
{ NULL, kpidComment, VT_BSTR},
{ NULL, kpidCRC, VT_UI4},
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidHostOS, VT_BSTR}
// { NULL, kpidUnpackVer, VT_UI1},
};
const wchar_t *kMethods[] =
{
L"Store",
L"Shrink",
L"Reduced1",
L"Reduced2",
L"Reduced2",
L"Reduced3",
L"Implode",
L"Tokenizing",
L"Deflate",
L"Deflate64",
L"PKImploding",
L"Unknown",
L"BZip2"
};
const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
// const wchar_t *kUnknownMethod = L"Unknown";
const wchar_t *kPPMdMethod = L"PPMd";
const wchar_t *kAESMethod = L"AES";
const wchar_t *kZipCryptoMethod = L"ZipCrypto";
const wchar_t *kStrongCryptoMethod = L"StrongCrypto";
struct CStrongCryptoPair
{
UInt16 Id;
const wchar_t *Name;
};
CStrongCryptoPair g_StrongCryptoPairs[] =
{
{ NStrongCryptoFlags::kDES, L"DES" },
{ NStrongCryptoFlags::kRC2old, L"RC2a" },
{ NStrongCryptoFlags::k3DES168, L"3DES-168" },
{ NStrongCryptoFlags::k3DES112, L"3DES-112" },
{ NStrongCryptoFlags::kAES128, L"pkAES-128" },
{ NStrongCryptoFlags::kAES192, L"pkAES-192" },
{ NStrongCryptoFlags::kAES256, L"pkAES-256" },
{ NStrongCryptoFlags::kRC2, L"RC2" },
{ NStrongCryptoFlags::kBlowfish, L"Blowfish" },
{ NStrongCryptoFlags::kTwofish, L"Twofish" },
{ NStrongCryptoFlags::kRC4, L"RC4" }
};
STATPROPSTG kArcProps[] =
{
{ NULL, kpidComment, VT_BSTR}
};
CHandler::CHandler():
m_ArchiveIsOpen(false)
{
InitMethodProperties();
}
static void StringToProp(const CByteBuffer &data, UINT codePage, NWindows::NCOM::CPropVariant &prop)
{
int size = (int)data.GetCapacity();
if (size <= 0)
return;
AString s;
char *p = s.GetBuffer(size + 1);
memcpy(p, (const Byte *)data, size);
p[size] = '\0';
s.ReleaseBuffer();
prop = MultiByteToUnicodeString(s, codePage);
}
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidComment:
{
StringToProp(m_Archive.m_ArchiveInfo.Comment, CP_ACP, prop);
break;
}
}
prop.Detach(value);
COM_TRY_END
return S_OK;
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = m_Items.Size();
return S_OK;
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
const CItemEx &item = m_Items[index];
switch(propID)
{
case kpidPath:
prop = NItemName::GetOSName2(
MultiByteToUnicodeString(item.Name, item.GetCodePage()));
break;
case kpidIsFolder:
prop = item.IsDirectory();
break;
case kpidSize:
prop = item.UnPackSize;
break;
case kpidPackedSize:
prop = item.PackSize;
break;
case kpidLastWriteTime:
{
FILETIME localFileTime, utcFileTime;
if (DosTimeToFileTime(item.Time, localFileTime))
{
if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
}
else
utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
prop = utcFileTime;
break;
}
case kpidAttributes:
prop = item.GetWinAttributes();
break;
case kpidEncrypted:
prop = item.IsEncrypted();
break;
case kpidComment:
{
StringToProp(item.Comment, item.GetCodePage(), prop);
break;
}
case kpidCRC:
if (item.IsThereCrc())
prop = item.FileCRC;
break;
case kpidMethod:
{
UInt16 methodId = item.CompressionMethod;
UString method;
if (item.IsEncrypted())
{
if (methodId == NFileHeader::NCompressionMethod::kWzAES)
{
method = kAESMethod;
CWzAesExtraField aesField;
if (item.CentralExtra.GetWzAesField(aesField))
{
method += L"-";
wchar_t s[32];
ConvertUInt64ToString((aesField.Strength + 1) * 64 , s);
method += s;
method += L" ";
methodId = aesField.Method;
}
}
else
{
if (item.IsStrongEncrypted())
{
CStrongCryptoField f;
bool finded = false;
if (item.CentralExtra.GetStrongCryptoField(f))
{
for (int i = 0; i < sizeof(g_StrongCryptoPairs) / sizeof(g_StrongCryptoPairs[0]); i++)
{
const CStrongCryptoPair &pair = g_StrongCryptoPairs[i];
if (f.AlgId == pair.Id)
{
method += pair.Name;
finded = true;
break;
}
}
}
if (!finded)
method += kStrongCryptoMethod;
}
else
method += kZipCryptoMethod;
method += L" ";
}
}
if (methodId < kNumMethods)
method += kMethods[methodId];
else if (methodId == NFileHeader::NCompressionMethod::kWzPPMd)
method += kPPMdMethod;
else
{
wchar_t s[32];
ConvertUInt64ToString(methodId, s);
method += s;
}
prop = method;
break;
}
case kpidHostOS:
prop = (item.MadeByVersion.HostOS < kNumHostOSes) ?
(kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS;
break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
class CPropgressImp: public CProgressVirt
{
CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback;
public:
STDMETHOD(SetCompleted)(const UInt64 *numFiles);
void Init(IArchiveOpenCallback *openArchiveCallback)
{ m_OpenArchiveCallback = openArchiveCallback; }
};
STDMETHODIMP CPropgressImp::SetCompleted(const UInt64 *numFiles)
{
if (m_OpenArchiveCallback)
return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
return S_OK;
}
STDMETHODIMP CHandler::Open(IInStream *inStream,
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback)
{
COM_TRY_BEGIN
// try
{
if(!m_Archive.Open(inStream, maxCheckStartPosition))
return S_FALSE;
m_ArchiveIsOpen = true;
m_Items.Clear();
if (openArchiveCallback != NULL)
{
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
{
UInt16 ZipMethod;
CMyComPtr<ICompressCoder> Coder;
};
class CZipDecoder
{
NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec;
NCrypto::NWzAES::CDecoder *_aesDecoderSpec;
CMyComPtr<ICompressFilter> _zipCryptoDecoder;
CMyComPtr<ICompressFilter> _aesDecoder;
#ifdef ZIP_STRONG_SUPORT
NCrypto::NZipStrong::CDecoder *_zsDecoderSpec;
CMyComPtr<ICompressFilter> _zsDecoder;
#endif
CFilterCoder *filterStreamSpec;
CMyComPtr<ISequentialInStream> filterStream;
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
CObjectVector<CMethodItem> methodItems;
public:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?