xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Zip/ZipAddCommon.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // ZipAddCommon.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/7zCrc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/Alloc.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include "../../ICoder.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../IPassword.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../MyVersion.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/CreateCoder.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/LzmaEncoder.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/PpmdZip.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/XzEncoder.h"
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker #include "../Common/InStreamWithCRC.h"
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker #include "ZipAddCommon.h"
25*f6dc9357SAndroid Build Coastguard Worker #include "ZipHeader.h"
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
28*f6dc9357SAndroid Build Coastguard Worker namespace NZip {
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker using namespace NFileHeader;
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker 
33*f6dc9357SAndroid Build Coastguard Worker static const unsigned kLzmaPropsSize = 5;
34*f6dc9357SAndroid Build Coastguard Worker static const unsigned kLzmaHeaderSize = 4 + kLzmaPropsSize;
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_3(
37*f6dc9357SAndroid Build Coastguard Worker   CLzmaEncoder
38*f6dc9357SAndroid Build Coastguard Worker   , ICompressCoder
39*f6dc9357SAndroid Build Coastguard Worker   , ICompressSetCoderProperties
40*f6dc9357SAndroid Build Coastguard Worker   , ICompressSetCoderPropertiesOpt
41*f6dc9357SAndroid Build Coastguard Worker )
42*f6dc9357SAndroid Build Coastguard Worker public:
43*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<ICompressCoder, NCompress::NLzma::CEncoder> Encoder;
44*f6dc9357SAndroid Build Coastguard Worker   Byte Header[kLzmaHeaderSize];
45*f6dc9357SAndroid Build Coastguard Worker };
46*f6dc9357SAndroid Build Coastguard Worker 
47*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
48*f6dc9357SAndroid Build Coastguard Worker {
49*f6dc9357SAndroid Build Coastguard Worker   Encoder.Create_if_Empty();
50*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;
51*f6dc9357SAndroid Build Coastguard Worker   outStream->Init(Header + 4, kLzmaPropsSize);
52*f6dc9357SAndroid Build Coastguard Worker   RINOK(Encoder->SetCoderProperties(propIDs, props, numProps))
53*f6dc9357SAndroid Build Coastguard Worker   RINOK(Encoder->WriteCoderProperties(outStream))
54*f6dc9357SAndroid Build Coastguard Worker   if (outStream->GetPos() != kLzmaPropsSize)
55*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
56*f6dc9357SAndroid Build Coastguard Worker   Header[0] = MY_VER_MAJOR;
57*f6dc9357SAndroid Build Coastguard Worker   Header[1] = MY_VER_MINOR;
58*f6dc9357SAndroid Build Coastguard Worker   Header[2] = kLzmaPropsSize;
59*f6dc9357SAndroid Build Coastguard Worker   Header[3] = 0;
60*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
61*f6dc9357SAndroid Build Coastguard Worker }
62*f6dc9357SAndroid Build Coastguard Worker 
63*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CLzmaEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
64*f6dc9357SAndroid Build Coastguard Worker {
65*f6dc9357SAndroid Build Coastguard Worker   return Encoder->SetCoderPropertiesOpt(propIDs, props, numProps);
66*f6dc9357SAndroid Build Coastguard Worker }
67*f6dc9357SAndroid Build Coastguard Worker 
68*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
69*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
70*f6dc9357SAndroid Build Coastguard Worker {
71*f6dc9357SAndroid Build Coastguard Worker   RINOK(WriteStream(outStream, Header, kLzmaHeaderSize))
72*f6dc9357SAndroid Build Coastguard Worker   return Encoder.Interface()->Code(inStream, outStream, inSize, outSize, progress);
73*f6dc9357SAndroid Build Coastguard Worker }
74*f6dc9357SAndroid Build Coastguard Worker 
75*f6dc9357SAndroid Build Coastguard Worker 
76*f6dc9357SAndroid Build Coastguard Worker CAddCommon::CAddCommon():
77*f6dc9357SAndroid Build Coastguard Worker     _isLzmaEos(false),
78*f6dc9357SAndroid Build Coastguard Worker     _buf(NULL)
79*f6dc9357SAndroid Build Coastguard Worker     {}
80*f6dc9357SAndroid Build Coastguard Worker 
81*f6dc9357SAndroid Build Coastguard Worker void CAddCommon::SetOptions(const CCompressionMethodMode &options)
82*f6dc9357SAndroid Build Coastguard Worker {
83*f6dc9357SAndroid Build Coastguard Worker   _options = options;
84*f6dc9357SAndroid Build Coastguard Worker }
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker CAddCommon::~CAddCommon()
87*f6dc9357SAndroid Build Coastguard Worker {
88*f6dc9357SAndroid Build Coastguard Worker   MidFree(_buf);
89*f6dc9357SAndroid Build Coastguard Worker }
90*f6dc9357SAndroid Build Coastguard Worker 
91*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kBufSize = ((UInt32)1 << 16);
92*f6dc9357SAndroid Build Coastguard Worker 
93*f6dc9357SAndroid Build Coastguard Worker HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
94*f6dc9357SAndroid Build Coastguard Worker {
95*f6dc9357SAndroid Build Coastguard Worker   if (!_buf)
96*f6dc9357SAndroid Build Coastguard Worker   {
97*f6dc9357SAndroid Build Coastguard Worker     _buf = (Byte *)MidAlloc(kBufSize);
98*f6dc9357SAndroid Build Coastguard Worker     if (!_buf)
99*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
100*f6dc9357SAndroid Build Coastguard Worker   }
101*f6dc9357SAndroid Build Coastguard Worker 
102*f6dc9357SAndroid Build Coastguard Worker   UInt32 crc = CRC_INIT_VAL;
103*f6dc9357SAndroid Build Coastguard Worker   for (;;)
104*f6dc9357SAndroid Build Coastguard Worker   {
105*f6dc9357SAndroid Build Coastguard Worker     UInt32 processed;
106*f6dc9357SAndroid Build Coastguard Worker     RINOK(inStream->Read(_buf, kBufSize, &processed))
107*f6dc9357SAndroid Build Coastguard Worker     if (processed == 0)
108*f6dc9357SAndroid Build Coastguard Worker     {
109*f6dc9357SAndroid Build Coastguard Worker       resultCRC = CRC_GET_DIGEST(crc);
110*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
111*f6dc9357SAndroid Build Coastguard Worker     }
112*f6dc9357SAndroid Build Coastguard Worker     crc = CrcUpdate(crc, _buf, (size_t)processed);
113*f6dc9357SAndroid Build Coastguard Worker   }
114*f6dc9357SAndroid Build Coastguard Worker }
115*f6dc9357SAndroid Build Coastguard Worker 
116*f6dc9357SAndroid Build Coastguard Worker 
117*f6dc9357SAndroid Build Coastguard Worker HRESULT CAddCommon::Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,
118*f6dc9357SAndroid Build Coastguard Worker     CCompressingResult &opRes) const
119*f6dc9357SAndroid Build Coastguard Worker {
120*f6dc9357SAndroid Build Coastguard Worker   // We use Zip64, if unPackSize size is larger than 0xF8000000 to support
121*f6dc9357SAndroid Build Coastguard Worker   // cases when compressed size can be about 3% larger than uncompressed size
122*f6dc9357SAndroid Build Coastguard Worker 
123*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kUnpackZip64Limit = 0xF8000000;
124*f6dc9357SAndroid Build Coastguard Worker 
125*f6dc9357SAndroid Build Coastguard Worker   opRes.UnpackSize = unpackSize;
126*f6dc9357SAndroid Build Coastguard Worker   opRes.PackSize = (UInt64)1 << 60; // we use big value to force Zip64 mode.
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker   if (unpackSize < kUnpackZip64Limit)
129*f6dc9357SAndroid Build Coastguard Worker     opRes.PackSize = (UInt32)0xFFFFFFFF - 1; // it will not use Zip64 for that size
130*f6dc9357SAndroid Build Coastguard Worker 
131*f6dc9357SAndroid Build Coastguard Worker   if (opRes.PackSize < unpackSize)
132*f6dc9357SAndroid Build Coastguard Worker     opRes.PackSize = unpackSize;
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker   const Byte method = _options.MethodSequence[0];
135*f6dc9357SAndroid Build Coastguard Worker 
136*f6dc9357SAndroid Build Coastguard Worker   if (method == NCompressionMethod::kStore && !_options.Password_Defined)
137*f6dc9357SAndroid Build Coastguard Worker     opRes.PackSize = unpackSize;
138*f6dc9357SAndroid Build Coastguard Worker 
139*f6dc9357SAndroid Build Coastguard Worker   opRes.CRC = 0;
140*f6dc9357SAndroid Build Coastguard Worker 
141*f6dc9357SAndroid Build Coastguard Worker   opRes.LzmaEos = false;
142*f6dc9357SAndroid Build Coastguard Worker 
143*f6dc9357SAndroid Build Coastguard Worker   opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
144*f6dc9357SAndroid Build Coastguard Worker   opRes.DescriptorMode = outSeqMode;
145*f6dc9357SAndroid Build Coastguard Worker 
146*f6dc9357SAndroid Build Coastguard Worker   if (_options.Password_Defined)
147*f6dc9357SAndroid Build Coastguard Worker   {
148*f6dc9357SAndroid Build Coastguard Worker     opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
149*f6dc9357SAndroid Build Coastguard Worker     if (_options.IsAesMode)
150*f6dc9357SAndroid Build Coastguard Worker       opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;
151*f6dc9357SAndroid Build Coastguard Worker     else
152*f6dc9357SAndroid Build Coastguard Worker     {
153*f6dc9357SAndroid Build Coastguard Worker       if (inSeqMode)
154*f6dc9357SAndroid Build Coastguard Worker         opRes.DescriptorMode = true;
155*f6dc9357SAndroid Build Coastguard Worker     }
156*f6dc9357SAndroid Build Coastguard Worker   }
157*f6dc9357SAndroid Build Coastguard Worker 
158*f6dc9357SAndroid Build Coastguard Worker   opRes.Method = method;
159*f6dc9357SAndroid Build Coastguard Worker   Byte ver = 0;
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker   switch (method)
162*f6dc9357SAndroid Build Coastguard Worker   {
163*f6dc9357SAndroid Build Coastguard Worker     case NCompressionMethod::kStore: break;
164*f6dc9357SAndroid Build Coastguard Worker     case NCompressionMethod::kDeflate: ver = NCompressionMethod::kExtractVersion_Deflate; break;
165*f6dc9357SAndroid Build Coastguard Worker     case NCompressionMethod::kDeflate64: ver = NCompressionMethod::kExtractVersion_Deflate64; break;
166*f6dc9357SAndroid Build Coastguard Worker     case NCompressionMethod::kXz   : ver = NCompressionMethod::kExtractVersion_Xz; break;
167*f6dc9357SAndroid Build Coastguard Worker     case NCompressionMethod::kPPMd : ver = NCompressionMethod::kExtractVersion_PPMd; break;
168*f6dc9357SAndroid Build Coastguard Worker     case NCompressionMethod::kBZip2: ver = NCompressionMethod::kExtractVersion_BZip2; break;
169*f6dc9357SAndroid Build Coastguard Worker     case NCompressionMethod::kLZMA :
170*f6dc9357SAndroid Build Coastguard Worker     {
171*f6dc9357SAndroid Build Coastguard Worker       ver = NCompressionMethod::kExtractVersion_LZMA;
172*f6dc9357SAndroid Build Coastguard Worker       const COneMethodInfo *oneMethodMain = &_options._methods[0];
173*f6dc9357SAndroid Build Coastguard Worker       opRes.LzmaEos = oneMethodMain->Get_Lzma_Eos();
174*f6dc9357SAndroid Build Coastguard Worker       break;
175*f6dc9357SAndroid Build Coastguard Worker     }
176*f6dc9357SAndroid Build Coastguard Worker     default: break;
177*f6dc9357SAndroid Build Coastguard Worker   }
178*f6dc9357SAndroid Build Coastguard Worker   if (opRes.ExtractVersion < ver)
179*f6dc9357SAndroid Build Coastguard Worker       opRes.ExtractVersion = ver;
180*f6dc9357SAndroid Build Coastguard Worker 
181*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker 
184*f6dc9357SAndroid Build Coastguard Worker 
185*f6dc9357SAndroid Build Coastguard Worker HRESULT CAddCommon::Compress(
186*f6dc9357SAndroid Build Coastguard Worker     DECL_EXTERNAL_CODECS_LOC_VARS
187*f6dc9357SAndroid Build Coastguard Worker     ISequentialInStream *inStream, IOutStream *outStream,
188*f6dc9357SAndroid Build Coastguard Worker     bool inSeqMode, bool outSeqMode,
189*f6dc9357SAndroid Build Coastguard Worker     UInt32 fileTime,
190*f6dc9357SAndroid Build Coastguard Worker     UInt64 expectedDataSize, bool expectedDataSize_IsConfirmed,
191*f6dc9357SAndroid Build Coastguard Worker     ICompressProgressInfo *progress, CCompressingResult &opRes)
192*f6dc9357SAndroid Build Coastguard Worker {
193*f6dc9357SAndroid Build Coastguard Worker   // opRes.LzmaEos = false;
194*f6dc9357SAndroid Build Coastguard Worker 
195*f6dc9357SAndroid Build Coastguard Worker   if (!inStream)
196*f6dc9357SAndroid Build Coastguard Worker   {
197*f6dc9357SAndroid Build Coastguard Worker     // We can create empty stream here. But it was already implemented in caller code in 9.33+
198*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
199*f6dc9357SAndroid Build Coastguard Worker   }
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ISequentialInStream, CSequentialInStreamWithCRC> inCrcStream;
202*f6dc9357SAndroid Build Coastguard Worker 
203*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IInStream> inStream2;
204*f6dc9357SAndroid Build Coastguard Worker   if (!inSeqMode)
205*f6dc9357SAndroid Build Coastguard Worker   {
206*f6dc9357SAndroid Build Coastguard Worker     inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
207*f6dc9357SAndroid Build Coastguard Worker     if (!inStream2)
208*f6dc9357SAndroid Build Coastguard Worker     {
209*f6dc9357SAndroid Build Coastguard Worker       // inSeqMode = true;
210*f6dc9357SAndroid Build Coastguard Worker       // inSeqMode must be correct before
211*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
212*f6dc9357SAndroid Build Coastguard Worker     }
213*f6dc9357SAndroid Build Coastguard Worker   }
214*f6dc9357SAndroid Build Coastguard Worker 
215*f6dc9357SAndroid Build Coastguard Worker   inCrcStream->SetStream(inStream);
216*f6dc9357SAndroid Build Coastguard Worker   inCrcStream->SetFullSize(expectedDataSize_IsConfirmed ? expectedDataSize : (UInt64)(Int64)-1);
217*f6dc9357SAndroid Build Coastguard Worker   // inCrcStream->Init();
218*f6dc9357SAndroid Build Coastguard Worker 
219*f6dc9357SAndroid Build Coastguard Worker   unsigned numTestMethods = _options.MethodSequence.Size();
220*f6dc9357SAndroid Build Coastguard Worker   // numTestMethods != 0
221*f6dc9357SAndroid Build Coastguard Worker 
222*f6dc9357SAndroid Build Coastguard Worker   bool descriptorMode = outSeqMode;
223*f6dc9357SAndroid Build Coastguard Worker 
224*f6dc9357SAndroid Build Coastguard Worker   // ZipCrypto without descriptor requires additional reading pass for
225*f6dc9357SAndroid Build Coastguard Worker   // inStream to calculate CRC for password check field.
226*f6dc9357SAndroid Build Coastguard Worker   // The descriptor allows to use ZipCrypto check field without CRC (InfoZip's modification).
227*f6dc9357SAndroid Build Coastguard Worker 
228*f6dc9357SAndroid Build Coastguard Worker   if (!outSeqMode)
229*f6dc9357SAndroid Build Coastguard Worker     if (inSeqMode && _options.Password_Defined && !_options.IsAesMode)
230*f6dc9357SAndroid Build Coastguard Worker       descriptorMode = true;
231*f6dc9357SAndroid Build Coastguard Worker   opRes.DescriptorMode = descriptorMode;
232*f6dc9357SAndroid Build Coastguard Worker 
233*f6dc9357SAndroid Build Coastguard Worker   if (numTestMethods > 1)
234*f6dc9357SAndroid Build Coastguard Worker     if (inSeqMode || outSeqMode || !inStream2)
235*f6dc9357SAndroid Build Coastguard Worker       numTestMethods = 1;
236*f6dc9357SAndroid Build Coastguard Worker 
237*f6dc9357SAndroid Build Coastguard Worker   UInt32 crc = 0;
238*f6dc9357SAndroid Build Coastguard Worker   bool crc_IsCalculated = false;
239*f6dc9357SAndroid Build Coastguard Worker 
240*f6dc9357SAndroid Build Coastguard Worker   CFilterCoder::C_OutStream_Releaser outStreamReleaser;
241*f6dc9357SAndroid Build Coastguard Worker   // opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < numTestMethods; i++)
244*f6dc9357SAndroid Build Coastguard Worker   {
245*f6dc9357SAndroid Build Coastguard Worker     inCrcStream->Init();
246*f6dc9357SAndroid Build Coastguard Worker 
247*f6dc9357SAndroid Build Coastguard Worker     if (i != 0)
248*f6dc9357SAndroid Build Coastguard Worker     {
249*f6dc9357SAndroid Build Coastguard Worker       // if (inStream2)
250*f6dc9357SAndroid Build Coastguard Worker       {
251*f6dc9357SAndroid Build Coastguard Worker         RINOK(InStream_SeekToBegin(inStream2))
252*f6dc9357SAndroid Build Coastguard Worker       }
253*f6dc9357SAndroid Build Coastguard Worker       RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL))
254*f6dc9357SAndroid Build Coastguard Worker       RINOK(outStream->SetSize(0))
255*f6dc9357SAndroid Build Coastguard Worker     }
256*f6dc9357SAndroid Build Coastguard Worker 
257*f6dc9357SAndroid Build Coastguard Worker     opRes.LzmaEos = false;
258*f6dc9357SAndroid Build Coastguard Worker     opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
259*f6dc9357SAndroid Build Coastguard Worker 
260*f6dc9357SAndroid Build Coastguard Worker     const Byte method = _options.MethodSequence[i];
261*f6dc9357SAndroid Build Coastguard Worker     if (method == NCompressionMethod::kStore && descriptorMode)
262*f6dc9357SAndroid Build Coastguard Worker     {
263*f6dc9357SAndroid Build Coastguard Worker       // we still can create descriptor_mode archives with "Store" method, but they are not good for 100%
264*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
265*f6dc9357SAndroid Build Coastguard Worker     }
266*f6dc9357SAndroid Build Coastguard Worker 
267*f6dc9357SAndroid Build Coastguard Worker     bool needCode = true;
268*f6dc9357SAndroid Build Coastguard Worker 
269*f6dc9357SAndroid Build Coastguard Worker     if (_options.Password_Defined)
270*f6dc9357SAndroid Build Coastguard Worker     {
271*f6dc9357SAndroid Build Coastguard Worker       opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
272*f6dc9357SAndroid Build Coastguard Worker 
273*f6dc9357SAndroid Build Coastguard Worker       if (!_cryptoStream.IsDefined())
274*f6dc9357SAndroid Build Coastguard Worker         _cryptoStream.SetFromCls(new CFilterCoder(true));
275*f6dc9357SAndroid Build Coastguard Worker 
276*f6dc9357SAndroid Build Coastguard Worker       if (_options.IsAesMode)
277*f6dc9357SAndroid Build Coastguard Worker       {
278*f6dc9357SAndroid Build Coastguard Worker         opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;
279*f6dc9357SAndroid Build Coastguard Worker         if (!_cryptoStream->Filter)
280*f6dc9357SAndroid Build Coastguard Worker         {
281*f6dc9357SAndroid Build Coastguard Worker           _cryptoStream->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;
282*f6dc9357SAndroid Build Coastguard Worker           _filterAesSpec->SetKeyMode(_options.AesKeyMode);
283*f6dc9357SAndroid Build Coastguard Worker           RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()))
284*f6dc9357SAndroid Build Coastguard Worker         }
285*f6dc9357SAndroid Build Coastguard Worker         RINOK(_filterAesSpec->WriteHeader(outStream))
286*f6dc9357SAndroid Build Coastguard Worker       }
287*f6dc9357SAndroid Build Coastguard Worker       else
288*f6dc9357SAndroid Build Coastguard Worker       {
289*f6dc9357SAndroid Build Coastguard Worker         if (!_cryptoStream->Filter)
290*f6dc9357SAndroid Build Coastguard Worker         {
291*f6dc9357SAndroid Build Coastguard Worker           _cryptoStream->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
292*f6dc9357SAndroid Build Coastguard Worker           _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len());
293*f6dc9357SAndroid Build Coastguard Worker         }
294*f6dc9357SAndroid Build Coastguard Worker 
295*f6dc9357SAndroid Build Coastguard Worker         UInt32 check;
296*f6dc9357SAndroid Build Coastguard Worker 
297*f6dc9357SAndroid Build Coastguard Worker         if (descriptorMode)
298*f6dc9357SAndroid Build Coastguard Worker         {
299*f6dc9357SAndroid Build Coastguard Worker           // it's Info-ZIP modification for stream_mode descriptor_mode (bit 3 of the general purpose bit flag is set)
300*f6dc9357SAndroid Build Coastguard Worker           check = (fileTime & 0xFFFF);
301*f6dc9357SAndroid Build Coastguard Worker         }
302*f6dc9357SAndroid Build Coastguard Worker         else
303*f6dc9357SAndroid Build Coastguard Worker         {
304*f6dc9357SAndroid Build Coastguard Worker           if (!crc_IsCalculated)
305*f6dc9357SAndroid Build Coastguard Worker           {
306*f6dc9357SAndroid Build Coastguard Worker             RINOK(CalcStreamCRC(inStream, crc))
307*f6dc9357SAndroid Build Coastguard Worker             crc_IsCalculated = true;
308*f6dc9357SAndroid Build Coastguard Worker             RINOK(InStream_SeekToBegin(inStream2))
309*f6dc9357SAndroid Build Coastguard Worker             inCrcStream->Init();
310*f6dc9357SAndroid Build Coastguard Worker           }
311*f6dc9357SAndroid Build Coastguard Worker           check = (crc >> 16);
312*f6dc9357SAndroid Build Coastguard Worker         }
313*f6dc9357SAndroid Build Coastguard Worker 
314*f6dc9357SAndroid Build Coastguard Worker         RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check))
315*f6dc9357SAndroid Build Coastguard Worker       }
316*f6dc9357SAndroid Build Coastguard Worker 
317*f6dc9357SAndroid Build Coastguard Worker       if (method == NCompressionMethod::kStore)
318*f6dc9357SAndroid Build Coastguard Worker       {
319*f6dc9357SAndroid Build Coastguard Worker         needCode = false;
320*f6dc9357SAndroid Build Coastguard Worker         RINOK(_cryptoStream->Code(inCrcStream, outStream, NULL, NULL, progress))
321*f6dc9357SAndroid Build Coastguard Worker       }
322*f6dc9357SAndroid Build Coastguard Worker       else
323*f6dc9357SAndroid Build Coastguard Worker       {
324*f6dc9357SAndroid Build Coastguard Worker         RINOK(_cryptoStream->SetOutStream(outStream))
325*f6dc9357SAndroid Build Coastguard Worker         RINOK(_cryptoStream->InitEncoder())
326*f6dc9357SAndroid Build Coastguard Worker         outStreamReleaser.FilterCoder = _cryptoStream.ClsPtr();
327*f6dc9357SAndroid Build Coastguard Worker       }
328*f6dc9357SAndroid Build Coastguard Worker     }
329*f6dc9357SAndroid Build Coastguard Worker 
330*f6dc9357SAndroid Build Coastguard Worker     if (needCode)
331*f6dc9357SAndroid Build Coastguard Worker     {
332*f6dc9357SAndroid Build Coastguard Worker       switch (method)
333*f6dc9357SAndroid Build Coastguard Worker       {
334*f6dc9357SAndroid Build Coastguard Worker       case NCompressionMethod::kStore:
335*f6dc9357SAndroid Build Coastguard Worker       {
336*f6dc9357SAndroid Build Coastguard Worker         _copyCoder.Create_if_Empty();
337*f6dc9357SAndroid Build Coastguard Worker         CMyComPtr<ISequentialOutStream> outStreamNew;
338*f6dc9357SAndroid Build Coastguard Worker         if (_options.Password_Defined)
339*f6dc9357SAndroid Build Coastguard Worker           outStreamNew = _cryptoStream;
340*f6dc9357SAndroid Build Coastguard Worker         else
341*f6dc9357SAndroid Build Coastguard Worker           outStreamNew = outStream;
342*f6dc9357SAndroid Build Coastguard Worker         RINOK(_copyCoder.Interface()->Code(inCrcStream, outStreamNew, NULL, NULL, progress))
343*f6dc9357SAndroid Build Coastguard Worker         break;
344*f6dc9357SAndroid Build Coastguard Worker       }
345*f6dc9357SAndroid Build Coastguard Worker 
346*f6dc9357SAndroid Build Coastguard Worker       default:
347*f6dc9357SAndroid Build Coastguard Worker       {
348*f6dc9357SAndroid Build Coastguard Worker         if (!_compressEncoder)
349*f6dc9357SAndroid Build Coastguard Worker         {
350*f6dc9357SAndroid Build Coastguard Worker           CLzmaEncoder *_lzmaEncoder = NULL;
351*f6dc9357SAndroid Build Coastguard Worker           if (method == NCompressionMethod::kLZMA)
352*f6dc9357SAndroid Build Coastguard Worker           {
353*f6dc9357SAndroid Build Coastguard Worker             _compressExtractVersion = NCompressionMethod::kExtractVersion_LZMA;
354*f6dc9357SAndroid Build Coastguard Worker             _lzmaEncoder = new CLzmaEncoder();
355*f6dc9357SAndroid Build Coastguard Worker             _compressEncoder = _lzmaEncoder;
356*f6dc9357SAndroid Build Coastguard Worker           }
357*f6dc9357SAndroid Build Coastguard Worker           else if (method == NCompressionMethod::kXz)
358*f6dc9357SAndroid Build Coastguard Worker           {
359*f6dc9357SAndroid Build Coastguard Worker             _compressExtractVersion = NCompressionMethod::kExtractVersion_Xz;
360*f6dc9357SAndroid Build Coastguard Worker             NCompress::NXz::CEncoder *encoder = new NCompress::NXz::CEncoder();
361*f6dc9357SAndroid Build Coastguard Worker             _compressEncoder = encoder;
362*f6dc9357SAndroid Build Coastguard Worker           }
363*f6dc9357SAndroid Build Coastguard Worker           else if (method == NCompressionMethod::kPPMd)
364*f6dc9357SAndroid Build Coastguard Worker           {
365*f6dc9357SAndroid Build Coastguard Worker             _compressExtractVersion = NCompressionMethod::kExtractVersion_PPMd;
366*f6dc9357SAndroid Build Coastguard Worker             NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
367*f6dc9357SAndroid Build Coastguard Worker             _compressEncoder = encoder;
368*f6dc9357SAndroid Build Coastguard Worker           }
369*f6dc9357SAndroid Build Coastguard Worker           else
370*f6dc9357SAndroid Build Coastguard Worker           {
371*f6dc9357SAndroid Build Coastguard Worker           CMethodId methodId;
372*f6dc9357SAndroid Build Coastguard Worker           switch (method)
373*f6dc9357SAndroid Build Coastguard Worker           {
374*f6dc9357SAndroid Build Coastguard Worker             case NCompressionMethod::kBZip2:
375*f6dc9357SAndroid Build Coastguard Worker               methodId = kMethodId_BZip2;
376*f6dc9357SAndroid Build Coastguard Worker               _compressExtractVersion = NCompressionMethod::kExtractVersion_BZip2;
377*f6dc9357SAndroid Build Coastguard Worker               break;
378*f6dc9357SAndroid Build Coastguard Worker             default:
379*f6dc9357SAndroid Build Coastguard Worker               _compressExtractVersion = ((method == NCompressionMethod::kDeflate64) ?
380*f6dc9357SAndroid Build Coastguard Worker                   NCompressionMethod::kExtractVersion_Deflate64 :
381*f6dc9357SAndroid Build Coastguard Worker                   NCompressionMethod::kExtractVersion_Deflate);
382*f6dc9357SAndroid Build Coastguard Worker               methodId = kMethodId_ZipBase + method;
383*f6dc9357SAndroid Build Coastguard Worker               break;
384*f6dc9357SAndroid Build Coastguard Worker           }
385*f6dc9357SAndroid Build Coastguard Worker           RINOK(CreateCoder_Id(
386*f6dc9357SAndroid Build Coastguard Worker               EXTERNAL_CODECS_LOC_VARS
387*f6dc9357SAndroid Build Coastguard Worker               methodId, true, _compressEncoder))
388*f6dc9357SAndroid Build Coastguard Worker           if (!_compressEncoder)
389*f6dc9357SAndroid Build Coastguard Worker             return E_NOTIMPL;
390*f6dc9357SAndroid Build Coastguard Worker 
391*f6dc9357SAndroid Build Coastguard Worker           if (method == NCompressionMethod::kDeflate ||
392*f6dc9357SAndroid Build Coastguard Worker               method == NCompressionMethod::kDeflate64)
393*f6dc9357SAndroid Build Coastguard Worker           {
394*f6dc9357SAndroid Build Coastguard Worker           }
395*f6dc9357SAndroid Build Coastguard Worker           else if (method == NCompressionMethod::kBZip2)
396*f6dc9357SAndroid Build Coastguard Worker           {
397*f6dc9357SAndroid Build Coastguard Worker           }
398*f6dc9357SAndroid Build Coastguard Worker           }
399*f6dc9357SAndroid Build Coastguard Worker           {
400*f6dc9357SAndroid Build Coastguard Worker             CMyComPtr<ICompressSetCoderProperties> setCoderProps;
401*f6dc9357SAndroid Build Coastguard Worker             _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
402*f6dc9357SAndroid Build Coastguard Worker             if (setCoderProps)
403*f6dc9357SAndroid Build Coastguard Worker             {
404*f6dc9357SAndroid Build Coastguard Worker               if (!_options._methods.IsEmpty())
405*f6dc9357SAndroid Build Coastguard Worker               {
406*f6dc9357SAndroid Build Coastguard Worker                 COneMethodInfo *oneMethodMain = &_options._methods[0];
407*f6dc9357SAndroid Build Coastguard Worker 
408*f6dc9357SAndroid Build Coastguard Worker                 RINOK(oneMethodMain->SetCoderProps(setCoderProps,
409*f6dc9357SAndroid Build Coastguard Worker                     _options.DataSizeReduce_Defined ? &_options.DataSizeReduce : NULL))
410*f6dc9357SAndroid Build Coastguard Worker               }
411*f6dc9357SAndroid Build Coastguard Worker             }
412*f6dc9357SAndroid Build Coastguard Worker           }
413*f6dc9357SAndroid Build Coastguard Worker           if (method == NCompressionMethod::kLZMA)
414*f6dc9357SAndroid Build Coastguard Worker             _isLzmaEos = _lzmaEncoder->Encoder->IsWriteEndMark();
415*f6dc9357SAndroid Build Coastguard Worker         }
416*f6dc9357SAndroid Build Coastguard Worker 
417*f6dc9357SAndroid Build Coastguard Worker         if (method == NCompressionMethod::kLZMA)
418*f6dc9357SAndroid Build Coastguard Worker           opRes.LzmaEos = _isLzmaEos;
419*f6dc9357SAndroid Build Coastguard Worker 
420*f6dc9357SAndroid Build Coastguard Worker         CMyComPtr<ISequentialOutStream> outStreamNew;
421*f6dc9357SAndroid Build Coastguard Worker         if (_options.Password_Defined)
422*f6dc9357SAndroid Build Coastguard Worker           outStreamNew = _cryptoStream;
423*f6dc9357SAndroid Build Coastguard Worker         else
424*f6dc9357SAndroid Build Coastguard Worker           outStreamNew = outStream;
425*f6dc9357SAndroid Build Coastguard Worker         if (_compressExtractVersion > opRes.ExtractVersion)
426*f6dc9357SAndroid Build Coastguard Worker           opRes.ExtractVersion = _compressExtractVersion;
427*f6dc9357SAndroid Build Coastguard Worker 
428*f6dc9357SAndroid Build Coastguard Worker         {
429*f6dc9357SAndroid Build Coastguard Worker           CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
430*f6dc9357SAndroid Build Coastguard Worker           _compressEncoder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);
431*f6dc9357SAndroid Build Coastguard Worker           if (optProps)
432*f6dc9357SAndroid Build Coastguard Worker           {
433*f6dc9357SAndroid Build Coastguard Worker             const PROPID propID = NCoderPropID::kExpectedDataSize;
434*f6dc9357SAndroid Build Coastguard Worker             NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
435*f6dc9357SAndroid Build Coastguard Worker             RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))
436*f6dc9357SAndroid Build Coastguard Worker           }
437*f6dc9357SAndroid Build Coastguard Worker         }
438*f6dc9357SAndroid Build Coastguard Worker 
439*f6dc9357SAndroid Build Coastguard Worker         try {
440*f6dc9357SAndroid Build Coastguard Worker         RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress))
441*f6dc9357SAndroid Build Coastguard Worker         } catch (...) { return E_FAIL; }
442*f6dc9357SAndroid Build Coastguard Worker         break;
443*f6dc9357SAndroid Build Coastguard Worker       }
444*f6dc9357SAndroid Build Coastguard Worker       } // switch end
445*f6dc9357SAndroid Build Coastguard Worker 
446*f6dc9357SAndroid Build Coastguard Worker       if (_options.Password_Defined)
447*f6dc9357SAndroid Build Coastguard Worker       {
448*f6dc9357SAndroid Build Coastguard Worker         RINOK(_cryptoStream->OutStreamFinish())
449*f6dc9357SAndroid Build Coastguard Worker       }
450*f6dc9357SAndroid Build Coastguard Worker     }
451*f6dc9357SAndroid Build Coastguard Worker 
452*f6dc9357SAndroid Build Coastguard Worker     if (_options.Password_Defined)
453*f6dc9357SAndroid Build Coastguard Worker     {
454*f6dc9357SAndroid Build Coastguard Worker       if (_options.IsAesMode)
455*f6dc9357SAndroid Build Coastguard Worker       {
456*f6dc9357SAndroid Build Coastguard Worker         RINOK(_filterAesSpec->WriteFooter(outStream))
457*f6dc9357SAndroid Build Coastguard Worker       }
458*f6dc9357SAndroid Build Coastguard Worker     }
459*f6dc9357SAndroid Build Coastguard Worker 
460*f6dc9357SAndroid Build Coastguard Worker     RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize))
461*f6dc9357SAndroid Build Coastguard Worker 
462*f6dc9357SAndroid Build Coastguard Worker     {
463*f6dc9357SAndroid Build Coastguard Worker       opRes.CRC = inCrcStream->GetCRC();
464*f6dc9357SAndroid Build Coastguard Worker       opRes.UnpackSize = inCrcStream->GetSize();
465*f6dc9357SAndroid Build Coastguard Worker       opRes.Method = method;
466*f6dc9357SAndroid Build Coastguard Worker     }
467*f6dc9357SAndroid Build Coastguard Worker 
468*f6dc9357SAndroid Build Coastguard Worker     if (!inCrcStream->WasFinished())
469*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
470*f6dc9357SAndroid Build Coastguard Worker 
471*f6dc9357SAndroid Build Coastguard Worker     if (_options.Password_Defined)
472*f6dc9357SAndroid Build Coastguard Worker     {
473*f6dc9357SAndroid Build Coastguard Worker       if (opRes.PackSize < opRes.UnpackSize +
474*f6dc9357SAndroid Build Coastguard Worker           (_options.IsAesMode ? _filterAesSpec->GetAddPackSize() : NCrypto::NZip::kHeaderSize))
475*f6dc9357SAndroid Build Coastguard Worker         break;
476*f6dc9357SAndroid Build Coastguard Worker     }
477*f6dc9357SAndroid Build Coastguard Worker     else if (opRes.PackSize < opRes.UnpackSize)
478*f6dc9357SAndroid Build Coastguard Worker       break;
479*f6dc9357SAndroid Build Coastguard Worker   }
480*f6dc9357SAndroid Build Coastguard Worker 
481*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
482*f6dc9357SAndroid Build Coastguard Worker }
483*f6dc9357SAndroid Build Coastguard Worker 
484*f6dc9357SAndroid Build Coastguard Worker }}
485