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