Initialer Commit

This commit is contained in:
Tino Reichardt
2016-06-25 21:15:50 +02:00
commit c3967fe27a
1199 changed files with 290375 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,363 @@
// ZipAddCommon.cpp
#include "StdAfx.h"
#include "../../../../C/7zCrc.h"
#include "../../../../C/Alloc.h"
#include "../../../Windows/PropVariant.h"
#include "../../ICoder.h"
#include "../../IPassword.h"
#include "../../MyVersion.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/StreamUtils.h"
#include "../../Compress/LzmaEncoder.h"
#include "../../Compress/PpmdZip.h"
#include "../Common/InStreamWithCRC.h"
#include "ZipAddCommon.h"
#include "ZipHeader.h"
namespace NArchive {
namespace NZip {
static const CMethodId kMethodId_ZipBase = 0x040100;
static const CMethodId kMethodId_BZip2 = 0x040202;
static const UInt32 kLzmaPropsSize = 5;
static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
class CLzmaEncoder:
public ICompressCoder,
public ICompressSetCoderProperties,
public CMyUnknownImp
{
NCompress::NLzma::CEncoder *EncoderSpec;
CMyComPtr<ICompressCoder> Encoder;
Byte Header[kLzmaHeaderSize];
public:
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
};
STDMETHODIMP CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
if (!Encoder)
{
EncoderSpec = new NCompress::NLzma::CEncoder;
Encoder = EncoderSpec;
}
CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init(Header + 4, kLzmaPropsSize);
RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps));
RINOK(EncoderSpec->WriteCoderProperties(outStream));
if (outStreamSpec->GetPos() != kLzmaPropsSize)
return E_FAIL;
Header[0] = MY_VER_MAJOR;
Header[1] = MY_VER_MINOR;
Header[2] = kLzmaPropsSize;
Header[3] = 0;
return S_OK;
}
STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
RINOK(WriteStream(outStream, Header, kLzmaHeaderSize));
return Encoder->Code(inStream, outStream, inSize, outSize, progress);
}
CAddCommon::CAddCommon(const CCompressionMethodMode &options):
_options(options),
_copyCoderSpec(NULL),
_cryptoStreamSpec(NULL),
_buf(NULL)
{}
CAddCommon::~CAddCommon()
{
MidFree(_buf);
}
static const UInt32 kBufSize = ((UInt32)1 << 16);
HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
{
if (!_buf)
{
_buf = (Byte *)MidAlloc(kBufSize);
if (!_buf)
return E_OUTOFMEMORY;
}
UInt32 crc = CRC_INIT_VAL;
for (;;)
{
UInt32 processed;
RINOK(inStream->Read(_buf, kBufSize, &processed));
if (processed == 0)
{
resultCRC = CRC_GET_DIGEST(crc);
return S_OK;
}
crc = CrcUpdate(crc, _buf, (size_t)processed);
}
}
HRESULT CAddCommon::Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
UInt32 /* fileTime */,
ICompressProgressInfo *progress, CCompressingResult &opRes)
{
if (!inStream)
{
// We can create empty stream here. But it was already implemented in caller code in 9.33+
return E_INVALIDARG;
}
// CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL;
CInStreamWithCRC *inCrcStreamSpec = NULL;
CMyComPtr<ISequentialInStream> inCrcStream;
{
CMyComPtr<IInStream> inStream2;
inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
if (inStream2)
{
inCrcStreamSpec = new CInStreamWithCRC;
inCrcStream = inCrcStreamSpec;
inCrcStreamSpec->SetStream(inStream2);
inCrcStreamSpec->Init();
}
else
{
// we don't support stdin, since stream from stdin can require 64-bit size header
return E_NOTIMPL;
/*
inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
inCrcStream = inSecCrcStreamSpec;
inSecCrcStreamSpec->SetStream(inStream);
inSecCrcStreamSpec->Init();
*/
}
}
unsigned numTestMethods = _options.MethodSequence.Size();
if (numTestMethods > 1 && !inCrcStreamSpec)
numTestMethods = 1;
UInt32 crc = 0;
bool crc_IsCalculated = false;
Byte method = 0;
CFilterCoder::C_OutStream_Releaser outStreamReleaser;
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
opRes.FileTimeWasUsed = false;
for (unsigned i = 0; i < numTestMethods; i++)
{
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
if (inCrcStreamSpec)
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(outStream->SetSize(0));
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
if (_options.PasswordIsDefined)
{
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto;
if (!_cryptoStream)
{
_cryptoStreamSpec = new CFilterCoder(true);
_cryptoStream = _cryptoStreamSpec;
}
if (_options.IsAesMode)
{
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes;
if (!_cryptoStreamSpec->Filter)
{
_cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;
_filterAesSpec->SetKeyMode(_options.AesKeyMode);
RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()));
}
RINOK(_filterAesSpec->WriteHeader(outStream));
}
else
{
if (!_cryptoStreamSpec->Filter)
{
_cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
_filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len());
}
UInt32 check;
// if (inCrcStreamSpec)
{
if (!crc_IsCalculated)
{
RINOK(CalcStreamCRC(inStream, crc));
crc_IsCalculated = true;
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
}
check = (crc >> 16);
}
/*
else
{
opRes.FileTimeWasUsed = true;
check = (fileTime & 0xFFFF);
}
*/
RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
}
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
RINOK(_cryptoStreamSpec->InitEncoder());
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
}
method = _options.MethodSequence[i];
switch (method)
{
case NFileHeader::NCompressionMethod::kStored:
{
if (_copyCoderSpec == NULL)
{
_copyCoderSpec = new NCompress::CCopyCoder;
_copyCoder = _copyCoderSpec;
}
CMyComPtr<ISequentialOutStream> outStreamNew;
if (_options.PasswordIsDefined)
outStreamNew = _cryptoStream;
else
outStreamNew = outStream;
RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
break;
}
default:
{
if (!_compressEncoder)
{
if (method == NFileHeader::NCompressionMethod::kLZMA)
{
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA;
CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder();
_compressEncoder = _lzmaEncoder;
}
else if (method == NFileHeader::NCompressionMethod::kPPMd)
{
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
_compressEncoder = encoder;
}
else
{
CMethodId methodId;
switch (method)
{
case NFileHeader::NCompressionMethod::kBZip2:
methodId = kMethodId_BZip2;
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_BZip2;
break;
default:
_compressExtractVersion = ((method == NFileHeader::NCompressionMethod::kDeflated64) ?
NFileHeader::NCompressionMethod::kExtractVersion_Deflate64 :
NFileHeader::NCompressionMethod::kExtractVersion_Deflate);
methodId = kMethodId_ZipBase + method;
break;
}
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
methodId, true, _compressEncoder));
if (!_compressEncoder)
return E_NOTIMPL;
if (method == NFileHeader::NCompressionMethod::kDeflated ||
method == NFileHeader::NCompressionMethod::kDeflated64)
{
}
else if (method == NFileHeader::NCompressionMethod::kBZip2)
{
}
}
{
CMyComPtr<ICompressSetCoderProperties> setCoderProps;
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
if (setCoderProps)
{
RINOK(_options.MethodInfo.SetCoderProps(setCoderProps,
_options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
}
}
}
CMyComPtr<ISequentialOutStream> outStreamNew;
if (_options.PasswordIsDefined)
outStreamNew = _cryptoStream;
else
outStreamNew = outStream;
if (_compressExtractVersion > opRes.ExtractVersion)
opRes.ExtractVersion = _compressExtractVersion;
RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
break;
}
}
if (_options.PasswordIsDefined)
{
RINOK(_cryptoStreamSpec->OutStreamFinish());
if (_options.IsAesMode)
{
RINOK(_filterAesSpec->WriteFooter(outStream));
}
}
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
// if (inCrcStreamSpec)
{
opRes.CRC = inCrcStreamSpec->GetCRC();
opRes.UnpackSize = inCrcStreamSpec->GetSize();
}
/*
else
{
opRes.CRC = inSecCrcStreamSpec->GetCRC();
opRes.UnpackSize = inSecCrcStreamSpec->GetSize();
}
*/
if (_options.PasswordIsDefined)
{
if (opRes.PackSize < opRes.UnpackSize +
(_options.IsAesMode ? _filterAesSpec->GetAddPackSize() : NCrypto::NZip::kHeaderSize))
break;
}
else if (opRes.PackSize < opRes.UnpackSize)
break;
}
opRes.Method = method;
return S_OK;
}
}}

View File

@@ -0,0 +1,62 @@
// ZipAddCommon.h
#ifndef __ZIP_ADD_COMMON_H
#define __ZIP_ADD_COMMON_H
#include "../../ICoder.h"
#include "../../IProgress.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
#include "../../Compress/CopyCoder.h"
#include "../../Crypto/ZipCrypto.h"
#include "../../Crypto/WzAes.h"
#include "ZipCompressionMode.h"
namespace NArchive {
namespace NZip {
struct CCompressingResult
{
UInt64 UnpackSize;
UInt64 PackSize;
UInt32 CRC;
UInt16 Method;
Byte ExtractVersion;
bool FileTimeWasUsed;
};
class CAddCommon
{
CCompressionMethodMode _options;
NCompress::CCopyCoder *_copyCoderSpec;
CMyComPtr<ICompressCoder> _copyCoder;
CMyComPtr<ICompressCoder> _compressEncoder;
Byte _compressExtractVersion;
CFilterCoder *_cryptoStreamSpec;
CMyComPtr<ISequentialOutStream> _cryptoStream;
NCrypto::NZip::CEncoder *_filterSpec;
NCrypto::NWzAes::CEncoder *_filterAesSpec;
Byte *_buf;
HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC);
public:
CAddCommon(const CCompressionMethodMode &options);
~CAddCommon();
HRESULT Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
UInt32 fileTime,
ICompressProgressInfo *progress, CCompressingResult &operationResult);
};
}}
#endif

View File

@@ -0,0 +1,62 @@
// CompressionMode.h
#ifndef __ZIP_COMPRESSION_MODE_H
#define __ZIP_COMPRESSION_MODE_H
#include "../../../Common/MyString.h"
#ifndef _7ZIP_ST
#include "../../../Windows/System.h"
#endif
#include "../Common/HandlerOut.h"
namespace NArchive {
namespace NZip {
struct CBaseProps
{
CMethodProps MethodInfo;
Int32 Level;
#ifndef _7ZIP_ST
UInt32 NumThreads;
bool NumThreadsWasChanged;
#endif
bool IsAesMode;
Byte AesKeyMode;
void Init()
{
MethodInfo.Clear();
Level = -1;
#ifndef _7ZIP_ST
NumThreads = NWindows::NSystem::GetNumberOfProcessors();;
NumThreadsWasChanged = false;
#endif
IsAesMode = false;
AesKeyMode = 3;
}
};
struct CCompressionMethodMode: public CBaseProps
{
CRecordVector<Byte> MethodSequence;
bool PasswordIsDefined;
AString Password;
UInt64 _dataSizeReduce;
bool _dataSizeReduceDefined;
bool IsRealAesMode() const { return PasswordIsDefined && IsAesMode; }
CCompressionMethodMode(): PasswordIsDefined(false)
{
_dataSizeReduceDefined = false;
_dataSizeReduce = 0;
}
};
}}
#endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
// Zip/Handler.h
#ifndef __ZIP_HANDLER_H
#define __ZIP_HANDLER_H
#include "../../../Common/DynamicBuffer.h"
#include "../../ICoder.h"
#include "../IArchive.h"
#include "../../Common/CreateCoder.h"
#include "ZipIn.h"
#include "ZipCompressionMode.h"
namespace NArchive {
namespace NZip {
class CHandler:
public IInArchive,
public IOutArchive,
public ISetProperties,
PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
MY_QUERYINTERFACE_ENTRY(IOutArchive)
MY_QUERYINTERFACE_ENTRY(ISetProperties)
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
DECL_ISetCompressCodecsInfo
CHandler();
private:
CObjectVector<CItemEx> m_Items;
CInArchive m_Archive;
CBaseProps _props;
int m_MainMethod;
bool m_ForceAesMode;
bool m_WriteNtfsTimeExtra;
bool _removeSfxBlock;
bool m_ForceLocal;
bool m_ForceUtf8;
bool _forceCodePage;
UInt32 _specifiedCodePage;
DECL_EXTERNAL_CODECS_VARS
void InitMethodProps()
{
_props.Init();
m_MainMethod = -1;
m_ForceAesMode = false;
m_WriteNtfsTimeExtra = true;
_removeSfxBlock = false;
m_ForceLocal = false;
m_ForceUtf8 = false;
_forceCodePage = false;
_specifiedCodePage = CP_OEMCP;
}
};
}}
#endif

View File

@@ -0,0 +1,442 @@
// ZipHandlerOut.cpp
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/TimeUtils.h"
#include "../../IPassword.h"
#include "../../Common/OutBuffer.h"
#include "../../Crypto/WzAes.h"
#include "../Common/ItemNameUtils.h"
#include "../Common/ParseProperties.h"
#include "ZipHandler.h"
#include "ZipUpdate.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;
}
static bool IsSimpleAsciiString(const wchar_t *s)
{
for (;;)
{
wchar_t c = *s++;
if (c == 0)
return true;
if (c < 0x20 || c > 0x7F)
return false;
}
}
#define COM_TRY_BEGIN2 try {
#define COM_TRY_END2 } \
catch(const CSystemException &e) { return e.ErrorCode; } \
catch(...) { return E_OUTOFMEMORY; }
static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime)
{
filetime.dwHighDateTime = filetime.dwLowDateTime = 0;
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(index, propID, &prop));
if (prop.vt == VT_FILETIME)
filetime = prop.filetime;
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
return S_OK;
}
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN2
if (m_Archive.IsOpen())
{
if (!m_Archive.CanUpdate())
return E_NOTIMPL;
}
CObjectVector<CUpdateItem> updateItems;
bool thereAreAesUpdates = false;
UInt64 largestSize = 0;
bool largestSizeDefined = false;
for (UInt32 i = 0; i < numItems; i++)
{
CUpdateItem ui;
Int32 newData;
Int32 newProps;
UInt32 indexInArchive;
if (!callback)
return E_FAIL;
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData);
ui.IndexInArc = indexInArchive;
ui.IndexInClient = i;
bool existInArchive = (indexInArchive != (UInt32)(Int32)-1);
if (existInArchive && newData)
if (m_Items[indexInArchive].IsAesEncrypted())
thereAreAesUpdates = true;
if (IntToBool(newProps))
{
UString name;
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidAttrib, &prop));
if (prop.vt == VT_EMPTY)
ui.Attrib = 0;
else if (prop.vt != VT_UI4)
return E_INVALIDARG;
else
ui.Attrib = prop.ulVal;
}
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidPath, &prop));
if (prop.vt == VT_EMPTY)
name.Empty();
else if (prop.vt != VT_BSTR)
return E_INVALIDARG;
else
name = prop.bstrVal;
}
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidIsDir, &prop));
if (prop.vt == VT_EMPTY)
ui.IsDir = false;
else if (prop.vt != VT_BOOL)
return E_INVALIDARG;
else
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
}
{
CPropVariant prop;
RINOK(callback->GetProperty(i, kpidTimeType, &prop));
if (prop.vt == VT_UI4)
ui.NtfsTimeIsDefined = (prop.ulVal == NFileTimeType::kWindows);
else
ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra;
}
RINOK(GetTime(callback, i, kpidMTime, ui.Ntfs_MTime));
RINOK(GetTime(callback, i, kpidATime, ui.Ntfs_ATime));
RINOK(GetTime(callback, i, kpidCTime, ui.Ntfs_CTime));
{
FILETIME localFileTime = { 0, 0 };
if (ui.Ntfs_MTime.dwHighDateTime != 0 ||
ui.Ntfs_MTime.dwLowDateTime != 0)
if (!FileTimeToLocalFileTime(&ui.Ntfs_MTime, &localFileTime))
return E_INVALIDARG;
FileTimeToDosTime(localFileTime, ui.Time);
}
name = NItemName::MakeLegalName(name);
bool needSlash = ui.IsDir;
const wchar_t kSlash = L'/';
if (!name.IsEmpty())
{
if (name.Back() == kSlash)
{
if (!ui.IsDir)
return E_INVALIDARG;
needSlash = false;
}
}
if (needSlash)
name += kSlash;
UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP;
bool tryUtf8 = true;
if ((m_ForceLocal || !m_ForceUtf8) && codePage != CP_UTF8)
{
bool defaultCharWasUsed;
ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed);
tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||
MultiByteToUnicodeString(ui.Name, codePage) != name));
}
if (tryUtf8)
{
ui.IsUtf8 = !name.IsAscii();
ConvertUnicodeToUTF8(name, ui.Name);
}
if (ui.Name.Len() >= (1 << 16))
return E_INVALIDARG;
ui.IndexInClient = i;
/*
if (existInArchive)
{
const CItemEx &itemInfo = m_Items[indexInArchive];
// ui.Commented = itemInfo.IsCommented();
ui.Commented = false;
if (ui.Commented)
{
ui.CommentRange.Position = itemInfo.GetCommentPosition();
ui.CommentRange.Size = itemInfo.CommentSize;
}
}
else
ui.Commented = false;
*/
}
if (IntToBool(newData))
{
UInt64 size = 0;
if (!ui.IsDir)
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
if (largestSize < size)
largestSize = size;
largestSizeDefined = true;
}
ui.Size = size;
// ui.Size -= ui.Size / 2;
}
updateItems.Add(ui);
}
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
{
CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback);
udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
}
CCompressionMethodMode options;
(CBaseProps &)options = _props;
options._dataSizeReduce = largestSize;
options._dataSizeReduceDefined = largestSizeDefined;
options.PasswordIsDefined = false;
options.Password.Empty();
if (getTextPassword)
{
CMyComBSTR password;
Int32 passwordIsDefined;
RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password));
options.PasswordIsDefined = IntToBool(passwordIsDefined);
if (options.PasswordIsDefined)
{
if (!m_ForceAesMode)
options.IsAesMode = thereAreAesUpdates;
if (!IsSimpleAsciiString(password))
return E_INVALIDARG;
if (password)
options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP);
if (options.IsAesMode)
{
if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax)
return E_INVALIDARG;
}
}
}
Byte mainMethod;
if (m_MainMethod < 0)
mainMethod = (Byte)(((_props.Level == 0) ?
NFileHeader::NCompressionMethod::kStored :
NFileHeader::NCompressionMethod::kDeflated));
else
mainMethod = (Byte)m_MainMethod;
options.MethodSequence.Add(mainMethod);
if (mainMethod != NFileHeader::NCompressionMethod::kStored)
options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
return Update(
EXTERNAL_CODECS_VARS
m_Items, updateItems, outStream,
m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock,
&options, callback);
COM_TRY_END2
}
struct CMethodIndexToName
{
unsigned Method;
const char *Name;
};
static const CMethodIndexToName k_SupportedMethods[] =
{
{ NFileHeader::NCompressionMethod::kStored, "copy" },
{ NFileHeader::NCompressionMethod::kDeflated, "deflate" },
{ NFileHeader::NCompressionMethod::kDeflated64, "deflate64" },
{ NFileHeader::NCompressionMethod::kBZip2, "bzip2" },
{ NFileHeader::NCompressionMethod::kLZMA, "lzma" },
{ NFileHeader::NCompressionMethod::kPPMd, "ppmd" }
};
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitMethodProps();
#ifndef _7ZIP_ST
const UInt32 numProcessors = _props.NumThreads;
#endif
for (UInt32 i = 0; i < numProps; i++)
{
UString name = names[i];
name.MakeLower_Ascii();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &prop = values[i];
if (name[0] == L'x')
{
UInt32 level = 9;
RINOK(ParsePropToUInt32(name.Ptr(1), prop, level));
_props.Level = level;
_props.MethodInfo.AddProp_Level(level);
}
else if (name == L"m")
{
if (prop.vt == VT_BSTR)
{
UString m = prop.bstrVal, m2;
m.MakeLower_Ascii();
int colonPos = m.Find(L':');
if (colonPos >= 0)
{
m2 = m.Ptr(colonPos + 1);
m.DeleteFrom(colonPos);
}
unsigned k;
for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
{
const CMethodIndexToName &pair = k_SupportedMethods[k];
if (m.IsEqualTo(pair.Name))
{
if (!m2.IsEmpty())
{
RINOK(_props.MethodInfo.ParseParamsFromString(m2));
}
m_MainMethod = pair.Method;
break;
}
}
if (k == ARRAY_SIZE(k_SupportedMethods))
return E_INVALIDARG;
}
else if (prop.vt == VT_UI4)
{
unsigned k;
for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
{
unsigned method = k_SupportedMethods[k].Method;
if (prop.ulVal == method)
{
m_MainMethod = method;
break;
}
}
if (k == ARRAY_SIZE(k_SupportedMethods))
return E_INVALIDARG;
}
else
return E_INVALIDARG;
}
else if (name.IsPrefixedBy(L"em"))
{
if (prop.vt != VT_BSTR)
return E_INVALIDARG;
{
UString m = prop.bstrVal;
m.MakeLower_Ascii();
if (m.IsPrefixedBy(L"aes"))
{
m.DeleteFrontal(3);
if (m == L"128")
_props.AesKeyMode = 1;
else if (m == L"192")
_props.AesKeyMode = 2;
else if (m == L"256" || m.IsEmpty())
_props.AesKeyMode = 3;
else
return E_INVALIDARG;
_props.IsAesMode = true;
m_ForceAesMode = true;
}
else if (m == L"zipcrypto")
{
_props.IsAesMode = false;
m_ForceAesMode = true;
}
else
return E_INVALIDARG;
}
}
else if (name.IsPrefixedBy(L"mt"))
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Ptr(2), prop, numProcessors, _props.NumThreads));
_props.NumThreadsWasChanged = true;
#endif
}
else if (name.IsEqualTo("tc"))
{
RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra));
}
else if (name.IsEqualTo("cl"))
{
RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal));
if (m_ForceLocal)
m_ForceUtf8 = false;
}
else if (name.IsEqualTo("cu"))
{
RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8));
if (m_ForceUtf8)
m_ForceLocal = false;
}
else if (name.IsEqualTo("cp"))
{
UInt32 cp = CP_OEMCP;
RINOK(ParsePropToUInt32(L"", prop, cp));
_forceCodePage = true;
_specifiedCodePage = cp;
}
else if (name.IsEqualTo("rsfx"))
{
RINOK(PROPVARIANT_to_bool(prop, _removeSfxBlock));
}
else
{
RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));
}
}
return S_OK;
}
}}

View File

@@ -0,0 +1,176 @@
// ZipHeader.h
#ifndef __ARCHIVE_ZIP_HEADER_H
#define __ARCHIVE_ZIP_HEADER_H
#include "../../../Common/MyTypes.h"
namespace NArchive {
namespace NZip {
const unsigned kMarkerSize = 4;
namespace NSignature
{
const UInt32 kLocalFileHeader = 0x04034B50;
const UInt32 kDataDescriptor = 0x08074B50;
const UInt32 kCentralFileHeader = 0x02014B50;
const UInt32 kEcd = 0x06054B50;
const UInt32 kEcd64 = 0x06064B50;
const UInt32 kEcd64Locator = 0x07064B50;
const UInt32 kSpan = 0x08074B50;
const UInt32 kNoSpan = 0x30304B50; // PK00, replaces kSpan, if there is only 1 segment
}
const unsigned kLocalHeaderSize = 4 + 26; // including signature
const unsigned kDataDescriptorSize = 4 + 12; // including signature
const unsigned kCentralHeaderSize = 4 + 42; // including signature
const unsigned kEcdSize = 22; // including signature
const unsigned kEcd64_MainSize = 44;
const unsigned kEcd64_FullSize = 12 + kEcd64_MainSize;
const unsigned kEcd64Locator_Size = 20;
namespace NFileHeader
{
namespace NCompressionMethod
{
enum EType
{
kStored = 0,
kShrunk = 1,
kReduced1 = 2,
kReduced2 = 3,
kReduced3 = 4,
kReduced4 = 5,
kImploded = 6,
kReservedTokenizing = 7, // reserved for tokenizing
kDeflated = 8,
kDeflated64 = 9,
kPKImploding = 10,
kBZip2 = 12,
kLZMA = 14,
kTerse = 18,
kLz77 = 19,
kXz = 0x5F,
kJpeg = 0x60,
kWavPack = 0x61,
kPPMd = 0x62,
kWzAES = 0x63
};
const Byte kMadeByProgramVersion = 63;
const Byte kExtractVersion_Default = 10;
const Byte kExtractVersion_Dir = 20;
const Byte kExtractVersion_ZipCrypto = 20;
const Byte kExtractVersion_Deflate = 20;
const Byte kExtractVersion_Deflate64 = 21;
const Byte kExtractVersion_Zip64 = 45;
const Byte kExtractVersion_BZip2 = 46;
const Byte kExtractVersion_Aes = 51;
const Byte kExtractVersion_LZMA = 63;
const Byte kExtractVersion_PPMd = 63;
}
namespace NExtraID
{
enum
{
kZip64 = 0x01,
kNTFS = 0x0A,
kStrongEncrypt = 0x17,
kUnixTime = 0x5455,
kIzUnicodeComment = 0x6375,
kIzUnicodeName = 0x7075,
kWzAES = 0x9901
};
}
namespace NNtfsExtra
{
const UInt16 kTagTime = 1;
enum
{
kMTime = 0,
kATime,
kCTime
};
}
namespace NUnixTime
{
enum
{
kMTime = 0,
kATime,
kCTime
};
}
namespace NFlags
{
const unsigned kEncrypted = 1 << 0;
const unsigned kLzmaEOS = 1 << 1;
const unsigned kDescriptorUsedMask = 1 << 3;
const unsigned kStrongEncrypted = 1 << 6;
const unsigned kUtf8 = 1 << 11;
const unsigned kImplodeDictionarySizeMask = 1 << 1;
const unsigned kImplodeLiteralsOnMask = 1 << 2;
const unsigned kDeflateTypeBitStart = 1;
const unsigned kNumDeflateTypeBits = 2;
const unsigned kNumDeflateTypes = (1 << kNumDeflateTypeBits);
const unsigned kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;
}
namespace NHostOS
{
enum EEnum
{
kFAT = 0,
kAMIGA = 1,
kVMS = 2, // VAX/VMS
kUnix = 3,
kVM_CMS = 4,
kAtari = 5, // what if it's a minix filesystem? [cjh]
kHPFS = 6, // filesystem used by OS/2 (and NT 3.x)
kMac = 7,
kZ_System = 8,
kCPM = 9,
kTOPS20 = 10, // pkzip 2.50 NTFS
kNTFS = 11, // filesystem used by Windows NT
kQDOS = 12, // SMS/QDOS
kAcorn = 13, // Archimedes Acorn RISC OS
kVFAT = 14, // filesystem used by Windows 95, NT
kMVS = 15,
kBeOS = 16, // hybrid POSIX/database filesystem
kTandem = 17,
kOS400 = 18,
kOSX = 19
};
}
namespace NAmigaAttrib
{
const UInt32 kIFMT = 06000; // Amiga file type mask
const UInt32 kIFDIR = 04000; // Amiga directory
const UInt32 kIFREG = 02000; // Amiga regular file
const UInt32 kIHIDDEN = 00200; // to be supported in AmigaDOS 3.x
const UInt32 kISCRIPT = 00100; // executable script (text command file)
const UInt32 kIPURE = 00040; // allow loading into resident memory
const UInt32 kIARCHIVE = 00020; // not modified since bit was last set
const UInt32 kIREAD = 00010; // can be opened for reading
const UInt32 kIWRITE = 00004; // can be opened for writing
const UInt32 kIEXECUTE = 00002; // executable image, a loadable runfile
const UInt32 kIDELETE = 00001; // can be deleted
}
}
}}
#endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,356 @@
// Archive/ZipIn.h
#ifndef __ZIP_IN_H
#define __ZIP_IN_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
#include "../../Common/InBuffer.h"
#include "ZipHeader.h"
#include "ZipItem.h"
API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size);
namespace NArchive {
namespace NZip {
class CItemEx: public CItem
{
public:
UInt32 LocalFullHeaderSize; // including Name and Extra
UInt64 GetLocalFullSize() const
{ return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); }
UInt64 GetDataPosition() const
{ return LocalHeaderPos + LocalFullHeaderSize; }
};
struct CInArchiveInfo
{
Int64 Base; /* Base offset of start of archive in stream.
Offsets in headers must be calculated from that Base.
Base is equal to MarkerPos for normal ZIPs.
Base can point to PE stub for some ZIP SFXs.
if CentralDir was read,
Base can be negative, if start of data is not available,
if CentralDirs was not read,
Base = ArcInfo.MarkerPos; */
/* The following *Pos variables contain absolute offsets in Stream */
UInt64 MarkerPos; /* Pos of first signature, it can point to kSpan/kNoSpan signature
= MarkerPos2 in most archives
= MarkerPos2 - 4 if there is kSpan/kNoSpan signature */
UInt64 MarkerPos2; // Pos of first local item signature in stream
UInt64 FinishPos; // Finish pos of archive data in starting volume
UInt64 FileEndPos; // Finish pos of stream
UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base).
= 0 in most archives
= size of stub for some SFXs */
bool CdWasRead;
bool IsSpanMode;
bool ThereIsTail;
// UInt32 BaseVolIndex;
CByteBuffer Comment;
CInArchiveInfo():
Base(0),
MarkerPos(0),
MarkerPos2(0),
FinishPos(0),
FileEndPos(0),
FirstItemRelatOffset(0),
CdWasRead(false),
IsSpanMode(false),
ThereIsTail(false)
// BaseVolIndex(0)
{}
void Clear()
{
// BaseVolIndex = 0;
Base = 0;
MarkerPos = 0;
MarkerPos2 = 0;
FinishPos = 0;
FileEndPos = 0;
ThereIsTail = false;
FirstItemRelatOffset = 0;
CdWasRead = false;
IsSpanMode = false;
Comment.Free();
}
};
struct CCdInfo
{
// 64
UInt16 VersionMade;
UInt16 VersionNeedExtract;
// old zip
UInt32 ThisDisk;
UInt32 CdDisk;
UInt64 NumEntries_in_ThisDisk;
UInt64 NumEntries;
UInt64 Size;
UInt64 Offset;
UInt16 CommentSize;
CCdInfo() { memset(this, 0, sizeof(*this)); }
void ParseEcd32(const Byte *p); // (p) includes signature
void ParseEcd64e(const Byte *p); // (p) exclude signature
};
class CVols
{
public:
struct CSubStreamInfo
{
CMyComPtr<IInStream> Stream;
UInt64 Size;
CSubStreamInfo(): Size(0) {}
};
CObjectVector<CSubStreamInfo> Streams;
int StreamIndex;
bool NeedSeek;
CMyComPtr<IInStream> ZipStream;
bool StartIsExe; // is .exe
bool StartIsZ; // is .zip or .zNN
bool StartIsZip; // is .zip
bool IsUpperCase;
Int32 StartVolIndex; // = (NN - 1), if StartStream is .zNN
Int32 StartParsingVol; // if we need local parsing, we must use that stream
unsigned NumVols;
int EndVolIndex; // index of last volume (ecd volume),
// -1, if is not multivol
UString BaseName; // including '.'
UString MissingName;
CCdInfo ecd;
bool ecd_wasRead;
void Clear()
{
StreamIndex = -1;
NeedSeek = false;
StartIsExe = false;
StartIsZ = false;
StartIsZip = false;
IsUpperCase = false;
StartVolIndex = -1;
StartParsingVol = 0;
NumVols = 0;
EndVolIndex = -1;
BaseName.Empty();
MissingName.Empty();
ecd_wasRead = false;
Streams.Clear();
ZipStream.Release();
}
HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
UInt64 GetTotalSize() const
{
UInt64 total = 0;
FOR_VECTOR (i, Streams)
total += Streams[i].Size;
return total;
}
};
class CVolStream:
public ISequentialInStream,
public CMyUnknownImp
{
public:
CVols *Vols;
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
class CInArchive
{
CInBuffer _inBuffer;
bool _inBufMode;
UInt32 m_Signature;
UInt64 m_Position;
UInt64 _processedCnt;
bool CanStartNewVol;
CMyComPtr<IInStream> StreamRef;
IInStream *Stream;
IInStream *StartStream;
bool IsArcOpen;
HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,
unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);
HRESULT ReadVols();
HRESULT Seek(UInt64 offset);
HRESULT FindMarker(IInStream *stream, const UInt64 *searchLimit);
HRESULT IncreaseRealPosition(Int64 addValue, bool &isFinished);
HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
void SafeReadBytes(void *data, unsigned size);
void ReadBuffer(CByteBuffer &buffer, unsigned size);
Byte ReadByte();
UInt16 ReadUInt16();
UInt32 ReadUInt32();
UInt64 ReadUInt64();
void Skip(unsigned num);
void Skip64(UInt64 num);
void ReadFileName(unsigned nameSize, AString &dest);
bool ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber);
bool ReadLocalItem(CItemEx &item);
HRESULT ReadLocalItemDescriptor(CItemEx &item);
HRESULT ReadCdItem(CItemEx &item);
HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);
HRESULT FindCd(bool checkOffsetMode);
HRESULT TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize);
HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize);
HRESULT ReadLocals(CObjectVector<CItemEx> &localItems);
HRESULT ReadHeaders2(CObjectVector<CItemEx> &items);
HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream);
public:
CInArchiveInfo ArcInfo;
bool IsArc;
bool IsZip64;
bool HeadersError;
bool HeadersWarning;
bool ExtraMinorError;
bool UnexpectedEnd;
bool NoCentralDir;
bool MarkerIsFound;
bool IsMultiVol;
bool UseDisk_in_SingleVol;
UInt32 EcdVolIndex;
CVols Vols;
IArchiveOpenCallback *Callback;
CInArchive(): Stream(NULL), Callback(NULL), IsArcOpen(false) {}
UInt64 GetPhySize() const
{
if (IsMultiVol)
return ArcInfo.FinishPos;
else
return ArcInfo.FinishPos - ArcInfo.Base;
}
UInt64 GetOffset() const
{
if (IsMultiVol)
return 0;
else
return ArcInfo.Base;
}
void ClearRefs();
void Close();
HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items);
HRESULT ReadHeaders(CObjectVector<CItemEx> &items);
bool IsOpen() const { return IsArcOpen; }
bool AreThereErrors() const
{
return HeadersError
|| UnexpectedEnd
|| !Vols.MissingName.IsEmpty();
}
bool IsLocalOffsetOK(const CItemEx &item) const
{
if (item.FromLocal)
return true;
return (Int64)GetOffset() + (Int64)item.LocalHeaderPos >= 0;
}
UInt64 GetEmbeddedStubSize() const
{
if (ArcInfo.CdWasRead)
return ArcInfo.FirstItemRelatOffset;
if (IsMultiVol)
return 0;
return ArcInfo.MarkerPos2 - ArcInfo.Base;
}
HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail);
HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);
HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream);
IInStream *GetBaseStream() { return StreamRef; }
bool CanUpdate() const
{
if (AreThereErrors()
|| IsMultiVol
|| ArcInfo.Base < 0
|| (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base
|| ArcInfo.ThereIsTail
|| GetEmbeddedStubSize() != 0)
return false;
// 7-zip probably can update archives with embedded stubs.
// we just disable that feature for more safety.
return true;
}
};
}}
#endif

View File

@@ -0,0 +1,253 @@
// Archive/ZipItem.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../../../C/7zCrc.h"
#include "../../../Common/MyLinux.h"
#include "../../../Common/StringConvert.h"
#include "../Common/ItemNameUtils.h"
#include "ZipItem.h"
namespace NArchive {
namespace NZip {
using namespace NFileHeader;
bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const
{
ft.dwHighDateTime = ft.dwLowDateTime = 0;
UInt32 size = (UInt32)Data.Size();
if (ID != NExtraID::kNTFS || size < 32)
return false;
const Byte *p = (const Byte *)Data;
p += 4; // for reserved
size -= 4;
while (size > 4)
{
UInt16 tag = GetUi16(p);
unsigned attrSize = GetUi16(p + 2);
p += 4;
size -= 4;
if (attrSize > size)
attrSize = size;
if (tag == NNtfsExtra::kTagTime && attrSize >= 24)
{
p += 8 * index;
ft.dwLowDateTime = GetUi32(p);
ft.dwHighDateTime = GetUi32(p + 4);
return true;
}
p += attrSize;
size -= attrSize;
}
return false;
}
bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const
{
res = 0;
UInt32 size = (UInt32)Data.Size();
if (ID != NExtraID::kUnixTime || size < 5)
return false;
const Byte *p = (const Byte *)Data;
Byte flags = *p++;
size--;
if (isCentral)
{
if (index != NUnixTime::kMTime ||
(flags & (1 << NUnixTime::kMTime)) == 0 ||
size < 4)
return false;
res = GetUi32(p);
return true;
}
for (unsigned i = 0; i < 3; i++)
if ((flags & (1 << i)) != 0)
{
if (size < 4)
return false;
if (index == i)
{
res = GetUi32(p);
return true;
}
p += 4;
size -= 4;
}
return false;
}
bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const
{
FOR_VECTOR (i, SubBlocks)
{
const CExtraSubBlock &sb = SubBlocks[i];
if (sb.ID == NFileHeader::NExtraID::kNTFS)
return sb.ExtractNtfsTime(index, ft);
}
return false;
}
bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const
{
FOR_VECTOR (i, SubBlocks)
{
const CExtraSubBlock &sb = SubBlocks[i];
if (sb.ID == NFileHeader::NExtraID::kUnixTime)
return sb.ExtractUnixTime(isCentral, index, res);
}
return false;
}
bool CLocalItem::IsDir() const
{
return NItemName::HasTailSlash(Name, GetCodePage());
}
bool CItem::IsDir() const
{
if (NItemName::HasTailSlash(Name, GetCodePage()))
return true;
Byte hostOS = GetHostOS();
if (Size == 0 && PackSize == 0 && !Name.IsEmpty() && Name.Back() == '\\')
{
// do we need to use CharPrevExA?
// .NET Framework 4.5 : System.IO.Compression::CreateFromDirectory() probably writes backslashes to headers?
// so we support that case
switch (hostOS)
{
case NHostOS::kFAT:
case NHostOS::kNTFS:
case NHostOS::kHPFS:
case NHostOS::kVFAT:
return true;
}
}
if (!FromCentral)
return false;
UInt16 highAttrib = (UInt16)((ExternalAttrib >> 16 ) & 0xFFFF);
switch (hostOS)
{
case NHostOS::kAMIGA:
switch (highAttrib & NAmigaAttrib::kIFMT)
{
case NAmigaAttrib::kIFDIR: return true;
case NAmigaAttrib::kIFREG: return false;
default: return false; // change it throw kUnknownAttributes;
}
case NHostOS::kFAT:
case NHostOS::kNTFS:
case NHostOS::kHPFS:
case NHostOS::kVFAT:
return ((ExternalAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0);
case NHostOS::kAtari:
case NHostOS::kMac:
case NHostOS::kVMS:
case NHostOS::kVM_CMS:
case NHostOS::kAcorn:
case NHostOS::kMVS:
return false; // change it throw kUnknownAttributes;
case NHostOS::kUnix:
return MY_LIN_S_ISDIR(highAttrib);
default:
return false;
}
}
UInt32 CItem::GetWinAttrib() const
{
UInt32 winAttrib = 0;
switch (GetHostOS())
{
case NHostOS::kFAT:
case NHostOS::kNTFS:
if (FromCentral)
winAttrib = ExternalAttrib;
break;
case NHostOS::kUnix:
// do we need to clear 16 low bits in this case?
if (FromCentral)
winAttrib = ExternalAttrib & 0xFFFF0000;
break;
}
if (IsDir()) // test it;
winAttrib |= FILE_ATTRIBUTE_DIRECTORY;
return winAttrib;
}
bool CItem::GetPosixAttrib(UInt32 &attrib) const
{
// some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT.
if (FromCentral && GetHostOS() == NHostOS::kUnix)
{
attrib = ExternalAttrib >> 16;
return (attrib != 0);
}
attrib = 0;
if (IsDir())
attrib = MY_LIN_S_IFDIR;
return false;
}
void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const
{
bool isUtf8 = IsUtf8();
bool ignore_Utf8_Errors = true;
if (!isUtf8)
{
{
const unsigned id = isComment ?
NFileHeader::NExtraID::kIzUnicodeComment:
NFileHeader::NExtraID::kIzUnicodeName;
const CObjectVector<CExtraSubBlock> &subBlocks = GetMainExtra().SubBlocks;
FOR_VECTOR (i, subBlocks)
{
const CExtraSubBlock &sb = subBlocks[i];
if (sb.ID == id)
{
AString utf;
if (sb.ExtractIzUnicode(CrcCalc(s, s.Len()), utf))
if (ConvertUTF8ToUnicode(utf, res))
return;
break;
}
}
}
if (useSpecifiedCodePage)
isUtf8 = (codePage == CP_UTF8);
#ifdef _WIN32
else if (GetHostOS() == NFileHeader::NHostOS::kUnix)
{
/* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header.
We try to get name as UTF-8.
Do we need to do it in POSIX version also? */
isUtf8 = true;
ignore_Utf8_Errors = false;
}
#endif
}
if (isUtf8)
if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors)
return;
MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage());
}
}}

View File

@@ -0,0 +1,310 @@
// Archive/ZipItem.h
#ifndef __ARCHIVE_ZIP_ITEM_H
#define __ARCHIVE_ZIP_ITEM_H
#include "../../../../C/CpuArch.h"
#include "../../../Common/MyBuffer.h"
#include "../../../Common/MyString.h"
#include "../../../Common/UTFConvert.h"
#include "ZipHeader.h"
namespace NArchive {
namespace NZip {
struct CVersion
{
Byte Version;
Byte HostOS;
};
struct CExtraSubBlock
{
UInt16 ID;
CByteBuffer Data;
bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;
bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
bool ExtractIzUnicode(UInt32 crc, AString &name) const
{
unsigned size = (unsigned)Data.Size();
if (size < 1 + 4)
return false;
const Byte *p = (const Byte *)Data;
if (p[0] > 1)
return false;
if (crc != GetUi32(p + 1))
return false;
size -= 5;
name.SetFrom_CalcLen((const char *)p + 5, size);
if (size != name.Len())
return false;
return CheckUTF8(name, false);
}
};
const unsigned k_WzAesExtra_Size = 7;
struct CWzAesExtra
{
UInt16 VendorVersion; // 1: AE-1, 2: AE-2,
// UInt16 VendorId; // 'A' 'E'
Byte Strength; // 1: 128-bit, 2: 192-bit, 3: 256-bit
UInt16 Method;
CWzAesExtra(): VendorVersion(2), Strength(3), Method(0) {}
bool NeedCrc() const { return (VendorVersion == 1); }
bool ParseFromSubBlock(const CExtraSubBlock &sb)
{
if (sb.ID != NFileHeader::NExtraID::kWzAES)
return false;
if (sb.Data.Size() < k_WzAesExtra_Size)
return false;
const Byte *p = (const Byte *)sb.Data;
VendorVersion = GetUi16(p);
if (p[2] != 'A' || p[3] != 'E')
return false;
Strength = p[4];
// 9.31: The BUG was fixed:
Method = GetUi16(p + 5);
return true;
}
void SetSubBlock(CExtraSubBlock &sb) const
{
sb.Data.Alloc(k_WzAesExtra_Size);
sb.ID = NFileHeader::NExtraID::kWzAES;
Byte *p = (Byte *)sb.Data;
p[0] = (Byte)VendorVersion;
p[1] = (Byte)(VendorVersion >> 8);
p[2] = 'A';
p[3] = 'E';
p[4] = Strength;
p[5] = (Byte)Method;
p[6] = (Byte)(Method >> 8);
}
};
namespace NStrongCrypto_AlgId
{
const UInt16 kDES = 0x6601;
const UInt16 kRC2old = 0x6602;
const UInt16 k3DES168 = 0x6603;
const UInt16 k3DES112 = 0x6609;
const UInt16 kAES128 = 0x660E;
const UInt16 kAES192 = 0x660F;
const UInt16 kAES256 = 0x6610;
const UInt16 kRC2 = 0x6702;
const UInt16 kBlowfish = 0x6720;
const UInt16 kTwofish = 0x6721;
const UInt16 kRC4 = 0x6801;
}
struct CStrongCryptoExtra
{
UInt16 Format;
UInt16 AlgId;
UInt16 BitLen;
UInt16 Flags;
bool ParseFromSubBlock(const CExtraSubBlock &sb)
{
if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt)
return false;
const Byte *p = (const Byte *)sb.Data;
if (sb.Data.Size() < 8)
return false;
Format = GetUi16(p + 0);
AlgId = GetUi16(p + 2);
BitLen = GetUi16(p + 4);
Flags = GetUi16(p + 6);
return (Format == 2);
}
bool CertificateIsUsed() const { return (Flags > 0x0001); }
};
struct CExtraBlock
{
CObjectVector<CExtraSubBlock> SubBlocks;
void Clear() { SubBlocks.Clear(); }
size_t GetSize() const
{
size_t res = 0;
FOR_VECTOR (i, SubBlocks)
res += SubBlocks[i].Data.Size() + 2 + 2;
return res;
}
bool GetWzAes(CWzAesExtra &e) const
{
FOR_VECTOR (i, SubBlocks)
if (e.ParseFromSubBlock(SubBlocks[i]))
return true;
return false;
}
bool HasWzAes() const
{
CWzAesExtra e;
return GetWzAes(e);
}
bool GetStrongCrypto(CStrongCryptoExtra &e) const
{
FOR_VECTOR (i, SubBlocks)
if (e.ParseFromSubBlock(SubBlocks[i]))
return true;
return false;
}
/*
bool HasStrongCrypto() const
{
CStrongCryptoExtra e;
return GetStrongCrypto(e);
}
*/
bool GetNtfsTime(unsigned index, FILETIME &ft) const;
bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
void RemoveUnknownSubBlocks()
{
for (unsigned i = SubBlocks.Size(); i != 0;)
{
i--;
if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES)
SubBlocks.Delete(i);
}
}
};
class CLocalItem
{
public:
UInt16 Flags;
UInt16 Method;
CVersion ExtractVersion;
UInt64 Size;
UInt64 PackSize;
UInt32 Time;
UInt32 Crc;
UInt32 Disk;
AString Name;
CExtraBlock LocalExtra;
bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }
bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
bool IsDir() const;
/*
void GetUnicodeString(const AString &s, UString &res) const
{
bool isUtf8 = IsUtf8();
if (isUtf8)
if (ConvertUTF8ToUnicode(s, res))
return;
MultiByteToUnicodeString2(res, s, GetCodePage());
}
*/
private:
void SetFlag(unsigned bitMask, bool enable)
{
if (enable)
Flags |= bitMask;
else
Flags &= ~bitMask;
}
public:
void ClearFlags() { Flags = 0; }
void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }
UINT GetCodePage() const { return CP_OEMCP; }
};
class CItem: public CLocalItem
{
public:
CVersion MadeByVersion;
UInt16 InternalAttrib;
UInt32 ExternalAttrib;
UInt64 LocalHeaderPos;
CExtraBlock CentralExtra;
CByteBuffer Comment;
bool FromLocal;
bool FromCentral;
// CItem can be used as CLocalItem. So we must clear unused fields
CItem():
InternalAttrib(0),
ExternalAttrib(0),
FromLocal(false),
FromCentral(false)
{
MadeByVersion.Version = 0;
MadeByVersion.HostOS = 0;
}
const CExtraBlock &GetMainExtra() const { return *(FromCentral ? &CentralExtra : &LocalExtra); }
bool IsDir() const;
UInt32 GetWinAttrib() const;
bool GetPosixAttrib(UInt32 &attrib) const;
Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : ExtractVersion.HostOS; }
void GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const;
bool IsThereCrc() const
{
if (Method == NFileHeader::NCompressionMethod::kWzAES)
{
CWzAesExtra aesField;
if (GetMainExtra().GetWzAes(aesField))
return aesField.NeedCrc();
}
return (Crc != 0 || !IsDir());
}
UINT GetCodePage() const
{
Byte hostOS = GetHostOS();
return (UINT)((
hostOS == NFileHeader::NHostOS::kFAT
|| hostOS == NFileHeader::NHostOS::kNTFS
|| hostOS == NFileHeader::NHostOS::kUnix // do we need it?
) ? CP_OEMCP : CP_ACP);
}
};
}}
#endif

View File

@@ -0,0 +1,312 @@
// ZipOut.cpp
#include "StdAfx.h"
#include "../../Common/OffsetStream.h"
#include "ZipOut.h"
namespace NArchive {
namespace NZip {
HRESULT COutArchive::Create(IOutStream *outStream)
{
m_CurPos = 0;
if (!m_OutBuffer.Create(1 << 16))
return E_OUTOFMEMORY;
m_Stream = outStream;
m_OutBuffer.SetStream(outStream);
m_OutBuffer.Init();
return m_Stream->Seek(0, STREAM_SEEK_CUR, &m_Base);
}
void COutArchive::MoveCurPos(UInt64 distanceToMove)
{
m_CurPos += distanceToMove; // test overflow
}
void COutArchive::SeekToRelatPos(UInt64 offset)
{
HRESULT res = m_Stream->Seek(m_Base + offset, STREAM_SEEK_SET, NULL);
if (res != S_OK)
throw CSystemException(res);
}
void COutArchive::PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption)
{
m_IsZip64 = isZip64;
m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0;
if (aesEncryption)
m_ExtraSize += 4 + k_WzAesExtra_Size;
m_LocalFileHeaderSize = kLocalHeaderSize + fileNameLen + m_ExtraSize;
}
void COutArchive::PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption)
{
// We use Zip64, if unPackSize size is larger than 0xF8000000 to support
// cases when compressed size can be about 3% larger than uncompressed size
PrepareWriteCompressedDataZip64(fileNameLen, unPackSize >= (UInt32)0xF8000000, aesEncryption);
}
#define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF)
void COutArchive::PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption)
{
bool isZip64 =
DOES_NEED_ZIP64(unPackSize) ||
DOES_NEED_ZIP64(packSize);
PrepareWriteCompressedDataZip64(fileNameLen, isZip64, aesEncryption);
}
void COutArchive::WriteBytes(const void *buffer, UInt32 size)
{
m_OutBuffer.WriteBytes(buffer, size);
m_CurPos += size;
}
void COutArchive::Write8(Byte b)
{
m_OutBuffer.WriteByte(b);
m_CurPos++;
}
void COutArchive::Write16(UInt16 val)
{
for (int i = 0; i < 2; i++)
{
Write8((Byte)val);
val >>= 8;
}
}
void COutArchive::Write32(UInt32 val)
{
for (int i = 0; i < 4; i++)
{
Write8((Byte)val);
val >>= 8;
}
}
void COutArchive::Write64(UInt64 val)
{
for (int i = 0; i < 8; i++)
{
Write8((Byte)val);
val >>= 8;
}
}
void COutArchive::WriteExtra(const CExtraBlock &extra)
{
if (extra.SubBlocks.Size() != 0)
{
FOR_VECTOR (i, extra.SubBlocks)
{
const CExtraSubBlock &subBlock = extra.SubBlocks[i];
Write16(subBlock.ID);
Write16((UInt16)subBlock.Data.Size());
WriteBytes(subBlock.Data, (UInt32)subBlock.Data.Size());
}
}
}
void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64)
{
{
Byte ver = item.ExtractVersion.Version;
if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)
ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;
Write8(ver);
}
Write8(item.ExtractVersion.HostOS);
Write16(item.Flags);
Write16(item.Method);
Write32(item.Time);
Write32(item.Crc);
}
#define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v));
void COutArchive::WriteLocalHeader(const CLocalItem &item)
{
SeekToCurPos();
bool isZip64 = m_IsZip64 ||
DOES_NEED_ZIP64(item.PackSize) ||
DOES_NEED_ZIP64(item.Size);
Write32(NSignature::kLocalFileHeader);
WriteCommonItemInfo(item, isZip64);
WRITE_32_VAL_SPEC(item.PackSize, isZip64);
WRITE_32_VAL_SPEC(item.Size, isZip64);
Write16((UInt16)item.Name.Len());
{
UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize());
if (localExtraSize != m_ExtraSize)
throw CSystemException(E_FAIL);
}
Write16((UInt16)m_ExtraSize);
WriteBytes((const char *)item.Name, item.Name.Len());
if (isZip64)
{
Write16(NFileHeader::NExtraID::kZip64);
Write16(8 + 8);
Write64(item.Size);
Write64(item.PackSize);
}
WriteExtra(item.LocalExtra);
// Why don't we write NTFS timestamps to local header?
// Probably we want to reduce size of archive?
m_OutBuffer.FlushWithCheck();
MoveCurPos(item.PackSize);
}
void COutArchive::WriteCentralHeader(const CItemOut &item)
{
bool isUnPack64 = DOES_NEED_ZIP64(item.Size);
bool isPack64 = DOES_NEED_ZIP64(item.PackSize);
bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos);
bool isZip64 = isPack64 || isUnPack64 || isPosition64;
Write32(NSignature::kCentralFileHeader);
Write8(item.MadeByVersion.Version);
Write8(item.MadeByVersion.HostOS);
WriteCommonItemInfo(item, isZip64);
WRITE_32_VAL_SPEC(item.PackSize, isPack64);
WRITE_32_VAL_SPEC(item.Size, isUnPack64);
Write16((UInt16)item.Name.Len());
UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8);
const UInt16 centralExtraSize = (UInt16)(
(isZip64 ? 4 + zip64ExtraSize : 0) +
(item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) +
item.CentralExtra.GetSize());
Write16(centralExtraSize); // test it;
Write16((UInt16)item.Comment.Size());
Write16(0); // DiskNumberStart;
Write16(item.InternalAttrib);
Write32(item.ExternalAttrib);
WRITE_32_VAL_SPEC(item.LocalHeaderPos, isPosition64);
WriteBytes((const char *)item.Name, item.Name.Len());
if (isZip64)
{
Write16(NFileHeader::NExtraID::kZip64);
Write16(zip64ExtraSize);
if (isUnPack64)
Write64(item.Size);
if (isPack64)
Write64(item.PackSize);
if (isPosition64)
Write64(item.LocalHeaderPos);
}
if (item.NtfsTimeIsDefined)
{
Write16(NFileHeader::NExtraID::kNTFS);
Write16(kNtfsExtraSize);
Write32(0); // reserved
Write16(NFileHeader::NNtfsExtra::kTagTime);
Write16(8 * 3);
WriteNtfsTime(item.Ntfs_MTime);
WriteNtfsTime(item.Ntfs_ATime);
WriteNtfsTime(item.Ntfs_CTime);
}
WriteExtra(item.CentralExtra);
if (item.Comment.Size() > 0)
WriteBytes(item.Comment, (UInt32)item.Comment.Size());
}
void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)
{
SeekToCurPos();
UInt64 cdOffset = GetCurPos();
FOR_VECTOR (i, items)
WriteCentralHeader(items[i]);
UInt64 cd64EndOffset = GetCurPos();
UInt64 cdSize = cd64EndOffset - cdOffset;
bool cdOffset64 = DOES_NEED_ZIP64(cdOffset);
bool cdSize64 = DOES_NEED_ZIP64(cdSize);
bool items64 = items.Size() >= 0xFFFF;
bool isZip64 = (cdOffset64 || cdSize64 || items64);
// isZip64 = true; // to test Zip64
if (isZip64)
{
Write32(NSignature::kEcd64);
Write64(kEcd64_MainSize);
Write16(45); // made by version
Write16(45); // extract version
Write32(0); // ThisDiskNumber = 0;
Write32(0); // StartCentralDirectoryDiskNumber;;
Write64((UInt64)items.Size());
Write64((UInt64)items.Size());
Write64((UInt64)cdSize);
Write64((UInt64)cdOffset);
Write32(NSignature::kEcd64Locator);
Write32(0); // number of the disk with the start of the zip64 end of central directory
Write64(cd64EndOffset);
Write32(1); // total number of disks
}
Write32(NSignature::kEcd);
Write16(0); // ThisDiskNumber = 0;
Write16(0); // StartCentralDirectoryDiskNumber;
Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
WRITE_32_VAL_SPEC(cdSize, cdSize64);
WRITE_32_VAL_SPEC(cdOffset, cdOffset64);
UInt32 commentSize = (UInt32)(comment ? comment->Size() : 0);
Write16((UInt16)commentSize);
if (commentSize > 0)
WriteBytes((const Byte *)*comment, commentSize);
m_OutBuffer.FlushWithCheck();
}
void COutArchive::CreateStreamForCompressing(IOutStream **outStream)
{
COffsetOutStream *streamSpec = new COffsetOutStream;
CMyComPtr<IOutStream> tempStream(streamSpec);
streamSpec->Init(m_Stream, m_Base + m_CurPos + m_LocalFileHeaderSize);
*outStream = tempStream.Detach();
}
/*
void COutArchive::SeekToPackedDataPosition()
{
SeekTo(m_BasePosition + m_LocalFileHeaderSize);
}
*/
void COutArchive::SeekToCurPos()
{
SeekToRelatPos(m_CurPos);
}
void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream)
{
CMyComPtr<ISequentialOutStream> tempStream(m_Stream);
*outStream = tempStream.Detach();
}
}}

View File

@@ -0,0 +1,88 @@
// ZipOut.h
#ifndef __ZIP_OUT_H
#define __ZIP_OUT_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
#include "../../Common/OutBuffer.h"
#include "ZipItem.h"
namespace NArchive {
namespace NZip {
// can throw CSystemException and COutBufferException
class CItemOut: public CItem
{
public:
FILETIME Ntfs_MTime;
FILETIME Ntfs_ATime;
FILETIME Ntfs_CTime;
bool NtfsTimeIsDefined;
// It's possible that NtfsTime is not defined, but there is NtfsTime in Extra.
CItemOut(): NtfsTimeIsDefined(false) {}
};
class COutArchive
{
CMyComPtr<IOutStream> m_Stream;
COutBuffer m_OutBuffer;
UInt64 m_Base; // Base of arc (offset in output Stream)
UInt64 m_CurPos; // Curent position in archive (relative from m_Base)
UInt32 m_LocalFileHeaderSize;
UInt32 m_ExtraSize;
bool m_IsZip64;
void SeekToRelatPos(UInt64 offset);
void WriteBytes(const void *buffer, UInt32 size);
void Write8(Byte b);
void Write16(UInt16 val);
void Write32(UInt32 val);
void Write64(UInt64 val);
void WriteNtfsTime(const FILETIME &ft)
{
Write32(ft.dwLowDateTime);
Write32(ft.dwHighDateTime);
}
void WriteExtra(const CExtraBlock &extra);
void WriteCommonItemInfo(const CLocalItem &item, bool isZip64);
void WriteCentralHeader(const CItemOut &item);
void PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption);
public:
HRESULT Create(IOutStream *outStream);
void MoveCurPos(UInt64 distanceToMove);
UInt64 GetCurPos() const { return m_CurPos; }
void SeekToCurPos();
void PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption);
void PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
void WriteLocalHeader(const CLocalItem &item);
void WriteLocalHeader_And_SeekToNextFile(const CLocalItem &item)
{
WriteLocalHeader(item);
SeekToCurPos();
}
void WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment);
void CreateStreamForCompressing(IOutStream **outStream);
void CreateStreamForCopying(ISequentialOutStream **outStream);
};
}}
#endif

View File

@@ -0,0 +1,27 @@
// ZipRegister.cpp
#include "StdAfx.h"
#include "../../Common/RegisterArc.h"
#include "ZipHandler.h"
namespace NArchive {
namespace NZip {
static const Byte k_Signature[] = {
4, 0x50, 0x4B, 0x03, 0x04,
4, 0x50, 0x4B, 0x05, 0x06,
6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B,
6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B };
REGISTER_ARC_IO(
"zip", "zip z01 zipx jar xpi odt ods docx xlsx epub", 0, 1,
k_Signature,
0,
NArcInfoFlags::kFindSignature |
NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kUseGlobalOffset,
IsArc_Zip)
}}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
// ZipUpdate.h
#ifndef __ZIP_UPDATE_H
#define __ZIP_UPDATE_H
#include "../../ICoder.h"
#include "../IArchive.h"
#include "../../Common/CreateCoder.h"
#include "ZipCompressionMode.h"
#include "ZipIn.h"
namespace NArchive {
namespace NZip {
struct CUpdateRange
{
UInt64 Position;
UInt64 Size;
// CUpdateRange() {};
CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {};
};
struct CUpdateItem
{
bool NewData;
bool NewProps;
bool IsDir;
bool NtfsTimeIsDefined;
bool IsUtf8;
int IndexInArc;
int IndexInClient;
UInt32 Attrib;
UInt32 Time;
UInt64 Size;
AString Name;
// bool Commented;
// CUpdateRange CommentRange;
FILETIME Ntfs_MTime;
FILETIME Ntfs_ATime;
FILETIME Ntfs_CTime;
CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}
};
HRESULT Update(
DECL_EXTERNAL_CODECS_LOC_VARS
const CObjectVector<CItemEx> &inputItems,
CObjectVector<CUpdateItem> &updateItems,
ISequentialOutStream *seqOutStream,
CInArchive *inArchive, bool removeSfx,
CCompressionMethodMode *compressionMethodMode,
IArchiveUpdateCallback *updateCallback);
}}
#endif