// 커맨드라인 정보로 options 셋팅 void zmodifyer::OptionSetting(UStringVector& commandStrings, CArchiveCommandLineOptions & options) { CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); //if (options.HelpMode) //{ //ShowCopyrightAndHelp(g_StdOut, true); //return; //} parser.Parse2(options, zdb_); if( options.PasswordEnabled ) { CMyComPtr< ICryptoSetPassword > setPassword = new CCryptoSetPassword; setPassword->CryptoSetPassword( (const Byte*)(&options.Password[0]), options.Password.Length() * 2 ); } }
HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { if (!folderInfo.CheckStructure()) return E_NOTIMPL; #ifndef _NO_CRYPTO passwordIsDefined = false; #endif CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unpackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; size_t size = props.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); CByteBuffer buffer; passwordIsDefined = true; const UString password(passwordBSTR); const UInt32 sizeInBytes = password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < password.Length(); i++) { wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unpackSizesPointers; packSizesPointers.Reserve(numInStreams); unpackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unpackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); }
HRESULT CZipDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS CInArchive &archive, const CItemEx &item, ISequentialOutStream *realOutStream, IArchiveExtractCallback *extractCallback, ICompressProgressInfo *compressProgress, UInt32 numThreads, Int32 &res) { res = NArchive::NExtract::NOperationResult::kDataError; CInStreamReleaser inStreamReleaser; bool needCRC = true; bool wzAesMode = false; bool pkAesMode = false; UInt16 methodId = item.CompressionMethod; if (item.IsEncrypted()) { if (item.IsStrongEncrypted()) { CStrongCryptoField f; if (item.CentralExtra.GetStrongCryptoField(f)) { pkAesMode = true; } if (!pkAesMode) { res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; return S_OK; } } if (methodId == NFileHeader::NCompressionMethod::kWzAES) { CWzAesExtraField aesField; if (item.CentralExtra.GetWzAesField(aesField)) { wzAesMode = true; needCRC = aesField.NeedCrc(); } } } COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->SetStream(realOutStream); outStreamSpec->Init(needCRC); UInt64 authenticationPos; CMyComPtr<ISequentialInStream> inStream; { UInt64 packSize = item.PackSize; if (wzAesMode) { if (packSize < NCrypto::NWzAes::kMacSize) return S_OK; packSize -= NCrypto::NWzAes::kMacSize; } UInt64 dataPos = item.GetDataPosition(); inStream.Attach(archive.CreateLimitedStream(dataPos, packSize)); authenticationPos = dataPos + packSize; } CMyComPtr<ICompressFilter> cryptoFilter; if (item.IsEncrypted()) { if (wzAesMode) { CWzAesExtraField aesField; if (!item.CentralExtra.GetWzAesField(aesField)) return S_OK; methodId = aesField.Method; if (!_wzAesDecoder) { _wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder; _wzAesDecoder = _wzAesDecoderSpec; } cryptoFilter = _wzAesDecoder; Byte properties = aesField.Strength; RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1)); } else if (pkAesMode) { if (!_pkAesDecoder) { _pkAesDecoderSpec = new NCrypto::NZipStrong::CDecoder; _pkAesDecoder = _pkAesDecoderSpec; } cryptoFilter = _pkAesDecoder; } else { if (!_zipCryptoDecoder) { _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder; _zipCryptoDecoder = _zipCryptoDecoderSpec; } cryptoFilter = _zipCryptoDecoder; } CMyComPtr<ICryptoSetPassword> cryptoSetPassword; RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); if (!getTextPassword) extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); if (getTextPassword) { CMyComBSTR password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); AString charPassword; if (wzAesMode || pkAesMode) { charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP); /* for (int i = 0;; i++) { wchar_t c = password[i]; if (c == 0) break; if (c >= 0x80) { res = NArchive::NExtract::NOperationResult::kDataError; return S_OK; } charPassword += (char)c; } */ } else { // we use OEM. WinZip/Windows probably use ANSI for some files charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); } HRESULT result = cryptoSetPassword->CryptoSetPassword( (const Byte *)(const char *)charPassword, charPassword.Length()); if (result != S_OK) return S_OK; } else { RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); } } int m; for (m = 0; m < methodItems.Size(); m++) if (methodItems[m].ZipMethod == methodId) break; if (m == methodItems.Size()) { CMethodItem mi; mi.ZipMethod = methodId; if (methodId == NFileHeader::NCompressionMethod::kStored) mi.Coder = new NCompress::CCopyCoder; else if (methodId == NFileHeader::NCompressionMethod::kShrunk) mi.Coder = new NCompress::NShrink::CDecoder; else if (methodId == NFileHeader::NCompressionMethod::kImploded) mi.Coder = new NCompress::NImplode::NDecoder::CCoder; else if (methodId == NFileHeader::NCompressionMethod::kLZMA) mi.Coder = new CLzmaDecoder; else { CMethodId szMethodID; if (methodId == NFileHeader::NCompressionMethod::kBZip2) szMethodID = kMethodId_BZip2; else { if (methodId > 0xFF) { res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; return S_OK; } szMethodID = kMethodId_ZipBase + (Byte)methodId; } RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false)); if (mi.Coder == 0) { res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; return S_OK; } } m = methodItems.Add(mi); } ICompressCoder *coder = methodItems[m].Coder; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties); if (setDecoderProperties) { Byte properties = (Byte)item.Flags; RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1)); } } #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif { HRESULT result = S_OK; CMyComPtr<ISequentialInStream> inStreamNew; if (item.IsEncrypted()) { if (!filterStream) { filterStreamSpec = new CFilterCoder; filterStream = filterStreamSpec; } filterStreamSpec->Filter = cryptoFilter; if (wzAesMode) { result = _wzAesDecoderSpec->ReadHeader(inStream); } else if (pkAesMode) { result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize); if (result == S_OK) { bool passwOK; result = _pkAesDecoderSpec->CheckPassword(passwOK); if (result == S_OK && !passwOK) result = S_FALSE; } } else { result = _zipCryptoDecoderSpec->ReadHeader(inStream); } if (result == S_OK) { RINOK(filterStreamSpec->SetInStream(inStream)); inStreamReleaser.FilterCoder = filterStreamSpec; inStreamNew = filterStream; if (wzAesMode) { if (!_wzAesDecoderSpec->CheckPasswordVerifyCode()) result = S_FALSE; } } } else inStreamNew = inStream; if (result == S_OK) result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress); if (result == S_FALSE) return S_OK; if (result == E_NOTIMPL) { res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; return S_OK; } RINOK(result); } bool crcOK = true; bool authOk = true; if (needCRC) crcOK = (outStreamSpec->GetCRC() == item.FileCRC); if (wzAesMode) { inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize)); if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) authOk = false; } res = ((crcOK && authOk) ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError); return S_OK; }
HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifndef _7ZIP_ST { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword = new CCryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { UString & password = _options.Password; /* const UInt32 sizeInBytes = (_options.Password.Length()+1) * 2; CByteBuffer buffer; buffer.SetCapacity(sizeInBytes); parallel::_for( 0,password.Length(), [&buffer, &password]( int i, bool & breakFlag ) { if( breakFlag ) return; wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } , 4 ); buffer[sizeInBytes-1] = 0; buffer[sizeInBytes-2] = 0; RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes-2)); */ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)(&_options.Password[0]), password.Length()*2)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; }