other-licenses/7zstub/src/7zip/Archive/7z/7zDecode.cpp

changeset 0
6474c204b198
     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 +}}

mercurial