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