Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Archive/7z/7zHandler.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/7z/7zHandler.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,503 @@ 1.4 +// 7zHandler.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +extern "C" 1.9 +{ 1.10 + #include "../../../../C/CpuArch.h" 1.11 +} 1.12 + 1.13 +#include "../../../Common/ComTry.h" 1.14 +#include "../../../Common/IntToString.h" 1.15 + 1.16 +#ifdef COMPRESS_MT 1.17 +#include "../../../Windows/System.h" 1.18 +#endif 1.19 + 1.20 +#include "../Common/ItemNameUtils.h" 1.21 + 1.22 +#include "7zHandler.h" 1.23 +#include "7zProperties.h" 1.24 + 1.25 +#ifdef __7Z_SET_PROPERTIES 1.26 +#ifdef EXTRACT_ONLY 1.27 +#include "../Common/ParseProperties.h" 1.28 +#endif 1.29 +#endif 1.30 + 1.31 +using namespace NWindows; 1.32 + 1.33 +extern UString ConvertMethodIdToString(UInt64 id); 1.34 + 1.35 +namespace NArchive { 1.36 +namespace N7z { 1.37 + 1.38 +CHandler::CHandler() 1.39 +{ 1.40 + _crcSize = 4; 1.41 + 1.42 + #ifndef _NO_CRYPTO 1.43 + _passwordIsDefined = false; 1.44 + #endif 1.45 + 1.46 + #ifdef EXTRACT_ONLY 1.47 + #ifdef COMPRESS_MT 1.48 + _numThreads = NSystem::GetNumberOfProcessors(); 1.49 + #endif 1.50 + #else 1.51 + Init(); 1.52 + #endif 1.53 +} 1.54 + 1.55 +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 1.56 +{ 1.57 + *numItems = _db.Files.Size(); 1.58 + return S_OK; 1.59 +} 1.60 + 1.61 +#ifdef _SFX 1.62 + 1.63 +IMP_IInArchive_ArcProps_NO 1.64 + 1.65 +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) 1.66 +{ 1.67 + return E_NOTIMPL; 1.68 +} 1.69 + 1.70 +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, 1.71 + BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) 1.72 +{ 1.73 + return E_NOTIMPL; 1.74 +} 1.75 + 1.76 + 1.77 +#else 1.78 + 1.79 +STATPROPSTG kArcProps[] = 1.80 +{ 1.81 + { NULL, kpidMethod, VT_BSTR}, 1.82 + { NULL, kpidSolid, VT_BOOL}, 1.83 + { NULL, kpidNumBlocks, VT_UI4}, 1.84 + { NULL, kpidPhySize, VT_UI8}, 1.85 + { NULL, kpidHeadersSize, VT_UI8}, 1.86 + { NULL, kpidOffset, VT_UI8} 1.87 +}; 1.88 + 1.89 +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) 1.90 +{ 1.91 + COM_TRY_BEGIN 1.92 + NCOM::CPropVariant prop; 1.93 + switch(propID) 1.94 + { 1.95 + case kpidMethod: 1.96 + { 1.97 + UString resString; 1.98 + CRecordVector<UInt64> ids; 1.99 + int i; 1.100 + for (i = 0; i < _db.Folders.Size(); i++) 1.101 + { 1.102 + const CFolder &f = _db.Folders[i]; 1.103 + for (int j = f.Coders.Size() - 1; j >= 0; j--) 1.104 + ids.AddToUniqueSorted(f.Coders[j].MethodID); 1.105 + } 1.106 + 1.107 + for (i = 0; i < ids.Size(); i++) 1.108 + { 1.109 + UInt64 id = ids[i]; 1.110 + UString methodName; 1.111 + /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); 1.112 + if (methodName.IsEmpty()) 1.113 + methodName = ConvertMethodIdToString(id); 1.114 + if (!resString.IsEmpty()) 1.115 + resString += L' '; 1.116 + resString += methodName; 1.117 + } 1.118 + prop = resString; 1.119 + break; 1.120 + } 1.121 + case kpidSolid: prop = _db.IsSolid(); break; 1.122 + case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; 1.123 + case kpidHeadersSize: prop = _db.HeadersSize; break; 1.124 + case kpidPhySize: prop = _db.PhySize; break; 1.125 + case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; 1.126 + } 1.127 + prop.Detach(value); 1.128 + return S_OK; 1.129 + COM_TRY_END 1.130 +} 1.131 + 1.132 +IMP_IInArchive_ArcProps 1.133 + 1.134 +#endif 1.135 + 1.136 +static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) 1.137 +{ 1.138 + UInt64 value; 1.139 + if (v.GetItem(index, value)) 1.140 + { 1.141 + FILETIME ft; 1.142 + ft.dwLowDateTime = (DWORD)value; 1.143 + ft.dwHighDateTime = (DWORD)(value >> 32); 1.144 + prop = ft; 1.145 + } 1.146 +} 1.147 + 1.148 +#ifndef _SFX 1.149 + 1.150 +static UString ConvertUInt32ToString(UInt32 value) 1.151 +{ 1.152 + wchar_t buffer[32]; 1.153 + ConvertUInt64ToString(value, buffer); 1.154 + return buffer; 1.155 +} 1.156 + 1.157 +static UString GetStringForSizeValue(UInt32 value) 1.158 +{ 1.159 + for (int i = 31; i >= 0; i--) 1.160 + if ((UInt32(1) << i) == value) 1.161 + return ConvertUInt32ToString(i); 1.162 + UString result; 1.163 + if (value % (1 << 20) == 0) 1.164 + { 1.165 + result += ConvertUInt32ToString(value >> 20); 1.166 + result += L"m"; 1.167 + } 1.168 + else if (value % (1 << 10) == 0) 1.169 + { 1.170 + result += ConvertUInt32ToString(value >> 10); 1.171 + result += L"k"; 1.172 + } 1.173 + else 1.174 + { 1.175 + result += ConvertUInt32ToString(value); 1.176 + result += L"b"; 1.177 + } 1.178 + return result; 1.179 +} 1.180 + 1.181 +static const UInt64 k_Copy = 0x0; 1.182 +static const UInt64 k_LZMA = 0x030101; 1.183 +static const UInt64 k_PPMD = 0x030401; 1.184 + 1.185 +static wchar_t GetHex(Byte value) 1.186 +{ 1.187 + return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); 1.188 +} 1.189 +static inline UString GetHex2(Byte value) 1.190 +{ 1.191 + UString result; 1.192 + result += GetHex((Byte)(value >> 4)); 1.193 + result += GetHex((Byte)(value & 0xF)); 1.194 + return result; 1.195 +} 1.196 + 1.197 +#endif 1.198 + 1.199 +static const UInt64 k_AES = 0x06F10701; 1.200 + 1.201 +bool CHandler::IsEncrypted(UInt32 index2) const 1.202 +{ 1.203 + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; 1.204 + if (folderIndex != kNumNoIndex) 1.205 + { 1.206 + const CFolder &folderInfo = _db.Folders[folderIndex]; 1.207 + for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) 1.208 + if (folderInfo.Coders[i].MethodID == k_AES) 1.209 + return true; 1.210 + } 1.211 + return false; 1.212 +} 1.213 + 1.214 +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) 1.215 +{ 1.216 + COM_TRY_BEGIN 1.217 + NCOM::CPropVariant prop; 1.218 + 1.219 + /* 1.220 + const CRef2 &ref2 = _refs[index]; 1.221 + if (ref2.Refs.IsEmpty()) 1.222 + return E_FAIL; 1.223 + const CRef &ref = ref2.Refs.Front(); 1.224 + */ 1.225 + 1.226 + const CFileItem &item = _db.Files[index]; 1.227 + UInt32 index2 = index; 1.228 + 1.229 + switch(propID) 1.230 + { 1.231 + case kpidPath: 1.232 + if (!item.Name.IsEmpty()) 1.233 + prop = NItemName::GetOSName(item.Name); 1.234 + break; 1.235 + case kpidIsDir: prop = item.IsDir; break; 1.236 + case kpidSize: 1.237 + { 1.238 + prop = item.Size; 1.239 + // prop = ref2.Size; 1.240 + break; 1.241 + } 1.242 + case kpidPackSize: 1.243 + { 1.244 + // prop = ref2.PackSize; 1.245 + { 1.246 + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; 1.247 + if (folderIndex != kNumNoIndex) 1.248 + { 1.249 + if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) 1.250 + prop = _db.GetFolderFullPackSize(folderIndex); 1.251 + /* 1.252 + else 1.253 + prop = (UInt64)0; 1.254 + */ 1.255 + } 1.256 + else 1.257 + prop = (UInt64)0; 1.258 + } 1.259 + break; 1.260 + } 1.261 + case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } 1.262 + case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; 1.263 + case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; 1.264 + case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; 1.265 + case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; 1.266 + case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; 1.267 + case kpidEncrypted: prop = IsEncrypted(index2); break; 1.268 + case kpidIsAnti: prop = _db.IsItemAnti(index2); break; 1.269 + #ifndef _SFX 1.270 + case kpidMethod: 1.271 + { 1.272 + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; 1.273 + if (folderIndex != kNumNoIndex) 1.274 + { 1.275 + const CFolder &folderInfo = _db.Folders[folderIndex]; 1.276 + UString methodsString; 1.277 + for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) 1.278 + { 1.279 + const CCoderInfo &coderInfo = folderInfo.Coders[i]; 1.280 + if (!methodsString.IsEmpty()) 1.281 + methodsString += L' '; 1.282 + 1.283 + { 1.284 + UString methodName; 1.285 + bool methodIsKnown = FindMethod( 1.286 + EXTERNAL_CODECS_VARS 1.287 + coderInfo.MethodID, methodName); 1.288 + 1.289 + if (methodIsKnown) 1.290 + { 1.291 + methodsString += methodName; 1.292 + if (coderInfo.MethodID == k_LZMA) 1.293 + { 1.294 + if (coderInfo.Props.GetCapacity() >= 5) 1.295 + { 1.296 + methodsString += L":"; 1.297 + UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); 1.298 + methodsString += GetStringForSizeValue(dicSize); 1.299 + } 1.300 + } 1.301 + else if (coderInfo.MethodID == k_PPMD) 1.302 + { 1.303 + if (coderInfo.Props.GetCapacity() >= 5) 1.304 + { 1.305 + Byte order = *(const Byte *)coderInfo.Props; 1.306 + methodsString += L":o"; 1.307 + methodsString += ConvertUInt32ToString(order); 1.308 + methodsString += L":mem"; 1.309 + UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); 1.310 + methodsString += GetStringForSizeValue(dicSize); 1.311 + } 1.312 + } 1.313 + else if (coderInfo.MethodID == k_AES) 1.314 + { 1.315 + if (coderInfo.Props.GetCapacity() >= 1) 1.316 + { 1.317 + methodsString += L":"; 1.318 + const Byte *data = (const Byte *)coderInfo.Props; 1.319 + Byte firstByte = *data++; 1.320 + UInt32 numCyclesPower = firstByte & 0x3F; 1.321 + methodsString += ConvertUInt32ToString(numCyclesPower); 1.322 + /* 1.323 + if ((firstByte & 0xC0) != 0) 1.324 + { 1.325 + methodsString += L":"; 1.326 + return S_OK; 1.327 + UInt32 saltSize = (firstByte >> 7) & 1; 1.328 + UInt32 ivSize = (firstByte >> 6) & 1; 1.329 + if (coderInfo.Props.GetCapacity() >= 2) 1.330 + { 1.331 + Byte secondByte = *data++; 1.332 + saltSize += (secondByte >> 4); 1.333 + ivSize += (secondByte & 0x0F); 1.334 + } 1.335 + } 1.336 + */ 1.337 + } 1.338 + } 1.339 + else 1.340 + { 1.341 + if (coderInfo.Props.GetCapacity() > 0) 1.342 + { 1.343 + methodsString += L":["; 1.344 + for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++) 1.345 + { 1.346 + if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity()) 1.347 + { 1.348 + methodsString += L".."; 1.349 + break; 1.350 + } 1.351 + else 1.352 + methodsString += GetHex2(coderInfo.Props[bi]); 1.353 + } 1.354 + methodsString += L"]"; 1.355 + } 1.356 + } 1.357 + } 1.358 + else 1.359 + { 1.360 + methodsString += ConvertMethodIdToString(coderInfo.MethodID); 1.361 + } 1.362 + } 1.363 + } 1.364 + prop = methodsString; 1.365 + } 1.366 + } 1.367 + break; 1.368 + case kpidBlock: 1.369 + { 1.370 + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; 1.371 + if (folderIndex != kNumNoIndex) 1.372 + prop = (UInt32)folderIndex; 1.373 + } 1.374 + break; 1.375 + case kpidPackedSize0: 1.376 + case kpidPackedSize1: 1.377 + case kpidPackedSize2: 1.378 + case kpidPackedSize3: 1.379 + case kpidPackedSize4: 1.380 + { 1.381 + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; 1.382 + if (folderIndex != kNumNoIndex) 1.383 + { 1.384 + const CFolder &folderInfo = _db.Folders[folderIndex]; 1.385 + if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && 1.386 + folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) 1.387 + { 1.388 + prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); 1.389 + } 1.390 + else 1.391 + prop = (UInt64)0; 1.392 + } 1.393 + else 1.394 + prop = (UInt64)0; 1.395 + } 1.396 + break; 1.397 + #endif 1.398 + } 1.399 + prop.Detach(value); 1.400 + return S_OK; 1.401 + COM_TRY_END 1.402 +} 1.403 + 1.404 +STDMETHODIMP CHandler::Open(IInStream *stream, 1.405 + const UInt64 *maxCheckStartPosition, 1.406 + IArchiveOpenCallback *openArchiveCallback) 1.407 +{ 1.408 + COM_TRY_BEGIN 1.409 + Close(); 1.410 + #ifndef _SFX 1.411 + _fileInfoPopIDs.Clear(); 1.412 + #endif 1.413 + try 1.414 + { 1.415 + CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; 1.416 + 1.417 + #ifndef _NO_CRYPTO 1.418 + CMyComPtr<ICryptoGetTextPassword> getTextPassword; 1.419 + if (openArchiveCallback) 1.420 + { 1.421 + openArchiveCallbackTemp.QueryInterface( 1.422 + IID_ICryptoGetTextPassword, &getTextPassword); 1.423 + } 1.424 + #endif 1.425 + CInArchive archive; 1.426 + RINOK(archive.Open(stream, maxCheckStartPosition)); 1.427 + #ifndef _NO_CRYPTO 1.428 + _passwordIsDefined = false; 1.429 + UString password; 1.430 + #endif 1.431 + HRESULT result = archive.ReadDatabase( 1.432 + EXTERNAL_CODECS_VARS 1.433 + _db 1.434 + #ifndef _NO_CRYPTO 1.435 + , getTextPassword, _passwordIsDefined 1.436 + #endif 1.437 + ); 1.438 + RINOK(result); 1.439 + _db.Fill(); 1.440 + _inStream = stream; 1.441 + } 1.442 + catch(...) 1.443 + { 1.444 + Close(); 1.445 + return S_FALSE; 1.446 + } 1.447 + // _inStream = stream; 1.448 + #ifndef _SFX 1.449 + FillPopIDs(); 1.450 + #endif 1.451 + return S_OK; 1.452 + COM_TRY_END 1.453 +} 1.454 + 1.455 +STDMETHODIMP CHandler::Close() 1.456 +{ 1.457 + COM_TRY_BEGIN 1.458 + _inStream.Release(); 1.459 + _db.Clear(); 1.460 + return S_OK; 1.461 + COM_TRY_END 1.462 +} 1.463 + 1.464 +#ifdef __7Z_SET_PROPERTIES 1.465 +#ifdef EXTRACT_ONLY 1.466 + 1.467 +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) 1.468 +{ 1.469 + COM_TRY_BEGIN 1.470 + #ifdef COMPRESS_MT 1.471 + const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); 1.472 + _numThreads = numProcessors; 1.473 + #endif 1.474 + 1.475 + for (int i = 0; i < numProperties; i++) 1.476 + { 1.477 + UString name = names[i]; 1.478 + name.MakeUpper(); 1.479 + if (name.IsEmpty()) 1.480 + return E_INVALIDARG; 1.481 + const PROPVARIANT &value = values[i]; 1.482 + UInt32 number; 1.483 + int index = ParseStringToUInt32(name, number); 1.484 + if (index == 0) 1.485 + { 1.486 + if(name.Left(2).CompareNoCase(L"MT") == 0) 1.487 + { 1.488 + #ifdef COMPRESS_MT 1.489 + RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); 1.490 + #endif 1.491 + continue; 1.492 + } 1.493 + else 1.494 + return E_INVALIDARG; 1.495 + } 1.496 + } 1.497 + return S_OK; 1.498 + COM_TRY_END 1.499 +} 1.500 + 1.501 +#endif 1.502 +#endif 1.503 + 1.504 +IMPL_ISetCompressCodecsInfo 1.505 + 1.506 +}}