diff options
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipAddCommon.cpp')
-rw-r--r-- | CPP/7zip/Archive/Zip/ZipAddCommon.cpp | 197 |
1 files changed, 132 insertions, 65 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 06fbe22f..dd83f87f 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -17,6 +17,7 @@ #include "../../Compress/LzmaEncoder.h" #include "../../Compress/PpmdZip.h" +#include "../../Compress/XzEncoder.h" #include "../Common/InStreamWithCRC.h" @@ -26,8 +27,8 @@ namespace NArchive { namespace NZip { -static const CMethodId kMethodId_ZipBase = 0x040100; -static const CMethodId kMethodId_BZip2 = 0x040202; +using namespace NFileHeader; + static const UInt32 kLzmaPropsSize = 5; static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize; @@ -37,10 +38,11 @@ class CLzmaEncoder: public ICompressSetCoderProperties, public CMyUnknownImp { +public: 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); @@ -81,7 +83,8 @@ CAddCommon::CAddCommon(const CCompressionMethodMode &options): _options(options), _copyCoderSpec(NULL), _cryptoStreamSpec(NULL), - _buf(NULL) + _buf(NULL), + _isLzmaEos(false) {} CAddCommon::~CAddCommon() @@ -114,49 +117,100 @@ HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultC } } + +HRESULT CAddCommon::Set_Pre_CompressionResult(bool seqMode, 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.FileTimeWasUsed = false; + + if (_options.PasswordIsDefined) + { + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto; + if (_options.IsAesMode) + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes; + else + { + if (seqMode) + opRes.FileTimeWasUsed = 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, - UInt32 /* fileTime */, + bool seqMode, UInt32 fileTime, 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 = NULL; - CInStreamWithCRC *inCrcStreamSpec = NULL; - CMyComPtr<ISequentialInStream> inCrcStream; - { - CMyComPtr<IInStream> inStream2; - + CSequentialInStreamWithCRC *inSecCrcStreamSpec = new CSequentialInStreamWithCRC; + CMyComPtr<ISequentialInStream> inCrcStream = inSecCrcStreamSpec; + + CMyComPtr<IInStream> inStream2; + if (!seqMode) 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(); - */ - } - } + inSecCrcStreamSpec->SetStream(inStream); + inSecCrcStreamSpec->Init(); unsigned numTestMethods = _options.MethodSequence.Size(); - if (numTestMethods > 1 && !inCrcStreamSpec) + if (seqMode || (numTestMethods > 1 && !inStream2)) numTestMethods = 1; UInt32 crc = 0; @@ -164,20 +218,24 @@ HRESULT CAddCommon::Compress( Byte method = 0; CFilterCoder::C_OutStream_Releaser outStreamReleaser; - opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default; + opRes.ExtractVersion = 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)); + opRes.LzmaEos = false; + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default; + if (inStream2 && i != 0) + { + 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 = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto; + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto; if (!_cryptoStream) { @@ -187,7 +245,7 @@ HRESULT CAddCommon::Compress( if (_options.IsAesMode) { - opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes; + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes; if (!_cryptoStreamSpec->Filter) { _cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder; @@ -206,23 +264,22 @@ HRESULT CAddCommon::Compress( UInt32 check; - // if (inCrcStreamSpec) + if (inStream2) { if (!crc_IsCalculated) { RINOK(CalcStreamCRC(inStream, crc)); crc_IsCalculated = true; - RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL)); + inSecCrcStreamSpec->Init(); } check = (crc >> 16); } - /* else { opRes.FileTimeWasUsed = true; check = (fileTime & 0xFFFF); } - */ RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check)); } @@ -236,7 +293,7 @@ HRESULT CAddCommon::Compress( switch (method) { - case NFileHeader::NCompressionMethod::kStored: + case NCompressionMethod::kStore: { if (_copyCoderSpec == NULL) { @@ -256,15 +313,22 @@ HRESULT CAddCommon::Compress( { if (!_compressEncoder) { - if (method == NFileHeader::NCompressionMethod::kLZMA) + CLzmaEncoder *_lzmaEncoder = NULL; + if (method == NCompressionMethod::kLZMA) { - _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA; - CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder(); + _compressExtractVersion = NCompressionMethod::kExtractVersion_LZMA; + _lzmaEncoder = new CLzmaEncoder(); _compressEncoder = _lzmaEncoder; } - else if (method == NFileHeader::NCompressionMethod::kPPMd) + 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 = NFileHeader::NCompressionMethod::kExtractVersion_PPMd; + _compressExtractVersion = NCompressionMethod::kExtractVersion_PPMd; NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder(); _compressEncoder = encoder; } @@ -273,14 +337,14 @@ HRESULT CAddCommon::Compress( CMethodId methodId; switch (method) { - case NFileHeader::NCompressionMethod::kBZip2: + case NCompressionMethod::kBZip2: methodId = kMethodId_BZip2; - _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_BZip2; + _compressExtractVersion = NCompressionMethod::kExtractVersion_BZip2; break; default: - _compressExtractVersion = ((method == NFileHeader::NCompressionMethod::kDeflated64) ? - NFileHeader::NCompressionMethod::kExtractVersion_Deflate64 : - NFileHeader::NCompressionMethod::kExtractVersion_Deflate); + _compressExtractVersion = ((method == NCompressionMethod::kDeflate64) ? + NCompressionMethod::kExtractVersion_Deflate64 : + NCompressionMethod::kExtractVersion_Deflate); methodId = kMethodId_ZipBase + method; break; } @@ -290,11 +354,11 @@ HRESULT CAddCommon::Compress( if (!_compressEncoder) return E_NOTIMPL; - if (method == NFileHeader::NCompressionMethod::kDeflated || - method == NFileHeader::NCompressionMethod::kDeflated64) + if (method == NCompressionMethod::kDeflate || + method == NCompressionMethod::kDeflate64) { } - else if (method == NFileHeader::NCompressionMethod::kBZip2) + else if (method == NCompressionMethod::kBZip2) { } } @@ -303,11 +367,22 @@ HRESULT CAddCommon::Compress( _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps); if (setCoderProps) { - RINOK(_options.MethodInfo.SetCoderProps(setCoderProps, - _options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL)); + 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; @@ -332,18 +407,10 @@ HRESULT CAddCommon::Compress( 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) { |