Mercurial > vba-linux
view 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 source
1 // 7zHandler.cpp3 #include "StdAfx.h"5 extern "C"6 {7 #include "../../../../C/CpuArch.h"8 }10 #include "../../../Common/ComTry.h"11 #include "../../../Common/IntToString.h"13 #ifdef COMPRESS_MT14 #include "../../../Windows/System.h"15 #endif17 #include "../Common/ItemNameUtils.h"19 #include "7zHandler.h"20 #include "7zProperties.h"22 #ifdef __7Z_SET_PROPERTIES23 #ifdef EXTRACT_ONLY24 #include "../Common/ParseProperties.h"25 #endif26 #endif28 using namespace NWindows;30 extern UString ConvertMethodIdToString(UInt64 id);32 namespace NArchive {33 namespace N7z {35 CHandler::CHandler()36 {37 _crcSize = 4;39 #ifndef _NO_CRYPTO40 _passwordIsDefined = false;41 #endif43 #ifdef EXTRACT_ONLY44 #ifdef COMPRESS_MT45 _numThreads = NSystem::GetNumberOfProcessors();46 #endif47 #else48 Init();49 #endif50 }52 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)53 {54 *numItems = _db.Files.Size();55 return S_OK;56 }58 #ifdef _SFX60 IMP_IInArchive_ArcProps_NO62 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)63 {64 return E_NOTIMPL;65 }67 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,68 BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)69 {70 return E_NOTIMPL;71 }74 #else76 STATPROPSTG kArcProps[] =77 {78 { NULL, kpidMethod, VT_BSTR},79 { NULL, kpidSolid, VT_BOOL},80 { NULL, kpidNumBlocks, VT_UI4},81 { NULL, kpidPhySize, VT_UI8},82 { NULL, kpidHeadersSize, VT_UI8},83 { NULL, kpidOffset, VT_UI8}84 };86 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)87 {88 COM_TRY_BEGIN89 NCOM::CPropVariant prop;90 switch(propID)91 {92 case kpidMethod:93 {94 UString resString;95 CRecordVector<UInt64> ids;96 int i;97 for (i = 0; i < _db.Folders.Size(); i++)98 {99 const CFolder &f = _db.Folders[i];100 for (int j = f.Coders.Size() - 1; j >= 0; j--)101 ids.AddToUniqueSorted(f.Coders[j].MethodID);102 }104 for (i = 0; i < ids.Size(); i++)105 {106 UInt64 id = ids[i];107 UString methodName;108 /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);109 if (methodName.IsEmpty())110 methodName = ConvertMethodIdToString(id);111 if (!resString.IsEmpty())112 resString += L' ';113 resString += methodName;114 }115 prop = resString;116 break;117 }118 case kpidSolid: prop = _db.IsSolid(); break;119 case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break;120 case kpidHeadersSize: prop = _db.HeadersSize; break;121 case kpidPhySize: prop = _db.PhySize; break;122 case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break;123 }124 prop.Detach(value);125 return S_OK;126 COM_TRY_END127 }129 IMP_IInArchive_ArcProps131 #endif133 static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop)134 {135 UInt64 value;136 if (v.GetItem(index, value))137 {138 FILETIME ft;139 ft.dwLowDateTime = (DWORD)value;140 ft.dwHighDateTime = (DWORD)(value >> 32);141 prop = ft;142 }143 }145 #ifndef _SFX147 static UString ConvertUInt32ToString(UInt32 value)148 {149 wchar_t buffer[32];150 ConvertUInt64ToString(value, buffer);151 return buffer;152 }154 static UString GetStringForSizeValue(UInt32 value)155 {156 for (int i = 31; i >= 0; i--)157 if ((UInt32(1) << i) == value)158 return ConvertUInt32ToString(i);159 UString result;160 if (value % (1 << 20) == 0)161 {162 result += ConvertUInt32ToString(value >> 20);163 result += L"m";164 }165 else if (value % (1 << 10) == 0)166 {167 result += ConvertUInt32ToString(value >> 10);168 result += L"k";169 }170 else171 {172 result += ConvertUInt32ToString(value);173 result += L"b";174 }175 return result;176 }178 static const UInt64 k_Copy = 0x0;179 static const UInt64 k_LZMA = 0x030101;180 static const UInt64 k_PPMD = 0x030401;182 static wchar_t GetHex(Byte value)183 {184 return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));185 }186 static inline UString GetHex2(Byte value)187 {188 UString result;189 result += GetHex((Byte)(value >> 4));190 result += GetHex((Byte)(value & 0xF));191 return result;192 }194 #endif196 static const UInt64 k_AES = 0x06F10701;198 bool CHandler::IsEncrypted(UInt32 index2) const199 {200 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];201 if (folderIndex != kNumNoIndex)202 {203 const CFolder &folderInfo = _db.Folders[folderIndex];204 for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)205 if (folderInfo.Coders[i].MethodID == k_AES)206 return true;207 }208 return false;209 }211 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)212 {213 COM_TRY_BEGIN214 NCOM::CPropVariant prop;216 /*217 const CRef2 &ref2 = _refs[index];218 if (ref2.Refs.IsEmpty())219 return E_FAIL;220 const CRef &ref = ref2.Refs.Front();221 */223 const CFileItem &item = _db.Files[index];224 UInt32 index2 = index;226 switch(propID)227 {228 case kpidPath:229 if (!item.Name.IsEmpty())230 prop = NItemName::GetOSName(item.Name);231 break;232 case kpidIsDir: prop = item.IsDir; break;233 case kpidSize:234 {235 prop = item.Size;236 // prop = ref2.Size;237 break;238 }239 case kpidPackSize:240 {241 // prop = ref2.PackSize;242 {243 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];244 if (folderIndex != kNumNoIndex)245 {246 if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)247 prop = _db.GetFolderFullPackSize(folderIndex);248 /*249 else250 prop = (UInt64)0;251 */252 }253 else254 prop = (UInt64)0;255 }256 break;257 }258 case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; }259 case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break;260 case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break;261 case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break;262 case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break;263 case kpidCRC: if (item.CrcDefined) prop = item.Crc; break;264 case kpidEncrypted: prop = IsEncrypted(index2); break;265 case kpidIsAnti: prop = _db.IsItemAnti(index2); break;266 #ifndef _SFX267 case kpidMethod:268 {269 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];270 if (folderIndex != kNumNoIndex)271 {272 const CFolder &folderInfo = _db.Folders[folderIndex];273 UString methodsString;274 for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)275 {276 const CCoderInfo &coderInfo = folderInfo.Coders[i];277 if (!methodsString.IsEmpty())278 methodsString += L' ';280 {281 UString methodName;282 bool methodIsKnown = FindMethod(283 EXTERNAL_CODECS_VARS284 coderInfo.MethodID, methodName);286 if (methodIsKnown)287 {288 methodsString += methodName;289 if (coderInfo.MethodID == k_LZMA)290 {291 if (coderInfo.Props.GetCapacity() >= 5)292 {293 methodsString += L":";294 UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1);295 methodsString += GetStringForSizeValue(dicSize);296 }297 }298 else if (coderInfo.MethodID == k_PPMD)299 {300 if (coderInfo.Props.GetCapacity() >= 5)301 {302 Byte order = *(const Byte *)coderInfo.Props;303 methodsString += L":o";304 methodsString += ConvertUInt32ToString(order);305 methodsString += L":mem";306 UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1);307 methodsString += GetStringForSizeValue(dicSize);308 }309 }310 else if (coderInfo.MethodID == k_AES)311 {312 if (coderInfo.Props.GetCapacity() >= 1)313 {314 methodsString += L":";315 const Byte *data = (const Byte *)coderInfo.Props;316 Byte firstByte = *data++;317 UInt32 numCyclesPower = firstByte & 0x3F;318 methodsString += ConvertUInt32ToString(numCyclesPower);319 /*320 if ((firstByte & 0xC0) != 0)321 {322 methodsString += L":";323 return S_OK;324 UInt32 saltSize = (firstByte >> 7) & 1;325 UInt32 ivSize = (firstByte >> 6) & 1;326 if (coderInfo.Props.GetCapacity() >= 2)327 {328 Byte secondByte = *data++;329 saltSize += (secondByte >> 4);330 ivSize += (secondByte & 0x0F);331 }332 }333 */334 }335 }336 else337 {338 if (coderInfo.Props.GetCapacity() > 0)339 {340 methodsString += L":[";341 for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++)342 {343 if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity())344 {345 methodsString += L"..";346 break;347 }348 else349 methodsString += GetHex2(coderInfo.Props[bi]);350 }351 methodsString += L"]";352 }353 }354 }355 else356 {357 methodsString += ConvertMethodIdToString(coderInfo.MethodID);358 }359 }360 }361 prop = methodsString;362 }363 }364 break;365 case kpidBlock:366 {367 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];368 if (folderIndex != kNumNoIndex)369 prop = (UInt32)folderIndex;370 }371 break;372 case kpidPackedSize0:373 case kpidPackedSize1:374 case kpidPackedSize2:375 case kpidPackedSize3:376 case kpidPackedSize4:377 {378 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];379 if (folderIndex != kNumNoIndex)380 {381 const CFolder &folderInfo = _db.Folders[folderIndex];382 if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&383 folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))384 {385 prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);386 }387 else388 prop = (UInt64)0;389 }390 else391 prop = (UInt64)0;392 }393 break;394 #endif395 }396 prop.Detach(value);397 return S_OK;398 COM_TRY_END399 }401 STDMETHODIMP CHandler::Open(IInStream *stream,402 const UInt64 *maxCheckStartPosition,403 IArchiveOpenCallback *openArchiveCallback)404 {405 COM_TRY_BEGIN406 Close();407 #ifndef _SFX408 _fileInfoPopIDs.Clear();409 #endif410 try411 {412 CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;414 #ifndef _NO_CRYPTO415 CMyComPtr<ICryptoGetTextPassword> getTextPassword;416 if (openArchiveCallback)417 {418 openArchiveCallbackTemp.QueryInterface(419 IID_ICryptoGetTextPassword, &getTextPassword);420 }421 #endif422 CInArchive archive;423 RINOK(archive.Open(stream, maxCheckStartPosition));424 #ifndef _NO_CRYPTO425 _passwordIsDefined = false;426 UString password;427 #endif428 HRESULT result = archive.ReadDatabase(429 EXTERNAL_CODECS_VARS430 _db431 #ifndef _NO_CRYPTO432 , getTextPassword, _passwordIsDefined433 #endif434 );435 RINOK(result);436 _db.Fill();437 _inStream = stream;438 }439 catch(...)440 {441 Close();442 return S_FALSE;443 }444 // _inStream = stream;445 #ifndef _SFX446 FillPopIDs();447 #endif448 return S_OK;449 COM_TRY_END450 }452 STDMETHODIMP CHandler::Close()453 {454 COM_TRY_BEGIN455 _inStream.Release();456 _db.Clear();457 return S_OK;458 COM_TRY_END459 }461 #ifdef __7Z_SET_PROPERTIES462 #ifdef EXTRACT_ONLY464 STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)465 {466 COM_TRY_BEGIN467 #ifdef COMPRESS_MT468 const UInt32 numProcessors = NSystem::GetNumberOfProcessors();469 _numThreads = numProcessors;470 #endif472 for (int i = 0; i < numProperties; i++)473 {474 UString name = names[i];475 name.MakeUpper();476 if (name.IsEmpty())477 return E_INVALIDARG;478 const PROPVARIANT &value = values[i];479 UInt32 number;480 int index = ParseStringToUInt32(name, number);481 if (index == 0)482 {483 if(name.Left(2).CompareNoCase(L"MT") == 0)484 {485 #ifdef COMPRESS_MT486 RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));487 #endif488 continue;489 }490 else491 return E_INVALIDARG;492 }493 }494 return S_OK;495 COM_TRY_END496 }498 #endif499 #endif501 IMPL_ISetCompressCodecsInfo503 }}