Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Archive/Rar/RarHandler.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/Rar/RarHandler.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,835 @@ 1.4 +// RarHandler.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "Common/ComTry.h" 1.9 +#include "Common/IntToString.h" 1.10 +#include "Common/StringConvert.h" 1.11 + 1.12 +#include "Windows/PropVariant.h" 1.13 +#include "Windows/Time.h" 1.14 + 1.15 +#include "../../IPassword.h" 1.16 + 1.17 +#include "../../Common/CreateCoder.h" 1.18 +#include "../../Common/FilterCoder.h" 1.19 +#include "../../Common/MethodId.h" 1.20 +#include "../../Common/ProgressUtils.h" 1.21 + 1.22 +#include "../../Compress/CopyCoder.h" 1.23 + 1.24 +#include "../../Crypto/Rar20Crypto.h" 1.25 +#include "../../Crypto/RarAes.h" 1.26 + 1.27 +#include "../Common/ItemNameUtils.h" 1.28 +#include "../Common/OutStreamWithCRC.h" 1.29 + 1.30 +#include "RarHandler.h" 1.31 + 1.32 +using namespace NWindows; 1.33 +using namespace NTime; 1.34 + 1.35 +namespace NArchive { 1.36 +namespace NRar { 1.37 + 1.38 +static const wchar_t *kHostOS[] = 1.39 +{ 1.40 + L"MS DOS", 1.41 + L"OS/2", 1.42 + L"Win32", 1.43 + L"Unix", 1.44 + L"Mac OS", 1.45 + L"BeOS" 1.46 +}; 1.47 + 1.48 +static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); 1.49 + 1.50 +static const wchar_t *kUnknownOS = L"Unknown"; 1.51 + 1.52 +STATPROPSTG kProps[] = 1.53 +{ 1.54 + { NULL, kpidPath, VT_BSTR}, 1.55 + { NULL, kpidIsDir, VT_BOOL}, 1.56 + { NULL, kpidSize, VT_UI8}, 1.57 + { NULL, kpidPackSize, VT_UI8}, 1.58 + { NULL, kpidMTime, VT_FILETIME}, 1.59 + { NULL, kpidCTime, VT_FILETIME}, 1.60 + { NULL, kpidATime, VT_FILETIME}, 1.61 + { NULL, kpidAttrib, VT_UI4}, 1.62 + 1.63 + { NULL, kpidEncrypted, VT_BOOL}, 1.64 + { NULL, kpidSolid, VT_BOOL}, 1.65 + { NULL, kpidCommented, VT_BOOL}, 1.66 + { NULL, kpidSplitBefore, VT_BOOL}, 1.67 + { NULL, kpidSplitAfter, VT_BOOL}, 1.68 + { NULL, kpidCRC, VT_UI4}, 1.69 + { NULL, kpidHostOS, VT_BSTR}, 1.70 + { NULL, kpidMethod, VT_BSTR}, 1.71 + { NULL, kpidUnpackVer, VT_UI1} 1.72 +}; 1.73 + 1.74 +STATPROPSTG kArcProps[] = 1.75 +{ 1.76 + { NULL, kpidSolid, VT_BOOL}, 1.77 + { NULL, kpidNumBlocks, VT_UI4}, 1.78 + // { NULL, kpidEncrypted, VT_BOOL}, 1.79 + { NULL, kpidIsVolume, VT_BOOL}, 1.80 + { NULL, kpidNumVolumes, VT_UI4}, 1.81 + { NULL, kpidPhySize, VT_UI8} 1.82 + // { NULL, kpidCommented, VT_BOOL} 1.83 +}; 1.84 + 1.85 +IMP_IInArchive_Props 1.86 +IMP_IInArchive_ArcProps 1.87 + 1.88 +UInt64 CHandler::GetPackSize(int refIndex) const 1.89 +{ 1.90 + const CRefItem &refItem = _refItems[refIndex]; 1.91 + UInt64 totalPackSize = 0; 1.92 + for (int i = 0; i < refItem.NumItems; i++) 1.93 + totalPackSize += _items[refItem.ItemIndex + i].PackSize; 1.94 + return totalPackSize; 1.95 +} 1.96 + 1.97 +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) 1.98 +{ 1.99 + // COM_TRY_BEGIN 1.100 + NWindows::NCOM::CPropVariant prop; 1.101 + switch(propID) 1.102 + { 1.103 + case kpidSolid: prop = _archiveInfo.IsSolid(); break; 1.104 + // case kpidEncrypted: prop = _archiveInfo.IsEncrypted(); break; // it's for encrypted names. 1.105 + case kpidIsVolume: prop = _archiveInfo.IsVolume(); break; 1.106 + case kpidNumVolumes: prop = (UInt32)_archives.Size(); break; 1.107 + case kpidOffset: if (_archiveInfo.StartPosition != 0) prop = _archiveInfo.StartPosition; break; 1.108 + // case kpidCommented: prop = _archiveInfo.IsCommented(); break; 1.109 + case kpidNumBlocks: 1.110 + { 1.111 + UInt32 numBlocks = 0; 1.112 + for (int i = 0; i < _refItems.Size(); i++) 1.113 + if (!IsSolid(i)) 1.114 + numBlocks++; 1.115 + prop = (UInt32)numBlocks; 1.116 + break; 1.117 + } 1.118 + } 1.119 + prop.Detach(value); 1.120 + return S_OK; 1.121 + // COM_TRY_END 1.122 +} 1.123 + 1.124 +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 1.125 +{ 1.126 + *numItems = _refItems.Size(); 1.127 + return S_OK; 1.128 +} 1.129 + 1.130 +static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result) 1.131 +{ 1.132 + if (!DosTimeToFileTime(rarTime.DosTime, result)) 1.133 + return false; 1.134 + UInt64 value = (((UInt64)result.dwHighDateTime) << 32) + result.dwLowDateTime; 1.135 + value += (UInt64)rarTime.LowSecond * 10000000; 1.136 + value += ((UInt64)rarTime.SubTime[2] << 16) + 1.137 + ((UInt64)rarTime.SubTime[1] << 8) + 1.138 + ((UInt64)rarTime.SubTime[0]); 1.139 + result.dwLowDateTime = (DWORD)value; 1.140 + result.dwHighDateTime = DWORD(value >> 32); 1.141 + return true; 1.142 +} 1.143 + 1.144 +static void RarTimeToProp(const CRarTime &rarTime, NWindows::NCOM::CPropVariant &prop) 1.145 +{ 1.146 + FILETIME localFileTime, utcFileTime; 1.147 + if (RarTimeToFileTime(rarTime, localFileTime)) 1.148 + { 1.149 + if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) 1.150 + utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; 1.151 + } 1.152 + else 1.153 + utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; 1.154 + prop = utcFileTime; 1.155 +} 1.156 + 1.157 +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) 1.158 +{ 1.159 + COM_TRY_BEGIN 1.160 + NWindows::NCOM::CPropVariant prop; 1.161 + const CRefItem &refItem = _refItems[index]; 1.162 + const CItemEx &item = _items[refItem.ItemIndex]; 1.163 + switch(propID) 1.164 + { 1.165 + case kpidPath: 1.166 + { 1.167 + UString u; 1.168 + if (item.HasUnicodeName() && !item.UnicodeName.IsEmpty()) 1.169 + u = item.UnicodeName; 1.170 + else 1.171 + u = MultiByteToUnicodeString(item.Name, CP_OEMCP); 1.172 + prop = (const wchar_t *)NItemName::WinNameToOSName(u); 1.173 + break; 1.174 + } 1.175 + case kpidIsDir: prop = item.IsDir(); break; 1.176 + case kpidSize: prop = item.Size; break; 1.177 + case kpidPackSize: prop = GetPackSize(index); break; 1.178 + case kpidMTime: RarTimeToProp(item.MTime, prop); break; 1.179 + case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break; 1.180 + case kpidATime: if (item.ATimeDefined) RarTimeToProp(item.ATime, prop); break; 1.181 + case kpidAttrib: prop = item.GetWinAttributes(); break; 1.182 + case kpidEncrypted: prop = item.IsEncrypted(); break; 1.183 + case kpidSolid: prop = IsSolid(index); break; 1.184 + case kpidCommented: prop = item.IsCommented(); break; 1.185 + case kpidSplitBefore: prop = item.IsSplitBefore(); break; 1.186 + case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break; 1.187 + case kpidCRC: 1.188 + { 1.189 + const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; 1.190 + prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC); 1.191 + break; 1.192 + } 1.193 + case kpidUnpackVer: prop = item.UnPackVersion; break; 1.194 + case kpidMethod: 1.195 + { 1.196 + UString method; 1.197 + if (item.Method >= Byte('0') && item.Method <= Byte('5')) 1.198 + { 1.199 + method = L"m"; 1.200 + wchar_t temp[32]; 1.201 + ConvertUInt64ToString(item.Method - Byte('0'), temp); 1.202 + method += temp; 1.203 + if (!item.IsDir()) 1.204 + { 1.205 + method += L":"; 1.206 + ConvertUInt64ToString(16 + item.GetDictSize(), temp); 1.207 + method += temp; 1.208 + } 1.209 + } 1.210 + else 1.211 + { 1.212 + wchar_t temp[32]; 1.213 + ConvertUInt64ToString(item.Method, temp); 1.214 + method += temp; 1.215 + } 1.216 + prop = method; 1.217 + break; 1.218 + } 1.219 + case kpidHostOS: prop = (item.HostOS < kNumHostOSes) ? (kHostOS[item.HostOS]) : kUnknownOS; break; 1.220 + } 1.221 + prop.Detach(value); 1.222 + return S_OK; 1.223 + COM_TRY_END 1.224 +} 1.225 + 1.226 +class CVolumeName 1.227 +{ 1.228 + bool _first; 1.229 + bool _newStyle; 1.230 + UString _unchangedPart; 1.231 + UString _changedPart; 1.232 + UString _afterPart; 1.233 +public: 1.234 + CVolumeName(): _newStyle(true) {}; 1.235 + 1.236 + bool InitName(const UString &name, bool newStyle) 1.237 + { 1.238 + _first = true; 1.239 + _newStyle = newStyle; 1.240 + int dotPos = name.ReverseFind('.'); 1.241 + UString basePart = name; 1.242 + if (dotPos >= 0) 1.243 + { 1.244 + UString ext = name.Mid(dotPos + 1); 1.245 + if (ext.CompareNoCase(L"rar") == 0) 1.246 + { 1.247 + _afterPart = name.Mid(dotPos); 1.248 + basePart = name.Left(dotPos); 1.249 + } 1.250 + else if (ext.CompareNoCase(L"exe") == 0) 1.251 + { 1.252 + _afterPart = L".rar"; 1.253 + basePart = name.Left(dotPos); 1.254 + } 1.255 + else if (!_newStyle) 1.256 + { 1.257 + if (ext.CompareNoCase(L"000") == 0 || ext.CompareNoCase(L"001") == 0) 1.258 + { 1.259 + _afterPart.Empty(); 1.260 + _first = false; 1.261 + _changedPart = ext; 1.262 + _unchangedPart = name.Left(dotPos + 1); 1.263 + return true; 1.264 + } 1.265 + } 1.266 + } 1.267 + 1.268 + if (!_newStyle) 1.269 + { 1.270 + _afterPart.Empty(); 1.271 + _unchangedPart = basePart + UString(L"."); 1.272 + _changedPart = L"r00"; 1.273 + return true; 1.274 + } 1.275 + 1.276 + int numLetters = 1; 1.277 + if (basePart.Right(numLetters) == L"1" || basePart.Right(numLetters) == L"0") 1.278 + { 1.279 + while (numLetters < basePart.Length()) 1.280 + { 1.281 + if (basePart[basePart.Length() - numLetters - 1] != '0') 1.282 + break; 1.283 + numLetters++; 1.284 + } 1.285 + } 1.286 + else 1.287 + return false; 1.288 + _unchangedPart = basePart.Left(basePart.Length() - numLetters); 1.289 + _changedPart = basePart.Right(numLetters); 1.290 + return true; 1.291 + } 1.292 + 1.293 + UString GetNextName() 1.294 + { 1.295 + UString newName; 1.296 + if (_newStyle || !_first) 1.297 + { 1.298 + int i; 1.299 + int numLetters = _changedPart.Length(); 1.300 + for (i = numLetters - 1; i >= 0; i--) 1.301 + { 1.302 + wchar_t c = _changedPart[i]; 1.303 + if (c == L'9') 1.304 + { 1.305 + c = L'0'; 1.306 + newName = c + newName; 1.307 + if (i == 0) 1.308 + newName = UString(L'1') + newName; 1.309 + continue; 1.310 + } 1.311 + c++; 1.312 + newName = UString(c) + newName; 1.313 + i--; 1.314 + for (; i >= 0; i--) 1.315 + newName = _changedPart[i] + newName; 1.316 + break; 1.317 + } 1.318 + _changedPart = newName; 1.319 + } 1.320 + _first = false; 1.321 + return _unchangedPart + _changedPart + _afterPart; 1.322 + } 1.323 +}; 1.324 + 1.325 +HRESULT CHandler::Open2(IInStream *stream, 1.326 + const UInt64 *maxCheckStartPosition, 1.327 + IArchiveOpenCallback *openArchiveCallback) 1.328 +{ 1.329 + { 1.330 + CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; 1.331 + CMyComPtr<ICryptoGetTextPassword> getTextPassword; 1.332 + CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; 1.333 + 1.334 + CVolumeName seqName; 1.335 + 1.336 + UInt64 totalBytes = 0; 1.337 + UInt64 curBytes = 0; 1.338 + 1.339 + if (openArchiveCallback != NULL) 1.340 + { 1.341 + openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); 1.342 + openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); 1.343 + } 1.344 + 1.345 + for (;;) 1.346 + { 1.347 + CMyComPtr<IInStream> inStream; 1.348 + if (!_archives.IsEmpty()) 1.349 + { 1.350 + if (!openVolumeCallback) 1.351 + break; 1.352 + 1.353 + if(_archives.Size() == 1) 1.354 + { 1.355 + if (!_archiveInfo.IsVolume()) 1.356 + break; 1.357 + UString baseName; 1.358 + { 1.359 + NCOM::CPropVariant prop; 1.360 + RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); 1.361 + if (prop.vt != VT_BSTR) 1.362 + break; 1.363 + baseName = prop.bstrVal; 1.364 + } 1.365 + seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName()); 1.366 + } 1.367 + 1.368 + UString fullName = seqName.GetNextName(); 1.369 + HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); 1.370 + if (result == S_FALSE) 1.371 + break; 1.372 + if (result != S_OK) 1.373 + return result; 1.374 + if (!stream) 1.375 + break; 1.376 + } 1.377 + else 1.378 + inStream = stream; 1.379 + 1.380 + UInt64 endPos = 0; 1.381 + if (openArchiveCallback != NULL) 1.382 + { 1.383 + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); 1.384 + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); 1.385 + totalBytes += endPos; 1.386 + RINOK(openArchiveCallback->SetTotal(NULL, &totalBytes)); 1.387 + } 1.388 + 1.389 + NArchive::NRar::CInArchive archive; 1.390 + RINOK(archive.Open(inStream, maxCheckStartPosition)); 1.391 + 1.392 + if (_archives.IsEmpty()) 1.393 + archive.GetArchiveInfo(_archiveInfo); 1.394 + 1.395 + CItemEx item; 1.396 + for (;;) 1.397 + { 1.398 + HRESULT result = archive.GetNextItem(item, getTextPassword); 1.399 + if (result == S_FALSE) 1.400 + break; 1.401 + RINOK(result); 1.402 + if (item.IgnoreItem()) 1.403 + continue; 1.404 + 1.405 + bool needAdd = true; 1.406 + if (item.IsSplitBefore()) 1.407 + { 1.408 + if (!_refItems.IsEmpty()) 1.409 + { 1.410 + CRefItem &refItem = _refItems.Back(); 1.411 + refItem.NumItems++; 1.412 + needAdd = false; 1.413 + } 1.414 + } 1.415 + if (needAdd) 1.416 + { 1.417 + CRefItem refItem; 1.418 + refItem.ItemIndex = _items.Size(); 1.419 + refItem.NumItems = 1; 1.420 + refItem.VolumeIndex = _archives.Size(); 1.421 + _refItems.Add(refItem); 1.422 + } 1.423 + _items.Add(item); 1.424 + if (openArchiveCallback != NULL && _items.Size() % 100 == 0) 1.425 + { 1.426 + UInt64 numFiles = _items.Size(); 1.427 + UInt64 numBytes = curBytes + item.Position; 1.428 + RINOK(openArchiveCallback->SetCompleted(&numFiles, &numBytes)); 1.429 + } 1.430 + } 1.431 + curBytes += endPos; 1.432 + _archives.Add(archive); 1.433 + } 1.434 + } 1.435 + return S_OK; 1.436 +} 1.437 + 1.438 +STDMETHODIMP CHandler::Open(IInStream *stream, 1.439 + const UInt64 *maxCheckStartPosition, 1.440 + IArchiveOpenCallback *openArchiveCallback) 1.441 +{ 1.442 + COM_TRY_BEGIN 1.443 + Close(); 1.444 + try 1.445 + { 1.446 + HRESULT res = Open2(stream, maxCheckStartPosition, openArchiveCallback); 1.447 + if (res != S_OK) 1.448 + Close(); 1.449 + return res; 1.450 + } 1.451 + catch(const CInArchiveException &) { Close(); return S_FALSE; } 1.452 + catch(...) { Close(); throw; } 1.453 + COM_TRY_END 1.454 +} 1.455 + 1.456 +STDMETHODIMP CHandler::Close() 1.457 +{ 1.458 + COM_TRY_BEGIN 1.459 + _refItems.Clear(); 1.460 + _items.Clear(); 1.461 + _archives.Clear(); 1.462 + return S_OK; 1.463 + COM_TRY_END 1.464 +} 1.465 + 1.466 +struct CMethodItem 1.467 +{ 1.468 + Byte RarUnPackVersion; 1.469 + CMyComPtr<ICompressCoder> Coder; 1.470 +}; 1.471 + 1.472 + 1.473 +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, 1.474 + Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) 1.475 +{ 1.476 + COM_TRY_BEGIN 1.477 + CMyComPtr<ICryptoGetTextPassword> getTextPassword; 1.478 + bool testMode = (_aTestMode != 0); 1.479 + CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; 1.480 + UInt64 censoredTotalUnPacked = 0, 1.481 + // censoredTotalPacked = 0, 1.482 + importantTotalUnPacked = 0; 1.483 + // importantTotalPacked = 0; 1.484 + bool allFilesMode = (numItems == UInt32(-1)); 1.485 + if (allFilesMode) 1.486 + numItems = _refItems.Size(); 1.487 + if(numItems == 0) 1.488 + return S_OK; 1.489 + int lastIndex = 0; 1.490 + CRecordVector<int> importantIndexes; 1.491 + CRecordVector<bool> extractStatuses; 1.492 + 1.493 + for(UInt32 t = 0; t < numItems; t++) 1.494 + { 1.495 + int index = allFilesMode ? t : indices[t]; 1.496 + const CRefItem &refItem = _refItems[index]; 1.497 + const CItemEx &item = _items[refItem.ItemIndex]; 1.498 + censoredTotalUnPacked += item.Size; 1.499 + // censoredTotalPacked += item.PackSize; 1.500 + int j; 1.501 + for(j = lastIndex; j <= index; j++) 1.502 + // if(!_items[_refItems[j].ItemIndex].IsSolid()) 1.503 + if(!IsSolid(j)) 1.504 + lastIndex = j; 1.505 + for(j = lastIndex; j <= index; j++) 1.506 + { 1.507 + const CRefItem &refItem = _refItems[j]; 1.508 + const CItemEx &item = _items[refItem.ItemIndex]; 1.509 + 1.510 + // const CItemEx &item = _items[j]; 1.511 + 1.512 + importantTotalUnPacked += item.Size; 1.513 + // importantTotalPacked += item.PackSize; 1.514 + importantIndexes.Add(j); 1.515 + extractStatuses.Add(j == index); 1.516 + } 1.517 + lastIndex = index + 1; 1.518 + } 1.519 + 1.520 + extractCallback->SetTotal(importantTotalUnPacked); 1.521 + UInt64 currentImportantTotalUnPacked = 0; 1.522 + UInt64 currentImportantTotalPacked = 0; 1.523 + UInt64 currentUnPackSize, currentPackSize; 1.524 + 1.525 + CObjectVector<CMethodItem> methodItems; 1.526 + 1.527 + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 1.528 + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 1.529 + 1.530 + CFilterCoder *filterStreamSpec = new CFilterCoder; 1.531 + CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec; 1.532 + 1.533 + NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL; 1.534 + CMyComPtr<ICompressFilter> rar20CryptoDecoder; 1.535 + NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL; 1.536 + CMyComPtr<ICompressFilter> rar29CryptoDecoder; 1.537 + 1.538 + CFolderInStream *folderInStreamSpec = NULL; 1.539 + CMyComPtr<ISequentialInStream> folderInStream; 1.540 + 1.541 + CLocalProgress *lps = new CLocalProgress; 1.542 + CMyComPtr<ICompressProgressInfo> progress = lps; 1.543 + lps->Init(extractCallback, false); 1.544 + 1.545 + bool solidStart = true; 1.546 + for(int i = 0; i < importantIndexes.Size(); i++, 1.547 + currentImportantTotalUnPacked += currentUnPackSize, 1.548 + currentImportantTotalPacked += currentPackSize) 1.549 + { 1.550 + lps->InSize = currentImportantTotalPacked; 1.551 + lps->OutSize = currentImportantTotalUnPacked; 1.552 + RINOK(lps->SetCur()); 1.553 + CMyComPtr<ISequentialOutStream> realOutStream; 1.554 + 1.555 + Int32 askMode; 1.556 + if(extractStatuses[i]) 1.557 + askMode = testMode ? 1.558 + NArchive::NExtract::NAskMode::kTest : 1.559 + NArchive::NExtract::NAskMode::kExtract; 1.560 + else 1.561 + askMode = NArchive::NExtract::NAskMode::kSkip; 1.562 + 1.563 + UInt32 index = importantIndexes[i]; 1.564 + 1.565 + const CRefItem &refItem = _refItems[index]; 1.566 + const CItemEx &item = _items[refItem.ItemIndex]; 1.567 + 1.568 + currentUnPackSize = item.Size; 1.569 + 1.570 + currentPackSize = GetPackSize(index); 1.571 + 1.572 + if(item.IgnoreItem()) 1.573 + continue; 1.574 + 1.575 + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); 1.576 + 1.577 + if (!IsSolid(index)) 1.578 + solidStart = true; 1.579 + if(item.IsDir()) 1.580 + { 1.581 + RINOK(extractCallback->PrepareOperation(askMode)); 1.582 + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); 1.583 + continue; 1.584 + } 1.585 + 1.586 + bool mustBeProcessedAnywhere = false; 1.587 + if(i < importantIndexes.Size() - 1) 1.588 + { 1.589 + // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]]; 1.590 + // const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex]; 1.591 + // mustBeProcessedAnywhere = nextItemInfo.IsSolid(); 1.592 + mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]); 1.593 + } 1.594 + 1.595 + if (!mustBeProcessedAnywhere && !testMode && !realOutStream) 1.596 + continue; 1.597 + 1.598 + if (!realOutStream && !testMode) 1.599 + askMode = NArchive::NExtract::NAskMode::kSkip; 1.600 + 1.601 + RINOK(extractCallback->PrepareOperation(askMode)); 1.602 + 1.603 + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; 1.604 + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 1.605 + outStreamSpec->SetStream(realOutStream); 1.606 + outStreamSpec->Init(); 1.607 + realOutStream.Release(); 1.608 + 1.609 + /* 1.610 + for (int partIndex = 0; partIndex < 1; partIndex++) 1.611 + { 1.612 + CMyComPtr<ISequentialInStream> inStream; 1.613 + 1.614 + // item redefinition 1.615 + const CItemEx &item = _items[refItem.ItemIndex + partIndex]; 1.616 + 1.617 + NArchive::NRar::CInArchive &archive = _archives[refItem.VolumeIndex + partIndex]; 1.618 + 1.619 + inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(), 1.620 + item.PackSize)); 1.621 + */ 1.622 + if (!folderInStream) 1.623 + { 1.624 + folderInStreamSpec = new CFolderInStream; 1.625 + folderInStream = folderInStreamSpec; 1.626 + } 1.627 + 1.628 + folderInStreamSpec->Init(&_archives, &_items, refItem); 1.629 + 1.630 + UInt64 packSize = currentPackSize; 1.631 + 1.632 + // packedPos += item.PackSize; 1.633 + // unpackedPos += 0; 1.634 + 1.635 + CMyComPtr<ISequentialInStream> inStream; 1.636 + if (item.IsEncrypted()) 1.637 + { 1.638 + CMyComPtr<ICryptoSetPassword> cryptoSetPassword; 1.639 + if (item.UnPackVersion >= 29) 1.640 + { 1.641 + if (!rar29CryptoDecoder) 1.642 + { 1.643 + rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder; 1.644 + rar29CryptoDecoder = rar29CryptoDecoderSpec; 1.645 + // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder)); 1.646 + } 1.647 + rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36); 1.648 + CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties; 1.649 + RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, 1.650 + &cryptoProperties)); 1.651 + RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)); 1.652 + filterStreamSpec->Filter = rar29CryptoDecoder; 1.653 + } 1.654 + else if (item.UnPackVersion >= 20) 1.655 + { 1.656 + if (!rar20CryptoDecoder) 1.657 + { 1.658 + rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder; 1.659 + rar20CryptoDecoder = rar20CryptoDecoderSpec; 1.660 + // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder)); 1.661 + } 1.662 + filterStreamSpec->Filter = rar20CryptoDecoder; 1.663 + } 1.664 + else 1.665 + { 1.666 + outStream.Release(); 1.667 + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); 1.668 + continue; 1.669 + } 1.670 + RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, 1.671 + &cryptoSetPassword)); 1.672 + 1.673 + if (!getTextPassword) 1.674 + extractCallback.QueryInterface(IID_ICryptoGetTextPassword, 1.675 + &getTextPassword); 1.676 + if (getTextPassword) 1.677 + { 1.678 + CMyComBSTR password; 1.679 + RINOK(getTextPassword->CryptoGetTextPassword(&password)); 1.680 + if (item.UnPackVersion >= 29) 1.681 + { 1.682 + CByteBuffer buffer; 1.683 + UString unicodePassword(password); 1.684 + const UInt32 sizeInBytes = unicodePassword.Length() * 2; 1.685 + buffer.SetCapacity(sizeInBytes); 1.686 + for (int i = 0; i < unicodePassword.Length(); i++) 1.687 + { 1.688 + wchar_t c = unicodePassword[i]; 1.689 + ((Byte *)buffer)[i * 2] = (Byte)c; 1.690 + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); 1.691 + } 1.692 + RINOK(cryptoSetPassword->CryptoSetPassword( 1.693 + (const Byte *)buffer, sizeInBytes)); 1.694 + } 1.695 + else 1.696 + { 1.697 + AString oemPassword = UnicodeStringToMultiByte( 1.698 + (const wchar_t *)password, CP_OEMCP); 1.699 + RINOK(cryptoSetPassword->CryptoSetPassword( 1.700 + (const Byte *)(const char *)oemPassword, oemPassword.Length())); 1.701 + } 1.702 + } 1.703 + else 1.704 + { 1.705 + RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); 1.706 + } 1.707 + filterStreamSpec->SetInStream(folderInStream); 1.708 + inStream = filterStream; 1.709 + } 1.710 + else 1.711 + { 1.712 + inStream = folderInStream; 1.713 + } 1.714 + CMyComPtr<ICompressCoder> commonCoder; 1.715 + switch(item.Method) 1.716 + { 1.717 + case '0': 1.718 + { 1.719 + commonCoder = copyCoder; 1.720 + break; 1.721 + } 1.722 + case '1': 1.723 + case '2': 1.724 + case '3': 1.725 + case '4': 1.726 + case '5': 1.727 + { 1.728 + /* 1.729 + if (item.UnPackVersion >= 29) 1.730 + { 1.731 + outStream.Release(); 1.732 + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); 1.733 + continue; 1.734 + } 1.735 + */ 1.736 + int m; 1.737 + for (m = 0; m < methodItems.Size(); m++) 1.738 + if (methodItems[m].RarUnPackVersion == item.UnPackVersion) 1.739 + break; 1.740 + if (m == methodItems.Size()) 1.741 + { 1.742 + CMethodItem mi; 1.743 + mi.RarUnPackVersion = item.UnPackVersion; 1.744 + 1.745 + mi.Coder.Release(); 1.746 + if (item.UnPackVersion <= 30) 1.747 + { 1.748 + UInt32 methodID = 0x040300; 1.749 + if (item.UnPackVersion < 20) 1.750 + methodID += 1; 1.751 + else if (item.UnPackVersion < 29) 1.752 + methodID += 2; 1.753 + else 1.754 + methodID += 3; 1.755 + RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false)); 1.756 + } 1.757 + 1.758 + if (mi.Coder == 0) 1.759 + { 1.760 + outStream.Release(); 1.761 + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); 1.762 + continue; 1.763 + } 1.764 + 1.765 + m = methodItems.Add(mi); 1.766 + } 1.767 + CMyComPtr<ICompressCoder> decoder = methodItems[m].Coder; 1.768 + 1.769 + CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; 1.770 + RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2, 1.771 + &compressSetDecoderProperties)); 1.772 + 1.773 + Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0); 1.774 + if (solidStart) 1.775 + { 1.776 + isSolid = false; 1.777 + solidStart = false; 1.778 + } 1.779 + 1.780 + 1.781 + RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1)); 1.782 + 1.783 + commonCoder = decoder; 1.784 + break; 1.785 + } 1.786 + default: 1.787 + outStream.Release(); 1.788 + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); 1.789 + continue; 1.790 + } 1.791 + HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress); 1.792 + if (item.IsEncrypted()) 1.793 + filterStreamSpec->ReleaseInStream(); 1.794 + if (result == S_FALSE) 1.795 + { 1.796 + outStream.Release(); 1.797 + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError)); 1.798 + continue; 1.799 + } 1.800 + if (result != S_OK) 1.801 + return result; 1.802 + 1.803 + /* 1.804 + if (refItem.NumItems == 1 && 1.805 + !item.IsSplitBefore() && !item.IsSplitAfter()) 1.806 + */ 1.807 + { 1.808 + const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; 1.809 + bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC; 1.810 + outStream.Release(); 1.811 + RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK: 1.812 + NArchive::NExtract::NOperationResult::kCRCError)); 1.813 + } 1.814 + /* 1.815 + else 1.816 + { 1.817 + bool crcOK = true; 1.818 + for (int partIndex = 0; partIndex < refItem.NumItems; partIndex++) 1.819 + { 1.820 + const CItemEx &item = _items[refItem.ItemIndex + partIndex]; 1.821 + if (item.FileCRC != folderInStreamSpec->CRCs[partIndex]) 1.822 + { 1.823 + crcOK = false; 1.824 + break; 1.825 + } 1.826 + } 1.827 + RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK: 1.828 + NArchive::NExtract::NOperationResult::kCRCError)); 1.829 + } 1.830 + */ 1.831 + } 1.832 + return S_OK; 1.833 + COM_TRY_END 1.834 +} 1.835 + 1.836 +IMPL_ISetCompressCodecsInfo 1.837 + 1.838 +}}