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   // #ifdef _WIN32
107   // we don't want to support wildcards in names here here
108   if (name2.Find(L'?') >= 0 ||
109       name2.Find(L'*') >= 0)
110     return S_FALSE;
111   // #endif
112 
113   #endif
114 
115 
116   FString fullPath;
117   if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath))
118     return S_FALSE;
119   if (!_fileInfo.Find(fullPath))
120     return S_FALSE;
121   if (_fileInfo.IsDir())
122     return S_FALSE;
123   CInFileStreamVol *inFile = new CInFileStreamVol;
124   CMyComPtr<IInStream> inStreamTemp = inFile;
125   if (!inFile->Open(fullPath))
126   {
127     DWORD lastError = ::GetLastError();
128     if (lastError == 0)
129       return E_FAIL;
130     return HRESULT_FROM_WIN32(lastError);
131   }
132 
133   FileSizes.Add(_fileInfo.Size);
134   FileNames.Add(name2);
135   inFile->FileNameIndex = FileNames_WasUsed.Add(true);
136   inFile->OpenCallbackImp = this;
137   inFile->OpenCallbackRef = this;
138   // TotalSize += _fileInfo.Size;
139   *inStream = inStreamTemp.Detach();
140   return S_OK;
141   COM_TRY_END
142 }
143 
144 #ifndef _NO_CRYPTO
CryptoGetTextPassword(BSTR * password)145 STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
146 {
147   COM_TRY_BEGIN
148   if (ReOpenCallback)
149   {
150     CMyComPtr<ICryptoGetTextPassword> getTextPassword;
151     ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
152     if (getTextPassword)
153       return getTextPassword->CryptoGetTextPassword(password);
154   }
155   if (!Callback)
156     return E_NOTIMPL;
157   PasswordWasAsked = true;
158   return Callback->Open_CryptoGetTextPassword(password);
159   COM_TRY_END
160 }
161 #endif
162