Normalize all the line endings

This commit is contained in:
Tino Reichardt
2020-05-31 13:08:03 +02:00
parent d8345ee3b3
commit 9c3c277ad7
1156 changed files with 292304 additions and 292304 deletions

View File

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

View File

@@ -1,478 +1,478 @@
// 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 "../../Compress/XzEncoder.h"
#include "../Common/InStreamWithCRC.h"
#include "ZipAddCommon.h"
#include "ZipHeader.h"
namespace NArchive {
namespace NZip {
using namespace NFileHeader;
static const UInt32 kLzmaPropsSize = 5;
static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
class CLzmaEncoder:
public ICompressCoder,
public ICompressSetCoderProperties,
public ICompressSetCoderPropertiesOpt,
public CMyUnknownImp
{
public:
NCompress::NLzma::CEncoder *EncoderSpec;
CMyComPtr<ICompressCoder> Encoder;
Byte Header[kLzmaHeaderSize];
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
MY_UNKNOWN_IMP2(
ICompressSetCoderProperties,
ICompressSetCoderPropertiesOpt)
};
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::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
return EncoderSpec->SetCoderPropertiesOpt(propIDs, props, numProps);
}
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),
_isLzmaEos(false)
{}
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::Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,
CCompressingResult &opRes) const
{
// We use Zip64, if unPackSize size is larger than 0xF8000000 to support
// cases when compressed size can be about 3% larger than uncompressed size
const UInt32 kUnpackZip64Limit = 0xF8000000;
opRes.UnpackSize = unpackSize;
opRes.PackSize = (UInt64)1 << 60; // we use big value to force Zip64 mode.
if (unpackSize < kUnpackZip64Limit)
opRes.PackSize = (UInt32)0xFFFFFFFF - 1; // it will not use Zip64 for that size
if (opRes.PackSize < unpackSize)
opRes.PackSize = unpackSize;
Byte method = _options.MethodSequence[0];
if (method == NCompressionMethod::kStore && !_options.PasswordIsDefined)
opRes.PackSize = unpackSize;
opRes.CRC = 0;
opRes.LzmaEos = false;
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
opRes.DescriptorMode = outSeqMode;
if (_options.PasswordIsDefined)
{
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
if (_options.IsAesMode)
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;
else
{
if (inSeqMode)
opRes.DescriptorMode = true;
}
}
opRes.Method = method;
Byte ver = 0;
switch (method)
{
case NCompressionMethod::kStore: break;
case NCompressionMethod::kDeflate: ver = NCompressionMethod::kExtractVersion_Deflate; break;
case NCompressionMethod::kDeflate64: ver = NCompressionMethod::kExtractVersion_Deflate64; break;
case NCompressionMethod::kXz : ver = NCompressionMethod::kExtractVersion_Xz; break;
case NCompressionMethod::kPPMd : ver = NCompressionMethod::kExtractVersion_PPMd; break;
case NCompressionMethod::kBZip2: ver = NCompressionMethod::kExtractVersion_BZip2; break;
case NCompressionMethod::kLZMA :
{
ver = NCompressionMethod::kExtractVersion_LZMA;
const COneMethodInfo *oneMethodMain = &_options._methods[0];
opRes.LzmaEos = oneMethodMain->Get_Lzma_Eos();
break;
}
}
if (opRes.ExtractVersion < ver)
opRes.ExtractVersion = ver;
return S_OK;
}
HRESULT CAddCommon::Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
bool inSeqMode, bool outSeqMode,
UInt32 fileTime, UInt64 expectedDataSize,
ICompressProgressInfo *progress, CCompressingResult &opRes)
{
opRes.LzmaEos = false;
if (!inStream)
{
// We can create empty stream here. But it was already implemented in caller code in 9.33+
return E_INVALIDARG;
}
CSequentialInStreamWithCRC *inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
CMyComPtr<ISequentialInStream> inCrcStream = inSecCrcStreamSpec;
CMyComPtr<IInStream> inStream2;
if (!inSeqMode)
{
inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
if (!inStream2)
{
// inSeqMode = true;
// inSeqMode must be correct before
return E_FAIL;
}
}
inSecCrcStreamSpec->SetStream(inStream);
inSecCrcStreamSpec->Init();
unsigned numTestMethods = _options.MethodSequence.Size();
bool descriptorMode = outSeqMode;
if (!outSeqMode)
if (inSeqMode && _options.PasswordIsDefined && !_options.IsAesMode)
descriptorMode = true;
opRes.DescriptorMode = descriptorMode;
if (numTestMethods > 1)
if (inSeqMode || outSeqMode || !inStream2)
numTestMethods = 1;
UInt32 crc = 0;
bool crc_IsCalculated = false;
Byte method = 0;
CFilterCoder::C_OutStream_Releaser outStreamReleaser;
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
for (unsigned i = 0; i < numTestMethods; i++)
{
opRes.LzmaEos = false;
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
if (i != 0)
{
if (inStream2)
{
inSecCrcStreamSpec->Init();
RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
}
RINOK(outStream->SetSize(0));
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
}
if (_options.PasswordIsDefined)
{
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
if (!_cryptoStream)
{
_cryptoStreamSpec = new CFilterCoder(true);
_cryptoStream = _cryptoStreamSpec;
}
if (_options.IsAesMode)
{
opRes.ExtractVersion = 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 (descriptorMode)
{
// it's Info-ZIP modification for stream_mode descriptor_mode (bit 3 of the general purpose bit flag is set)
check = (fileTime & 0xFFFF);
}
else
{
if (!crc_IsCalculated)
{
RINOK(CalcStreamCRC(inStream, crc));
crc_IsCalculated = true;
RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
inSecCrcStreamSpec->Init();
}
check = (crc >> 16);
}
RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
}
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
RINOK(_cryptoStreamSpec->InitEncoder());
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
}
method = _options.MethodSequence[i];
switch (method)
{
case NCompressionMethod::kStore:
{
if (descriptorMode)
{
// we still can create descriptor_mode archives with "Store" method, but they are not good for 100%
return E_NOTIMPL;
}
if (!_copyCoderSpec)
{
_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)
{
CLzmaEncoder *_lzmaEncoder = NULL;
if (method == NCompressionMethod::kLZMA)
{
_compressExtractVersion = NCompressionMethod::kExtractVersion_LZMA;
_lzmaEncoder = new CLzmaEncoder();
_compressEncoder = _lzmaEncoder;
}
else if (method == NCompressionMethod::kXz)
{
_compressExtractVersion = NCompressionMethod::kExtractVersion_Xz;
NCompress::NXz::CEncoder *encoder = new NCompress::NXz::CEncoder();
_compressEncoder = encoder;
}
else if (method == NCompressionMethod::kPPMd)
{
_compressExtractVersion = NCompressionMethod::kExtractVersion_PPMd;
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
_compressEncoder = encoder;
}
else
{
CMethodId methodId;
switch (method)
{
case NCompressionMethod::kBZip2:
methodId = kMethodId_BZip2;
_compressExtractVersion = NCompressionMethod::kExtractVersion_BZip2;
break;
default:
_compressExtractVersion = ((method == NCompressionMethod::kDeflate64) ?
NCompressionMethod::kExtractVersion_Deflate64 :
NCompressionMethod::kExtractVersion_Deflate);
methodId = kMethodId_ZipBase + method;
break;
}
RINOK(CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
methodId, true, _compressEncoder));
if (!_compressEncoder)
return E_NOTIMPL;
if (method == NCompressionMethod::kDeflate ||
method == NCompressionMethod::kDeflate64)
{
}
else if (method == NCompressionMethod::kBZip2)
{
}
}
{
CMyComPtr<ICompressSetCoderProperties> setCoderProps;
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
if (setCoderProps)
{
if (!_options._methods.IsEmpty())
{
COneMethodInfo *oneMethodMain = &_options._methods[0];
RINOK(oneMethodMain->SetCoderProps(setCoderProps,
_options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
}
}
}
if (method == NCompressionMethod::kLZMA)
_isLzmaEos = _lzmaEncoder->EncoderSpec->IsWriteEndMark();
}
if (method == NCompressionMethod::kLZMA)
opRes.LzmaEos = _isLzmaEos;
CMyComPtr<ISequentialOutStream> outStreamNew;
if (_options.PasswordIsDefined)
outStreamNew = _cryptoStream;
else
outStreamNew = outStream;
if (_compressExtractVersion > opRes.ExtractVersion)
opRes.ExtractVersion = _compressExtractVersion;
{
CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
_compressEncoder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);
if (optProps)
{
PROPID propID = NCoderPropID::kExpectedDataSize;
NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1));
}
}
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));
{
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;
}
}}
// 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 "../../Compress/XzEncoder.h"
#include "../Common/InStreamWithCRC.h"
#include "ZipAddCommon.h"
#include "ZipHeader.h"
namespace NArchive {
namespace NZip {
using namespace NFileHeader;
static const UInt32 kLzmaPropsSize = 5;
static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
class CLzmaEncoder:
public ICompressCoder,
public ICompressSetCoderProperties,
public ICompressSetCoderPropertiesOpt,
public CMyUnknownImp
{
public:
NCompress::NLzma::CEncoder *EncoderSpec;
CMyComPtr<ICompressCoder> Encoder;
Byte Header[kLzmaHeaderSize];
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
MY_UNKNOWN_IMP2(
ICompressSetCoderProperties,
ICompressSetCoderPropertiesOpt)
};
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::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
return EncoderSpec->SetCoderPropertiesOpt(propIDs, props, numProps);
}
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),
_isLzmaEos(false)
{}
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::Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,
CCompressingResult &opRes) const
{
// We use Zip64, if unPackSize size is larger than 0xF8000000 to support
// cases when compressed size can be about 3% larger than uncompressed size
const UInt32 kUnpackZip64Limit = 0xF8000000;
opRes.UnpackSize = unpackSize;
opRes.PackSize = (UInt64)1 << 60; // we use big value to force Zip64 mode.
if (unpackSize < kUnpackZip64Limit)
opRes.PackSize = (UInt32)0xFFFFFFFF - 1; // it will not use Zip64 for that size
if (opRes.PackSize < unpackSize)
opRes.PackSize = unpackSize;
Byte method = _options.MethodSequence[0];
if (method == NCompressionMethod::kStore && !_options.PasswordIsDefined)
opRes.PackSize = unpackSize;
opRes.CRC = 0;
opRes.LzmaEos = false;
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
opRes.DescriptorMode = outSeqMode;
if (_options.PasswordIsDefined)
{
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
if (_options.IsAesMode)
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;
else
{
if (inSeqMode)
opRes.DescriptorMode = true;
}
}
opRes.Method = method;
Byte ver = 0;
switch (method)
{
case NCompressionMethod::kStore: break;
case NCompressionMethod::kDeflate: ver = NCompressionMethod::kExtractVersion_Deflate; break;
case NCompressionMethod::kDeflate64: ver = NCompressionMethod::kExtractVersion_Deflate64; break;
case NCompressionMethod::kXz : ver = NCompressionMethod::kExtractVersion_Xz; break;
case NCompressionMethod::kPPMd : ver = NCompressionMethod::kExtractVersion_PPMd; break;
case NCompressionMethod::kBZip2: ver = NCompressionMethod::kExtractVersion_BZip2; break;
case NCompressionMethod::kLZMA :
{
ver = NCompressionMethod::kExtractVersion_LZMA;
const COneMethodInfo *oneMethodMain = &_options._methods[0];
opRes.LzmaEos = oneMethodMain->Get_Lzma_Eos();
break;
}
}
if (opRes.ExtractVersion < ver)
opRes.ExtractVersion = ver;
return S_OK;
}
HRESULT CAddCommon::Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
bool inSeqMode, bool outSeqMode,
UInt32 fileTime, UInt64 expectedDataSize,
ICompressProgressInfo *progress, CCompressingResult &opRes)
{
opRes.LzmaEos = false;
if (!inStream)
{
// We can create empty stream here. But it was already implemented in caller code in 9.33+
return E_INVALIDARG;
}
CSequentialInStreamWithCRC *inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
CMyComPtr<ISequentialInStream> inCrcStream = inSecCrcStreamSpec;
CMyComPtr<IInStream> inStream2;
if (!inSeqMode)
{
inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
if (!inStream2)
{
// inSeqMode = true;
// inSeqMode must be correct before
return E_FAIL;
}
}
inSecCrcStreamSpec->SetStream(inStream);
inSecCrcStreamSpec->Init();
unsigned numTestMethods = _options.MethodSequence.Size();
bool descriptorMode = outSeqMode;
if (!outSeqMode)
if (inSeqMode && _options.PasswordIsDefined && !_options.IsAesMode)
descriptorMode = true;
opRes.DescriptorMode = descriptorMode;
if (numTestMethods > 1)
if (inSeqMode || outSeqMode || !inStream2)
numTestMethods = 1;
UInt32 crc = 0;
bool crc_IsCalculated = false;
Byte method = 0;
CFilterCoder::C_OutStream_Releaser outStreamReleaser;
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
for (unsigned i = 0; i < numTestMethods; i++)
{
opRes.LzmaEos = false;
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
if (i != 0)
{
if (inStream2)
{
inSecCrcStreamSpec->Init();
RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
}
RINOK(outStream->SetSize(0));
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
}
if (_options.PasswordIsDefined)
{
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
if (!_cryptoStream)
{
_cryptoStreamSpec = new CFilterCoder(true);
_cryptoStream = _cryptoStreamSpec;
}
if (_options.IsAesMode)
{
opRes.ExtractVersion = 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 (descriptorMode)
{
// it's Info-ZIP modification for stream_mode descriptor_mode (bit 3 of the general purpose bit flag is set)
check = (fileTime & 0xFFFF);
}
else
{
if (!crc_IsCalculated)
{
RINOK(CalcStreamCRC(inStream, crc));
crc_IsCalculated = true;
RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
inSecCrcStreamSpec->Init();
}
check = (crc >> 16);
}
RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
}
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
RINOK(_cryptoStreamSpec->InitEncoder());
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
}
method = _options.MethodSequence[i];
switch (method)
{
case NCompressionMethod::kStore:
{
if (descriptorMode)
{
// we still can create descriptor_mode archives with "Store" method, but they are not good for 100%
return E_NOTIMPL;
}
if (!_copyCoderSpec)
{
_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)
{
CLzmaEncoder *_lzmaEncoder = NULL;
if (method == NCompressionMethod::kLZMA)
{
_compressExtractVersion = NCompressionMethod::kExtractVersion_LZMA;
_lzmaEncoder = new CLzmaEncoder();
_compressEncoder = _lzmaEncoder;
}
else if (method == NCompressionMethod::kXz)
{
_compressExtractVersion = NCompressionMethod::kExtractVersion_Xz;
NCompress::NXz::CEncoder *encoder = new NCompress::NXz::CEncoder();
_compressEncoder = encoder;
}
else if (method == NCompressionMethod::kPPMd)
{
_compressExtractVersion = NCompressionMethod::kExtractVersion_PPMd;
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
_compressEncoder = encoder;
}
else
{
CMethodId methodId;
switch (method)
{
case NCompressionMethod::kBZip2:
methodId = kMethodId_BZip2;
_compressExtractVersion = NCompressionMethod::kExtractVersion_BZip2;
break;
default:
_compressExtractVersion = ((method == NCompressionMethod::kDeflate64) ?
NCompressionMethod::kExtractVersion_Deflate64 :
NCompressionMethod::kExtractVersion_Deflate);
methodId = kMethodId_ZipBase + method;
break;
}
RINOK(CreateCoder_Id(
EXTERNAL_CODECS_LOC_VARS
methodId, true, _compressEncoder));
if (!_compressEncoder)
return E_NOTIMPL;
if (method == NCompressionMethod::kDeflate ||
method == NCompressionMethod::kDeflate64)
{
}
else if (method == NCompressionMethod::kBZip2)
{
}
}
{
CMyComPtr<ICompressSetCoderProperties> setCoderProps;
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
if (setCoderProps)
{
if (!_options._methods.IsEmpty())
{
COneMethodInfo *oneMethodMain = &_options._methods[0];
RINOK(oneMethodMain->SetCoderProps(setCoderProps,
_options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
}
}
}
if (method == NCompressionMethod::kLZMA)
_isLzmaEos = _lzmaEncoder->EncoderSpec->IsWriteEndMark();
}
if (method == NCompressionMethod::kLZMA)
opRes.LzmaEos = _isLzmaEos;
CMyComPtr<ISequentialOutStream> outStreamNew;
if (_options.PasswordIsDefined)
outStreamNew = _cryptoStream;
else
outStreamNew = outStream;
if (_compressExtractVersion > opRes.ExtractVersion)
opRes.ExtractVersion = _compressExtractVersion;
{
CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
_compressEncoder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);
if (optProps)
{
PROPID propID = NCoderPropID::kExpectedDataSize;
NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1));
}
}
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));
{
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

@@ -1,69 +1,69 @@
// 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 DescriptorMode;
bool LzmaEos;
};
class CAddCommon
{
CCompressionMethodMode _options;
NCompress::CCopyCoder *_copyCoderSpec;
CMyComPtr<ICompressCoder> _copyCoder;
CMyComPtr<ICompressCoder> _compressEncoder;
Byte _compressExtractVersion;
bool _isLzmaEos;
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 Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,
CCompressingResult &opRes) const;
HRESULT Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
bool inSeqMode, bool outSeqMode,
UInt32 fileTime, UInt64 expectedDataSize,
ICompressProgressInfo *progress, CCompressingResult &opRes);
};
}}
#endif
// 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 DescriptorMode;
bool LzmaEos;
};
class CAddCommon
{
CCompressionMethodMode _options;
NCompress::CCopyCoder *_copyCoderSpec;
CMyComPtr<ICompressCoder> _copyCoder;
CMyComPtr<ICompressCoder> _compressEncoder;
Byte _compressExtractVersion;
bool _isLzmaEos;
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 Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,
CCompressingResult &opRes) const;
HRESULT Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
bool inSeqMode, bool outSeqMode,
UInt32 fileTime, UInt64 expectedDataSize,
ICompressProgressInfo *progress, CCompressingResult &opRes);
};
}}
#endif

View File

@@ -1,54 +1,54 @@
// 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 {
const CMethodId kMethodId_ZipBase = 0x040100;
const CMethodId kMethodId_BZip2 = 0x040202;
struct CBaseProps: public CMultiMethodProps
{
bool IsAesMode;
Byte AesKeyMode;
void Init()
{
CMultiMethodProps::Init();
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
// 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 {
const CMethodId kMethodId_ZipBase = 0x040100;
const CMethodId kMethodId_BZip2 = 0x040202;
struct CBaseProps: public CMultiMethodProps
{
bool IsAesMode;
Byte AesKeyMode;
void Init()
{
CMultiMethodProps::Init();
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

@@ -1,89 +1,89 @@
// 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 "ZipCompressionMode.h"
#include "ZipIn.h"
namespace NArchive {
namespace NZip {
const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kLZMA + 1;
const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kXz;
const unsigned kNumMethodNames2 = NFileHeader::NCompressionMethod::kWzAES + 1 - kMethodNames2Start;
extern const char * const kMethodNames1[kNumMethodNames1];
extern const char * const kMethodNames2[kNumMethodNames2];
class CHandler:
public IInArchive,
// public IArchiveGetRawProps,
public IOutArchive,
public ISetProperties,
PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
// MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
MY_QUERYINTERFACE_ENTRY(IOutArchive)
MY_QUERYINTERFACE_ENTRY(ISetProperties)
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
// INTERFACE_IArchiveGetRawProps(;)
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;
}
// void MarkAltStreams(CObjectVector<CItemEx> &items);
HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value);
};
}}
#endif
// 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 "ZipCompressionMode.h"
#include "ZipIn.h"
namespace NArchive {
namespace NZip {
const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kLZMA + 1;
const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kXz;
const unsigned kNumMethodNames2 = NFileHeader::NCompressionMethod::kWzAES + 1 - kMethodNames2Start;
extern const char * const kMethodNames1[kNumMethodNames1];
extern const char * const kMethodNames2[kNumMethodNames2];
class CHandler:
public IInArchive,
// public IArchiveGetRawProps,
public IOutArchive,
public ISetProperties,
PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
// MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
MY_QUERYINTERFACE_ENTRY(IOutArchive)
MY_QUERYINTERFACE_ENTRY(ISetProperties)
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IInArchive(;)
// INTERFACE_IArchiveGetRawProps(;)
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;
}
// void MarkAltStreams(CObjectVector<CItemEx> &items);
HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value);
};
}}
#endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,193 +1,193 @@
// 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 kDataDescriptorSize32 = 4 + 4 + 4 * 2; // including signature
const unsigned kDataDescriptorSize64 = 4 + 4 + 8 * 2; // 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
{
kStore = 0,
kShrink = 1,
kReduce1 = 2,
kReduce2 = 3,
kReduce3 = 4,
kReduce4 = 5,
kImplode = 6,
kTokenize = 7,
kDeflate = 8,
kDeflate64 = 9,
kPKImploding = 10,
kBZip2 = 12,
kLZMA = 14,
kTerse = 18,
kLz77 = 19,
kXz = 95,
kJpeg = 96,
kWavPack = 97,
kPPMd = 98,
kWzAES = 99
};
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;
const Byte kExtractVersion_Xz = 20; // test it
}
namespace NExtraID
{
enum
{
kZip64 = 0x01,
kNTFS = 0x0A,
kStrongEncrypt = 0x17,
kUnixTime = 0x5455,
kUnixExtra = 0x5855,
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 NUnixExtra
{
enum
{
kATime = 0,
kMTime
};
}
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 kAltStream = 1 << 14;
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
// 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 kDataDescriptorSize32 = 4 + 4 + 4 * 2; // including signature
const unsigned kDataDescriptorSize64 = 4 + 4 + 8 * 2; // 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
{
kStore = 0,
kShrink = 1,
kReduce1 = 2,
kReduce2 = 3,
kReduce3 = 4,
kReduce4 = 5,
kImplode = 6,
kTokenize = 7,
kDeflate = 8,
kDeflate64 = 9,
kPKImploding = 10,
kBZip2 = 12,
kLZMA = 14,
kTerse = 18,
kLz77 = 19,
kXz = 95,
kJpeg = 96,
kWavPack = 97,
kPPMd = 98,
kWzAES = 99
};
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;
const Byte kExtractVersion_Xz = 20; // test it
}
namespace NExtraID
{
enum
{
kZip64 = 0x01,
kNTFS = 0x0A,
kStrongEncrypt = 0x17,
kUnixTime = 0x5455,
kUnixExtra = 0x5855,
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 NUnixExtra
{
enum
{
kATime = 0,
kMTime
};
}
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 kAltStream = 1 << 14;
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

@@ -1,427 +1,427 @@
// Archive/ZipIn.h
#ifndef __ZIP_IN_H
#define __ZIP_IN_H
#include "../../../Common/MyBuffer2.h"
#include "../../../Common/MyCom.h"
#include "../../IStream.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
// int ParentOfAltStream; // -1, if not AltStream
bool DescriptorWasRead;
CItemEx():
// ParentOfAltStream(-1),
DescriptorWasRead(false) {}
UInt64 GetLocalFullSize() const
{ return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }
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 */
int MarkerVolIndex;
bool CdWasRead;
bool IsSpanMode;
bool ThereIsTail;
// UInt32 BaseVolIndex;
CByteBuffer Comment;
CInArchiveInfo():
Base(0),
MarkerPos(0),
MarkerPos2(0),
FinishPos(0),
FileEndPos(0),
FirstItemRelatOffset(0),
MarkerVolIndex(-1),
CdWasRead(false),
IsSpanMode(false),
ThereIsTail(false)
// BaseVolIndex(0)
{}
void Clear()
{
// BaseVolIndex = 0;
Base = 0;
MarkerPos = 0;
MarkerPos2 = 0;
FinishPos = 0;
FileEndPos = 0;
MarkerVolIndex = -1;
ThereIsTail = false;
FirstItemRelatOffset = 0;
CdWasRead = false;
IsSpanMode = false;
Comment.Free();
}
};
struct CCdInfo
{
bool IsFromEcd64;
UInt16 CommentSize;
// 64
UInt16 VersionMade;
UInt16 VersionNeedExtract;
// old zip
UInt32 ThisDisk;
UInt32 CdDisk;
UInt64 NumEntries_in_ThisDisk;
UInt64 NumEntries;
UInt64 Size;
UInt64 Offset;
CCdInfo() { memset(this, 0, sizeof(*this)); IsFromEcd64 = false; }
void ParseEcd32(const Byte *p); // (p) includes signature
void ParseEcd64e(const Byte *p); // (p) exclude signature
bool IsEmptyArc() const
{
return ThisDisk == 0
&& CdDisk == 0
&& NumEntries_in_ThisDisk == 0
&& NumEntries == 0
&& Size == 0
&& Offset == 0 // test it
;
}
};
struct CVols
{
struct CSubStreamInfo
{
CMyComPtr<IInStream> Stream;
UInt64 Size;
HRESULT SeekToStart() const { return Stream->Seek(0, STREAM_SEEK_SET, NULL); }
CSubStreamInfo(): Size(0) {}
};
CObjectVector<CSubStreamInfo> Streams;
int StreamIndex; // -1 for StartStream
// -2 for ZipStream at multivol detection code
// >=0 volume index in multivol
bool NeedSeek;
bool DisableVolsSearch;
bool StartIsExe; // is .exe
bool StartIsZ; // is .zip or .zNN
bool StartIsZip; // is .zip
bool IsUpperCase;
bool MissingZip;
bool ecd_wasRead;
Int32 StartVolIndex; // -1, if unknown vol index
// = (NN - 1), if StartStream is .zNN
// = 0, if start vol is exe
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; // name of archive including '.'
UString MissingName;
CMyComPtr<IInStream> ZipStream;
CCdInfo ecd;
UInt64 TotalBytesSize; // for MultiVol only
void ClearRefs()
{
Streams.Clear();
ZipStream.Release();
TotalBytesSize = 0;
}
void Clear()
{
StreamIndex = -1;
NeedSeek = false;
DisableVolsSearch = false;
StartIsExe = false;
StartIsZ = false;
StartIsZip = false;
IsUpperCase = false;
StartVolIndex = -1;
StartParsingVol = 0;
NumVols = 0;
EndVolIndex = -1;
BaseName.Empty();
MissingName.Empty();
MissingZip = false;
ecd_wasRead = false;
ClearRefs();
}
HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
};
class CVolStream:
public ISequentialInStream,
public CMyUnknownImp
{
public:
CVols *Vols;
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
class CInArchive
{
CMidBuffer Buffer;
size_t _bufPos;
size_t _bufCached;
UInt64 _streamPos;
UInt64 _cnt;
// UInt32 _startLocalFromCd_Disk;
// UInt64 _startLocalFromCd_Offset;
size_t GetAvail() const { return _bufCached - _bufPos; }
void InitBuf() { _bufPos = 0; _bufCached = 0; }
void DisableBufMode() { InitBuf(); _inBufMode = false; }
void SkipLookahed(size_t skip)
{
_bufPos += skip;
_cnt += skip;
}
UInt64 GetVirtStreamPos() { return _streamPos - _bufCached + _bufPos; }
bool _inBufMode;
bool IsArcOpen;
bool CanStartNewVol;
UInt32 _signature;
CMyComPtr<IInStream> StreamRef;
IInStream *Stream;
IInStream *StartStream;
IArchiveOpenCallback *Callback;
HRESULT Seek_SavePos(UInt64 offset);
HRESULT SeekToVol(int volIndex, UInt64 offset);
HRESULT ReadFromCache(Byte *data, unsigned size, unsigned &processed);
HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,
unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);
HRESULT ReadVols();
HRESULT FindMarker(const UInt64 *searchLimit);
HRESULT IncreaseRealPosition(UInt64 addValue, bool &isFinished);
HRESULT LookAhead(size_t minRequiredInBuffer);
void SafeRead(Byte *data, unsigned size);
void ReadBuffer(CByteBuffer &buffer, unsigned size);
// Byte ReadByte();
// UInt16 ReadUInt16();
UInt32 ReadUInt32();
UInt64 ReadUInt64();
void ReadSignature();
void Skip(size_t num);
HRESULT Skip64(UInt64 num, unsigned numFiles);
bool ReadFileName(unsigned nameSize, AString &dest);
bool ReadExtra(unsigned extraSize, CExtraBlock &extra,
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk);
bool ReadLocalItem(CItemEx &item);
HRESULT FindDescriptor(CItemEx &item, unsigned numFiles);
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 ReadHeaders(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 LocalsWereRead;
bool LocalsCenterMerged;
bool NoCentralDir;
bool Overflow32bit; // = true, if zip without Zip64 extension support and it has some fields values truncated to 32-bits.
bool Cd_NumEntries_Overflow_16bit; // = true, if no Zip64 and 16-bit ecd:NumEntries was overflowed.
bool MarkerIsFound;
bool MarkerIsSafe;
bool IsMultiVol;
bool UseDisk_in_SingleVol;
UInt32 EcdVolIndex;
CVols Vols;
CInArchive(): Stream(NULL), StartStream(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);
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
{
// it's possible that first item in CD doesn refers to first local item
// so FirstItemRelatOffset is not first local item
if (ArcInfo.CdWasRead)
return ArcInfo.FirstItemRelatOffset;
if (IsMultiVol)
return 0;
return ArcInfo.MarkerPos2 - ArcInfo.Base;
}
HRESULT CheckDescriptor(const CItemEx &item);
HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool &headersError);
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
// Archive/ZipIn.h
#ifndef __ZIP_IN_H
#define __ZIP_IN_H
#include "../../../Common/MyBuffer2.h"
#include "../../../Common/MyCom.h"
#include "../../IStream.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
// int ParentOfAltStream; // -1, if not AltStream
bool DescriptorWasRead;
CItemEx():
// ParentOfAltStream(-1),
DescriptorWasRead(false) {}
UInt64 GetLocalFullSize() const
{ return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }
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 */
int MarkerVolIndex;
bool CdWasRead;
bool IsSpanMode;
bool ThereIsTail;
// UInt32 BaseVolIndex;
CByteBuffer Comment;
CInArchiveInfo():
Base(0),
MarkerPos(0),
MarkerPos2(0),
FinishPos(0),
FileEndPos(0),
FirstItemRelatOffset(0),
MarkerVolIndex(-1),
CdWasRead(false),
IsSpanMode(false),
ThereIsTail(false)
// BaseVolIndex(0)
{}
void Clear()
{
// BaseVolIndex = 0;
Base = 0;
MarkerPos = 0;
MarkerPos2 = 0;
FinishPos = 0;
FileEndPos = 0;
MarkerVolIndex = -1;
ThereIsTail = false;
FirstItemRelatOffset = 0;
CdWasRead = false;
IsSpanMode = false;
Comment.Free();
}
};
struct CCdInfo
{
bool IsFromEcd64;
UInt16 CommentSize;
// 64
UInt16 VersionMade;
UInt16 VersionNeedExtract;
// old zip
UInt32 ThisDisk;
UInt32 CdDisk;
UInt64 NumEntries_in_ThisDisk;
UInt64 NumEntries;
UInt64 Size;
UInt64 Offset;
CCdInfo() { memset(this, 0, sizeof(*this)); IsFromEcd64 = false; }
void ParseEcd32(const Byte *p); // (p) includes signature
void ParseEcd64e(const Byte *p); // (p) exclude signature
bool IsEmptyArc() const
{
return ThisDisk == 0
&& CdDisk == 0
&& NumEntries_in_ThisDisk == 0
&& NumEntries == 0
&& Size == 0
&& Offset == 0 // test it
;
}
};
struct CVols
{
struct CSubStreamInfo
{
CMyComPtr<IInStream> Stream;
UInt64 Size;
HRESULT SeekToStart() const { return Stream->Seek(0, STREAM_SEEK_SET, NULL); }
CSubStreamInfo(): Size(0) {}
};
CObjectVector<CSubStreamInfo> Streams;
int StreamIndex; // -1 for StartStream
// -2 for ZipStream at multivol detection code
// >=0 volume index in multivol
bool NeedSeek;
bool DisableVolsSearch;
bool StartIsExe; // is .exe
bool StartIsZ; // is .zip or .zNN
bool StartIsZip; // is .zip
bool IsUpperCase;
bool MissingZip;
bool ecd_wasRead;
Int32 StartVolIndex; // -1, if unknown vol index
// = (NN - 1), if StartStream is .zNN
// = 0, if start vol is exe
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; // name of archive including '.'
UString MissingName;
CMyComPtr<IInStream> ZipStream;
CCdInfo ecd;
UInt64 TotalBytesSize; // for MultiVol only
void ClearRefs()
{
Streams.Clear();
ZipStream.Release();
TotalBytesSize = 0;
}
void Clear()
{
StreamIndex = -1;
NeedSeek = false;
DisableVolsSearch = false;
StartIsExe = false;
StartIsZ = false;
StartIsZip = false;
IsUpperCase = false;
StartVolIndex = -1;
StartParsingVol = 0;
NumVols = 0;
EndVolIndex = -1;
BaseName.Empty();
MissingName.Empty();
MissingZip = false;
ecd_wasRead = false;
ClearRefs();
}
HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
};
class CVolStream:
public ISequentialInStream,
public CMyUnknownImp
{
public:
CVols *Vols;
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
class CInArchive
{
CMidBuffer Buffer;
size_t _bufPos;
size_t _bufCached;
UInt64 _streamPos;
UInt64 _cnt;
// UInt32 _startLocalFromCd_Disk;
// UInt64 _startLocalFromCd_Offset;
size_t GetAvail() const { return _bufCached - _bufPos; }
void InitBuf() { _bufPos = 0; _bufCached = 0; }
void DisableBufMode() { InitBuf(); _inBufMode = false; }
void SkipLookahed(size_t skip)
{
_bufPos += skip;
_cnt += skip;
}
UInt64 GetVirtStreamPos() { return _streamPos - _bufCached + _bufPos; }
bool _inBufMode;
bool IsArcOpen;
bool CanStartNewVol;
UInt32 _signature;
CMyComPtr<IInStream> StreamRef;
IInStream *Stream;
IInStream *StartStream;
IArchiveOpenCallback *Callback;
HRESULT Seek_SavePos(UInt64 offset);
HRESULT SeekToVol(int volIndex, UInt64 offset);
HRESULT ReadFromCache(Byte *data, unsigned size, unsigned &processed);
HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,
unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);
HRESULT ReadVols();
HRESULT FindMarker(const UInt64 *searchLimit);
HRESULT IncreaseRealPosition(UInt64 addValue, bool &isFinished);
HRESULT LookAhead(size_t minRequiredInBuffer);
void SafeRead(Byte *data, unsigned size);
void ReadBuffer(CByteBuffer &buffer, unsigned size);
// Byte ReadByte();
// UInt16 ReadUInt16();
UInt32 ReadUInt32();
UInt64 ReadUInt64();
void ReadSignature();
void Skip(size_t num);
HRESULT Skip64(UInt64 num, unsigned numFiles);
bool ReadFileName(unsigned nameSize, AString &dest);
bool ReadExtra(unsigned extraSize, CExtraBlock &extra,
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk);
bool ReadLocalItem(CItemEx &item);
HRESULT FindDescriptor(CItemEx &item, unsigned numFiles);
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 ReadHeaders(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 LocalsWereRead;
bool LocalsCenterMerged;
bool NoCentralDir;
bool Overflow32bit; // = true, if zip without Zip64 extension support and it has some fields values truncated to 32-bits.
bool Cd_NumEntries_Overflow_16bit; // = true, if no Zip64 and 16-bit ecd:NumEntries was overflowed.
bool MarkerIsFound;
bool MarkerIsSafe;
bool IsMultiVol;
bool UseDisk_in_SingleVol;
UInt32 EcdVolIndex;
CVols Vols;
CInArchive(): Stream(NULL), StartStream(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);
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
{
// it's possible that first item in CD doesn refers to first local item
// so FirstItemRelatOffset is not first local item
if (ArcInfo.CdWasRead)
return ArcInfo.FirstItemRelatOffset;
if (IsMultiVol)
return 0;
return ArcInfo.MarkerPos2 - ArcInfo.Base;
}
HRESULT CheckDescriptor(const CItemEx &item);
HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool &headersError);
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

@@ -1,367 +1,367 @@
// Archive/ZipItem.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../../../C/7zCrc.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/MyLinux.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/PropVariantUtils.h"
#include "../Common/ItemNameUtils.h"
#include "ZipItem.h"
namespace NArchive {
namespace NZip {
using namespace NFileHeader;
/*
const char *k_SpecName_NTFS_STREAM = "@@NTFS@STREAM@";
const char *k_SpecName_MAC_RESOURCE_FORK = "@@MAC@RESOURCE-FORK@";
*/
static const CUInt32PCharPair g_ExtraTypes[] =
{
{ NExtraID::kZip64, "Zip64" },
{ NExtraID::kNTFS, "NTFS" },
{ NExtraID::kStrongEncrypt, "StrongCrypto" },
{ NExtraID::kUnixTime, "UT" },
{ NExtraID::kUnixExtra, "UX" },
{ NExtraID::kIzUnicodeComment, "uc" },
{ NExtraID::kIzUnicodeName, "up" },
{ NExtraID::kWzAES, "WzAES" }
};
void CExtraSubBlock::PrintInfo(AString &s) const
{
for (unsigned i = 0; i < ARRAY_SIZE(g_ExtraTypes); i++)
{
const CUInt32PCharPair &pair = g_ExtraTypes[i];
if (pair.Value == ID)
{
s += pair.Name;
return;
}
}
{
char sz[32];
sz[0] = '0';
sz[1] = 'x';
ConvertUInt32ToHex(ID, sz + 2);
s += sz;
}
}
void CExtraBlock::PrintInfo(AString &s) const
{
if (Error)
s.Add_OptSpaced("Extra_ERROR");
if (MinorError)
s.Add_OptSpaced("Minor_Extra_ERROR");
if (IsZip64 || IsZip64_Error)
{
s.Add_OptSpaced("Zip64");
if (IsZip64_Error)
s += "_ERROR";
}
FOR_VECTOR (i, SubBlocks)
{
s.Add_Space_if_NotEmpty();
SubBlocks[i].PrintInfo(s);
}
}
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 CExtraSubBlock::ExtractUnixExtraTime(unsigned index, UInt32 &res) const
{
res = 0;
const size_t size = Data.Size();
unsigned offset = index * 4;
if (ID != NExtraID::kUnixExtra || size < offset + 4)
return false;
const Byte *p = (const Byte *)Data + offset;
res = GetUi32(p);
return true;
}
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);
}
}
switch (index)
{
case NUnixTime::kMTime: index = NUnixExtra::kMTime; break;
case NUnixTime::kATime: index = NUnixExtra::kATime; break;
default: return false;
}
{
FOR_VECTOR (i, SubBlocks)
{
const CExtraSubBlock &sb = SubBlocks[i];
if (sb.ID == NFileHeader::NExtraID::kUnixExtra)
return sb.ExtractUnixExtraTime(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)
{
/*
Some programs write posix attributes in high 16 bits of ExternalAttrib
Also some programs can write additional marker flag:
0x8000 - p7zip
0x4000 - Zip in MacOS
no marker - Info-Zip
Client code has two options to detect posix field:
1) check 0x8000 marker. In that case we must add 0x8000 marker here.
2) check that high 4 bits (file type bits in posix field) of attributes are not zero.
*/
winAttrib = ExternalAttrib & 0xFFFF0000;
// #ifndef _WIN32
winAttrib |= 0x8000; // add posix mode marker
// #endif
}
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());
}
}}
// Archive/ZipItem.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../../../C/7zCrc.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/MyLinux.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/PropVariantUtils.h"
#include "../Common/ItemNameUtils.h"
#include "ZipItem.h"
namespace NArchive {
namespace NZip {
using namespace NFileHeader;
/*
const char *k_SpecName_NTFS_STREAM = "@@NTFS@STREAM@";
const char *k_SpecName_MAC_RESOURCE_FORK = "@@MAC@RESOURCE-FORK@";
*/
static const CUInt32PCharPair g_ExtraTypes[] =
{
{ NExtraID::kZip64, "Zip64" },
{ NExtraID::kNTFS, "NTFS" },
{ NExtraID::kStrongEncrypt, "StrongCrypto" },
{ NExtraID::kUnixTime, "UT" },
{ NExtraID::kUnixExtra, "UX" },
{ NExtraID::kIzUnicodeComment, "uc" },
{ NExtraID::kIzUnicodeName, "up" },
{ NExtraID::kWzAES, "WzAES" }
};
void CExtraSubBlock::PrintInfo(AString &s) const
{
for (unsigned i = 0; i < ARRAY_SIZE(g_ExtraTypes); i++)
{
const CUInt32PCharPair &pair = g_ExtraTypes[i];
if (pair.Value == ID)
{
s += pair.Name;
return;
}
}
{
char sz[32];
sz[0] = '0';
sz[1] = 'x';
ConvertUInt32ToHex(ID, sz + 2);
s += sz;
}
}
void CExtraBlock::PrintInfo(AString &s) const
{
if (Error)
s.Add_OptSpaced("Extra_ERROR");
if (MinorError)
s.Add_OptSpaced("Minor_Extra_ERROR");
if (IsZip64 || IsZip64_Error)
{
s.Add_OptSpaced("Zip64");
if (IsZip64_Error)
s += "_ERROR";
}
FOR_VECTOR (i, SubBlocks)
{
s.Add_Space_if_NotEmpty();
SubBlocks[i].PrintInfo(s);
}
}
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 CExtraSubBlock::ExtractUnixExtraTime(unsigned index, UInt32 &res) const
{
res = 0;
const size_t size = Data.Size();
unsigned offset = index * 4;
if (ID != NExtraID::kUnixExtra || size < offset + 4)
return false;
const Byte *p = (const Byte *)Data + offset;
res = GetUi32(p);
return true;
}
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);
}
}
switch (index)
{
case NUnixTime::kMTime: index = NUnixExtra::kMTime; break;
case NUnixTime::kATime: index = NUnixExtra::kATime; break;
default: return false;
}
{
FOR_VECTOR (i, SubBlocks)
{
const CExtraSubBlock &sb = SubBlocks[i];
if (sb.ID == NFileHeader::NExtraID::kUnixExtra)
return sb.ExtractUnixExtraTime(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)
{
/*
Some programs write posix attributes in high 16 bits of ExternalAttrib
Also some programs can write additional marker flag:
0x8000 - p7zip
0x4000 - Zip in MacOS
no marker - Info-Zip
Client code has two options to detect posix field:
1) check 0x8000 marker. In that case we must add 0x8000 marker here.
2) check that high 4 bits (file type bits in posix field) of attributes are not zero.
*/
winAttrib = ExternalAttrib & 0xFFFF0000;
// #ifndef _WIN32
winAttrib |= 0x8000; // add posix mode marker
// #endif
}
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

@@ -1,350 +1,350 @@
// 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 {
/*
extern const char *k_SpecName_NTFS_STREAM;
extern const char *k_SpecName_MAC_RESOURCE_FORK;
*/
struct CVersion
{
Byte Version;
Byte HostOS;
};
struct CExtraSubBlock
{
UInt32 ID;
CByteBuffer Data;
bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;
bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
bool ExtractUnixExtraTime(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);
}
void PrintInfo(AString &s) const;
};
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;
bool Error;
bool MinorError;
bool IsZip64;
bool IsZip64_Error;
CExtraBlock(): Error(false), MinorError(false), IsZip64(false), IsZip64_Error(false) {}
void Clear()
{
SubBlocks.Clear();
IsZip64 = false;
}
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 PrintInfo(AString &s) 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;
/*
Zip specification doesn't mention that ExtractVersion field uses HostOS subfield.
18.06: 7-Zip now doesn't use ExtractVersion::HostOS to detect codePage
*/
CVersion ExtractVersion;
UInt64 Size;
UInt64 PackSize;
UInt32 Time;
UInt32 Crc;
UInt32 Disk;
AString Name;
CExtraBlock LocalExtra;
unsigned GetDescriptorSize() const { return LocalExtra.IsZip64 ? kDataDescriptorSize64 : kDataDescriptorSize32; }
UInt64 GetPackSizeWithDescriptor() const
{ return PackSize + (HasDescriptor() ? GetDescriptorSize() : 0); }
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 IsAltStream() const { return (Flags & NFileHeader::NFlags::kAltStream) != 0; }
unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; }
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 SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); }
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;
// 18.06: 0 instead of ExtractVersion.HostOS for local item
Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : (Byte)0; }
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
{
// 18.06: now we use HostOS only from Central::MadeByVersion
if (!FromCentral)
return CP_OEMCP;
Byte hostOS = MadeByVersion.HostOS;
return (UINT)((
hostOS == NFileHeader::NHostOS::kFAT
|| hostOS == NFileHeader::NHostOS::kNTFS
|| hostOS == NFileHeader::NHostOS::kUnix // do we need it?
) ? CP_OEMCP : CP_ACP);
}
};
}}
#endif
// 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 {
/*
extern const char *k_SpecName_NTFS_STREAM;
extern const char *k_SpecName_MAC_RESOURCE_FORK;
*/
struct CVersion
{
Byte Version;
Byte HostOS;
};
struct CExtraSubBlock
{
UInt32 ID;
CByteBuffer Data;
bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;
bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
bool ExtractUnixExtraTime(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);
}
void PrintInfo(AString &s) const;
};
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;
bool Error;
bool MinorError;
bool IsZip64;
bool IsZip64_Error;
CExtraBlock(): Error(false), MinorError(false), IsZip64(false), IsZip64_Error(false) {}
void Clear()
{
SubBlocks.Clear();
IsZip64 = false;
}
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 PrintInfo(AString &s) 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;
/*
Zip specification doesn't mention that ExtractVersion field uses HostOS subfield.
18.06: 7-Zip now doesn't use ExtractVersion::HostOS to detect codePage
*/
CVersion ExtractVersion;
UInt64 Size;
UInt64 PackSize;
UInt32 Time;
UInt32 Crc;
UInt32 Disk;
AString Name;
CExtraBlock LocalExtra;
unsigned GetDescriptorSize() const { return LocalExtra.IsZip64 ? kDataDescriptorSize64 : kDataDescriptorSize32; }
UInt64 GetPackSizeWithDescriptor() const
{ return PackSize + (HasDescriptor() ? GetDescriptorSize() : 0); }
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 IsAltStream() const { return (Flags & NFileHeader::NFlags::kAltStream) != 0; }
unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; }
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 SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); }
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;
// 18.06: 0 instead of ExtractVersion.HostOS for local item
Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : (Byte)0; }
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
{
// 18.06: now we use HostOS only from Central::MadeByVersion
if (!FromCentral)
return CP_OEMCP;
Byte hostOS = MadeByVersion.HostOS;
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

@@ -1,348 +1,348 @@
// 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::SeekToCurPos()
{
HRESULT res = m_Stream->Seek(m_Base + m_CurPos, STREAM_SEEK_SET, NULL);
if (res != S_OK)
throw CSystemException(res);
}
#define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF)
// #define DOES_NEED_ZIP64(v) (v >= 0)
void COutArchive::WriteBytes(const void *data, size_t size)
{
m_OutBuffer.WriteBytes(data, size);
m_CurPos += size;
}
void COutArchive::Write8(Byte b)
{
m_OutBuffer.WriteByte(b);
m_CurPos++;
}
void COutArchive::Write16(UInt16 val)
{
Write8((Byte)val);
Write8((Byte)(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)
{
FOR_VECTOR (i, extra.SubBlocks)
{
const CExtraSubBlock &subBlock = extra.SubBlocks[i];
Write16((UInt16)subBlock.ID);
Write16((UInt16)subBlock.Data.Size());
WriteBytes(subBlock.Data, (UInt16)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);
}
#define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v));
void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)
{
m_LocalHeaderPos = m_CurPos;
item.LocalHeaderPos = m_CurPos;
bool isZip64 =
DOES_NEED_ZIP64(item.PackSize) ||
DOES_NEED_ZIP64(item.Size);
if (needCheck && m_IsZip64)
isZip64 = true;
const UInt32 localExtraSize = (UInt32)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize());
if ((UInt16)localExtraSize != localExtraSize)
throw CSystemException(E_FAIL);
if (needCheck && m_ExtraSize != localExtraSize)
throw CSystemException(E_FAIL);
m_IsZip64 = isZip64;
m_ExtraSize = localExtraSize;
item.LocalExtra.IsZip64 = isZip64;
Write32(NSignature::kLocalFileHeader);
WriteCommonItemInfo(item, isZip64);
Write32(item.HasDescriptor() ? 0 : item.Crc);
UInt64 packSize = item.PackSize;
UInt64 size = item.Size;
if (item.HasDescriptor())
{
packSize = 0;
size = 0;
}
WRITE_32_VAL_SPEC(packSize, isZip64);
WRITE_32_VAL_SPEC(size, isZip64);
Write16((UInt16)item.Name.Len());
Write16((UInt16)localExtraSize);
WriteBytes((const char *)item.Name, (UInt16)item.Name.Len());
if (isZip64)
{
Write16(NFileHeader::NExtraID::kZip64);
Write16(8 + 8);
Write64(size);
Write64(packSize);
}
WriteExtra(item.LocalExtra);
// Why don't we write NTFS timestamps to local header?
// Probably we want to reduce size of archive?
const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos);
if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize)
throw CSystemException(E_FAIL);
m_LocalFileHeaderSize = localFileHeaderSize;
m_OutBuffer.FlushWithCheck();
}
void COutArchive::WriteLocalHeader_Replace(CItemOut &item)
{
m_CurPos = m_LocalHeaderPos + m_LocalFileHeaderSize + item.PackSize;
if (item.HasDescriptor())
{
WriteDescriptor(item);
m_OutBuffer.FlushWithCheck();
return;
// we don't replace local header, if we write Descriptor.
// so local header with Descriptor flag must be written to local header before.
}
const UInt64 nextPos = m_CurPos;
m_CurPos = m_LocalHeaderPos;
SeekToCurPos();
WriteLocalHeader(item, true);
m_CurPos = nextPos;
SeekToCurPos();
}
void COutArchive::WriteDescriptor(const CItemOut &item)
{
Byte buf[kDataDescriptorSize64];
SetUi32(buf, NSignature::kDataDescriptor);
SetUi32(buf + 4, item.Crc);
unsigned descriptorSize;
if (m_IsZip64)
{
SetUi64(buf + 8, item.PackSize);
SetUi64(buf + 16, item.Size);
descriptorSize = kDataDescriptorSize64;
}
else
{
SetUi32(buf + 8, (UInt32)item.PackSize);
SetUi32(buf + 12, (UInt32)item.Size);
descriptorSize = kDataDescriptorSize32;
}
WriteBytes(buf, descriptorSize);
}
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);
Write32(item.Crc);
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;
const UInt16 commentSize = (UInt16)item.Comment.Size();
Write16(commentSize);
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 (commentSize != 0)
WriteBytes(item.Comment, commentSize);
}
void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)
{
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);
// to test extra block:
// const UInt32 extraSize = 1 << 26;
// Write64(kEcd64_MainSize + extraSize);
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);
// for (UInt32 iii = 0; iii < extraSize; iii++) Write8(1);
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);
const UInt16 commentSize = (UInt16)(comment ? comment->Size() : 0);
Write16((UInt16)commentSize);
if (commentSize != 0)
WriteBytes((const Byte *)*comment, commentSize);
m_OutBuffer.FlushWithCheck();
}
void COutArchive::CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream)
{
COffsetOutStream *streamSpec = new COffsetOutStream;
outStream = streamSpec;
streamSpec->Init(m_Stream, m_Base + m_CurPos);
}
void COutArchive::CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream)
{
outStream = m_Stream;
}
}}
// 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::SeekToCurPos()
{
HRESULT res = m_Stream->Seek(m_Base + m_CurPos, STREAM_SEEK_SET, NULL);
if (res != S_OK)
throw CSystemException(res);
}
#define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF)
// #define DOES_NEED_ZIP64(v) (v >= 0)
void COutArchive::WriteBytes(const void *data, size_t size)
{
m_OutBuffer.WriteBytes(data, size);
m_CurPos += size;
}
void COutArchive::Write8(Byte b)
{
m_OutBuffer.WriteByte(b);
m_CurPos++;
}
void COutArchive::Write16(UInt16 val)
{
Write8((Byte)val);
Write8((Byte)(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)
{
FOR_VECTOR (i, extra.SubBlocks)
{
const CExtraSubBlock &subBlock = extra.SubBlocks[i];
Write16((UInt16)subBlock.ID);
Write16((UInt16)subBlock.Data.Size());
WriteBytes(subBlock.Data, (UInt16)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);
}
#define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v));
void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)
{
m_LocalHeaderPos = m_CurPos;
item.LocalHeaderPos = m_CurPos;
bool isZip64 =
DOES_NEED_ZIP64(item.PackSize) ||
DOES_NEED_ZIP64(item.Size);
if (needCheck && m_IsZip64)
isZip64 = true;
const UInt32 localExtraSize = (UInt32)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize());
if ((UInt16)localExtraSize != localExtraSize)
throw CSystemException(E_FAIL);
if (needCheck && m_ExtraSize != localExtraSize)
throw CSystemException(E_FAIL);
m_IsZip64 = isZip64;
m_ExtraSize = localExtraSize;
item.LocalExtra.IsZip64 = isZip64;
Write32(NSignature::kLocalFileHeader);
WriteCommonItemInfo(item, isZip64);
Write32(item.HasDescriptor() ? 0 : item.Crc);
UInt64 packSize = item.PackSize;
UInt64 size = item.Size;
if (item.HasDescriptor())
{
packSize = 0;
size = 0;
}
WRITE_32_VAL_SPEC(packSize, isZip64);
WRITE_32_VAL_SPEC(size, isZip64);
Write16((UInt16)item.Name.Len());
Write16((UInt16)localExtraSize);
WriteBytes((const char *)item.Name, (UInt16)item.Name.Len());
if (isZip64)
{
Write16(NFileHeader::NExtraID::kZip64);
Write16(8 + 8);
Write64(size);
Write64(packSize);
}
WriteExtra(item.LocalExtra);
// Why don't we write NTFS timestamps to local header?
// Probably we want to reduce size of archive?
const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos);
if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize)
throw CSystemException(E_FAIL);
m_LocalFileHeaderSize = localFileHeaderSize;
m_OutBuffer.FlushWithCheck();
}
void COutArchive::WriteLocalHeader_Replace(CItemOut &item)
{
m_CurPos = m_LocalHeaderPos + m_LocalFileHeaderSize + item.PackSize;
if (item.HasDescriptor())
{
WriteDescriptor(item);
m_OutBuffer.FlushWithCheck();
return;
// we don't replace local header, if we write Descriptor.
// so local header with Descriptor flag must be written to local header before.
}
const UInt64 nextPos = m_CurPos;
m_CurPos = m_LocalHeaderPos;
SeekToCurPos();
WriteLocalHeader(item, true);
m_CurPos = nextPos;
SeekToCurPos();
}
void COutArchive::WriteDescriptor(const CItemOut &item)
{
Byte buf[kDataDescriptorSize64];
SetUi32(buf, NSignature::kDataDescriptor);
SetUi32(buf + 4, item.Crc);
unsigned descriptorSize;
if (m_IsZip64)
{
SetUi64(buf + 8, item.PackSize);
SetUi64(buf + 16, item.Size);
descriptorSize = kDataDescriptorSize64;
}
else
{
SetUi32(buf + 8, (UInt32)item.PackSize);
SetUi32(buf + 12, (UInt32)item.Size);
descriptorSize = kDataDescriptorSize32;
}
WriteBytes(buf, descriptorSize);
}
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);
Write32(item.Crc);
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;
const UInt16 commentSize = (UInt16)item.Comment.Size();
Write16(commentSize);
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 (commentSize != 0)
WriteBytes(item.Comment, commentSize);
}
void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)
{
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);
// to test extra block:
// const UInt32 extraSize = 1 << 26;
// Write64(kEcd64_MainSize + extraSize);
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);
// for (UInt32 iii = 0; iii < extraSize; iii++) Write8(1);
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);
const UInt16 commentSize = (UInt16)(comment ? comment->Size() : 0);
Write16((UInt16)commentSize);
if (commentSize != 0)
WriteBytes((const Byte *)*comment, commentSize);
m_OutBuffer.FlushWithCheck();
}
void COutArchive::CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream)
{
COffsetOutStream *streamSpec = new COffsetOutStream;
outStream = streamSpec;
streamSpec->Init(m_Stream, m_Base + m_CurPos);
}
void COutArchive::CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream)
{
outStream = m_Stream;
}
}}

View File

@@ -1,83 +1,83 @@
// ZipOut.h
#ifndef __ZIP_OUT_H
#define __ZIP_OUT_H
#include "../../../Common/MyCom.h"
#include "../../Common/OutBuffer.h"
#include "ZipItem.h"
namespace NArchive {
namespace NZip {
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) {}
};
// COutArchive can throw CSystemException and COutBufferException
class COutArchive
{
COutBuffer m_OutBuffer;
CMyComPtr<IOutStream> m_Stream;
UInt64 m_Base; // Base of archive (offset in output Stream)
UInt64 m_CurPos; // Curent position in archive (relative from m_Base)
UInt64 m_LocalHeaderPos; // LocalHeaderPos (relative from m_Base) for last WriteLocalHeader() call
UInt32 m_LocalFileHeaderSize;
UInt32 m_ExtraSize;
bool m_IsZip64;
void WriteBytes(const void *data, size_t 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 SeekToCurPos();
public:
HRESULT Create(IOutStream *outStream);
UInt64 GetCurPos() const { return m_CurPos; }
void MoveCurPos(UInt64 distanceToMove)
{
m_CurPos += distanceToMove;
}
void WriteLocalHeader(CItemOut &item, bool needCheck = false);
void WriteLocalHeader_Replace(CItemOut &item);
void WriteDescriptor(const CItemOut &item);
void WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment);
void CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream);
void CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream);
};
}}
#endif
// ZipOut.h
#ifndef __ZIP_OUT_H
#define __ZIP_OUT_H
#include "../../../Common/MyCom.h"
#include "../../Common/OutBuffer.h"
#include "ZipItem.h"
namespace NArchive {
namespace NZip {
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) {}
};
// COutArchive can throw CSystemException and COutBufferException
class COutArchive
{
COutBuffer m_OutBuffer;
CMyComPtr<IOutStream> m_Stream;
UInt64 m_Base; // Base of archive (offset in output Stream)
UInt64 m_CurPos; // Curent position in archive (relative from m_Base)
UInt64 m_LocalHeaderPos; // LocalHeaderPos (relative from m_Base) for last WriteLocalHeader() call
UInt32 m_LocalFileHeaderSize;
UInt32 m_ExtraSize;
bool m_IsZip64;
void WriteBytes(const void *data, size_t 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 SeekToCurPos();
public:
HRESULT Create(IOutStream *outStream);
UInt64 GetCurPos() const { return m_CurPos; }
void MoveCurPos(UInt64 distanceToMove)
{
m_CurPos += distanceToMove;
}
void WriteLocalHeader(CItemOut &item, bool needCheck = false);
void WriteLocalHeader_Replace(CItemOut &item);
void WriteDescriptor(const CItemOut &item);
void WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment);
void CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream);
void CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream);
};
}}
#endif

View File

@@ -1,28 +1,28 @@
// 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, // Local
4, 0x50, 0x4B, 0x05, 0x06, // Ecd
4, 0x50, 0x4B, 0x06, 0x06, // Ecd64
6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B, // Span / Descriptor
6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B }; // NoSpan
REGISTER_ARC_IO(
"zip", "zip z01 zipx jar xpi odt ods docx xlsx epub ipa apk appx", 0, 1,
k_Signature,
0,
NArcInfoFlags::kFindSignature |
NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kUseGlobalOffset,
IsArc_Zip)
}}
// 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, // Local
4, 0x50, 0x4B, 0x05, 0x06, // Ecd
4, 0x50, 0x4B, 0x06, 0x06, // Ecd64
6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B, // Span / Descriptor
6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B }; // NoSpan
REGISTER_ARC_IO(
"zip", "zip z01 zipx jar xpi odt ods docx xlsx epub ipa apk appx", 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

@@ -1,80 +1,80 @@
// 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;
// bool IsAltStream;
int IndexInArc;
int IndexInClient;
UInt32 Attrib;
UInt32 Time;
UInt64 Size;
AString Name;
CByteBuffer Comment;
// bool Commented;
// CUpdateRange CommentRange;
FILETIME Ntfs_MTime;
FILETIME Ntfs_ATime;
FILETIME Ntfs_CTime;
void Clear()
{
IsDir = false;
NtfsTimeIsDefined = false;
IsUtf8 = false;
// IsAltStream = false;
Size = 0;
Name.Empty();
Comment.Free();
}
CUpdateItem():
IsDir(false),
NtfsTimeIsDefined(false),
IsUtf8(false),
// IsAltStream(false),
Size(0)
{}
};
HRESULT Update(
DECL_EXTERNAL_CODECS_LOC_VARS
const CObjectVector<CItemEx> &inputItems,
CObjectVector<CUpdateItem> &updateItems,
ISequentialOutStream *seqOutStream,
CInArchive *inArchive, bool removeSfx,
const CCompressionMethodMode &compressionMethodMode,
IArchiveUpdateCallback *updateCallback);
}}
#endif
// 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;
// bool IsAltStream;
int IndexInArc;
int IndexInClient;
UInt32 Attrib;
UInt32 Time;
UInt64 Size;
AString Name;
CByteBuffer Comment;
// bool Commented;
// CUpdateRange CommentRange;
FILETIME Ntfs_MTime;
FILETIME Ntfs_ATime;
FILETIME Ntfs_CTime;
void Clear()
{
IsDir = false;
NtfsTimeIsDefined = false;
IsUtf8 = false;
// IsAltStream = false;
Size = 0;
Name.Empty();
Comment.Free();
}
CUpdateItem():
IsDir(false),
NtfsTimeIsDefined(false),
IsUtf8(false),
// IsAltStream(false),
Size(0)
{}
};
HRESULT Update(
DECL_EXTERNAL_CODECS_LOC_VARS
const CObjectVector<CItemEx> &inputItems,
CObjectVector<CUpdateItem> &updateItems,
ISequentialOutStream *seqOutStream,
CInArchive *inArchive, bool removeSfx,
const CCompressionMethodMode &compressionMethodMode,
IArchiveUpdateCallback *updateCallback);
}}
#endif