Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipAddCommon.cpp')
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.cpp197
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)
{