diff src/win32/7zip/7z/CPP/7zip/Archive/7z/7zHandler.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/7z/7zHandler.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,503 @@
     1.4 +// 7zHandler.cpp
     1.5 +
     1.6 +#include "StdAfx.h"
     1.7 +
     1.8 +extern "C"
     1.9 +{
    1.10 +  #include "../../../../C/CpuArch.h"
    1.11 +}
    1.12 +
    1.13 +#include "../../../Common/ComTry.h"
    1.14 +#include "../../../Common/IntToString.h"
    1.15 +
    1.16 +#ifdef COMPRESS_MT
    1.17 +#include "../../../Windows/System.h"
    1.18 +#endif
    1.19 +
    1.20 +#include "../Common/ItemNameUtils.h"
    1.21 +
    1.22 +#include "7zHandler.h"
    1.23 +#include "7zProperties.h"
    1.24 +
    1.25 +#ifdef __7Z_SET_PROPERTIES
    1.26 +#ifdef EXTRACT_ONLY
    1.27 +#include "../Common/ParseProperties.h"
    1.28 +#endif
    1.29 +#endif
    1.30 +
    1.31 +using namespace NWindows;
    1.32 +
    1.33 +extern UString ConvertMethodIdToString(UInt64 id);
    1.34 +
    1.35 +namespace NArchive {
    1.36 +namespace N7z {
    1.37 +
    1.38 +CHandler::CHandler()
    1.39 +{
    1.40 +  _crcSize = 4;
    1.41 +
    1.42 +  #ifndef _NO_CRYPTO
    1.43 +  _passwordIsDefined = false;
    1.44 +  #endif
    1.45 +
    1.46 +  #ifdef EXTRACT_ONLY
    1.47 +  #ifdef COMPRESS_MT
    1.48 +  _numThreads = NSystem::GetNumberOfProcessors();
    1.49 +  #endif
    1.50 +  #else
    1.51 +  Init();
    1.52 +  #endif
    1.53 +}
    1.54 +
    1.55 +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
    1.56 +{
    1.57 +  *numItems = _db.Files.Size();
    1.58 +  return S_OK;
    1.59 +}
    1.60 +
    1.61 +#ifdef _SFX
    1.62 +
    1.63 +IMP_IInArchive_ArcProps_NO
    1.64 +
    1.65 +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
    1.66 +{
    1.67 +  return E_NOTIMPL;
    1.68 +}
    1.69 +
    1.70 +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
    1.71 +      BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
    1.72 +{
    1.73 +  return E_NOTIMPL;
    1.74 +}
    1.75 +
    1.76 +
    1.77 +#else
    1.78 +
    1.79 +STATPROPSTG kArcProps[] =
    1.80 +{
    1.81 +  { NULL, kpidMethod, VT_BSTR},
    1.82 +  { NULL, kpidSolid, VT_BOOL},
    1.83 +  { NULL, kpidNumBlocks, VT_UI4},
    1.84 +  { NULL, kpidPhySize, VT_UI8},
    1.85 +  { NULL, kpidHeadersSize, VT_UI8},
    1.86 +  { NULL, kpidOffset, VT_UI8}
    1.87 +};
    1.88 +
    1.89 +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
    1.90 +{
    1.91 +  COM_TRY_BEGIN
    1.92 +  NCOM::CPropVariant prop;
    1.93 +  switch(propID)
    1.94 +  {
    1.95 +    case kpidMethod:
    1.96 +    {
    1.97 +      UString resString;
    1.98 +      CRecordVector<UInt64> ids;
    1.99 +      int i;
   1.100 +      for (i = 0; i < _db.Folders.Size(); i++)
   1.101 +      {
   1.102 +        const CFolder &f = _db.Folders[i];
   1.103 +        for (int j = f.Coders.Size() - 1; j >= 0; j--)
   1.104 +          ids.AddToUniqueSorted(f.Coders[j].MethodID);
   1.105 +      }
   1.106 +
   1.107 +      for (i = 0; i < ids.Size(); i++)
   1.108 +      {
   1.109 +        UInt64 id = ids[i];
   1.110 +        UString methodName;
   1.111 +        /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
   1.112 +        if (methodName.IsEmpty())
   1.113 +          methodName = ConvertMethodIdToString(id);
   1.114 +        if (!resString.IsEmpty())
   1.115 +          resString += L' ';
   1.116 +        resString += methodName;
   1.117 +      }
   1.118 +      prop = resString;
   1.119 +      break;
   1.120 +    }
   1.121 +    case kpidSolid: prop = _db.IsSolid(); break;
   1.122 +    case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break;
   1.123 +    case kpidHeadersSize:  prop = _db.HeadersSize; break;
   1.124 +    case kpidPhySize:  prop = _db.PhySize; break;
   1.125 +    case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break;
   1.126 +  }
   1.127 +  prop.Detach(value);
   1.128 +  return S_OK;
   1.129 +  COM_TRY_END
   1.130 +}
   1.131 +
   1.132 +IMP_IInArchive_ArcProps
   1.133 +
   1.134 +#endif
   1.135 +
   1.136 +static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop)
   1.137 +{
   1.138 +  UInt64 value;
   1.139 +  if (v.GetItem(index, value))
   1.140 +  {
   1.141 +    FILETIME ft;
   1.142 +    ft.dwLowDateTime = (DWORD)value;
   1.143 +    ft.dwHighDateTime = (DWORD)(value >> 32);
   1.144 +    prop = ft;
   1.145 +  }
   1.146 +}
   1.147 +
   1.148 +#ifndef _SFX
   1.149 +
   1.150 +static UString ConvertUInt32ToString(UInt32 value)
   1.151 +{
   1.152 +  wchar_t buffer[32];
   1.153 +  ConvertUInt64ToString(value, buffer);
   1.154 +  return buffer;
   1.155 +}
   1.156 +
   1.157 +static UString GetStringForSizeValue(UInt32 value)
   1.158 +{
   1.159 +  for (int i = 31; i >= 0; i--)
   1.160 +    if ((UInt32(1) << i) == value)
   1.161 +      return ConvertUInt32ToString(i);
   1.162 +  UString result;
   1.163 +  if (value % (1 << 20) == 0)
   1.164 +  {
   1.165 +    result += ConvertUInt32ToString(value >> 20);
   1.166 +    result += L"m";
   1.167 +  }
   1.168 +  else if (value % (1 << 10) == 0)
   1.169 +  {
   1.170 +    result += ConvertUInt32ToString(value >> 10);
   1.171 +    result += L"k";
   1.172 +  }
   1.173 +  else
   1.174 +  {
   1.175 +    result += ConvertUInt32ToString(value);
   1.176 +    result += L"b";
   1.177 +  }
   1.178 +  return result;
   1.179 +}
   1.180 +
   1.181 +static const UInt64 k_Copy = 0x0;
   1.182 +static const UInt64 k_LZMA  = 0x030101;
   1.183 +static const UInt64 k_PPMD  = 0x030401;
   1.184 +
   1.185 +static wchar_t GetHex(Byte value)
   1.186 +{
   1.187 +  return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
   1.188 +}
   1.189 +static inline UString GetHex2(Byte value)
   1.190 +{
   1.191 +  UString result;
   1.192 +  result += GetHex((Byte)(value >> 4));
   1.193 +  result += GetHex((Byte)(value & 0xF));
   1.194 +  return result;
   1.195 +}
   1.196 +
   1.197 +#endif
   1.198 +
   1.199 +static const UInt64 k_AES  = 0x06F10701;
   1.200 +
   1.201 +bool CHandler::IsEncrypted(UInt32 index2) const
   1.202 +{
   1.203 +  CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
   1.204 +  if (folderIndex != kNumNoIndex)
   1.205 +  {
   1.206 +    const CFolder &folderInfo = _db.Folders[folderIndex];
   1.207 +    for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
   1.208 +      if (folderInfo.Coders[i].MethodID == k_AES)
   1.209 +        return true;
   1.210 +  }
   1.211 +  return false;
   1.212 +}
   1.213 +
   1.214 +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)
   1.215 +{
   1.216 +  COM_TRY_BEGIN
   1.217 +  NCOM::CPropVariant prop;
   1.218 +  
   1.219 +  /*
   1.220 +  const CRef2 &ref2 = _refs[index];
   1.221 +  if (ref2.Refs.IsEmpty())
   1.222 +    return E_FAIL;
   1.223 +  const CRef &ref = ref2.Refs.Front();
   1.224 +  */
   1.225 +  
   1.226 +  const CFileItem &item = _db.Files[index];
   1.227 +  UInt32 index2 = index;
   1.228 +
   1.229 +  switch(propID)
   1.230 +  {
   1.231 +    case kpidPath:
   1.232 +      if (!item.Name.IsEmpty())
   1.233 +        prop = NItemName::GetOSName(item.Name);
   1.234 +      break;
   1.235 +    case kpidIsDir:  prop = item.IsDir; break;
   1.236 +    case kpidSize:
   1.237 +    {
   1.238 +      prop = item.Size;
   1.239 +      // prop = ref2.Size;
   1.240 +      break;
   1.241 +    }
   1.242 +    case kpidPackSize:
   1.243 +    {
   1.244 +      // prop = ref2.PackSize;
   1.245 +      {
   1.246 +        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
   1.247 +        if (folderIndex != kNumNoIndex)
   1.248 +        {
   1.249 +          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
   1.250 +            prop = _db.GetFolderFullPackSize(folderIndex);
   1.251 +          /*
   1.252 +          else
   1.253 +            prop = (UInt64)0;
   1.254 +          */
   1.255 +        }
   1.256 +        else
   1.257 +          prop = (UInt64)0;
   1.258 +      }
   1.259 +      break;
   1.260 +    }
   1.261 +    case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; }
   1.262 +    case kpidCTime:  SetPropFromUInt64Def(_db.CTime, index2, prop); break;
   1.263 +    case kpidATime:  SetPropFromUInt64Def(_db.ATime, index2, prop); break;
   1.264 +    case kpidMTime:  SetPropFromUInt64Def(_db.MTime, index2, prop); break;
   1.265 +    case kpidAttrib:  if (item.AttribDefined) prop = item.Attrib; break;
   1.266 +    case kpidCRC:  if (item.CrcDefined) prop = item.Crc; break;
   1.267 +    case kpidEncrypted:  prop = IsEncrypted(index2); break;
   1.268 +    case kpidIsAnti:  prop = _db.IsItemAnti(index2); break;
   1.269 +    #ifndef _SFX
   1.270 +    case kpidMethod:
   1.271 +      {
   1.272 +        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
   1.273 +        if (folderIndex != kNumNoIndex)
   1.274 +        {
   1.275 +          const CFolder &folderInfo = _db.Folders[folderIndex];
   1.276 +          UString methodsString;
   1.277 +          for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
   1.278 +          {
   1.279 +            const CCoderInfo &coderInfo = folderInfo.Coders[i];
   1.280 +            if (!methodsString.IsEmpty())
   1.281 +              methodsString += L' ';
   1.282 +
   1.283 +            {
   1.284 +              UString methodName;
   1.285 +              bool methodIsKnown = FindMethod(
   1.286 +                  EXTERNAL_CODECS_VARS
   1.287 +                  coderInfo.MethodID, methodName);
   1.288 +
   1.289 +              if (methodIsKnown)
   1.290 +              {
   1.291 +                methodsString += methodName;
   1.292 +                if (coderInfo.MethodID == k_LZMA)
   1.293 +                {
   1.294 +                  if (coderInfo.Props.GetCapacity() >= 5)
   1.295 +                  {
   1.296 +                    methodsString += L":";
   1.297 +                    UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1);
   1.298 +                    methodsString += GetStringForSizeValue(dicSize);
   1.299 +                  }
   1.300 +                }
   1.301 +                else if (coderInfo.MethodID == k_PPMD)
   1.302 +                {
   1.303 +                  if (coderInfo.Props.GetCapacity() >= 5)
   1.304 +                  {
   1.305 +                    Byte order = *(const Byte *)coderInfo.Props;
   1.306 +                    methodsString += L":o";
   1.307 +                    methodsString += ConvertUInt32ToString(order);
   1.308 +                    methodsString += L":mem";
   1.309 +                    UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1);
   1.310 +                    methodsString += GetStringForSizeValue(dicSize);
   1.311 +                  }
   1.312 +                }
   1.313 +                else if (coderInfo.MethodID == k_AES)
   1.314 +                {
   1.315 +                  if (coderInfo.Props.GetCapacity() >= 1)
   1.316 +                  {
   1.317 +                    methodsString += L":";
   1.318 +                    const Byte *data = (const Byte *)coderInfo.Props;
   1.319 +                    Byte firstByte = *data++;
   1.320 +                    UInt32 numCyclesPower = firstByte & 0x3F;
   1.321 +                    methodsString += ConvertUInt32ToString(numCyclesPower);
   1.322 +                    /*
   1.323 +                    if ((firstByte & 0xC0) != 0)
   1.324 +                    {
   1.325 +                      methodsString += L":";
   1.326 +                      return S_OK;
   1.327 +                      UInt32 saltSize = (firstByte >> 7) & 1;
   1.328 +                      UInt32 ivSize = (firstByte >> 6) & 1;
   1.329 +                      if (coderInfo.Props.GetCapacity() >= 2)
   1.330 +                      {
   1.331 +                        Byte secondByte = *data++;
   1.332 +                        saltSize += (secondByte >> 4);
   1.333 +                        ivSize += (secondByte & 0x0F);
   1.334 +                      }
   1.335 +                    }
   1.336 +                    */
   1.337 +                  }
   1.338 +                }
   1.339 +                else
   1.340 +                {
   1.341 +                  if (coderInfo.Props.GetCapacity() > 0)
   1.342 +                  {
   1.343 +                    methodsString += L":[";
   1.344 +                    for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++)
   1.345 +                    {
   1.346 +                      if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity())
   1.347 +                      {
   1.348 +                        methodsString += L"..";
   1.349 +                        break;
   1.350 +                      }
   1.351 +                      else
   1.352 +                        methodsString += GetHex2(coderInfo.Props[bi]);
   1.353 +                    }
   1.354 +                    methodsString += L"]";
   1.355 +                  }
   1.356 +                }
   1.357 +              }
   1.358 +              else
   1.359 +              {
   1.360 +                methodsString += ConvertMethodIdToString(coderInfo.MethodID);
   1.361 +              }
   1.362 +            }
   1.363 +          }
   1.364 +          prop = methodsString;
   1.365 +        }
   1.366 +      }
   1.367 +      break;
   1.368 +    case kpidBlock:
   1.369 +      {
   1.370 +        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
   1.371 +        if (folderIndex != kNumNoIndex)
   1.372 +          prop = (UInt32)folderIndex;
   1.373 +      }
   1.374 +      break;
   1.375 +    case kpidPackedSize0:
   1.376 +    case kpidPackedSize1:
   1.377 +    case kpidPackedSize2:
   1.378 +    case kpidPackedSize3:
   1.379 +    case kpidPackedSize4:
   1.380 +      {
   1.381 +        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
   1.382 +        if (folderIndex != kNumNoIndex)
   1.383 +        {
   1.384 +          const CFolder &folderInfo = _db.Folders[folderIndex];
   1.385 +          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
   1.386 +              folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
   1.387 +          {
   1.388 +            prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
   1.389 +          }
   1.390 +          else
   1.391 +            prop = (UInt64)0;
   1.392 +        }
   1.393 +        else
   1.394 +          prop = (UInt64)0;
   1.395 +      }
   1.396 +      break;
   1.397 +    #endif
   1.398 +  }
   1.399 +  prop.Detach(value);
   1.400 +  return S_OK;
   1.401 +  COM_TRY_END
   1.402 +}
   1.403 +
   1.404 +STDMETHODIMP CHandler::Open(IInStream *stream,
   1.405 +    const UInt64 *maxCheckStartPosition,
   1.406 +    IArchiveOpenCallback *openArchiveCallback)
   1.407 +{
   1.408 +  COM_TRY_BEGIN
   1.409 +  Close();
   1.410 +  #ifndef _SFX
   1.411 +  _fileInfoPopIDs.Clear();
   1.412 +  #endif
   1.413 +  try
   1.414 +  {
   1.415 +    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
   1.416 +
   1.417 +    #ifndef _NO_CRYPTO
   1.418 +    CMyComPtr<ICryptoGetTextPassword> getTextPassword;
   1.419 +    if (openArchiveCallback)
   1.420 +    {
   1.421 +      openArchiveCallbackTemp.QueryInterface(
   1.422 +          IID_ICryptoGetTextPassword, &getTextPassword);
   1.423 +    }
   1.424 +    #endif
   1.425 +    CInArchive archive;
   1.426 +    RINOK(archive.Open(stream, maxCheckStartPosition));
   1.427 +    #ifndef _NO_CRYPTO
   1.428 +    _passwordIsDefined = false;
   1.429 +    UString password;
   1.430 +    #endif
   1.431 +    HRESULT result = archive.ReadDatabase(
   1.432 +      EXTERNAL_CODECS_VARS
   1.433 +      _db
   1.434 +      #ifndef _NO_CRYPTO
   1.435 +      , getTextPassword, _passwordIsDefined
   1.436 +      #endif
   1.437 +      );
   1.438 +    RINOK(result);
   1.439 +    _db.Fill();
   1.440 +    _inStream = stream;
   1.441 +  }
   1.442 +  catch(...)
   1.443 +  {
   1.444 +    Close();
   1.445 +    return S_FALSE;
   1.446 +  }
   1.447 +  // _inStream = stream;
   1.448 +  #ifndef _SFX
   1.449 +  FillPopIDs();
   1.450 +  #endif
   1.451 +  return S_OK;
   1.452 +  COM_TRY_END
   1.453 +}
   1.454 +
   1.455 +STDMETHODIMP CHandler::Close()
   1.456 +{
   1.457 +  COM_TRY_BEGIN
   1.458 +  _inStream.Release();
   1.459 +  _db.Clear();
   1.460 +  return S_OK;
   1.461 +  COM_TRY_END
   1.462 +}
   1.463 +
   1.464 +#ifdef __7Z_SET_PROPERTIES
   1.465 +#ifdef EXTRACT_ONLY
   1.466 +
   1.467 +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
   1.468 +{
   1.469 +  COM_TRY_BEGIN
   1.470 +  #ifdef COMPRESS_MT
   1.471 +  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
   1.472 +  _numThreads = numProcessors;
   1.473 +  #endif
   1.474 +
   1.475 +  for (int i = 0; i < numProperties; i++)
   1.476 +  {
   1.477 +    UString name = names[i];
   1.478 +    name.MakeUpper();
   1.479 +    if (name.IsEmpty())
   1.480 +      return E_INVALIDARG;
   1.481 +    const PROPVARIANT &value = values[i];
   1.482 +    UInt32 number;
   1.483 +    int index = ParseStringToUInt32(name, number);
   1.484 +    if (index == 0)
   1.485 +    {
   1.486 +      if(name.Left(2).CompareNoCase(L"MT") == 0)
   1.487 +      {
   1.488 +        #ifdef COMPRESS_MT
   1.489 +        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
   1.490 +        #endif
   1.491 +        continue;
   1.492 +      }
   1.493 +      else
   1.494 +        return E_INVALIDARG;
   1.495 +    }
   1.496 +  }
   1.497 +  return S_OK;
   1.498 +  COM_TRY_END
   1.499 +}
   1.500 +
   1.501 +#endif
   1.502 +#endif
   1.503 +
   1.504 +IMPL_ISetCompressCodecsInfo
   1.505 +
   1.506 +}}