1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/7zstub/src/7zip/Archive/7z/7zDecode.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,443 @@ 1.4 +// 7zDecode.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "7zDecode.h" 1.9 + 1.10 +#include "../../IPassword.h" 1.11 +#include "../../Common/LockedStream.h" 1.12 +#include "../../Common/StreamObjects.h" 1.13 +#include "../../Common/ProgressUtils.h" 1.14 +#include "../../Common/LimitedStreams.h" 1.15 +#include "../Common/FilterCoder.h" 1.16 + 1.17 +#include "7zMethods.h" 1.18 + 1.19 +#ifdef COMPRESS_LZMA 1.20 +#include "../../Compress/LZMA/LZMADecoder.h" 1.21 +static NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; 1.22 +#endif 1.23 + 1.24 +#ifdef COMPRESS_PPMD 1.25 +#include "../../Compress/PPMD/PPMDDecoder.h" 1.26 +static NArchive::N7z::CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 }; 1.27 +#endif 1.28 + 1.29 +#ifdef COMPRESS_BCJ_X86 1.30 +#include "../../Compress/Branch/x86.h" 1.31 +static NArchive::N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 }; 1.32 +#endif 1.33 + 1.34 +#ifdef COMPRESS_BCJ2 1.35 +#include "../../Compress/Branch/x86_2.h" 1.36 +static NArchive::N7z::CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 }; 1.37 +#endif 1.38 + 1.39 +#ifdef COMPRESS_DEFLATE 1.40 +#ifndef COMPRESS_DEFLATE_DECODER 1.41 +#define COMPRESS_DEFLATE_DECODER 1.42 +#endif 1.43 +#endif 1.44 + 1.45 +#ifdef COMPRESS_DEFLATE_DECODER 1.46 +#include "../../Compress/Deflate/DeflateDecoder.h" 1.47 +static NArchive::N7z::CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 }; 1.48 +#endif 1.49 + 1.50 +#ifdef COMPRESS_BZIP2 1.51 +#ifndef COMPRESS_BZIP2_DECODER 1.52 +#define COMPRESS_BZIP2_DECODER 1.53 +#endif 1.54 +#endif 1.55 + 1.56 +#ifdef COMPRESS_BZIP2_DECODER 1.57 +#include "../../Compress/BZip2/BZip2Decoder.h" 1.58 +static NArchive::N7z::CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 }; 1.59 +#endif 1.60 + 1.61 +#ifdef COMPRESS_COPY 1.62 +#include "../../Compress/Copy/CopyCoder.h" 1.63 +static NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 }; 1.64 +#endif 1.65 + 1.66 +#ifdef CRYPTO_7ZAES 1.67 +#include "../../Crypto/7zAES/7zAES.h" 1.68 +static NArchive::N7z::CMethodID k_7zAES = { { 0x6, 0xF1, 0x07, 0x01 }, 4 }; 1.69 +#endif 1.70 + 1.71 +namespace NArchive { 1.72 +namespace N7z { 1.73 + 1.74 +static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, 1.75 + CBindInfoEx &bindInfo) 1.76 +{ 1.77 + bindInfo.Clear(); 1.78 + int i; 1.79 + for (i = 0; i < folder.BindPairs.Size(); i++) 1.80 + { 1.81 + NCoderMixer2::CBindPair bindPair; 1.82 + bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; 1.83 + bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; 1.84 + bindInfo.BindPairs.Add(bindPair); 1.85 + } 1.86 + UInt32 outStreamIndex = 0; 1.87 + for (i = 0; i < folder.Coders.Size(); i++) 1.88 + { 1.89 + NCoderMixer2::CCoderStreamsInfo coderStreamsInfo; 1.90 + const CCoderInfo &coderInfo = folder.Coders[i]; 1.91 + coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; 1.92 + coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; 1.93 + bindInfo.Coders.Add(coderStreamsInfo); 1.94 + const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front(); 1.95 + bindInfo.CoderMethodIDs.Add(altCoderInfo.MethodID); 1.96 + for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) 1.97 + if (folder.FindBindPairForOutStream(outStreamIndex) < 0) 1.98 + bindInfo.OutStreams.Add(outStreamIndex); 1.99 + } 1.100 + for (i = 0; i < folder.PackStreams.Size(); i++) 1.101 + bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); 1.102 +} 1.103 + 1.104 +static bool AreCodersEqual(const NCoderMixer2::CCoderStreamsInfo &a1, 1.105 + const NCoderMixer2::CCoderStreamsInfo &a2) 1.106 +{ 1.107 + return (a1.NumInStreams == a2.NumInStreams) && 1.108 + (a1.NumOutStreams == a2.NumOutStreams); 1.109 +} 1.110 + 1.111 +static bool AreBindPairsEqual(const NCoderMixer2::CBindPair &a1, const NCoderMixer2::CBindPair &a2) 1.112 +{ 1.113 + return (a1.InIndex == a2.InIndex) && 1.114 + (a1.OutIndex == a2.OutIndex); 1.115 +} 1.116 + 1.117 +static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) 1.118 +{ 1.119 + if (a1.Coders.Size() != a2.Coders.Size()) 1.120 + return false; 1.121 + int i; 1.122 + for (i = 0; i < a1.Coders.Size(); i++) 1.123 + if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) 1.124 + return false; 1.125 + if (a1.BindPairs.Size() != a2.BindPairs.Size()) 1.126 + return false; 1.127 + for (i = 0; i < a1.BindPairs.Size(); i++) 1.128 + if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) 1.129 + return false; 1.130 + for (i = 0; i < a1.CoderMethodIDs.Size(); i++) 1.131 + if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) 1.132 + return false; 1.133 + if (a1.InStreams.Size() != a2.InStreams.Size()) 1.134 + return false; 1.135 + if (a1.OutStreams.Size() != a2.OutStreams.Size()) 1.136 + return false; 1.137 + return true; 1.138 +} 1.139 + 1.140 +CDecoder::CDecoder(bool multiThread) 1.141 +{ 1.142 + #ifndef _ST_MODE 1.143 + multiThread = true; 1.144 + #endif 1.145 + _multiThread = multiThread; 1.146 + _bindInfoExPrevIsDefinded = false; 1.147 + #ifndef EXCLUDE_COM 1.148 + LoadMethodMap(); 1.149 + #endif 1.150 +} 1.151 + 1.152 +HRESULT CDecoder::Decode(IInStream *inStream, 1.153 + UInt64 startPos, 1.154 + const UInt64 *packSizes, 1.155 + const CFolder &folderInfo, 1.156 + ISequentialOutStream *outStream, 1.157 + ICompressProgressInfo *compressProgress 1.158 + #ifndef _NO_CRYPTO 1.159 + , ICryptoGetTextPassword *getTextPassword 1.160 + #endif 1.161 + #ifdef COMPRESS_MT 1.162 + , bool mtMode, UInt32 numThreads 1.163 + #endif 1.164 + ) 1.165 +{ 1.166 + CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; 1.167 + 1.168 + CLockedInStream lockedInStream; 1.169 + lockedInStream.Init(inStream); 1.170 + 1.171 + for (int j = 0; j < folderInfo.PackStreams.Size(); j++) 1.172 + { 1.173 + CLockedSequentialInStreamImp *lockedStreamImpSpec = new 1.174 + CLockedSequentialInStreamImp; 1.175 + CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; 1.176 + lockedStreamImpSpec->Init(&lockedInStream, startPos); 1.177 + startPos += packSizes[j]; 1.178 + 1.179 + CLimitedSequentialInStream *streamSpec = new 1.180 + CLimitedSequentialInStream; 1.181 + CMyComPtr<ISequentialInStream> inStream = streamSpec; 1.182 + streamSpec->Init(lockedStreamImp, packSizes[j]); 1.183 + inStreams.Add(inStream); 1.184 + } 1.185 + 1.186 + int numCoders = folderInfo.Coders.Size(); 1.187 + 1.188 + CBindInfoEx bindInfo; 1.189 + ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); 1.190 + bool createNewCoders; 1.191 + if (!_bindInfoExPrevIsDefinded) 1.192 + createNewCoders = true; 1.193 + else 1.194 + createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); 1.195 + if (createNewCoders) 1.196 + { 1.197 + int i; 1.198 + _decoders.Clear(); 1.199 + // _decoders2.Clear(); 1.200 + 1.201 + _mixerCoder.Release(); 1.202 + 1.203 + if (_multiThread) 1.204 + { 1.205 + _mixerCoderMTSpec = new NCoderMixer2::CCoderMixer2MT; 1.206 + _mixerCoder = _mixerCoderMTSpec; 1.207 + _mixerCoderCommon = _mixerCoderMTSpec; 1.208 + } 1.209 + else 1.210 + { 1.211 + #ifdef _ST_MODE 1.212 + _mixerCoderSTSpec = new NCoderMixer2::CCoderMixer2ST; 1.213 + _mixerCoder = _mixerCoderSTSpec; 1.214 + _mixerCoderCommon = _mixerCoderSTSpec; 1.215 + #endif 1.216 + } 1.217 + _mixerCoderCommon->SetBindInfo(bindInfo); 1.218 + 1.219 + for (i = 0; i < numCoders; i++) 1.220 + { 1.221 + const CCoderInfo &coderInfo = folderInfo.Coders[i]; 1.222 + const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front(); 1.223 + #ifndef EXCLUDE_COM 1.224 + CMethodInfo methodInfo; 1.225 + if (!GetMethodInfo(altCoderInfo.MethodID, methodInfo)) 1.226 + return E_NOTIMPL; 1.227 + #endif 1.228 + 1.229 + if (coderInfo.IsSimpleCoder()) 1.230 + { 1.231 + CMyComPtr<ICompressCoder> decoder; 1.232 + CMyComPtr<ICompressFilter> filter; 1.233 + 1.234 + #ifdef COMPRESS_LZMA 1.235 + if (altCoderInfo.MethodID == k_LZMA) 1.236 + decoder = new NCompress::NLZMA::CDecoder; 1.237 + #endif 1.238 + 1.239 + #ifdef COMPRESS_PPMD 1.240 + if (altCoderInfo.MethodID == k_PPMD) 1.241 + decoder = new NCompress::NPPMD::CDecoder; 1.242 + #endif 1.243 + 1.244 + #ifdef COMPRESS_BCJ_X86 1.245 + if (altCoderInfo.MethodID == k_BCJ_X86) 1.246 + filter = new CBCJ_x86_Decoder; 1.247 + #endif 1.248 + 1.249 + #ifdef COMPRESS_DEFLATE_DECODER 1.250 + if (altCoderInfo.MethodID == k_Deflate) 1.251 + decoder = new NCompress::NDeflate::NDecoder::CCOMCoder; 1.252 + #endif 1.253 + 1.254 + #ifdef COMPRESS_BZIP2_DECODER 1.255 + if (altCoderInfo.MethodID == k_BZip2) 1.256 + decoder = new NCompress::NBZip2::CDecoder; 1.257 + #endif 1.258 + 1.259 + #ifdef COMPRESS_COPY 1.260 + if (altCoderInfo.MethodID == k_Copy) 1.261 + decoder = new NCompress::CCopyCoder; 1.262 + #endif 1.263 + 1.264 + #ifdef CRYPTO_7ZAES 1.265 + if (altCoderInfo.MethodID == k_7zAES) 1.266 + filter = new NCrypto::NSevenZ::CDecoder; 1.267 + #endif 1.268 + 1.269 + if (filter) 1.270 + { 1.271 + CFilterCoder *coderSpec = new CFilterCoder; 1.272 + decoder = coderSpec; 1.273 + coderSpec->Filter = filter; 1.274 + } 1.275 + #ifndef EXCLUDE_COM 1.276 + if (decoder == 0) 1.277 + { 1.278 + RINOK(_libraries.CreateCoderSpec(methodInfo.FilePath, 1.279 + methodInfo.Decoder, &decoder)); 1.280 + } 1.281 + #endif 1.282 + 1.283 + if (decoder == 0) 1.284 + return E_NOTIMPL; 1.285 + 1.286 + _decoders.Add((IUnknown *)decoder); 1.287 + 1.288 + if (_multiThread) 1.289 + _mixerCoderMTSpec->AddCoder(decoder); 1.290 + #ifdef _ST_MODE 1.291 + else 1.292 + _mixerCoderSTSpec->AddCoder(decoder, false); 1.293 + #endif 1.294 + } 1.295 + else 1.296 + { 1.297 + CMyComPtr<ICompressCoder2> decoder; 1.298 + 1.299 + #ifdef COMPRESS_BCJ2 1.300 + if (altCoderInfo.MethodID == k_BCJ2) 1.301 + decoder = new CBCJ2_x86_Decoder; 1.302 + #endif 1.303 + 1.304 + #ifndef EXCLUDE_COM 1.305 + if (decoder == 0) 1.306 + { 1.307 + RINOK(_libraries.CreateCoder2(methodInfo.FilePath, 1.308 + methodInfo.Decoder, &decoder)); 1.309 + } 1.310 + #endif 1.311 + 1.312 + if (decoder == 0) 1.313 + return E_NOTIMPL; 1.314 + 1.315 + _decoders.Add((IUnknown *)decoder); 1.316 + if (_multiThread) 1.317 + _mixerCoderMTSpec->AddCoder2(decoder); 1.318 + #ifdef _ST_MODE 1.319 + else 1.320 + _mixerCoderSTSpec->AddCoder2(decoder, false); 1.321 + #endif 1.322 + } 1.323 + } 1.324 + _bindInfoExPrev = bindInfo; 1.325 + _bindInfoExPrevIsDefinded = true; 1.326 + } 1.327 + int i; 1.328 + _mixerCoderCommon->ReInit(); 1.329 + 1.330 + UInt32 packStreamIndex = 0, unPackStreamIndex = 0; 1.331 + UInt32 coderIndex = 0; 1.332 + // UInt32 coder2Index = 0; 1.333 + 1.334 + for (i = 0; i < numCoders; i++) 1.335 + { 1.336 + const CCoderInfo &coderInfo = folderInfo.Coders[i]; 1.337 + const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front(); 1.338 + CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; 1.339 + 1.340 + { 1.341 + CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; 1.342 + HRESULT result = decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); 1.343 + if (setDecoderProperties) 1.344 + { 1.345 + const CByteBuffer &properties = altCoderInfo.Properties; 1.346 + size_t size = properties.GetCapacity(); 1.347 + if (size > 0xFFFFFFFF) 1.348 + return E_NOTIMPL; 1.349 + if (size > 0) 1.350 + { 1.351 + RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size)); 1.352 + } 1.353 + } 1.354 + } 1.355 + 1.356 + #ifdef COMPRESS_MT 1.357 + if (mtMode) 1.358 + { 1.359 + CMyComPtr<ICompressSetCoderMt> setCoderMt; 1.360 + decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); 1.361 + if (setCoderMt) 1.362 + { 1.363 + RINOK(setCoderMt->SetNumberOfThreads(numThreads)); 1.364 + } 1.365 + } 1.366 + #endif 1.367 + 1.368 + #ifndef _NO_CRYPTO 1.369 + { 1.370 + CMyComPtr<ICryptoSetPassword> cryptoSetPassword; 1.371 + HRESULT result = decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); 1.372 + if (cryptoSetPassword) 1.373 + { 1.374 + if (getTextPassword == 0) 1.375 + return E_FAIL; 1.376 + CMyComBSTR password; 1.377 + RINOK(getTextPassword->CryptoGetTextPassword(&password)); 1.378 + CByteBuffer buffer; 1.379 + UString unicodePassword(password); 1.380 + const UInt32 sizeInBytes = unicodePassword.Length() * 2; 1.381 + buffer.SetCapacity(sizeInBytes); 1.382 + for (int i = 0; i < unicodePassword.Length(); i++) 1.383 + { 1.384 + wchar_t c = unicodePassword[i]; 1.385 + ((Byte *)buffer)[i * 2] = (Byte)c; 1.386 + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); 1.387 + } 1.388 + RINOK(cryptoSetPassword->CryptoSetPassword( 1.389 + (const Byte *)buffer, sizeInBytes)); 1.390 + } 1.391 + } 1.392 + #endif 1.393 + 1.394 + coderIndex++; 1.395 + 1.396 + UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; 1.397 + UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; 1.398 + CRecordVector<const UInt64 *> packSizesPointers; 1.399 + CRecordVector<const UInt64 *> unPackSizesPointers; 1.400 + packSizesPointers.Reserve(numInStreams); 1.401 + unPackSizesPointers.Reserve(numOutStreams); 1.402 + UInt32 j; 1.403 + for (j = 0; j < numOutStreams; j++, unPackStreamIndex++) 1.404 + unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]); 1.405 + 1.406 + for (j = 0; j < numInStreams; j++, packStreamIndex++) 1.407 + { 1.408 + int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); 1.409 + if (bindPairIndex >= 0) 1.410 + packSizesPointers.Add( 1.411 + &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); 1.412 + else 1.413 + { 1.414 + int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); 1.415 + if (index < 0) 1.416 + return E_FAIL; 1.417 + packSizesPointers.Add(&packSizes[index]); 1.418 + } 1.419 + } 1.420 + 1.421 + _mixerCoderCommon->SetCoderInfo(i, 1.422 + &packSizesPointers.Front(), 1.423 + &unPackSizesPointers.Front()); 1.424 + } 1.425 + UInt32 mainCoder, temp; 1.426 + bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); 1.427 + 1.428 + if (_multiThread) 1.429 + _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); 1.430 + /* 1.431 + else 1.432 + _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; 1.433 + */ 1.434 + 1.435 + if (numCoders == 0) 1.436 + return 0; 1.437 + CRecordVector<ISequentialInStream *> inStreamPointers; 1.438 + inStreamPointers.Reserve(inStreams.Size()); 1.439 + for (i = 0; i < inStreams.Size(); i++) 1.440 + inStreamPointers.Add(inStreams[i]); 1.441 + ISequentialOutStream *outStreamPointer = outStream; 1.442 + return _mixerCoder->Code(&inStreamPointers.Front(), NULL, 1.443 + inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); 1.444 +} 1.445 + 1.446 +}}