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 
SetTotal(const UInt64 * files,const UInt64 * bytes)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 
SetCompleted(const UInt64 * files,const UInt64 * bytes)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 
GetProperty(PROPID propID,PROPVARIANT * value)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 
~CInFileStreamVolCInFileStreamVol70   ~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 
GetStream(const wchar_t * name,IInStream ** inStream)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
CryptoGetTextPassword(BSTR * password)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