Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(495)

Side by Side Diff: third_party/lzma/v4_65/files/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // ArchiveExtractCallback.cpp
2
3 #include "StdAfx.h"
4
5 #include "ArchiveExtractCallback.h"
6
7 #include "Common/Wildcard.h"
8 #include "Common/StringConvert.h"
9 #include "Common/ComTry.h"
10
11 #include "Windows/FileDir.h"
12 #include "Windows/FileFind.h"
13 #include "Windows/Time.h"
14 #include "Windows/Defs.h"
15 #include "Windows/PropVariant.h"
16
17 #include "Windows/PropVariantConversions.h"
18
19 #include "../../Common/FilePathAutoRename.h"
20
21 #include "../Common/ExtractingFilePath.h"
22 #include "OpenArchive.h"
23
24 using namespace NWindows;
25
26 static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto n ame";
27 static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file ";
28 static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output fil e ";
29
30
31 void CArchiveExtractCallback::Init(
32 IInArchive *archiveHandler,
33 IFolderArchiveExtractCallback *extractCallback2,
34 bool stdOutMode,
35 const UString &directoryPath,
36 const UStringVector &removePathParts,
37 const UString &itemDefaultName,
38 const FILETIME &utcMTimeDefault,
39 UInt32 attributesDefault,
40 UInt64 packSize)
41 {
42 _stdOutMode = stdOutMode;
43 _numErrors = 0;
44 _unpTotal = 1;
45 _packTotal = packSize;
46
47 _extractCallback2 = extractCallback2;
48 _compressProgress.Release();
49 _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress );
50
51 LocalProgressSpec->Init(extractCallback2, true);
52 LocalProgressSpec->SendProgress = false;
53
54 _itemDefaultName = itemDefaultName;
55 _utcMTimeDefault = utcMTimeDefault;
56 _attributesDefault = attributesDefault;
57 _removePathParts = removePathParts;
58 _archiveHandler = archiveHandler;
59 _directoryPath = directoryPath;
60 NFile::NName::NormalizeDirPathPrefix(_directoryPath);
61 }
62
63 STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
64 {
65 COM_TRY_BEGIN
66 _unpTotal = size;
67 if (!_multiArchives && _extractCallback2)
68 return _extractCallback2->SetTotal(size);
69 return S_OK;
70 COM_TRY_END
71 }
72
73 static void NormalizeVals(UInt64 &v1, UInt64 &v2)
74 {
75 const UInt64 kMax = (UInt64)1 << 31;
76 while (v1 > kMax)
77 {
78 v1 >>= 1;
79 v2 >>= 1;
80 }
81 }
82
83 static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)
84 {
85 NormalizeVals(packTotal, unpTotal);
86 NormalizeVals(unpCur, unpTotal);
87 if (unpTotal == 0)
88 unpTotal = 1;
89 return unpCur * packTotal / unpTotal;
90 }
91
92 STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
93 {
94 COM_TRY_BEGIN
95 if (!_extractCallback2)
96 return S_OK;
97
98 if (_multiArchives)
99 {
100 if (completeValue != NULL)
101 {
102 UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _ unpTotal, _packTotal);
103 return _extractCallback2->SetCompleted(&packCur);
104 }
105 }
106 return _extractCallback2->SetCompleted(completeValue);
107 COM_TRY_END
108 }
109
110 STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U Int64 *outSize)
111 {
112 COM_TRY_BEGIN
113 return _localProgress->SetRatioInfo(inSize, outSize);
114 COM_TRY_END
115 }
116
117 void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat hParts, UString &fullPath)
118 {
119 fullPath = _directoryPath;
120 for(int i = 0; i < dirPathParts.Size(); i++)
121 {
122 if (i > 0)
123 fullPath += wchar_t(NFile::NName::kDirDelimiter);
124 fullPath += dirPathParts[i];
125 NFile::NDirectory::MyCreateDirectory(fullPath);
126 }
127 }
128
129 static UString MakePathNameFromParts(const UStringVector &parts)
130 {
131 UString result;
132 for(int i = 0; i < parts.Size(); i++)
133 {
134 if(i != 0)
135 result += wchar_t(NFile::NName::kDirDelimiter);
136 result += parts[i];
137 }
138 return result;
139 }
140
141
142 HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &fil etime, bool &filetimeIsDefined)
143 {
144 filetimeIsDefined = false;
145 NCOM::CPropVariant prop;
146 RINOK(_archiveHandler->GetProperty(index, propID, &prop));
147 if (prop.vt == VT_FILETIME)
148 {
149 filetime = prop.filetime;
150 filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);
151 }
152 else if (prop.vt != VT_EMPTY)
153 return E_FAIL;
154 return S_OK;
155 }
156
157 STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre am **outStream, Int32 askExtractMode)
158 {
159 COM_TRY_BEGIN
160 *outStream = 0;
161 _outFileStream.Release();
162
163 _encrypted = false;
164 _isSplit = false;
165 _curSize = 0;
166
167 UString fullPath;
168
169 RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath));
170 RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDir));
171
172 _filePath = fullPath;
173
174 {
175 NCOM::CPropVariant prop;
176 RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop));
177 if (prop.vt != VT_EMPTY)
178 {
179 if (prop.vt != VT_UI8)
180 return E_FAIL;
181 _position = prop.uhVal.QuadPart;
182 _isSplit = true;
183 }
184 }
185
186 RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted));
187
188 bool newFileSizeDefined;
189 UInt64 newFileSize;
190 {
191 NCOM::CPropVariant prop;
192 RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));
193 newFileSizeDefined = (prop.vt != VT_EMPTY);
194 if (newFileSizeDefined)
195 {
196 newFileSize = ConvertPropVariantToUInt64(prop);
197 _curSize = newFileSize;
198 }
199 }
200
201 if(askExtractMode == NArchive::NExtract::NAskMode::kExtract)
202 {
203 if (_stdOutMode)
204 {
205 CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;
206 *outStream = outStreamLoc.Detach();
207 return S_OK;
208 }
209
210 {
211 NCOM::CPropVariant prop;
212 RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
213 if (prop.vt == VT_EMPTY)
214 {
215 _processedFileInfo.Attributes = _attributesDefault;
216 _processedFileInfo.AttributesAreDefined = false;
217 }
218 else
219 {
220 if (prop.vt != VT_UI4)
221 return E_FAIL;
222 _processedFileInfo.Attributes = prop.ulVal;
223 _processedFileInfo.AttributesAreDefined = true;
224 }
225 }
226
227 RINOK(GetTime(index, kpidCTime, _processedFileInfo.CTime, _processedFileInfo .CTimeDefined));
228 RINOK(GetTime(index, kpidATime, _processedFileInfo.ATime, _processedFileInfo .ATimeDefined));
229 RINOK(GetTime(index, kpidMTime, _processedFileInfo.MTime, _processedFileInfo .MTimeDefined));
230
231 bool isAnti = false;
232 RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti));
233
234 UStringVector pathParts;
235 SplitPathToParts(fullPath, pathParts);
236
237 if(pathParts.IsEmpty())
238 return E_FAIL;
239 int numRemovePathParts = 0;
240 switch(_pathMode)
241 {
242 case NExtract::NPathMode::kFullPathnames:
243 break;
244 case NExtract::NPathMode::kCurrentPathnames:
245 {
246 numRemovePathParts = _removePathParts.Size();
247 if (pathParts.Size() <= numRemovePathParts)
248 return E_FAIL;
249 for (int i = 0; i < numRemovePathParts; i++)
250 if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0)
251 return E_FAIL;
252 break;
253 }
254 case NExtract::NPathMode::kNoPathnames:
255 {
256 numRemovePathParts = pathParts.Size() - 1;
257 break;
258 }
259 }
260 pathParts.Delete(0, numRemovePathParts);
261 MakeCorrectPath(pathParts);
262 UString processedPath = MakePathNameFromParts(pathParts);
263 if (!isAnti)
264 {
265 if (!_processedFileInfo.IsDir)
266 {
267 if (!pathParts.IsEmpty())
268 pathParts.DeleteBack();
269 }
270
271 if (!pathParts.IsEmpty())
272 {
273 UString fullPathNew;
274 CreateComplexDirectory(pathParts, fullPathNew);
275 if (_processedFileInfo.IsDir)
276 NFile::NDirectory::SetDirTime(fullPathNew,
277 (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInf o.CTime : NULL,
278 (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInf o.ATime : NULL,
279 (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInf o.MTime : &_utcMTimeDefault);
280 }
281 }
282
283
284 UString fullProcessedPath = _directoryPath + processedPath;
285
286 if(_processedFileInfo.IsDir)
287 {
288 _diskFilePath = fullProcessedPath;
289 if (isAnti)
290 NFile::NDirectory::MyRemoveDirectory(_diskFilePath);
291 return S_OK;
292 }
293
294 if (!_isSplit)
295 {
296 NFile::NFind::CFileInfoW fileInfo;
297 if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
298 {
299 switch(_overwriteMode)
300 {
301 case NExtract::NOverwriteMode::kSkipExisting:
302 return S_OK;
303 case NExtract::NOverwriteMode::kAskBefore:
304 {
305 Int32 overwiteResult;
306 RINOK(_extractCallback2->AskOverwrite(
307 fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath,
308 _processedFileInfo.MTimeDefined ? &_processedFileInfo.MTime : NULL ,
309 newFileSizeDefined ? &newFileSize : NULL,
310 &overwiteResult))
311
312 switch(overwiteResult)
313 {
314 case NOverwriteAnswer::kCancel:
315 return E_ABORT;
316 case NOverwriteAnswer::kNo:
317 return S_OK;
318 case NOverwriteAnswer::kNoToAll:
319 _overwriteMode = NExtract::NOverwriteMode::kSkipExisting;
320 return S_OK;
321 case NOverwriteAnswer::kYesToAll:
322 _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
323 break;
324 case NOverwriteAnswer::kYes:
325 break;
326 case NOverwriteAnswer::kAutoRename:
327 _overwriteMode = NExtract::NOverwriteMode::kAutoRename;
328 break;
329 default:
330 return E_FAIL;
331 }
332 }
333 }
334 if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)
335 {
336 if (!AutoRenamePath(fullProcessedPath))
337 {
338 UString message = UString(kCantAutoRename) + fullProcessedPath;
339 RINOK(_extractCallback2->MessageError(message));
340 return E_FAIL;
341 }
342 }
343 else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)
344 {
345 UString existPath = fullProcessedPath;
346 if (!AutoRenamePath(existPath))
347 {
348 UString message = kCantAutoRename + fullProcessedPath;
349 RINOK(_extractCallback2->MessageError(message));
350 return E_FAIL;
351 }
352 if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))
353 {
354 UString message = UString(kCantRenameFile) + fullProcessedPath;
355 RINOK(_extractCallback2->MessageError(message));
356 return E_FAIL;
357 }
358 }
359 else
360 if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
361 {
362 UString message = UString(kCantDeleteOutputFile) + fullProcessedPath;
363 RINOK(_extractCallback2->MessageError(message));
364 return S_OK;
365 // return E_FAIL;
366 }
367 }
368 }
369 if (!isAnti)
370 {
371 _outFileStreamSpec = new COutFileStream;
372 CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
373 if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: C REATE_ALWAYS))
374 {
375 // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
376 {
377 UString message = L"can not open output file " + fullProcessedPath;
378 RINOK(_extractCallback2->MessageError(message));
379 return S_OK;
380 }
381 }
382 if (_isSplit)
383 {
384 RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
385 }
386 _outFileStream = outStreamLoc;
387 *outStream = outStreamLoc.Detach();
388 }
389 _diskFilePath = fullProcessedPath;
390 }
391 else
392 {
393 *outStream = NULL;
394 }
395 return S_OK;
396 COM_TRY_END
397 }
398
399 STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
400 {
401 COM_TRY_BEGIN
402 _extractMode = false;
403 switch (askExtractMode)
404 {
405 case NArchive::NExtract::NAskMode::kExtract:
406 _extractMode = true;
407 };
408 return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDir ,
409 askExtractMode, _isSplit ? &_position: 0);
410 COM_TRY_END
411 }
412
413 STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
414 {
415 COM_TRY_BEGIN
416 switch(operationResult)
417 {
418 case NArchive::NExtract::NOperationResult::kOK:
419 case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
420 case NArchive::NExtract::NOperationResult::kCRCError:
421 case NArchive::NExtract::NOperationResult::kDataError:
422 break;
423 default:
424 _outFileStream.Release();
425 return E_FAIL;
426 }
427 if (_outFileStream != NULL)
428 {
429 _outFileStreamSpec->SetTime(
430 (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CT ime : NULL,
431 (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.AT ime : NULL,
432 (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MT ime : &_utcMTimeDefault);
433 _curSize = _outFileStreamSpec->ProcessedSize;
434 RINOK(_outFileStreamSpec->Close());
435 _outFileStream.Release();
436 }
437 UnpackSize += _curSize;
438 if (_processedFileInfo.IsDir)
439 NumFolders++;
440 else
441 NumFiles++;
442
443 if (_extractMode && _processedFileInfo.AttributesAreDefined)
444 NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Att ributes);
445 RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));
446 return S_OK;
447 COM_TRY_END
448 }
449
450 /*
451 STDMETHODIMP CArchiveExtractCallback::GetInStream(
452 const wchar_t *name, ISequentialInStream **inStream)
453 {
454 COM_TRY_BEGIN
455 CInFileStream *inFile = new CInFileStream;
456 CMyComPtr<ISequentialInStream> inStreamTemp = inFile;
457 if (!inFile->Open(_srcDirectoryPrefix + name))
458 return ::GetLastError();
459 *inStream = inStreamTemp.Detach();
460 return S_OK;
461 COM_TRY_END
462 }
463 */
464
465 STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
466 {
467 COM_TRY_BEGIN
468 if (!_cryptoGetTextPassword)
469 {
470 RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,
471 &_cryptoGetTextPassword));
472 }
473 return _cryptoGetTextPassword->CryptoGetTextPassword(password);
474 COM_TRY_END
475 }
476
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698