Home | History | Annotate | Download | only in Common
      1 // ArchiveOpenCallback.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../Common/ComTry.h"
      6 
      7 #include "../../../Windows/FileName.h"
      8 #include "../../../Windows/PropVariant.h"
      9 
     10 #include "../../Common/FileStreams.h"
     11 
     12 #include "ArchiveOpenCallback.h"
     13 
     14 using namespace NWindows;
     15 
     16 STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
     17 {
     18   COM_TRY_BEGIN
     19   if (ReOpenCallback)
     20     return ReOpenCallback->SetTotal(files, bytes);
     21   if (!Callback)
     22     return S_OK;
     23   return Callback->Open_SetTotal(files, bytes);
     24   COM_TRY_END
     25 }
     26 
     27 STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
     28 {
     29   COM_TRY_BEGIN
     30   if (ReOpenCallback)
     31     return ReOpenCallback->SetCompleted(files, bytes);
     32   if (!Callback)
     33     return S_OK;
     34   return Callback->Open_SetCompleted(files, bytes);
     35   COM_TRY_END
     36 }
     37 
     38 STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
     39 {
     40   COM_TRY_BEGIN
     41   NCOM::CPropVariant prop;
     42   if (_subArchiveMode)
     43     switch (propID)
     44     {
     45       case kpidName: prop = _subArchiveName; break;
     46       // case kpidSize:  prop = _subArchiveSize; break; // we don't use it now
     47     }
     48   else
     49     switch (propID)
     50     {
     51       case kpidName:  prop = _fileInfo.Name; break;
     52       case kpidIsDir:  prop = _fileInfo.IsDir(); break;
     53       case kpidSize:  prop = _fileInfo.Size; break;
     54       case kpidAttrib:  prop = (UInt32)_fileInfo.Attrib; break;
     55       case kpidCTime:  prop = _fileInfo.CTime; break;
     56       case kpidATime:  prop = _fileInfo.ATime; break;
     57       case kpidMTime:  prop = _fileInfo.MTime; break;
     58     }
     59   prop.Detach(value);
     60   return S_OK;
     61   COM_TRY_END
     62 }
     63 
     64 struct CInFileStreamVol: public CInFileStream
     65 {
     66   int FileNameIndex;
     67   COpenCallbackImp *OpenCallbackImp;
     68   CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
     69 
     70   ~CInFileStreamVol()
     71   {
     72     if (OpenCallbackRef)
     73       OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false;
     74   }
     75 };
     76 
     77 
     78 // from ArchiveExtractCallback.cpp
     79 bool IsSafePath(const UString &path);
     80 
     81 STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
     82 {
     83   COM_TRY_BEGIN
     84   *inStream = NULL;
     85 
     86   if (_subArchiveMode)
     87     return S_FALSE;
     88   if (Callback)
     89   {
     90     RINOK(Callback->Open_CheckBreak());
     91   }
     92 
     93   UString name2 = name;
     94 
     95 
     96   #ifndef _SFX
     97 
     98   #ifdef _WIN32
     99   name2.Replace(L'/', WCHAR_PATH_SEPARATOR);
    100   #endif
    101 
    102   // if (!allowAbsVolPaths)
    103   if (!IsSafePath(name2))
    104     return S_FALSE;
    105 
    106   #endif
    107 
    108 
    109   FString fullPath;
    110   if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath))
    111     return S_FALSE;
    112   if (!_fileInfo.Find(fullPath))
    113     return S_FALSE;
    114   if (_fileInfo.IsDir())
    115     return S_FALSE;
    116   CInFileStreamVol *inFile = new CInFileStreamVol;
    117   CMyComPtr<IInStream> inStreamTemp = inFile;
    118   if (!inFile->Open(fullPath))
    119   {
    120     DWORD lastError = ::GetLastError();
    121     if (lastError == 0)
    122       return E_FAIL;
    123     return HRESULT_FROM_WIN32(lastError);
    124   }
    125 
    126   FileSizes.Add(_fileInfo.Size);
    127   FileNames.Add(name2);
    128   inFile->FileNameIndex = FileNames_WasUsed.Add(true);
    129   inFile->OpenCallbackImp = this;
    130   inFile->OpenCallbackRef = this;
    131   // TotalSize += _fileInfo.Size;
    132   *inStream = inStreamTemp.Detach();
    133   return S_OK;
    134   COM_TRY_END
    135 }
    136 
    137 #ifndef _NO_CRYPTO
    138 STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
    139 {
    140   COM_TRY_BEGIN
    141   if (ReOpenCallback)
    142   {
    143     CMyComPtr<ICryptoGetTextPassword> getTextPassword;
    144     ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
    145     if (getTextPassword)
    146       return getTextPassword->CryptoGetTextPassword(password);
    147   }
    148   if (!Callback)
    149     return E_NOTIMPL;
    150   PasswordWasAsked = true;
    151   return Callback->Open_CryptoGetTextPassword(password);
    152   COM_TRY_END
    153 }
    154 #endif
    155