mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 05:15:01 -06:00
Initialer Commit
This commit is contained in:
8
CPP/7zip/Archive/Zip/StdAfx.h
Normal file
8
CPP/7zip/Archive/Zip/StdAfx.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
363
CPP/7zip/Archive/Zip/ZipAddCommon.cpp
Normal file
363
CPP/7zip/Archive/Zip/ZipAddCommon.cpp
Normal file
@@ -0,0 +1,363 @@
|
||||
// ZipAddCommon.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../../IPassword.h"
|
||||
#include "../../MyVersion.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../../Compress/LzmaEncoder.h"
|
||||
#include "../../Compress/PpmdZip.h"
|
||||
|
||||
#include "../Common/InStreamWithCRC.h"
|
||||
|
||||
#include "ZipAddCommon.h"
|
||||
#include "ZipHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
static const CMethodId kMethodId_ZipBase = 0x040100;
|
||||
static const CMethodId kMethodId_BZip2 = 0x040202;
|
||||
|
||||
static const UInt32 kLzmaPropsSize = 5;
|
||||
static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
|
||||
|
||||
class CLzmaEncoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
NCompress::NLzma::CEncoder *EncoderSpec;
|
||||
CMyComPtr<ICompressCoder> Encoder;
|
||||
Byte Header[kLzmaHeaderSize];
|
||||
public:
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
|
||||
};
|
||||
|
||||
STDMETHODIMP CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
|
||||
{
|
||||
if (!Encoder)
|
||||
{
|
||||
EncoderSpec = new NCompress::NLzma::CEncoder;
|
||||
Encoder = EncoderSpec;
|
||||
}
|
||||
CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->Init(Header + 4, kLzmaPropsSize);
|
||||
RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps));
|
||||
RINOK(EncoderSpec->WriteCoderProperties(outStream));
|
||||
if (outStreamSpec->GetPos() != kLzmaPropsSize)
|
||||
return E_FAIL;
|
||||
Header[0] = MY_VER_MAJOR;
|
||||
Header[1] = MY_VER_MINOR;
|
||||
Header[2] = kLzmaPropsSize;
|
||||
Header[3] = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
RINOK(WriteStream(outStream, Header, kLzmaHeaderSize));
|
||||
return Encoder->Code(inStream, outStream, inSize, outSize, progress);
|
||||
}
|
||||
|
||||
|
||||
CAddCommon::CAddCommon(const CCompressionMethodMode &options):
|
||||
_options(options),
|
||||
_copyCoderSpec(NULL),
|
||||
_cryptoStreamSpec(NULL),
|
||||
_buf(NULL)
|
||||
{}
|
||||
|
||||
CAddCommon::~CAddCommon()
|
||||
{
|
||||
MidFree(_buf);
|
||||
}
|
||||
|
||||
static const UInt32 kBufSize = ((UInt32)1 << 16);
|
||||
|
||||
HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
|
||||
{
|
||||
if (!_buf)
|
||||
{
|
||||
_buf = (Byte *)MidAlloc(kBufSize);
|
||||
if (!_buf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
UInt32 crc = CRC_INIT_VAL;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 processed;
|
||||
RINOK(inStream->Read(_buf, kBufSize, &processed));
|
||||
if (processed == 0)
|
||||
{
|
||||
resultCRC = CRC_GET_DIGEST(crc);
|
||||
return S_OK;
|
||||
}
|
||||
crc = CrcUpdate(crc, _buf, (size_t)processed);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CAddCommon::Compress(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
ISequentialInStream *inStream, IOutStream *outStream,
|
||||
UInt32 /* fileTime */,
|
||||
ICompressProgressInfo *progress, CCompressingResult &opRes)
|
||||
{
|
||||
if (!inStream)
|
||||
{
|
||||
// We can create empty stream here. But it was already implemented in caller code in 9.33+
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL;
|
||||
CInStreamWithCRC *inCrcStreamSpec = NULL;
|
||||
CMyComPtr<ISequentialInStream> inCrcStream;
|
||||
{
|
||||
CMyComPtr<IInStream> inStream2;
|
||||
|
||||
inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
|
||||
|
||||
if (inStream2)
|
||||
{
|
||||
inCrcStreamSpec = new CInStreamWithCRC;
|
||||
inCrcStream = inCrcStreamSpec;
|
||||
inCrcStreamSpec->SetStream(inStream2);
|
||||
inCrcStreamSpec->Init();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we don't support stdin, since stream from stdin can require 64-bit size header
|
||||
return E_NOTIMPL;
|
||||
/*
|
||||
inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
|
||||
inCrcStream = inSecCrcStreamSpec;
|
||||
inSecCrcStreamSpec->SetStream(inStream);
|
||||
inSecCrcStreamSpec->Init();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
unsigned numTestMethods = _options.MethodSequence.Size();
|
||||
|
||||
if (numTestMethods > 1 && !inCrcStreamSpec)
|
||||
numTestMethods = 1;
|
||||
|
||||
UInt32 crc = 0;
|
||||
bool crc_IsCalculated = false;
|
||||
|
||||
Byte method = 0;
|
||||
CFilterCoder::C_OutStream_Releaser outStreamReleaser;
|
||||
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
|
||||
opRes.FileTimeWasUsed = false;
|
||||
|
||||
for (unsigned i = 0; i < numTestMethods; i++)
|
||||
{
|
||||
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
|
||||
if (inCrcStreamSpec)
|
||||
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
RINOK(outStream->SetSize(0));
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto;
|
||||
|
||||
if (!_cryptoStream)
|
||||
{
|
||||
_cryptoStreamSpec = new CFilterCoder(true);
|
||||
_cryptoStream = _cryptoStreamSpec;
|
||||
}
|
||||
|
||||
if (_options.IsAesMode)
|
||||
{
|
||||
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes;
|
||||
if (!_cryptoStreamSpec->Filter)
|
||||
{
|
||||
_cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;
|
||||
_filterAesSpec->SetKeyMode(_options.AesKeyMode);
|
||||
RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()));
|
||||
}
|
||||
RINOK(_filterAesSpec->WriteHeader(outStream));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_cryptoStreamSpec->Filter)
|
||||
{
|
||||
_cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
|
||||
_filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len());
|
||||
}
|
||||
|
||||
UInt32 check;
|
||||
|
||||
// if (inCrcStreamSpec)
|
||||
{
|
||||
if (!crc_IsCalculated)
|
||||
{
|
||||
RINOK(CalcStreamCRC(inStream, crc));
|
||||
crc_IsCalculated = true;
|
||||
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
check = (crc >> 16);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
opRes.FileTimeWasUsed = true;
|
||||
check = (fileTime & 0xFFFF);
|
||||
}
|
||||
*/
|
||||
|
||||
RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
|
||||
}
|
||||
|
||||
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
|
||||
RINOK(_cryptoStreamSpec->InitEncoder());
|
||||
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
|
||||
}
|
||||
|
||||
method = _options.MethodSequence[i];
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case NFileHeader::NCompressionMethod::kStored:
|
||||
{
|
||||
if (_copyCoderSpec == NULL)
|
||||
{
|
||||
_copyCoderSpec = new NCompress::CCopyCoder;
|
||||
_copyCoder = _copyCoderSpec;
|
||||
}
|
||||
CMyComPtr<ISequentialOutStream> outStreamNew;
|
||||
if (_options.PasswordIsDefined)
|
||||
outStreamNew = _cryptoStream;
|
||||
else
|
||||
outStreamNew = outStream;
|
||||
RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (!_compressEncoder)
|
||||
{
|
||||
if (method == NFileHeader::NCompressionMethod::kLZMA)
|
||||
{
|
||||
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA;
|
||||
CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder();
|
||||
_compressEncoder = _lzmaEncoder;
|
||||
}
|
||||
else if (method == NFileHeader::NCompressionMethod::kPPMd)
|
||||
{
|
||||
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;
|
||||
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
|
||||
_compressEncoder = encoder;
|
||||
}
|
||||
else
|
||||
{
|
||||
CMethodId methodId;
|
||||
switch (method)
|
||||
{
|
||||
case NFileHeader::NCompressionMethod::kBZip2:
|
||||
methodId = kMethodId_BZip2;
|
||||
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_BZip2;
|
||||
break;
|
||||
default:
|
||||
_compressExtractVersion = ((method == NFileHeader::NCompressionMethod::kDeflated64) ?
|
||||
NFileHeader::NCompressionMethod::kExtractVersion_Deflate64 :
|
||||
NFileHeader::NCompressionMethod::kExtractVersion_Deflate);
|
||||
methodId = kMethodId_ZipBase + method;
|
||||
break;
|
||||
}
|
||||
RINOK(CreateCoder(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodId, true, _compressEncoder));
|
||||
if (!_compressEncoder)
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (method == NFileHeader::NCompressionMethod::kDeflated ||
|
||||
method == NFileHeader::NCompressionMethod::kDeflated64)
|
||||
{
|
||||
}
|
||||
else if (method == NFileHeader::NCompressionMethod::kBZip2)
|
||||
{
|
||||
}
|
||||
}
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderProperties> setCoderProps;
|
||||
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
|
||||
if (setCoderProps)
|
||||
{
|
||||
RINOK(_options.MethodInfo.SetCoderProps(setCoderProps,
|
||||
_options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
|
||||
}
|
||||
}
|
||||
}
|
||||
CMyComPtr<ISequentialOutStream> outStreamNew;
|
||||
if (_options.PasswordIsDefined)
|
||||
outStreamNew = _cryptoStream;
|
||||
else
|
||||
outStreamNew = outStream;
|
||||
if (_compressExtractVersion > opRes.ExtractVersion)
|
||||
opRes.ExtractVersion = _compressExtractVersion;
|
||||
RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
RINOK(_cryptoStreamSpec->OutStreamFinish());
|
||||
|
||||
if (_options.IsAesMode)
|
||||
{
|
||||
RINOK(_filterAesSpec->WriteFooter(outStream));
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
|
||||
|
||||
// if (inCrcStreamSpec)
|
||||
{
|
||||
opRes.CRC = inCrcStreamSpec->GetCRC();
|
||||
opRes.UnpackSize = inCrcStreamSpec->GetSize();
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
opRes.CRC = inSecCrcStreamSpec->GetCRC();
|
||||
opRes.UnpackSize = inSecCrcStreamSpec->GetSize();
|
||||
}
|
||||
*/
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
if (opRes.PackSize < opRes.UnpackSize +
|
||||
(_options.IsAesMode ? _filterAesSpec->GetAddPackSize() : NCrypto::NZip::kHeaderSize))
|
||||
break;
|
||||
}
|
||||
else if (opRes.PackSize < opRes.UnpackSize)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
opRes.Method = method;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
62
CPP/7zip/Archive/Zip/ZipAddCommon.h
Normal file
62
CPP/7zip/Archive/Zip/ZipAddCommon.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// ZipAddCommon.h
|
||||
|
||||
#ifndef __ZIP_ADD_COMMON_H
|
||||
#define __ZIP_ADD_COMMON_H
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../../IProgress.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/FilterCoder.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
|
||||
#include "../../Crypto/ZipCrypto.h"
|
||||
#include "../../Crypto/WzAes.h"
|
||||
|
||||
#include "ZipCompressionMode.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
struct CCompressingResult
|
||||
{
|
||||
UInt64 UnpackSize;
|
||||
UInt64 PackSize;
|
||||
UInt32 CRC;
|
||||
UInt16 Method;
|
||||
Byte ExtractVersion;
|
||||
bool FileTimeWasUsed;
|
||||
};
|
||||
|
||||
class CAddCommon
|
||||
{
|
||||
CCompressionMethodMode _options;
|
||||
NCompress::CCopyCoder *_copyCoderSpec;
|
||||
CMyComPtr<ICompressCoder> _copyCoder;
|
||||
|
||||
CMyComPtr<ICompressCoder> _compressEncoder;
|
||||
Byte _compressExtractVersion;
|
||||
|
||||
CFilterCoder *_cryptoStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _cryptoStream;
|
||||
|
||||
NCrypto::NZip::CEncoder *_filterSpec;
|
||||
NCrypto::NWzAes::CEncoder *_filterAesSpec;
|
||||
|
||||
Byte *_buf;
|
||||
|
||||
HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC);
|
||||
public:
|
||||
CAddCommon(const CCompressionMethodMode &options);
|
||||
~CAddCommon();
|
||||
HRESULT Compress(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
ISequentialInStream *inStream, IOutStream *outStream,
|
||||
UInt32 fileTime,
|
||||
ICompressProgressInfo *progress, CCompressingResult &operationResult);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
62
CPP/7zip/Archive/Zip/ZipCompressionMode.h
Normal file
62
CPP/7zip/Archive/Zip/ZipCompressionMode.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// CompressionMode.h
|
||||
|
||||
#ifndef __ZIP_COMPRESSION_MODE_H
|
||||
#define __ZIP_COMPRESSION_MODE_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "../../../Windows/System.h"
|
||||
#endif
|
||||
|
||||
#include "../Common/HandlerOut.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
struct CBaseProps
|
||||
{
|
||||
CMethodProps MethodInfo;
|
||||
Int32 Level;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 NumThreads;
|
||||
bool NumThreadsWasChanged;
|
||||
#endif
|
||||
bool IsAesMode;
|
||||
Byte AesKeyMode;
|
||||
|
||||
void Init()
|
||||
{
|
||||
MethodInfo.Clear();
|
||||
Level = -1;
|
||||
#ifndef _7ZIP_ST
|
||||
NumThreads = NWindows::NSystem::GetNumberOfProcessors();;
|
||||
NumThreadsWasChanged = false;
|
||||
#endif
|
||||
IsAesMode = false;
|
||||
AesKeyMode = 3;
|
||||
}
|
||||
};
|
||||
|
||||
struct CCompressionMethodMode: public CBaseProps
|
||||
{
|
||||
CRecordVector<Byte> MethodSequence;
|
||||
bool PasswordIsDefined;
|
||||
AString Password;
|
||||
|
||||
UInt64 _dataSizeReduce;
|
||||
bool _dataSizeReduceDefined;
|
||||
|
||||
bool IsRealAesMode() const { return PasswordIsDefined && IsAesMode; }
|
||||
|
||||
CCompressionMethodMode(): PasswordIsDefined(false)
|
||||
{
|
||||
_dataSizeReduceDefined = false;
|
||||
_dataSizeReduce = 0;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
1089
CPP/7zip/Archive/Zip/ZipHandler.cpp
Normal file
1089
CPP/7zip/Archive/Zip/ZipHandler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
74
CPP/7zip/Archive/Zip/ZipHandler.h
Normal file
74
CPP/7zip/Archive/Zip/ZipHandler.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Zip/Handler.h
|
||||
|
||||
#ifndef __ZIP_HANDLER_H
|
||||
#define __ZIP_HANDLER_H
|
||||
|
||||
#include "../../../Common/DynamicBuffer.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "ZipIn.h"
|
||||
#include "ZipCompressionMode.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IOutArchive,
|
||||
public ISetProperties,
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(IOutArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IOutArchive(;)
|
||||
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
|
||||
DECL_ISetCompressCodecsInfo
|
||||
|
||||
CHandler();
|
||||
private:
|
||||
CObjectVector<CItemEx> m_Items;
|
||||
CInArchive m_Archive;
|
||||
|
||||
CBaseProps _props;
|
||||
|
||||
int m_MainMethod;
|
||||
bool m_ForceAesMode;
|
||||
bool m_WriteNtfsTimeExtra;
|
||||
bool _removeSfxBlock;
|
||||
bool m_ForceLocal;
|
||||
bool m_ForceUtf8;
|
||||
bool _forceCodePage;
|
||||
UInt32 _specifiedCodePage;
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
|
||||
void InitMethodProps()
|
||||
{
|
||||
_props.Init();
|
||||
m_MainMethod = -1;
|
||||
m_ForceAesMode = false;
|
||||
m_WriteNtfsTimeExtra = true;
|
||||
_removeSfxBlock = false;
|
||||
m_ForceLocal = false;
|
||||
m_ForceUtf8 = false;
|
||||
_forceCodePage = false;
|
||||
_specifiedCodePage = CP_OEMCP;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
442
CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
Normal file
442
CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
Normal file
@@ -0,0 +1,442 @@
|
||||
// ZipHandlerOut.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
#include "../../../Common/StringToInt.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#include "../../Common/OutBuffer.h"
|
||||
|
||||
#include "../../Crypto/WzAes.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
#include "../Common/ParseProperties.h"
|
||||
|
||||
#include "ZipHandler.h"
|
||||
#include "ZipUpdate.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
|
||||
{
|
||||
*timeType = NFileTimeType::kDOS;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static bool IsSimpleAsciiString(const wchar_t *s)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = *s++;
|
||||
if (c == 0)
|
||||
return true;
|
||||
if (c < 0x20 || c > 0x7F)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define COM_TRY_BEGIN2 try {
|
||||
#define COM_TRY_END2 } \
|
||||
catch(const CSystemException &e) { return e.ErrorCode; } \
|
||||
catch(...) { return E_OUTOFMEMORY; }
|
||||
|
||||
static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime)
|
||||
{
|
||||
filetime.dwHighDateTime = filetime.dwLowDateTime = 0;
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(index, propID, &prop));
|
||||
if (prop.vt == VT_FILETIME)
|
||||
filetime = prop.filetime;
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN2
|
||||
|
||||
if (m_Archive.IsOpen())
|
||||
{
|
||||
if (!m_Archive.CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
CObjectVector<CUpdateItem> updateItems;
|
||||
bool thereAreAesUpdates = false;
|
||||
UInt64 largestSize = 0;
|
||||
bool largestSizeDefined = false;
|
||||
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
CUpdateItem ui;
|
||||
Int32 newData;
|
||||
Int32 newProps;
|
||||
UInt32 indexInArchive;
|
||||
if (!callback)
|
||||
return E_FAIL;
|
||||
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
|
||||
ui.NewProps = IntToBool(newProps);
|
||||
ui.NewData = IntToBool(newData);
|
||||
ui.IndexInArc = indexInArchive;
|
||||
ui.IndexInClient = i;
|
||||
bool existInArchive = (indexInArchive != (UInt32)(Int32)-1);
|
||||
if (existInArchive && newData)
|
||||
if (m_Items[indexInArchive].IsAesEncrypted())
|
||||
thereAreAesUpdates = true;
|
||||
|
||||
if (IntToBool(newProps))
|
||||
{
|
||||
UString name;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidAttrib, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
ui.Attrib = 0;
|
||||
else if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
ui.Attrib = prop.ulVal;
|
||||
}
|
||||
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidPath, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
name.Empty();
|
||||
else if (prop.vt != VT_BSTR)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
name = prop.bstrVal;
|
||||
}
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidIsDir, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
ui.IsDir = false;
|
||||
else if (prop.vt != VT_BOOL)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
|
||||
}
|
||||
|
||||
{
|
||||
CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidTimeType, &prop));
|
||||
if (prop.vt == VT_UI4)
|
||||
ui.NtfsTimeIsDefined = (prop.ulVal == NFileTimeType::kWindows);
|
||||
else
|
||||
ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra;
|
||||
}
|
||||
RINOK(GetTime(callback, i, kpidMTime, ui.Ntfs_MTime));
|
||||
RINOK(GetTime(callback, i, kpidATime, ui.Ntfs_ATime));
|
||||
RINOK(GetTime(callback, i, kpidCTime, ui.Ntfs_CTime));
|
||||
|
||||
{
|
||||
FILETIME localFileTime = { 0, 0 };
|
||||
if (ui.Ntfs_MTime.dwHighDateTime != 0 ||
|
||||
ui.Ntfs_MTime.dwLowDateTime != 0)
|
||||
if (!FileTimeToLocalFileTime(&ui.Ntfs_MTime, &localFileTime))
|
||||
return E_INVALIDARG;
|
||||
FileTimeToDosTime(localFileTime, ui.Time);
|
||||
}
|
||||
|
||||
name = NItemName::MakeLegalName(name);
|
||||
bool needSlash = ui.IsDir;
|
||||
const wchar_t kSlash = L'/';
|
||||
if (!name.IsEmpty())
|
||||
{
|
||||
if (name.Back() == kSlash)
|
||||
{
|
||||
if (!ui.IsDir)
|
||||
return E_INVALIDARG;
|
||||
needSlash = false;
|
||||
}
|
||||
}
|
||||
if (needSlash)
|
||||
name += kSlash;
|
||||
|
||||
UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP;
|
||||
|
||||
bool tryUtf8 = true;
|
||||
if ((m_ForceLocal || !m_ForceUtf8) && codePage != CP_UTF8)
|
||||
{
|
||||
bool defaultCharWasUsed;
|
||||
ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed);
|
||||
tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||
|
||||
MultiByteToUnicodeString(ui.Name, codePage) != name));
|
||||
}
|
||||
|
||||
if (tryUtf8)
|
||||
{
|
||||
ui.IsUtf8 = !name.IsAscii();
|
||||
ConvertUnicodeToUTF8(name, ui.Name);
|
||||
}
|
||||
|
||||
if (ui.Name.Len() >= (1 << 16))
|
||||
return E_INVALIDARG;
|
||||
|
||||
ui.IndexInClient = i;
|
||||
/*
|
||||
if (existInArchive)
|
||||
{
|
||||
const CItemEx &itemInfo = m_Items[indexInArchive];
|
||||
// ui.Commented = itemInfo.IsCommented();
|
||||
ui.Commented = false;
|
||||
if (ui.Commented)
|
||||
{
|
||||
ui.CommentRange.Position = itemInfo.GetCommentPosition();
|
||||
ui.CommentRange.Size = itemInfo.CommentSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
ui.Commented = false;
|
||||
*/
|
||||
}
|
||||
if (IntToBool(newData))
|
||||
{
|
||||
UInt64 size = 0;
|
||||
if (!ui.IsDir)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidSize, &prop));
|
||||
if (prop.vt != VT_UI8)
|
||||
return E_INVALIDARG;
|
||||
size = prop.uhVal.QuadPart;
|
||||
if (largestSize < size)
|
||||
largestSize = size;
|
||||
largestSizeDefined = true;
|
||||
}
|
||||
ui.Size = size;
|
||||
|
||||
// ui.Size -= ui.Size / 2;
|
||||
}
|
||||
updateItems.Add(ui);
|
||||
}
|
||||
|
||||
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
|
||||
{
|
||||
CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback);
|
||||
udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
|
||||
}
|
||||
CCompressionMethodMode options;
|
||||
(CBaseProps &)options = _props;
|
||||
options._dataSizeReduce = largestSize;
|
||||
options._dataSizeReduceDefined = largestSizeDefined;
|
||||
|
||||
options.PasswordIsDefined = false;
|
||||
options.Password.Empty();
|
||||
if (getTextPassword)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
Int32 passwordIsDefined;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password));
|
||||
options.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||
if (options.PasswordIsDefined)
|
||||
{
|
||||
if (!m_ForceAesMode)
|
||||
options.IsAesMode = thereAreAesUpdates;
|
||||
|
||||
if (!IsSimpleAsciiString(password))
|
||||
return E_INVALIDARG;
|
||||
if (password)
|
||||
options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP);
|
||||
if (options.IsAesMode)
|
||||
{
|
||||
if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Byte mainMethod;
|
||||
if (m_MainMethod < 0)
|
||||
mainMethod = (Byte)(((_props.Level == 0) ?
|
||||
NFileHeader::NCompressionMethod::kStored :
|
||||
NFileHeader::NCompressionMethod::kDeflated));
|
||||
else
|
||||
mainMethod = (Byte)m_MainMethod;
|
||||
options.MethodSequence.Add(mainMethod);
|
||||
if (mainMethod != NFileHeader::NCompressionMethod::kStored)
|
||||
options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
|
||||
|
||||
return Update(
|
||||
EXTERNAL_CODECS_VARS
|
||||
m_Items, updateItems, outStream,
|
||||
m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock,
|
||||
&options, callback);
|
||||
|
||||
COM_TRY_END2
|
||||
}
|
||||
|
||||
struct CMethodIndexToName
|
||||
{
|
||||
unsigned Method;
|
||||
const char *Name;
|
||||
};
|
||||
|
||||
static const CMethodIndexToName k_SupportedMethods[] =
|
||||
{
|
||||
{ NFileHeader::NCompressionMethod::kStored, "copy" },
|
||||
{ NFileHeader::NCompressionMethod::kDeflated, "deflate" },
|
||||
{ NFileHeader::NCompressionMethod::kDeflated64, "deflate64" },
|
||||
{ NFileHeader::NCompressionMethod::kBZip2, "bzip2" },
|
||||
{ NFileHeader::NCompressionMethod::kLZMA, "lzma" },
|
||||
{ NFileHeader::NCompressionMethod::kPPMd, "ppmd" }
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
InitMethodProps();
|
||||
#ifndef _7ZIP_ST
|
||||
const UInt32 numProcessors = _props.NumThreads;
|
||||
#endif
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
UString name = names[i];
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
const PROPVARIANT &prop = values[i];
|
||||
|
||||
if (name[0] == L'x')
|
||||
{
|
||||
UInt32 level = 9;
|
||||
RINOK(ParsePropToUInt32(name.Ptr(1), prop, level));
|
||||
_props.Level = level;
|
||||
_props.MethodInfo.AddProp_Level(level);
|
||||
}
|
||||
else if (name == L"m")
|
||||
{
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
UString m = prop.bstrVal, m2;
|
||||
m.MakeLower_Ascii();
|
||||
int colonPos = m.Find(L':');
|
||||
if (colonPos >= 0)
|
||||
{
|
||||
m2 = m.Ptr(colonPos + 1);
|
||||
m.DeleteFrom(colonPos);
|
||||
}
|
||||
unsigned k;
|
||||
for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
|
||||
{
|
||||
const CMethodIndexToName &pair = k_SupportedMethods[k];
|
||||
if (m.IsEqualTo(pair.Name))
|
||||
{
|
||||
if (!m2.IsEmpty())
|
||||
{
|
||||
RINOK(_props.MethodInfo.ParseParamsFromString(m2));
|
||||
}
|
||||
m_MainMethod = pair.Method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == ARRAY_SIZE(k_SupportedMethods))
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else if (prop.vt == VT_UI4)
|
||||
{
|
||||
unsigned k;
|
||||
for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
|
||||
{
|
||||
unsigned method = k_SupportedMethods[k].Method;
|
||||
if (prop.ulVal == method)
|
||||
{
|
||||
m_MainMethod = method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == ARRAY_SIZE(k_SupportedMethods))
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else if (name.IsPrefixedBy(L"em"))
|
||||
{
|
||||
if (prop.vt != VT_BSTR)
|
||||
return E_INVALIDARG;
|
||||
{
|
||||
UString m = prop.bstrVal;
|
||||
m.MakeLower_Ascii();
|
||||
if (m.IsPrefixedBy(L"aes"))
|
||||
{
|
||||
m.DeleteFrontal(3);
|
||||
if (m == L"128")
|
||||
_props.AesKeyMode = 1;
|
||||
else if (m == L"192")
|
||||
_props.AesKeyMode = 2;
|
||||
else if (m == L"256" || m.IsEmpty())
|
||||
_props.AesKeyMode = 3;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
_props.IsAesMode = true;
|
||||
m_ForceAesMode = true;
|
||||
}
|
||||
else if (m == L"zipcrypto")
|
||||
{
|
||||
_props.IsAesMode = false;
|
||||
m_ForceAesMode = true;
|
||||
}
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
else if (name.IsPrefixedBy(L"mt"))
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
RINOK(ParseMtProp(name.Ptr(2), prop, numProcessors, _props.NumThreads));
|
||||
_props.NumThreadsWasChanged = true;
|
||||
#endif
|
||||
}
|
||||
else if (name.IsEqualTo("tc"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra));
|
||||
}
|
||||
else if (name.IsEqualTo("cl"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal));
|
||||
if (m_ForceLocal)
|
||||
m_ForceUtf8 = false;
|
||||
}
|
||||
else if (name.IsEqualTo("cu"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8));
|
||||
if (m_ForceUtf8)
|
||||
m_ForceLocal = false;
|
||||
}
|
||||
else if (name.IsEqualTo("cp"))
|
||||
{
|
||||
UInt32 cp = CP_OEMCP;
|
||||
RINOK(ParsePropToUInt32(L"", prop, cp));
|
||||
_forceCodePage = true;
|
||||
_specifiedCodePage = cp;
|
||||
}
|
||||
else if (name.IsEqualTo("rsfx"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, _removeSfxBlock));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
176
CPP/7zip/Archive/Zip/ZipHeader.h
Normal file
176
CPP/7zip/Archive/Zip/ZipHeader.h
Normal file
@@ -0,0 +1,176 @@
|
||||
// ZipHeader.h
|
||||
|
||||
#ifndef __ARCHIVE_ZIP_HEADER_H
|
||||
#define __ARCHIVE_ZIP_HEADER_H
|
||||
|
||||
#include "../../../Common/MyTypes.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
const unsigned kMarkerSize = 4;
|
||||
|
||||
namespace NSignature
|
||||
{
|
||||
const UInt32 kLocalFileHeader = 0x04034B50;
|
||||
const UInt32 kDataDescriptor = 0x08074B50;
|
||||
const UInt32 kCentralFileHeader = 0x02014B50;
|
||||
const UInt32 kEcd = 0x06054B50;
|
||||
const UInt32 kEcd64 = 0x06064B50;
|
||||
const UInt32 kEcd64Locator = 0x07064B50;
|
||||
const UInt32 kSpan = 0x08074B50;
|
||||
const UInt32 kNoSpan = 0x30304B50; // PK00, replaces kSpan, if there is only 1 segment
|
||||
}
|
||||
|
||||
const unsigned kLocalHeaderSize = 4 + 26; // including signature
|
||||
const unsigned kDataDescriptorSize = 4 + 12; // including signature
|
||||
const unsigned kCentralHeaderSize = 4 + 42; // including signature
|
||||
|
||||
const unsigned kEcdSize = 22; // including signature
|
||||
const unsigned kEcd64_MainSize = 44;
|
||||
const unsigned kEcd64_FullSize = 12 + kEcd64_MainSize;
|
||||
const unsigned kEcd64Locator_Size = 20;
|
||||
|
||||
namespace NFileHeader
|
||||
{
|
||||
namespace NCompressionMethod
|
||||
{
|
||||
enum EType
|
||||
{
|
||||
kStored = 0,
|
||||
kShrunk = 1,
|
||||
kReduced1 = 2,
|
||||
kReduced2 = 3,
|
||||
kReduced3 = 4,
|
||||
kReduced4 = 5,
|
||||
kImploded = 6,
|
||||
kReservedTokenizing = 7, // reserved for tokenizing
|
||||
kDeflated = 8,
|
||||
kDeflated64 = 9,
|
||||
kPKImploding = 10,
|
||||
|
||||
kBZip2 = 12,
|
||||
kLZMA = 14,
|
||||
kTerse = 18,
|
||||
kLz77 = 19,
|
||||
|
||||
kXz = 0x5F,
|
||||
kJpeg = 0x60,
|
||||
kWavPack = 0x61,
|
||||
kPPMd = 0x62,
|
||||
kWzAES = 0x63
|
||||
};
|
||||
|
||||
const Byte kMadeByProgramVersion = 63;
|
||||
|
||||
const Byte kExtractVersion_Default = 10;
|
||||
const Byte kExtractVersion_Dir = 20;
|
||||
const Byte kExtractVersion_ZipCrypto = 20;
|
||||
const Byte kExtractVersion_Deflate = 20;
|
||||
const Byte kExtractVersion_Deflate64 = 21;
|
||||
const Byte kExtractVersion_Zip64 = 45;
|
||||
const Byte kExtractVersion_BZip2 = 46;
|
||||
const Byte kExtractVersion_Aes = 51;
|
||||
const Byte kExtractVersion_LZMA = 63;
|
||||
const Byte kExtractVersion_PPMd = 63;
|
||||
}
|
||||
|
||||
namespace NExtraID
|
||||
{
|
||||
enum
|
||||
{
|
||||
kZip64 = 0x01,
|
||||
kNTFS = 0x0A,
|
||||
kStrongEncrypt = 0x17,
|
||||
kUnixTime = 0x5455,
|
||||
kIzUnicodeComment = 0x6375,
|
||||
kIzUnicodeName = 0x7075,
|
||||
kWzAES = 0x9901
|
||||
};
|
||||
}
|
||||
|
||||
namespace NNtfsExtra
|
||||
{
|
||||
const UInt16 kTagTime = 1;
|
||||
enum
|
||||
{
|
||||
kMTime = 0,
|
||||
kATime,
|
||||
kCTime
|
||||
};
|
||||
}
|
||||
|
||||
namespace NUnixTime
|
||||
{
|
||||
enum
|
||||
{
|
||||
kMTime = 0,
|
||||
kATime,
|
||||
kCTime
|
||||
};
|
||||
}
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const unsigned kEncrypted = 1 << 0;
|
||||
const unsigned kLzmaEOS = 1 << 1;
|
||||
const unsigned kDescriptorUsedMask = 1 << 3;
|
||||
const unsigned kStrongEncrypted = 1 << 6;
|
||||
const unsigned kUtf8 = 1 << 11;
|
||||
|
||||
const unsigned kImplodeDictionarySizeMask = 1 << 1;
|
||||
const unsigned kImplodeLiteralsOnMask = 1 << 2;
|
||||
|
||||
const unsigned kDeflateTypeBitStart = 1;
|
||||
const unsigned kNumDeflateTypeBits = 2;
|
||||
const unsigned kNumDeflateTypes = (1 << kNumDeflateTypeBits);
|
||||
const unsigned kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;
|
||||
}
|
||||
|
||||
namespace NHostOS
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kFAT = 0,
|
||||
kAMIGA = 1,
|
||||
kVMS = 2, // VAX/VMS
|
||||
kUnix = 3,
|
||||
kVM_CMS = 4,
|
||||
kAtari = 5, // what if it's a minix filesystem? [cjh]
|
||||
kHPFS = 6, // filesystem used by OS/2 (and NT 3.x)
|
||||
kMac = 7,
|
||||
kZ_System = 8,
|
||||
kCPM = 9,
|
||||
kTOPS20 = 10, // pkzip 2.50 NTFS
|
||||
kNTFS = 11, // filesystem used by Windows NT
|
||||
kQDOS = 12, // SMS/QDOS
|
||||
kAcorn = 13, // Archimedes Acorn RISC OS
|
||||
kVFAT = 14, // filesystem used by Windows 95, NT
|
||||
kMVS = 15,
|
||||
kBeOS = 16, // hybrid POSIX/database filesystem
|
||||
kTandem = 17,
|
||||
kOS400 = 18,
|
||||
kOSX = 19
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace NAmigaAttrib
|
||||
{
|
||||
const UInt32 kIFMT = 06000; // Amiga file type mask
|
||||
const UInt32 kIFDIR = 04000; // Amiga directory
|
||||
const UInt32 kIFREG = 02000; // Amiga regular file
|
||||
const UInt32 kIHIDDEN = 00200; // to be supported in AmigaDOS 3.x
|
||||
const UInt32 kISCRIPT = 00100; // executable script (text command file)
|
||||
const UInt32 kIPURE = 00040; // allow loading into resident memory
|
||||
const UInt32 kIARCHIVE = 00020; // not modified since bit was last set
|
||||
const UInt32 kIREAD = 00010; // can be opened for reading
|
||||
const UInt32 kIWRITE = 00004; // can be opened for writing
|
||||
const UInt32 kIEXECUTE = 00002; // executable image, a loadable runfile
|
||||
const UInt32 kIDELETE = 00001; // can be deleted
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
2277
CPP/7zip/Archive/Zip/ZipIn.cpp
Normal file
2277
CPP/7zip/Archive/Zip/ZipIn.cpp
Normal file
File diff suppressed because it is too large
Load Diff
356
CPP/7zip/Archive/Zip/ZipIn.h
Normal file
356
CPP/7zip/Archive/Zip/ZipIn.h
Normal file
@@ -0,0 +1,356 @@
|
||||
// Archive/ZipIn.h
|
||||
|
||||
#ifndef __ZIP_IN_H
|
||||
#define __ZIP_IN_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
#include "ZipHeader.h"
|
||||
#include "ZipItem.h"
|
||||
|
||||
API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size);
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
class CItemEx: public CItem
|
||||
{
|
||||
public:
|
||||
UInt32 LocalFullHeaderSize; // including Name and Extra
|
||||
|
||||
UInt64 GetLocalFullSize() const
|
||||
{ return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); }
|
||||
UInt64 GetDataPosition() const
|
||||
{ return LocalHeaderPos + LocalFullHeaderSize; }
|
||||
};
|
||||
|
||||
|
||||
struct CInArchiveInfo
|
||||
{
|
||||
Int64 Base; /* Base offset of start of archive in stream.
|
||||
Offsets in headers must be calculated from that Base.
|
||||
Base is equal to MarkerPos for normal ZIPs.
|
||||
Base can point to PE stub for some ZIP SFXs.
|
||||
if CentralDir was read,
|
||||
Base can be negative, if start of data is not available,
|
||||
if CentralDirs was not read,
|
||||
Base = ArcInfo.MarkerPos; */
|
||||
|
||||
/* The following *Pos variables contain absolute offsets in Stream */
|
||||
|
||||
UInt64 MarkerPos; /* Pos of first signature, it can point to kSpan/kNoSpan signature
|
||||
= MarkerPos2 in most archives
|
||||
= MarkerPos2 - 4 if there is kSpan/kNoSpan signature */
|
||||
UInt64 MarkerPos2; // Pos of first local item signature in stream
|
||||
UInt64 FinishPos; // Finish pos of archive data in starting volume
|
||||
UInt64 FileEndPos; // Finish pos of stream
|
||||
|
||||
UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base).
|
||||
= 0 in most archives
|
||||
= size of stub for some SFXs */
|
||||
bool CdWasRead;
|
||||
bool IsSpanMode;
|
||||
bool ThereIsTail;
|
||||
|
||||
// UInt32 BaseVolIndex;
|
||||
|
||||
CByteBuffer Comment;
|
||||
|
||||
|
||||
CInArchiveInfo():
|
||||
Base(0),
|
||||
MarkerPos(0),
|
||||
MarkerPos2(0),
|
||||
FinishPos(0),
|
||||
FileEndPos(0),
|
||||
FirstItemRelatOffset(0),
|
||||
CdWasRead(false),
|
||||
IsSpanMode(false),
|
||||
ThereIsTail(false)
|
||||
// BaseVolIndex(0)
|
||||
{}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
// BaseVolIndex = 0;
|
||||
Base = 0;
|
||||
MarkerPos = 0;
|
||||
MarkerPos2 = 0;
|
||||
FinishPos = 0;
|
||||
FileEndPos = 0;
|
||||
ThereIsTail = false;
|
||||
|
||||
FirstItemRelatOffset = 0;
|
||||
|
||||
CdWasRead = false;
|
||||
IsSpanMode = false;
|
||||
|
||||
Comment.Free();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CCdInfo
|
||||
{
|
||||
// 64
|
||||
UInt16 VersionMade;
|
||||
UInt16 VersionNeedExtract;
|
||||
|
||||
// old zip
|
||||
UInt32 ThisDisk;
|
||||
UInt32 CdDisk;
|
||||
UInt64 NumEntries_in_ThisDisk;
|
||||
UInt64 NumEntries;
|
||||
UInt64 Size;
|
||||
UInt64 Offset;
|
||||
|
||||
UInt16 CommentSize;
|
||||
|
||||
CCdInfo() { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
void ParseEcd32(const Byte *p); // (p) includes signature
|
||||
void ParseEcd64e(const Byte *p); // (p) exclude signature
|
||||
};
|
||||
|
||||
|
||||
class CVols
|
||||
{
|
||||
public:
|
||||
|
||||
struct CSubStreamInfo
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Size;
|
||||
|
||||
CSubStreamInfo(): Size(0) {}
|
||||
};
|
||||
|
||||
CObjectVector<CSubStreamInfo> Streams;
|
||||
int StreamIndex;
|
||||
bool NeedSeek;
|
||||
|
||||
CMyComPtr<IInStream> ZipStream;
|
||||
|
||||
bool StartIsExe; // is .exe
|
||||
bool StartIsZ; // is .zip or .zNN
|
||||
bool StartIsZip; // is .zip
|
||||
bool IsUpperCase;
|
||||
Int32 StartVolIndex; // = (NN - 1), if StartStream is .zNN
|
||||
|
||||
Int32 StartParsingVol; // if we need local parsing, we must use that stream
|
||||
unsigned NumVols;
|
||||
|
||||
int EndVolIndex; // index of last volume (ecd volume),
|
||||
// -1, if is not multivol
|
||||
|
||||
UString BaseName; // including '.'
|
||||
|
||||
UString MissingName;
|
||||
|
||||
CCdInfo ecd;
|
||||
bool ecd_wasRead;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
StreamIndex = -1;
|
||||
NeedSeek = false;
|
||||
|
||||
|
||||
StartIsExe = false;
|
||||
StartIsZ = false;
|
||||
StartIsZip = false;
|
||||
IsUpperCase = false;
|
||||
|
||||
StartVolIndex = -1;
|
||||
StartParsingVol = 0;
|
||||
NumVols = 0;
|
||||
EndVolIndex = -1;
|
||||
|
||||
BaseName.Empty();
|
||||
MissingName.Empty();
|
||||
|
||||
ecd_wasRead = false;
|
||||
|
||||
Streams.Clear();
|
||||
ZipStream.Release();
|
||||
}
|
||||
|
||||
HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);
|
||||
|
||||
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
UInt64 GetTotalSize() const
|
||||
{
|
||||
UInt64 total = 0;
|
||||
FOR_VECTOR (i, Streams)
|
||||
total += Streams[i].Size;
|
||||
return total;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CVolStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
CVols *Vols;
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CInBuffer _inBuffer;
|
||||
bool _inBufMode;
|
||||
UInt32 m_Signature;
|
||||
UInt64 m_Position;
|
||||
|
||||
UInt64 _processedCnt;
|
||||
|
||||
bool CanStartNewVol;
|
||||
|
||||
CMyComPtr<IInStream> StreamRef;
|
||||
IInStream *Stream;
|
||||
IInStream *StartStream;
|
||||
|
||||
bool IsArcOpen;
|
||||
|
||||
HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,
|
||||
unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);
|
||||
HRESULT ReadVols();
|
||||
|
||||
HRESULT Seek(UInt64 offset);
|
||||
HRESULT FindMarker(IInStream *stream, const UInt64 *searchLimit);
|
||||
HRESULT IncreaseRealPosition(Int64 addValue, bool &isFinished);
|
||||
|
||||
HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
|
||||
void SafeReadBytes(void *data, unsigned size);
|
||||
void ReadBuffer(CByteBuffer &buffer, unsigned size);
|
||||
Byte ReadByte();
|
||||
UInt16 ReadUInt16();
|
||||
UInt32 ReadUInt32();
|
||||
UInt64 ReadUInt64();
|
||||
void Skip(unsigned num);
|
||||
void Skip64(UInt64 num);
|
||||
void ReadFileName(unsigned nameSize, AString &dest);
|
||||
|
||||
bool ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
|
||||
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber);
|
||||
bool ReadLocalItem(CItemEx &item);
|
||||
HRESULT ReadLocalItemDescriptor(CItemEx &item);
|
||||
HRESULT ReadCdItem(CItemEx &item);
|
||||
HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);
|
||||
HRESULT FindCd(bool checkOffsetMode);
|
||||
HRESULT TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize);
|
||||
HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize);
|
||||
HRESULT ReadLocals(CObjectVector<CItemEx> &localItems);
|
||||
|
||||
HRESULT ReadHeaders2(CObjectVector<CItemEx> &items);
|
||||
|
||||
HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream);
|
||||
public:
|
||||
CInArchiveInfo ArcInfo;
|
||||
|
||||
bool IsArc;
|
||||
bool IsZip64;
|
||||
bool HeadersError;
|
||||
bool HeadersWarning;
|
||||
bool ExtraMinorError;
|
||||
bool UnexpectedEnd;
|
||||
bool NoCentralDir;
|
||||
|
||||
bool MarkerIsFound;
|
||||
|
||||
bool IsMultiVol;
|
||||
bool UseDisk_in_SingleVol;
|
||||
UInt32 EcdVolIndex;
|
||||
|
||||
CVols Vols;
|
||||
|
||||
IArchiveOpenCallback *Callback;
|
||||
|
||||
CInArchive(): Stream(NULL), Callback(NULL), IsArcOpen(false) {}
|
||||
|
||||
UInt64 GetPhySize() const
|
||||
{
|
||||
if (IsMultiVol)
|
||||
return ArcInfo.FinishPos;
|
||||
else
|
||||
return ArcInfo.FinishPos - ArcInfo.Base;
|
||||
}
|
||||
|
||||
UInt64 GetOffset() const
|
||||
{
|
||||
if (IsMultiVol)
|
||||
return 0;
|
||||
else
|
||||
return ArcInfo.Base;
|
||||
}
|
||||
|
||||
|
||||
void ClearRefs();
|
||||
void Close();
|
||||
HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items);
|
||||
HRESULT ReadHeaders(CObjectVector<CItemEx> &items);
|
||||
|
||||
bool IsOpen() const { return IsArcOpen; }
|
||||
|
||||
bool AreThereErrors() const
|
||||
{
|
||||
return HeadersError
|
||||
|| UnexpectedEnd
|
||||
|| !Vols.MissingName.IsEmpty();
|
||||
}
|
||||
|
||||
bool IsLocalOffsetOK(const CItemEx &item) const
|
||||
{
|
||||
if (item.FromLocal)
|
||||
return true;
|
||||
return (Int64)GetOffset() + (Int64)item.LocalHeaderPos >= 0;
|
||||
}
|
||||
|
||||
UInt64 GetEmbeddedStubSize() const
|
||||
{
|
||||
if (ArcInfo.CdWasRead)
|
||||
return ArcInfo.FirstItemRelatOffset;
|
||||
if (IsMultiVol)
|
||||
return 0;
|
||||
return ArcInfo.MarkerPos2 - ArcInfo.Base;
|
||||
}
|
||||
|
||||
|
||||
HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail);
|
||||
HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);
|
||||
|
||||
HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream);
|
||||
|
||||
IInStream *GetBaseStream() { return StreamRef; }
|
||||
|
||||
bool CanUpdate() const
|
||||
{
|
||||
if (AreThereErrors()
|
||||
|| IsMultiVol
|
||||
|| ArcInfo.Base < 0
|
||||
|| (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base
|
||||
|| ArcInfo.ThereIsTail
|
||||
|| GetEmbeddedStubSize() != 0)
|
||||
return false;
|
||||
|
||||
// 7-zip probably can update archives with embedded stubs.
|
||||
// we just disable that feature for more safety.
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
253
CPP/7zip/Archive/Zip/ZipItem.cpp
Normal file
253
CPP/7zip/Archive/Zip/ZipItem.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
// Archive/ZipItem.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/MyLinux.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
|
||||
#include "ZipItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
using namespace NFileHeader;
|
||||
|
||||
bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const
|
||||
{
|
||||
ft.dwHighDateTime = ft.dwLowDateTime = 0;
|
||||
UInt32 size = (UInt32)Data.Size();
|
||||
if (ID != NExtraID::kNTFS || size < 32)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)Data;
|
||||
p += 4; // for reserved
|
||||
size -= 4;
|
||||
while (size > 4)
|
||||
{
|
||||
UInt16 tag = GetUi16(p);
|
||||
unsigned attrSize = GetUi16(p + 2);
|
||||
p += 4;
|
||||
size -= 4;
|
||||
if (attrSize > size)
|
||||
attrSize = size;
|
||||
|
||||
if (tag == NNtfsExtra::kTagTime && attrSize >= 24)
|
||||
{
|
||||
p += 8 * index;
|
||||
ft.dwLowDateTime = GetUi32(p);
|
||||
ft.dwHighDateTime = GetUi32(p + 4);
|
||||
return true;
|
||||
}
|
||||
p += attrSize;
|
||||
size -= attrSize;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const
|
||||
{
|
||||
res = 0;
|
||||
UInt32 size = (UInt32)Data.Size();
|
||||
if (ID != NExtraID::kUnixTime || size < 5)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)Data;
|
||||
Byte flags = *p++;
|
||||
size--;
|
||||
if (isCentral)
|
||||
{
|
||||
if (index != NUnixTime::kMTime ||
|
||||
(flags & (1 << NUnixTime::kMTime)) == 0 ||
|
||||
size < 4)
|
||||
return false;
|
||||
res = GetUi32(p);
|
||||
return true;
|
||||
}
|
||||
for (unsigned i = 0; i < 3; i++)
|
||||
if ((flags & (1 << i)) != 0)
|
||||
{
|
||||
if (size < 4)
|
||||
return false;
|
||||
if (index == i)
|
||||
{
|
||||
res = GetUi32(p);
|
||||
return true;
|
||||
}
|
||||
p += 4;
|
||||
size -= 4;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const
|
||||
{
|
||||
FOR_VECTOR (i, SubBlocks)
|
||||
{
|
||||
const CExtraSubBlock &sb = SubBlocks[i];
|
||||
if (sb.ID == NFileHeader::NExtraID::kNTFS)
|
||||
return sb.ExtractNtfsTime(index, ft);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const
|
||||
{
|
||||
FOR_VECTOR (i, SubBlocks)
|
||||
{
|
||||
const CExtraSubBlock &sb = SubBlocks[i];
|
||||
if (sb.ID == NFileHeader::NExtraID::kUnixTime)
|
||||
return sb.ExtractUnixTime(isCentral, index, res);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CLocalItem::IsDir() const
|
||||
{
|
||||
return NItemName::HasTailSlash(Name, GetCodePage());
|
||||
}
|
||||
|
||||
bool CItem::IsDir() const
|
||||
{
|
||||
if (NItemName::HasTailSlash(Name, GetCodePage()))
|
||||
return true;
|
||||
|
||||
Byte hostOS = GetHostOS();
|
||||
|
||||
if (Size == 0 && PackSize == 0 && !Name.IsEmpty() && Name.Back() == '\\')
|
||||
{
|
||||
// do we need to use CharPrevExA?
|
||||
// .NET Framework 4.5 : System.IO.Compression::CreateFromDirectory() probably writes backslashes to headers?
|
||||
// so we support that case
|
||||
switch (hostOS)
|
||||
{
|
||||
case NHostOS::kFAT:
|
||||
case NHostOS::kNTFS:
|
||||
case NHostOS::kHPFS:
|
||||
case NHostOS::kVFAT:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FromCentral)
|
||||
return false;
|
||||
|
||||
UInt16 highAttrib = (UInt16)((ExternalAttrib >> 16 ) & 0xFFFF);
|
||||
|
||||
switch (hostOS)
|
||||
{
|
||||
case NHostOS::kAMIGA:
|
||||
switch (highAttrib & NAmigaAttrib::kIFMT)
|
||||
{
|
||||
case NAmigaAttrib::kIFDIR: return true;
|
||||
case NAmigaAttrib::kIFREG: return false;
|
||||
default: return false; // change it throw kUnknownAttributes;
|
||||
}
|
||||
case NHostOS::kFAT:
|
||||
case NHostOS::kNTFS:
|
||||
case NHostOS::kHPFS:
|
||||
case NHostOS::kVFAT:
|
||||
return ((ExternalAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
||||
case NHostOS::kAtari:
|
||||
case NHostOS::kMac:
|
||||
case NHostOS::kVMS:
|
||||
case NHostOS::kVM_CMS:
|
||||
case NHostOS::kAcorn:
|
||||
case NHostOS::kMVS:
|
||||
return false; // change it throw kUnknownAttributes;
|
||||
case NHostOS::kUnix:
|
||||
return MY_LIN_S_ISDIR(highAttrib);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 CItem::GetWinAttrib() const
|
||||
{
|
||||
UInt32 winAttrib = 0;
|
||||
switch (GetHostOS())
|
||||
{
|
||||
case NHostOS::kFAT:
|
||||
case NHostOS::kNTFS:
|
||||
if (FromCentral)
|
||||
winAttrib = ExternalAttrib;
|
||||
break;
|
||||
case NHostOS::kUnix:
|
||||
// do we need to clear 16 low bits in this case?
|
||||
if (FromCentral)
|
||||
winAttrib = ExternalAttrib & 0xFFFF0000;
|
||||
break;
|
||||
}
|
||||
if (IsDir()) // test it;
|
||||
winAttrib |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
return winAttrib;
|
||||
}
|
||||
|
||||
bool CItem::GetPosixAttrib(UInt32 &attrib) const
|
||||
{
|
||||
// some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT.
|
||||
if (FromCentral && GetHostOS() == NHostOS::kUnix)
|
||||
{
|
||||
attrib = ExternalAttrib >> 16;
|
||||
return (attrib != 0);
|
||||
}
|
||||
attrib = 0;
|
||||
if (IsDir())
|
||||
attrib = MY_LIN_S_IFDIR;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const
|
||||
{
|
||||
bool isUtf8 = IsUtf8();
|
||||
bool ignore_Utf8_Errors = true;
|
||||
|
||||
if (!isUtf8)
|
||||
{
|
||||
{
|
||||
const unsigned id = isComment ?
|
||||
NFileHeader::NExtraID::kIzUnicodeComment:
|
||||
NFileHeader::NExtraID::kIzUnicodeName;
|
||||
const CObjectVector<CExtraSubBlock> &subBlocks = GetMainExtra().SubBlocks;
|
||||
|
||||
FOR_VECTOR (i, subBlocks)
|
||||
{
|
||||
const CExtraSubBlock &sb = subBlocks[i];
|
||||
if (sb.ID == id)
|
||||
{
|
||||
AString utf;
|
||||
if (sb.ExtractIzUnicode(CrcCalc(s, s.Len()), utf))
|
||||
if (ConvertUTF8ToUnicode(utf, res))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useSpecifiedCodePage)
|
||||
isUtf8 = (codePage == CP_UTF8);
|
||||
#ifdef _WIN32
|
||||
else if (GetHostOS() == NFileHeader::NHostOS::kUnix)
|
||||
{
|
||||
/* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header.
|
||||
We try to get name as UTF-8.
|
||||
Do we need to do it in POSIX version also? */
|
||||
isUtf8 = true;
|
||||
ignore_Utf8_Errors = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (isUtf8)
|
||||
if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors)
|
||||
return;
|
||||
|
||||
MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage());
|
||||
}
|
||||
|
||||
}}
|
||||
310
CPP/7zip/Archive/Zip/ZipItem.h
Normal file
310
CPP/7zip/Archive/Zip/ZipItem.h
Normal file
@@ -0,0 +1,310 @@
|
||||
// Archive/ZipItem.h
|
||||
|
||||
#ifndef __ARCHIVE_ZIP_ITEM_H
|
||||
#define __ARCHIVE_ZIP_ITEM_H
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
|
||||
#include "ZipHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
struct CVersion
|
||||
{
|
||||
Byte Version;
|
||||
Byte HostOS;
|
||||
};
|
||||
|
||||
struct CExtraSubBlock
|
||||
{
|
||||
UInt16 ID;
|
||||
CByteBuffer Data;
|
||||
|
||||
bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;
|
||||
bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
|
||||
|
||||
bool ExtractIzUnicode(UInt32 crc, AString &name) const
|
||||
{
|
||||
unsigned size = (unsigned)Data.Size();
|
||||
if (size < 1 + 4)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)Data;
|
||||
if (p[0] > 1)
|
||||
return false;
|
||||
if (crc != GetUi32(p + 1))
|
||||
return false;
|
||||
size -= 5;
|
||||
name.SetFrom_CalcLen((const char *)p + 5, size);
|
||||
if (size != name.Len())
|
||||
return false;
|
||||
return CheckUTF8(name, false);
|
||||
}
|
||||
};
|
||||
|
||||
const unsigned k_WzAesExtra_Size = 7;
|
||||
|
||||
struct CWzAesExtra
|
||||
{
|
||||
UInt16 VendorVersion; // 1: AE-1, 2: AE-2,
|
||||
// UInt16 VendorId; // 'A' 'E'
|
||||
Byte Strength; // 1: 128-bit, 2: 192-bit, 3: 256-bit
|
||||
UInt16 Method;
|
||||
|
||||
CWzAesExtra(): VendorVersion(2), Strength(3), Method(0) {}
|
||||
|
||||
bool NeedCrc() const { return (VendorVersion == 1); }
|
||||
|
||||
bool ParseFromSubBlock(const CExtraSubBlock &sb)
|
||||
{
|
||||
if (sb.ID != NFileHeader::NExtraID::kWzAES)
|
||||
return false;
|
||||
if (sb.Data.Size() < k_WzAesExtra_Size)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)sb.Data;
|
||||
VendorVersion = GetUi16(p);
|
||||
if (p[2] != 'A' || p[3] != 'E')
|
||||
return false;
|
||||
Strength = p[4];
|
||||
// 9.31: The BUG was fixed:
|
||||
Method = GetUi16(p + 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetSubBlock(CExtraSubBlock &sb) const
|
||||
{
|
||||
sb.Data.Alloc(k_WzAesExtra_Size);
|
||||
sb.ID = NFileHeader::NExtraID::kWzAES;
|
||||
Byte *p = (Byte *)sb.Data;
|
||||
p[0] = (Byte)VendorVersion;
|
||||
p[1] = (Byte)(VendorVersion >> 8);
|
||||
p[2] = 'A';
|
||||
p[3] = 'E';
|
||||
p[4] = Strength;
|
||||
p[5] = (Byte)Method;
|
||||
p[6] = (Byte)(Method >> 8);
|
||||
}
|
||||
};
|
||||
|
||||
namespace NStrongCrypto_AlgId
|
||||
{
|
||||
const UInt16 kDES = 0x6601;
|
||||
const UInt16 kRC2old = 0x6602;
|
||||
const UInt16 k3DES168 = 0x6603;
|
||||
const UInt16 k3DES112 = 0x6609;
|
||||
const UInt16 kAES128 = 0x660E;
|
||||
const UInt16 kAES192 = 0x660F;
|
||||
const UInt16 kAES256 = 0x6610;
|
||||
const UInt16 kRC2 = 0x6702;
|
||||
const UInt16 kBlowfish = 0x6720;
|
||||
const UInt16 kTwofish = 0x6721;
|
||||
const UInt16 kRC4 = 0x6801;
|
||||
}
|
||||
|
||||
struct CStrongCryptoExtra
|
||||
{
|
||||
UInt16 Format;
|
||||
UInt16 AlgId;
|
||||
UInt16 BitLen;
|
||||
UInt16 Flags;
|
||||
|
||||
bool ParseFromSubBlock(const CExtraSubBlock &sb)
|
||||
{
|
||||
if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt)
|
||||
return false;
|
||||
const Byte *p = (const Byte *)sb.Data;
|
||||
if (sb.Data.Size() < 8)
|
||||
return false;
|
||||
Format = GetUi16(p + 0);
|
||||
AlgId = GetUi16(p + 2);
|
||||
BitLen = GetUi16(p + 4);
|
||||
Flags = GetUi16(p + 6);
|
||||
return (Format == 2);
|
||||
}
|
||||
|
||||
bool CertificateIsUsed() const { return (Flags > 0x0001); }
|
||||
};
|
||||
|
||||
struct CExtraBlock
|
||||
{
|
||||
CObjectVector<CExtraSubBlock> SubBlocks;
|
||||
|
||||
void Clear() { SubBlocks.Clear(); }
|
||||
|
||||
size_t GetSize() const
|
||||
{
|
||||
size_t res = 0;
|
||||
FOR_VECTOR (i, SubBlocks)
|
||||
res += SubBlocks[i].Data.Size() + 2 + 2;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool GetWzAes(CWzAesExtra &e) const
|
||||
{
|
||||
FOR_VECTOR (i, SubBlocks)
|
||||
if (e.ParseFromSubBlock(SubBlocks[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasWzAes() const
|
||||
{
|
||||
CWzAesExtra e;
|
||||
return GetWzAes(e);
|
||||
}
|
||||
|
||||
bool GetStrongCrypto(CStrongCryptoExtra &e) const
|
||||
{
|
||||
FOR_VECTOR (i, SubBlocks)
|
||||
if (e.ParseFromSubBlock(SubBlocks[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
bool HasStrongCrypto() const
|
||||
{
|
||||
CStrongCryptoExtra e;
|
||||
return GetStrongCrypto(e);
|
||||
}
|
||||
*/
|
||||
|
||||
bool GetNtfsTime(unsigned index, FILETIME &ft) const;
|
||||
bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
|
||||
|
||||
void RemoveUnknownSubBlocks()
|
||||
{
|
||||
for (unsigned i = SubBlocks.Size(); i != 0;)
|
||||
{
|
||||
i--;
|
||||
if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES)
|
||||
SubBlocks.Delete(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CLocalItem
|
||||
{
|
||||
public:
|
||||
UInt16 Flags;
|
||||
UInt16 Method;
|
||||
CVersion ExtractVersion;
|
||||
|
||||
UInt64 Size;
|
||||
UInt64 PackSize;
|
||||
UInt32 Time;
|
||||
UInt32 Crc;
|
||||
|
||||
UInt32 Disk;
|
||||
|
||||
AString Name;
|
||||
|
||||
CExtraBlock LocalExtra;
|
||||
|
||||
bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
|
||||
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
|
||||
bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }
|
||||
bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
|
||||
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
|
||||
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
|
||||
|
||||
bool IsDir() const;
|
||||
|
||||
/*
|
||||
void GetUnicodeString(const AString &s, UString &res) const
|
||||
{
|
||||
bool isUtf8 = IsUtf8();
|
||||
if (isUtf8)
|
||||
if (ConvertUTF8ToUnicode(s, res))
|
||||
return;
|
||||
MultiByteToUnicodeString2(res, s, GetCodePage());
|
||||
}
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
void SetFlag(unsigned bitMask, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
Flags |= bitMask;
|
||||
else
|
||||
Flags &= ~bitMask;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void ClearFlags() { Flags = 0; }
|
||||
void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
|
||||
void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
|
||||
void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }
|
||||
|
||||
UINT GetCodePage() const { return CP_OEMCP; }
|
||||
};
|
||||
|
||||
|
||||
class CItem: public CLocalItem
|
||||
{
|
||||
public:
|
||||
CVersion MadeByVersion;
|
||||
UInt16 InternalAttrib;
|
||||
UInt32 ExternalAttrib;
|
||||
|
||||
UInt64 LocalHeaderPos;
|
||||
|
||||
CExtraBlock CentralExtra;
|
||||
CByteBuffer Comment;
|
||||
|
||||
bool FromLocal;
|
||||
bool FromCentral;
|
||||
|
||||
// CItem can be used as CLocalItem. So we must clear unused fields
|
||||
CItem():
|
||||
InternalAttrib(0),
|
||||
ExternalAttrib(0),
|
||||
FromLocal(false),
|
||||
FromCentral(false)
|
||||
{
|
||||
MadeByVersion.Version = 0;
|
||||
MadeByVersion.HostOS = 0;
|
||||
}
|
||||
|
||||
const CExtraBlock &GetMainExtra() const { return *(FromCentral ? &CentralExtra : &LocalExtra); }
|
||||
|
||||
bool IsDir() const;
|
||||
UInt32 GetWinAttrib() const;
|
||||
bool GetPosixAttrib(UInt32 &attrib) const;
|
||||
|
||||
Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : ExtractVersion.HostOS; }
|
||||
|
||||
void GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const;
|
||||
|
||||
bool IsThereCrc() const
|
||||
{
|
||||
if (Method == NFileHeader::NCompressionMethod::kWzAES)
|
||||
{
|
||||
CWzAesExtra aesField;
|
||||
if (GetMainExtra().GetWzAes(aesField))
|
||||
return aesField.NeedCrc();
|
||||
}
|
||||
return (Crc != 0 || !IsDir());
|
||||
}
|
||||
|
||||
UINT GetCodePage() const
|
||||
{
|
||||
Byte hostOS = GetHostOS();
|
||||
return (UINT)((
|
||||
hostOS == NFileHeader::NHostOS::kFAT
|
||||
|| hostOS == NFileHeader::NHostOS::kNTFS
|
||||
|| hostOS == NFileHeader::NHostOS::kUnix // do we need it?
|
||||
) ? CP_OEMCP : CP_ACP);
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
312
CPP/7zip/Archive/Zip/ZipOut.cpp
Normal file
312
CPP/7zip/Archive/Zip/ZipOut.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
// ZipOut.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/OffsetStream.h"
|
||||
|
||||
#include "ZipOut.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
HRESULT COutArchive::Create(IOutStream *outStream)
|
||||
{
|
||||
m_CurPos = 0;
|
||||
if (!m_OutBuffer.Create(1 << 16))
|
||||
return E_OUTOFMEMORY;
|
||||
m_Stream = outStream;
|
||||
m_OutBuffer.SetStream(outStream);
|
||||
m_OutBuffer.Init();
|
||||
|
||||
return m_Stream->Seek(0, STREAM_SEEK_CUR, &m_Base);
|
||||
}
|
||||
|
||||
void COutArchive::MoveCurPos(UInt64 distanceToMove)
|
||||
{
|
||||
m_CurPos += distanceToMove; // test overflow
|
||||
}
|
||||
|
||||
void COutArchive::SeekToRelatPos(UInt64 offset)
|
||||
{
|
||||
HRESULT res = m_Stream->Seek(m_Base + offset, STREAM_SEEK_SET, NULL);
|
||||
if (res != S_OK)
|
||||
throw CSystemException(res);
|
||||
}
|
||||
|
||||
void COutArchive::PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption)
|
||||
{
|
||||
m_IsZip64 = isZip64;
|
||||
m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0;
|
||||
if (aesEncryption)
|
||||
m_ExtraSize += 4 + k_WzAesExtra_Size;
|
||||
m_LocalFileHeaderSize = kLocalHeaderSize + fileNameLen + m_ExtraSize;
|
||||
}
|
||||
|
||||
void COutArchive::PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption)
|
||||
{
|
||||
// We use Zip64, if unPackSize size is larger than 0xF8000000 to support
|
||||
// cases when compressed size can be about 3% larger than uncompressed size
|
||||
|
||||
PrepareWriteCompressedDataZip64(fileNameLen, unPackSize >= (UInt32)0xF8000000, aesEncryption);
|
||||
}
|
||||
|
||||
#define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF)
|
||||
|
||||
void COutArchive::PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption)
|
||||
{
|
||||
bool isZip64 =
|
||||
DOES_NEED_ZIP64(unPackSize) ||
|
||||
DOES_NEED_ZIP64(packSize);
|
||||
PrepareWriteCompressedDataZip64(fileNameLen, isZip64, aesEncryption);
|
||||
}
|
||||
|
||||
void COutArchive::WriteBytes(const void *buffer, UInt32 size)
|
||||
{
|
||||
m_OutBuffer.WriteBytes(buffer, size);
|
||||
m_CurPos += size;
|
||||
}
|
||||
|
||||
void COutArchive::Write8(Byte b)
|
||||
{
|
||||
m_OutBuffer.WriteByte(b);
|
||||
m_CurPos++;
|
||||
}
|
||||
|
||||
void COutArchive::Write16(UInt16 val)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Write8((Byte)val);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void COutArchive::Write32(UInt32 val)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Write8((Byte)val);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void COutArchive::Write64(UInt64 val)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
Write8((Byte)val);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void COutArchive::WriteExtra(const CExtraBlock &extra)
|
||||
{
|
||||
if (extra.SubBlocks.Size() != 0)
|
||||
{
|
||||
FOR_VECTOR (i, extra.SubBlocks)
|
||||
{
|
||||
const CExtraSubBlock &subBlock = extra.SubBlocks[i];
|
||||
Write16(subBlock.ID);
|
||||
Write16((UInt16)subBlock.Data.Size());
|
||||
WriteBytes(subBlock.Data, (UInt32)subBlock.Data.Size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64)
|
||||
{
|
||||
{
|
||||
Byte ver = item.ExtractVersion.Version;
|
||||
if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)
|
||||
ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;
|
||||
Write8(ver);
|
||||
}
|
||||
Write8(item.ExtractVersion.HostOS);
|
||||
Write16(item.Flags);
|
||||
Write16(item.Method);
|
||||
Write32(item.Time);
|
||||
Write32(item.Crc);
|
||||
}
|
||||
|
||||
#define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v));
|
||||
|
||||
void COutArchive::WriteLocalHeader(const CLocalItem &item)
|
||||
{
|
||||
SeekToCurPos();
|
||||
|
||||
bool isZip64 = m_IsZip64 ||
|
||||
DOES_NEED_ZIP64(item.PackSize) ||
|
||||
DOES_NEED_ZIP64(item.Size);
|
||||
|
||||
Write32(NSignature::kLocalFileHeader);
|
||||
WriteCommonItemInfo(item, isZip64);
|
||||
|
||||
WRITE_32_VAL_SPEC(item.PackSize, isZip64);
|
||||
WRITE_32_VAL_SPEC(item.Size, isZip64);
|
||||
|
||||
Write16((UInt16)item.Name.Len());
|
||||
{
|
||||
UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize());
|
||||
if (localExtraSize != m_ExtraSize)
|
||||
throw CSystemException(E_FAIL);
|
||||
}
|
||||
Write16((UInt16)m_ExtraSize);
|
||||
WriteBytes((const char *)item.Name, item.Name.Len());
|
||||
|
||||
if (isZip64)
|
||||
{
|
||||
Write16(NFileHeader::NExtraID::kZip64);
|
||||
Write16(8 + 8);
|
||||
Write64(item.Size);
|
||||
Write64(item.PackSize);
|
||||
}
|
||||
|
||||
WriteExtra(item.LocalExtra);
|
||||
|
||||
// Why don't we write NTFS timestamps to local header?
|
||||
// Probably we want to reduce size of archive?
|
||||
|
||||
m_OutBuffer.FlushWithCheck();
|
||||
MoveCurPos(item.PackSize);
|
||||
}
|
||||
|
||||
void COutArchive::WriteCentralHeader(const CItemOut &item)
|
||||
{
|
||||
bool isUnPack64 = DOES_NEED_ZIP64(item.Size);
|
||||
bool isPack64 = DOES_NEED_ZIP64(item.PackSize);
|
||||
bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos);
|
||||
bool isZip64 = isPack64 || isUnPack64 || isPosition64;
|
||||
|
||||
Write32(NSignature::kCentralFileHeader);
|
||||
Write8(item.MadeByVersion.Version);
|
||||
Write8(item.MadeByVersion.HostOS);
|
||||
|
||||
WriteCommonItemInfo(item, isZip64);
|
||||
|
||||
WRITE_32_VAL_SPEC(item.PackSize, isPack64);
|
||||
WRITE_32_VAL_SPEC(item.Size, isUnPack64);
|
||||
|
||||
Write16((UInt16)item.Name.Len());
|
||||
|
||||
UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
|
||||
const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8);
|
||||
const UInt16 centralExtraSize = (UInt16)(
|
||||
(isZip64 ? 4 + zip64ExtraSize : 0) +
|
||||
(item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) +
|
||||
item.CentralExtra.GetSize());
|
||||
|
||||
Write16(centralExtraSize); // test it;
|
||||
Write16((UInt16)item.Comment.Size());
|
||||
Write16(0); // DiskNumberStart;
|
||||
Write16(item.InternalAttrib);
|
||||
Write32(item.ExternalAttrib);
|
||||
WRITE_32_VAL_SPEC(item.LocalHeaderPos, isPosition64);
|
||||
WriteBytes((const char *)item.Name, item.Name.Len());
|
||||
|
||||
if (isZip64)
|
||||
{
|
||||
Write16(NFileHeader::NExtraID::kZip64);
|
||||
Write16(zip64ExtraSize);
|
||||
if (isUnPack64)
|
||||
Write64(item.Size);
|
||||
if (isPack64)
|
||||
Write64(item.PackSize);
|
||||
if (isPosition64)
|
||||
Write64(item.LocalHeaderPos);
|
||||
}
|
||||
|
||||
if (item.NtfsTimeIsDefined)
|
||||
{
|
||||
Write16(NFileHeader::NExtraID::kNTFS);
|
||||
Write16(kNtfsExtraSize);
|
||||
Write32(0); // reserved
|
||||
Write16(NFileHeader::NNtfsExtra::kTagTime);
|
||||
Write16(8 * 3);
|
||||
WriteNtfsTime(item.Ntfs_MTime);
|
||||
WriteNtfsTime(item.Ntfs_ATime);
|
||||
WriteNtfsTime(item.Ntfs_CTime);
|
||||
}
|
||||
|
||||
WriteExtra(item.CentralExtra);
|
||||
if (item.Comment.Size() > 0)
|
||||
WriteBytes(item.Comment, (UInt32)item.Comment.Size());
|
||||
}
|
||||
|
||||
void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)
|
||||
{
|
||||
SeekToCurPos();
|
||||
|
||||
UInt64 cdOffset = GetCurPos();
|
||||
FOR_VECTOR (i, items)
|
||||
WriteCentralHeader(items[i]);
|
||||
UInt64 cd64EndOffset = GetCurPos();
|
||||
UInt64 cdSize = cd64EndOffset - cdOffset;
|
||||
bool cdOffset64 = DOES_NEED_ZIP64(cdOffset);
|
||||
bool cdSize64 = DOES_NEED_ZIP64(cdSize);
|
||||
bool items64 = items.Size() >= 0xFFFF;
|
||||
bool isZip64 = (cdOffset64 || cdSize64 || items64);
|
||||
|
||||
// isZip64 = true; // to test Zip64
|
||||
|
||||
if (isZip64)
|
||||
{
|
||||
Write32(NSignature::kEcd64);
|
||||
Write64(kEcd64_MainSize);
|
||||
Write16(45); // made by version
|
||||
Write16(45); // extract version
|
||||
Write32(0); // ThisDiskNumber = 0;
|
||||
Write32(0); // StartCentralDirectoryDiskNumber;;
|
||||
Write64((UInt64)items.Size());
|
||||
Write64((UInt64)items.Size());
|
||||
Write64((UInt64)cdSize);
|
||||
Write64((UInt64)cdOffset);
|
||||
|
||||
Write32(NSignature::kEcd64Locator);
|
||||
Write32(0); // number of the disk with the start of the zip64 end of central directory
|
||||
Write64(cd64EndOffset);
|
||||
Write32(1); // total number of disks
|
||||
}
|
||||
|
||||
Write32(NSignature::kEcd);
|
||||
Write16(0); // ThisDiskNumber = 0;
|
||||
Write16(0); // StartCentralDirectoryDiskNumber;
|
||||
Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
|
||||
Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
|
||||
|
||||
WRITE_32_VAL_SPEC(cdSize, cdSize64);
|
||||
WRITE_32_VAL_SPEC(cdOffset, cdOffset64);
|
||||
|
||||
UInt32 commentSize = (UInt32)(comment ? comment->Size() : 0);
|
||||
Write16((UInt16)commentSize);
|
||||
if (commentSize > 0)
|
||||
WriteBytes((const Byte *)*comment, commentSize);
|
||||
m_OutBuffer.FlushWithCheck();
|
||||
}
|
||||
|
||||
void COutArchive::CreateStreamForCompressing(IOutStream **outStream)
|
||||
{
|
||||
COffsetOutStream *streamSpec = new COffsetOutStream;
|
||||
CMyComPtr<IOutStream> tempStream(streamSpec);
|
||||
streamSpec->Init(m_Stream, m_Base + m_CurPos + m_LocalFileHeaderSize);
|
||||
*outStream = tempStream.Detach();
|
||||
}
|
||||
|
||||
/*
|
||||
void COutArchive::SeekToPackedDataPosition()
|
||||
{
|
||||
SeekTo(m_BasePosition + m_LocalFileHeaderSize);
|
||||
}
|
||||
*/
|
||||
|
||||
void COutArchive::SeekToCurPos()
|
||||
{
|
||||
SeekToRelatPos(m_CurPos);
|
||||
}
|
||||
|
||||
void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> tempStream(m_Stream);
|
||||
*outStream = tempStream.Detach();
|
||||
}
|
||||
|
||||
}}
|
||||
88
CPP/7zip/Archive/Zip/ZipOut.h
Normal file
88
CPP/7zip/Archive/Zip/ZipOut.h
Normal file
@@ -0,0 +1,88 @@
|
||||
// ZipOut.h
|
||||
|
||||
#ifndef __ZIP_OUT_H
|
||||
#define __ZIP_OUT_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../../Common/OutBuffer.h"
|
||||
|
||||
#include "ZipItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
// can throw CSystemException and COutBufferException
|
||||
|
||||
class CItemOut: public CItem
|
||||
{
|
||||
public:
|
||||
FILETIME Ntfs_MTime;
|
||||
FILETIME Ntfs_ATime;
|
||||
FILETIME Ntfs_CTime;
|
||||
bool NtfsTimeIsDefined;
|
||||
|
||||
// It's possible that NtfsTime is not defined, but there is NtfsTime in Extra.
|
||||
|
||||
CItemOut(): NtfsTimeIsDefined(false) {}
|
||||
};
|
||||
|
||||
class COutArchive
|
||||
{
|
||||
CMyComPtr<IOutStream> m_Stream;
|
||||
COutBuffer m_OutBuffer;
|
||||
|
||||
UInt64 m_Base; // Base of arc (offset in output Stream)
|
||||
UInt64 m_CurPos; // Curent position in archive (relative from m_Base)
|
||||
|
||||
UInt32 m_LocalFileHeaderSize;
|
||||
UInt32 m_ExtraSize;
|
||||
bool m_IsZip64;
|
||||
|
||||
void SeekToRelatPos(UInt64 offset);
|
||||
|
||||
void WriteBytes(const void *buffer, UInt32 size);
|
||||
void Write8(Byte b);
|
||||
void Write16(UInt16 val);
|
||||
void Write32(UInt32 val);
|
||||
void Write64(UInt64 val);
|
||||
void WriteNtfsTime(const FILETIME &ft)
|
||||
{
|
||||
Write32(ft.dwLowDateTime);
|
||||
Write32(ft.dwHighDateTime);
|
||||
}
|
||||
|
||||
void WriteExtra(const CExtraBlock &extra);
|
||||
void WriteCommonItemInfo(const CLocalItem &item, bool isZip64);
|
||||
void WriteCentralHeader(const CItemOut &item);
|
||||
|
||||
void PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption);
|
||||
|
||||
public:
|
||||
HRESULT Create(IOutStream *outStream);
|
||||
|
||||
void MoveCurPos(UInt64 distanceToMove);
|
||||
UInt64 GetCurPos() const { return m_CurPos; }
|
||||
|
||||
void SeekToCurPos();
|
||||
|
||||
void PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption);
|
||||
void PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
|
||||
void WriteLocalHeader(const CLocalItem &item);
|
||||
|
||||
void WriteLocalHeader_And_SeekToNextFile(const CLocalItem &item)
|
||||
{
|
||||
WriteLocalHeader(item);
|
||||
SeekToCurPos();
|
||||
}
|
||||
|
||||
void WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment);
|
||||
|
||||
void CreateStreamForCompressing(IOutStream **outStream);
|
||||
void CreateStreamForCopying(ISequentialOutStream **outStream);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
27
CPP/7zip/Archive/Zip/ZipRegister.cpp
Normal file
27
CPP/7zip/Archive/Zip/ZipRegister.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
// ZipRegister.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "ZipHandler.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
static const Byte k_Signature[] = {
|
||||
4, 0x50, 0x4B, 0x03, 0x04,
|
||||
4, 0x50, 0x4B, 0x05, 0x06,
|
||||
6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B,
|
||||
6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B };
|
||||
|
||||
REGISTER_ARC_IO(
|
||||
"zip", "zip z01 zipx jar xpi odt ods docx xlsx epub", 0, 1,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature |
|
||||
NArcInfoFlags::kMultiSignature |
|
||||
NArcInfoFlags::kUseGlobalOffset,
|
||||
IsArc_Zip)
|
||||
|
||||
}}
|
||||
1234
CPP/7zip/Archive/Zip/ZipUpdate.cpp
Normal file
1234
CPP/7zip/Archive/Zip/ZipUpdate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
59
CPP/7zip/Archive/Zip/ZipUpdate.h
Normal file
59
CPP/7zip/Archive/Zip/ZipUpdate.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// ZipUpdate.h
|
||||
|
||||
#ifndef __ZIP_UPDATE_H
|
||||
#define __ZIP_UPDATE_H
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "ZipCompressionMode.h"
|
||||
#include "ZipIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
struct CUpdateRange
|
||||
{
|
||||
UInt64 Position;
|
||||
UInt64 Size;
|
||||
|
||||
// CUpdateRange() {};
|
||||
CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {};
|
||||
};
|
||||
|
||||
struct CUpdateItem
|
||||
{
|
||||
bool NewData;
|
||||
bool NewProps;
|
||||
bool IsDir;
|
||||
bool NtfsTimeIsDefined;
|
||||
bool IsUtf8;
|
||||
int IndexInArc;
|
||||
int IndexInClient;
|
||||
UInt32 Attrib;
|
||||
UInt32 Time;
|
||||
UInt64 Size;
|
||||
AString Name;
|
||||
// bool Commented;
|
||||
// CUpdateRange CommentRange;
|
||||
FILETIME Ntfs_MTime;
|
||||
FILETIME Ntfs_ATime;
|
||||
FILETIME Ntfs_CTime;
|
||||
|
||||
CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}
|
||||
};
|
||||
|
||||
HRESULT Update(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
CInArchive *inArchive, bool removeSfx,
|
||||
CCompressionMethodMode *compressionMethodMode,
|
||||
IArchiveUpdateCallback *updateCallback);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user