1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/7zstub/src/7zip/UI/Common/OpenArchive.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,528 @@ 1.4 +// OpenArchive.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "OpenArchive.h" 1.9 + 1.10 +#include "Common/Wildcard.h" 1.11 + 1.12 +#include "Windows/FileName.h" 1.13 +#include "Windows/FileDir.h" 1.14 +#include "Windows/Defs.h" 1.15 +#include "Windows/PropVariant.h" 1.16 + 1.17 +#include "../../Common/FileStreams.h" 1.18 +#include "../../Common/StreamUtils.h" 1.19 + 1.20 +#include "Common/StringConvert.h" 1.21 + 1.22 +#ifdef FORMAT_7Z 1.23 +#include "../../Archive/7z/7zHandler.h" 1.24 +#endif 1.25 + 1.26 +#ifdef FORMAT_BZIP2 1.27 +#include "../../Archive/BZip2/BZip2Handler.h" 1.28 +#endif 1.29 + 1.30 +#ifdef FORMAT_GZIP 1.31 +#include "../../Archive/GZip/GZipHandler.h" 1.32 +#endif 1.33 + 1.34 +#ifdef FORMAT_SPLIT 1.35 +#include "../../Archive/Split/SplitHandler.h" 1.36 +#endif 1.37 + 1.38 +#ifdef FORMAT_TAR 1.39 +#include "../../Archive/Tar/TarHandler.h" 1.40 +#endif 1.41 + 1.42 +#ifdef FORMAT_ZIP 1.43 +#include "../../Archive/Zip/ZipHandler.h" 1.44 +#endif 1.45 + 1.46 +#ifdef FORMAT_Z 1.47 +#include "../../Archive/Z/ZHandler.h" 1.48 +#endif 1.49 + 1.50 +#ifndef EXCLUDE_COM 1.51 +#include "HandlerLoader.h" 1.52 +#endif 1.53 + 1.54 +#include "DefaultName.h" 1.55 + 1.56 +using namespace NWindows; 1.57 + 1.58 +HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) 1.59 +{ 1.60 + NCOM::CPropVariant prop; 1.61 + RINOK(archive->GetProperty(index, kpidPath, &prop)); 1.62 + if(prop.vt == VT_BSTR) 1.63 + result = prop.bstrVal; 1.64 + else if (prop.vt == VT_EMPTY) 1.65 + result.Empty(); 1.66 + else 1.67 + return E_FAIL; 1.68 + return S_OK; 1.69 +} 1.70 + 1.71 +HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) 1.72 +{ 1.73 + RINOK(GetArchiveItemPath(archive, index, result)); 1.74 + if (result.IsEmpty()) 1.75 + result = defaultName; 1.76 + return S_OK; 1.77 +} 1.78 + 1.79 +HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, 1.80 + const FILETIME &defaultFileTime, FILETIME &fileTime) 1.81 +{ 1.82 + NCOM::CPropVariant prop; 1.83 + RINOK(archive->GetProperty(index, kpidLastWriteTime, &prop)); 1.84 + if (prop.vt == VT_FILETIME) 1.85 + fileTime = prop.filetime; 1.86 + else if (prop.vt == VT_EMPTY) 1.87 + fileTime = defaultFileTime; 1.88 + else 1.89 + return E_FAIL; 1.90 + return S_OK; 1.91 +} 1.92 + 1.93 +static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) 1.94 +{ 1.95 + NCOM::CPropVariant prop; 1.96 + RINOK(archive->GetProperty(index, propID, &prop)); 1.97 + if(prop.vt == VT_BOOL) 1.98 + result = VARIANT_BOOLToBool(prop.boolVal); 1.99 + else if (prop.vt == VT_EMPTY) 1.100 + result = false; 1.101 + else 1.102 + return E_FAIL; 1.103 + return S_OK; 1.104 +} 1.105 + 1.106 +HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) 1.107 +{ 1.108 + return IsArchiveItemProp(archive, index, kpidIsFolder, result); 1.109 +} 1.110 + 1.111 +HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) 1.112 +{ 1.113 + return IsArchiveItemProp(archive, index, kpidIsAnti, result); 1.114 +} 1.115 + 1.116 +// Static-SFX (for Linux) can be big 1.117 +const UInt64 kMaxCheckStartPosition = 1.118 +#ifdef _WIN32 1.119 +1 << 20; 1.120 +#else 1.121 +1 << 22; 1.122 +#endif 1.123 + 1.124 + 1.125 +HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName) 1.126 +{ 1.127 + CInFileStream *inStreamSpec = new CInFileStream; 1.128 + CMyComPtr<IInStream> inStream(inStreamSpec); 1.129 + inStreamSpec->Open(fileName); 1.130 + return archive->Open(inStream, &kMaxCheckStartPosition, NULL); 1.131 +} 1.132 + 1.133 +#ifndef _SFX 1.134 +static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) 1.135 +{ 1.136 + for (size_t i = 0; i < size; i++) 1.137 + if (p1[i] != p2[i]) 1.138 + return false; 1.139 + return true; 1.140 +} 1.141 +#endif 1.142 + 1.143 +HRESULT OpenArchive( 1.144 + IInStream *inStream, 1.145 + const UString &fileName, 1.146 + #ifndef EXCLUDE_COM 1.147 + HMODULE *module, 1.148 + #endif 1.149 + IInArchive **archiveResult, 1.150 + CArchiverInfo &archiverInfoResult, 1.151 + UString &defaultItemName, 1.152 + IArchiveOpenCallback *openArchiveCallback) 1.153 +{ 1.154 + *archiveResult = NULL; 1.155 + CObjectVector<CArchiverInfo> archiverInfoList; 1.156 + ReadArchiverInfoList(archiverInfoList); 1.157 + UString extension; 1.158 + { 1.159 + int dotPos = fileName.ReverseFind(L'.'); 1.160 + if (dotPos >= 0) 1.161 + extension = fileName.Mid(dotPos + 1); 1.162 + } 1.163 + CIntVector orderIndices; 1.164 + int i; 1.165 + bool finded = false; 1.166 + for(i = 0; i < archiverInfoList.Size(); i++) 1.167 + { 1.168 + if (archiverInfoList[i].FindExtension(extension) >= 0) 1.169 + { 1.170 + orderIndices.Insert(0, i); 1.171 + finded = true; 1.172 + } 1.173 + else 1.174 + orderIndices.Add(i); 1.175 + } 1.176 + 1.177 + #ifndef _SFX 1.178 + if (!finded) 1.179 + { 1.180 + CByteBuffer byteBuffer; 1.181 + const UInt32 kBufferSize = (200 << 10); 1.182 + byteBuffer.SetCapacity(kBufferSize); 1.183 + Byte *buffer = byteBuffer; 1.184 + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); 1.185 + UInt32 processedSize; 1.186 + RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); 1.187 + int numFinded = 0; 1.188 + for (int pos = (int)processedSize; pos >= 0 ; pos--) 1.189 + { 1.190 + for(int i = numFinded; i < orderIndices.Size(); i++) 1.191 + { 1.192 + int index = orderIndices[i]; 1.193 + const CArchiverInfo &ai = archiverInfoList[index]; 1.194 + const CByteBuffer &sig = ai.StartSignature; 1.195 + if (sig.GetCapacity() == 0) 1.196 + continue; 1.197 + if (pos + sig.GetCapacity() > processedSize) 1.198 + continue; 1.199 + if (TestSignature(buffer + pos, sig, sig.GetCapacity())) 1.200 + { 1.201 + orderIndices.Delete(i); 1.202 + orderIndices.Insert(0, index); 1.203 + numFinded++; 1.204 + } 1.205 + } 1.206 + } 1.207 + } 1.208 + #endif 1.209 + 1.210 + HRESULT badResult = S_OK; 1.211 + for(i = 0; i < orderIndices.Size(); i++) 1.212 + { 1.213 + inStream->Seek(0, STREAM_SEEK_SET, NULL); 1.214 + const CArchiverInfo &archiverInfo = archiverInfoList[orderIndices[i]]; 1.215 + #ifndef EXCLUDE_COM 1.216 + CHandlerLoader loader; 1.217 + #endif 1.218 + CMyComPtr<IInArchive> archive; 1.219 + 1.220 + #ifdef FORMAT_7Z 1.221 + if (archiverInfo.Name.CompareNoCase(L"7z") == 0) 1.222 + archive = new NArchive::N7z::CHandler; 1.223 + #endif 1.224 + 1.225 + #ifdef FORMAT_BZIP2 1.226 + if (archiverInfo.Name.CompareNoCase(L"BZip2") == 0) 1.227 + archive = new NArchive::NBZip2::CHandler; 1.228 + #endif 1.229 + 1.230 + #ifdef FORMAT_GZIP 1.231 + if (archiverInfo.Name.CompareNoCase(L"GZip") == 0) 1.232 + archive = new NArchive::NGZip::CHandler; 1.233 + #endif 1.234 + 1.235 + #ifdef FORMAT_SPLIT 1.236 + if (archiverInfo.Name.CompareNoCase(L"Split") == 0) 1.237 + archive = new NArchive::NSplit::CHandler; 1.238 + #endif 1.239 + 1.240 + #ifdef FORMAT_TAR 1.241 + if (archiverInfo.Name.CompareNoCase(L"Tar") == 0) 1.242 + archive = new NArchive::NTar::CHandler; 1.243 + #endif 1.244 + 1.245 + #ifdef FORMAT_ZIP 1.246 + if (archiverInfo.Name.CompareNoCase(L"Zip") == 0) 1.247 + archive = new NArchive::NZip::CHandler; 1.248 + #endif 1.249 + 1.250 + #ifdef FORMAT_Z 1.251 + if (archiverInfo.Name.CompareNoCase(L"Z") == 0) 1.252 + archive = new NArchive::NZ::CHandler; 1.253 + #endif 1.254 + 1.255 + 1.256 + #ifndef EXCLUDE_COM 1.257 + if (!archive) 1.258 + { 1.259 + HRESULT result = loader.CreateHandler(archiverInfo.FilePath, 1.260 + archiverInfo.ClassID, (void **)&archive, false); 1.261 + if (result != S_OK) 1.262 + continue; 1.263 + } 1.264 + #endif 1.265 + 1.266 + if (!archive) 1.267 + return E_FAIL; 1.268 + 1.269 + HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); 1.270 + if(result == S_FALSE) 1.271 + continue; 1.272 + if(result != S_OK) 1.273 + { 1.274 + badResult = result; 1.275 + if(result == E_ABORT) 1.276 + break; 1.277 + continue; 1.278 + } 1.279 + *archiveResult = archive.Detach(); 1.280 + #ifndef EXCLUDE_COM 1.281 + *module = loader.Detach(); 1.282 + #endif 1.283 + archiverInfoResult = archiverInfo; 1.284 + int subExtIndex = archiverInfo.FindExtension(extension); 1.285 + if (subExtIndex < 0) 1.286 + subExtIndex = 0; 1.287 + defaultItemName = GetDefaultName2(fileName, 1.288 + archiverInfo.Extensions[subExtIndex].Ext, 1.289 + archiverInfo.Extensions[subExtIndex].AddExt); 1.290 + 1.291 + return S_OK; 1.292 + } 1.293 + if (badResult != S_OK) 1.294 + return badResult; 1.295 + return S_FALSE; 1.296 +} 1.297 + 1.298 +HRESULT OpenArchive(const UString &filePath, 1.299 + #ifndef EXCLUDE_COM 1.300 + HMODULE *module, 1.301 + #endif 1.302 + IInArchive **archiveResult, 1.303 + CArchiverInfo &archiverInfo, 1.304 + UString &defaultItemName, 1.305 + IArchiveOpenCallback *openArchiveCallback) 1.306 +{ 1.307 + CInFileStream *inStreamSpec = new CInFileStream; 1.308 + CMyComPtr<IInStream> inStream(inStreamSpec); 1.309 + if (!inStreamSpec->Open(filePath)) 1.310 + return GetLastError(); 1.311 + return OpenArchive(inStream, ExtractFileNameFromPath(filePath), 1.312 + #ifndef EXCLUDE_COM 1.313 + module, 1.314 + #endif 1.315 + archiveResult, archiverInfo, 1.316 + defaultItemName, openArchiveCallback); 1.317 +} 1.318 + 1.319 +static void MakeDefaultName(UString &name) 1.320 +{ 1.321 + int dotPos = name.ReverseFind(L'.'); 1.322 + if (dotPos < 0) 1.323 + return; 1.324 + UString ext = name.Mid(dotPos + 1); 1.325 + if (ext.IsEmpty()) 1.326 + return; 1.327 + for (int pos = 0; pos < ext.Length(); pos++) 1.328 + if (ext[pos] < L'0' || ext[pos] > L'9') 1.329 + return; 1.330 + name = name.Left(dotPos); 1.331 +} 1.332 + 1.333 +HRESULT OpenArchive(const UString &fileName, 1.334 + #ifndef EXCLUDE_COM 1.335 + HMODULE *module0, 1.336 + HMODULE *module1, 1.337 + #endif 1.338 + IInArchive **archive0, 1.339 + IInArchive **archive1, 1.340 + CArchiverInfo &archiverInfo0, 1.341 + CArchiverInfo &archiverInfo1, 1.342 + UString &defaultItemName0, 1.343 + UString &defaultItemName1, 1.344 + IArchiveOpenCallback *openArchiveCallback) 1.345 +{ 1.346 + HRESULT result = OpenArchive(fileName, 1.347 + #ifndef EXCLUDE_COM 1.348 + module0, 1.349 + #endif 1.350 + archive0, archiverInfo0, defaultItemName0, openArchiveCallback); 1.351 + RINOK(result); 1.352 + CMyComPtr<IInArchiveGetStream> getStream; 1.353 + result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); 1.354 + if (result != S_OK || getStream == 0) 1.355 + return S_OK; 1.356 + 1.357 + CMyComPtr<ISequentialInStream> subSeqStream; 1.358 + result = getStream->GetStream(0, &subSeqStream); 1.359 + if (result != S_OK) 1.360 + return S_OK; 1.361 + 1.362 + CMyComPtr<IInStream> subStream; 1.363 + if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK) 1.364 + return S_OK; 1.365 + if (!subStream) 1.366 + return S_OK; 1.367 + 1.368 + UInt32 numItems; 1.369 + RINOK((*archive0)->GetNumberOfItems(&numItems)); 1.370 + if (numItems < 1) 1.371 + return S_OK; 1.372 + 1.373 + UString subPath; 1.374 + RINOK(GetArchiveItemPath(*archive0, 0, subPath)) 1.375 + if (subPath.IsEmpty()) 1.376 + { 1.377 + MakeDefaultName(defaultItemName0); 1.378 + subPath = defaultItemName0; 1.379 + if (archiverInfo0.Name.CompareNoCase(L"7z") == 0) 1.380 + { 1.381 + if (subPath.Right(3).CompareNoCase(L".7z") != 0) 1.382 + subPath += L".7z"; 1.383 + } 1.384 + } 1.385 + else 1.386 + subPath = ExtractFileNameFromPath(subPath); 1.387 + 1.388 + CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; 1.389 + openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); 1.390 + if (setSubArchiveName) 1.391 + setSubArchiveName->SetSubArchiveName(subPath); 1.392 + 1.393 + result = OpenArchive(subStream, subPath, 1.394 + #ifndef EXCLUDE_COM 1.395 + module1, 1.396 + #endif 1.397 + archive1, archiverInfo1, defaultItemName1, openArchiveCallback); 1.398 + return S_OK; 1.399 +} 1.400 + 1.401 +HRESULT MyOpenArchive(const UString &archiveName, 1.402 + #ifndef EXCLUDE_COM 1.403 + HMODULE *module, 1.404 + #endif 1.405 + IInArchive **archive, 1.406 + UString &defaultItemName, 1.407 + IOpenCallbackUI *openCallbackUI) 1.408 +{ 1.409 + COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; 1.410 + CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; 1.411 + openCallbackSpec->Callback = openCallbackUI; 1.412 + 1.413 + UString fullName; 1.414 + int fileNamePartStartIndex; 1.415 + NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); 1.416 + openCallbackSpec->Init( 1.417 + fullName.Left(fileNamePartStartIndex), 1.418 + fullName.Mid(fileNamePartStartIndex)); 1.419 + 1.420 + CArchiverInfo archiverInfo; 1.421 + return OpenArchive(archiveName, 1.422 + #ifndef EXCLUDE_COM 1.423 + module, 1.424 + #endif 1.425 + archive, 1.426 + archiverInfo, 1.427 + defaultItemName, 1.428 + openCallback); 1.429 +} 1.430 + 1.431 +HRESULT MyOpenArchive(const UString &archiveName, 1.432 + #ifndef EXCLUDE_COM 1.433 + HMODULE *module0, 1.434 + HMODULE *module1, 1.435 + #endif 1.436 + IInArchive **archive0, 1.437 + IInArchive **archive1, 1.438 + UString &defaultItemName0, 1.439 + UString &defaultItemName1, 1.440 + UStringVector &volumePaths, 1.441 + IOpenCallbackUI *openCallbackUI) 1.442 +{ 1.443 + COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; 1.444 + CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; 1.445 + openCallbackSpec->Callback = openCallbackUI; 1.446 + 1.447 + UString fullName; 1.448 + int fileNamePartStartIndex; 1.449 + NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); 1.450 + UString prefix = fullName.Left(fileNamePartStartIndex); 1.451 + UString name = fullName.Mid(fileNamePartStartIndex); 1.452 + openCallbackSpec->Init(prefix, name); 1.453 + 1.454 + CArchiverInfo archiverInfo0, archiverInfo1; 1.455 + HRESULT result = OpenArchive(archiveName, 1.456 + #ifndef EXCLUDE_COM 1.457 + module0, 1.458 + module1, 1.459 + #endif 1.460 + archive0, 1.461 + archive1, 1.462 + archiverInfo0, 1.463 + archiverInfo1, 1.464 + defaultItemName0, 1.465 + defaultItemName1, 1.466 + openCallback); 1.467 + RINOK(result); 1.468 + volumePaths.Add(prefix + name); 1.469 + for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) 1.470 + volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); 1.471 + return S_OK; 1.472 +} 1.473 + 1.474 +HRESULT CArchiveLink::Close() 1.475 +{ 1.476 + if (Archive1 != 0) 1.477 + RINOK(Archive1->Close()); 1.478 + if (Archive0 != 0) 1.479 + RINOK(Archive0->Close()); 1.480 + return S_OK; 1.481 +} 1.482 + 1.483 +void CArchiveLink::Release() 1.484 +{ 1.485 + if (Archive1 != 0) 1.486 + Archive1.Release(); 1.487 + if (Archive0 != 0) 1.488 + Archive0.Release(); 1.489 + #ifndef EXCLUDE_COM 1.490 + Library1.Free(); 1.491 + Library0.Free(); 1.492 + #endif 1.493 +} 1.494 + 1.495 +HRESULT OpenArchive(const UString &archiveName, 1.496 + CArchiveLink &archiveLink, 1.497 + IArchiveOpenCallback *openCallback) 1.498 +{ 1.499 + return OpenArchive(archiveName, 1.500 + #ifndef EXCLUDE_COM 1.501 + &archiveLink.Library0, &archiveLink.Library1, 1.502 + #endif 1.503 + &archiveLink.Archive0, &archiveLink.Archive1, 1.504 + archiveLink.ArchiverInfo0, archiveLink.ArchiverInfo1, 1.505 + archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, 1.506 + openCallback); 1.507 +} 1.508 + 1.509 +HRESULT MyOpenArchive(const UString &archiveName, 1.510 + CArchiveLink &archiveLink, 1.511 + IOpenCallbackUI *openCallbackUI) 1.512 +{ 1.513 + return MyOpenArchive(archiveName, 1.514 + #ifndef EXCLUDE_COM 1.515 + &archiveLink.Library0, &archiveLink.Library1, 1.516 + #endif 1.517 + &archiveLink.Archive0, &archiveLink.Archive1, 1.518 + archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, 1.519 + archiveLink.VolumePaths, 1.520 + openCallbackUI); 1.521 +} 1.522 + 1.523 +HRESULT ReOpenArchive(CArchiveLink &archiveLink, 1.524 + const UString &fileName) 1.525 +{ 1.526 + if (archiveLink.GetNumLevels() > 1) 1.527 + return E_NOTIMPL; 1.528 + if (archiveLink.GetNumLevels() == 0) 1.529 + return MyOpenArchive(fileName, archiveLink, 0); 1.530 + return ReOpenArchive(archiveLink.GetArchive(), fileName); 1.531 +}