mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-14 14:11:40 -06:00
Normalize all the line endings
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
}}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user