diff -r 0135e64c6c66 -r c4fd2813b127 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHandler.cpp --- a/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHandler.cpp Wed May 16 18:22:28 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,793 +0,0 @@ -// 7zHandler.cpp - -#include "StdAfx.h" - -#include "7zHandler.h" -#include "7zProperties.h" - -#include "../../../Common/IntToString.h" -#include "../../../Common/ComTry.h" -#include "../../../Windows/Defs.h" - -#include "../Common/ItemNameUtils.h" -#ifdef _7Z_VOL -#include "../Common/MultiStream.h" -#endif - -#ifdef __7Z_SET_PROPERTIES -#ifdef EXTRACT_ONLY -#include "../Common/ParseProperties.h" -#endif -#endif - -#ifdef COMPRESS_MT -#include "../../../Windows/System.h" -#endif - -using namespace NWindows; - -extern UString ConvertMethodIdToString(UInt64 id); - -namespace NArchive { -namespace N7z { - -CHandler::CHandler() -{ - _crcSize = 4; - - #ifdef EXTRACT_ONLY - #ifdef COMPRESS_MT - _numThreads = NWindows::NSystem::GetNumberOfProcessors(); - #endif - #else - Init(); - #endif -} - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = - #ifdef _7Z_VOL - _refs.Size(); - #else - *numItems = _database.Files.Size(); - #endif - return S_OK; -} - -#ifdef _SFX - -IMP_IInArchive_ArcProps_NO - -STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) -{ - return E_NOTIMPL; -} - -STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, - BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) -{ - return E_NOTIMPL; -} - - -#else - -STATPROPSTG kArcProps[] = -{ - { NULL, kpidMethod, VT_BSTR}, - { NULL, kpidSolid, VT_BOOL}, - { NULL, kpidNumBlocks, VT_UI4} -}; - -STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - switch(propID) - { - case kpidMethod: - { - UString resString; - CRecordVector ids; - int i; - for (i = 0; i < _database.Folders.Size(); i++) - { - const CFolder &f = _database.Folders[i]; - for (int j = f.Coders.Size() - 1; j >= 0; j--) - ids.AddToUniqueSorted(f.Coders[j].MethodID); - } - - for (i = 0; i < ids.Size(); i++) - { - UInt64 id = ids[i]; - UString methodName; - /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); - if (methodName.IsEmpty()) - methodName = ConvertMethodIdToString(id); - if (!resString.IsEmpty()) - resString += L' '; - resString += methodName; - } - prop = resString; - break; - } - case kpidSolid: prop = _database.IsSolid(); break; - case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break; - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -IMP_IInArchive_ArcProps - -#endif - -static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop) -{ - if (timeDefined) - prop = unixTime; -} - -#ifndef _SFX - -static UString ConvertUInt32ToString(UInt32 value) -{ - wchar_t buffer[32]; - ConvertUInt64ToString(value, buffer); - return buffer; -} - -static UString GetStringForSizeValue(UInt32 value) -{ - for (int i = 31; i >= 0; i--) - if ((UInt32(1) << i) == value) - return ConvertUInt32ToString(i); - UString result; - if (value % (1 << 20) == 0) - { - result += ConvertUInt32ToString(value >> 20); - result += L"m"; - } - else if (value % (1 << 10) == 0) - { - result += ConvertUInt32ToString(value >> 10); - result += L"k"; - } - else - { - result += ConvertUInt32ToString(value); - result += L"b"; - } - return result; -} - -static const UInt64 k_Copy = 0x0; -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_PPMD = 0x030401; - -static wchar_t GetHex(Byte value) -{ - return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); -} -static inline UString GetHex2(Byte value) -{ - UString result; - result += GetHex((Byte)(value >> 4)); - result += GetHex((Byte)(value & 0xF)); - return result; -} - -#endif - -static const UInt64 k_AES = 0x06F10701; - -#ifndef _SFX -static inline UInt32 GetUInt32FromMemLE(const Byte *p) -{ - return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); -} -#endif - -bool CHandler::IsEncrypted(UInt32 index2) const -{ - CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) - { - const CFolder &folderInfo = _database.Folders[folderIndex]; - for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) - if (folderInfo.Coders[i].MethodID == k_AES) - return true; - } - return false; -} - -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - - /* - const CRef2 &ref2 = _refs[index]; - if (ref2.Refs.IsEmpty()) - return E_FAIL; - const CRef &ref = ref2.Refs.Front(); - */ - - #ifdef _7Z_VOL - const CRef &ref = _refs[index]; - const CVolume &volume = _volumes[ref.VolumeIndex]; - const CArchiveDatabaseEx &_database = volume.Database; - UInt32 index2 = ref.ItemIndex; - const CFileItem &item = _database.Files[index2]; - #else - const CFileItem &item = _database.Files[index]; - UInt32 index2 = index; - #endif - - switch(propID) - { - case kpidPath: - { - if (!item.Name.IsEmpty()) - prop = NItemName::GetOSName(item.Name); - break; - } - case kpidIsFolder: - prop = item.IsDirectory; - break; - case kpidSize: - { - prop = item.UnPackSize; - // prop = ref2.UnPackSize; - break; - } - case kpidPosition: - { - /* - if (ref2.Refs.Size() > 1) - prop = ref2.StartPos; - else - */ - if (item.IsStartPosDefined) - prop = item.StartPos; - break; - } - case kpidPackedSize: - { - // prop = ref2.PackSize; - { - CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) - { - if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2) - prop = _database.GetFolderFullPackSize(folderIndex); - /* - else - prop = (UInt64)0; - */ - } - else - prop = (UInt64)0; - } - break; - } - case kpidLastAccessTime: - MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop); - break; - case kpidCreationTime: - MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop); - break; - case kpidLastWriteTime: - MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop); - break; - case kpidAttributes: - if (item.AreAttributesDefined) - prop = item.Attributes; - break; - case kpidCRC: - if (item.IsFileCRCDefined) - prop = item.FileCRC; - break; - case kpidEncrypted: - { - prop = IsEncrypted(index2); - break; - } - #ifndef _SFX - case kpidMethod: - { - CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) - { - const CFolder &folderInfo = _database.Folders[folderIndex]; - UString methodsString; - for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) - { - const CCoderInfo &coderInfo = folderInfo.Coders[i]; - if (!methodsString.IsEmpty()) - methodsString += L' '; - - { - UString methodName; - bool methodIsKnown = FindMethod( - EXTERNAL_CODECS_VARS - coderInfo.MethodID, methodName); - - if (methodIsKnown) - { - methodsString += methodName; - if (coderInfo.MethodID == k_LZMA) - { - if (coderInfo.Properties.GetCapacity() >= 5) - { - methodsString += L":"; - UInt32 dicSize = GetUInt32FromMemLE( - ((const Byte *)coderInfo.Properties + 1)); - methodsString += GetStringForSizeValue(dicSize); - } - } - else if (coderInfo.MethodID == k_PPMD) - { - if (coderInfo.Properties.GetCapacity() >= 5) - { - Byte order = *(const Byte *)coderInfo.Properties; - methodsString += L":o"; - methodsString += ConvertUInt32ToString(order); - methodsString += L":mem"; - UInt32 dicSize = GetUInt32FromMemLE( - ((const Byte *)coderInfo.Properties + 1)); - methodsString += GetStringForSizeValue(dicSize); - } - } - else if (coderInfo.MethodID == k_AES) - { - if (coderInfo.Properties.GetCapacity() >= 1) - { - methodsString += L":"; - const Byte *data = (const Byte *)coderInfo.Properties; - Byte firstByte = *data++; - UInt32 numCyclesPower = firstByte & 0x3F; - methodsString += ConvertUInt32ToString(numCyclesPower); - /* - if ((firstByte & 0xC0) != 0) - { - methodsString += L":"; - return S_OK; - UInt32 saltSize = (firstByte >> 7) & 1; - UInt32 ivSize = (firstByte >> 6) & 1; - if (coderInfo.Properties.GetCapacity() >= 2) - { - Byte secondByte = *data++; - saltSize += (secondByte >> 4); - ivSize += (secondByte & 0x0F); - } - } - */ - } - } - else - { - if (coderInfo.Properties.GetCapacity() > 0) - { - methodsString += L":["; - for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++) - { - if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity()) - { - methodsString += L".."; - break; - } - else - methodsString += GetHex2(coderInfo.Properties[bi]); - } - methodsString += L"]"; - } - } - } - else - { - methodsString += ConvertMethodIdToString(coderInfo.MethodID); - } - } - } - prop = methodsString; - } - } - break; - case kpidBlock: - { - CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) - prop = (UInt32)folderIndex; - } - break; - case kpidPackedSize0: - case kpidPackedSize1: - case kpidPackedSize2: - case kpidPackedSize3: - case kpidPackedSize4: - { - CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) - { - const CFolder &folderInfo = _database.Folders[folderIndex]; - if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 && - folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) - { - prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); - } - else - prop = (UInt64)0; - } - else - prop = (UInt64)0; - } - break; - #endif - case kpidIsAnti: - prop = item.IsAnti; - break; - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -#ifdef _7Z_VOL - -static const wchar_t *kExt = L"7z"; -static const wchar_t *kAfterPart = L".7z"; - -class CVolumeName -{ - bool _first; - UString _unchangedPart; - UString _changedPart; - UString _afterPart; -public: - bool InitName(const UString &name) - { - _first = true; - int dotPos = name.ReverseFind('.'); - UString basePart = name; - if (dotPos >= 0) - { - UString ext = name.Mid(dotPos + 1); - if (ext.CompareNoCase(kExt)==0 || - ext.CompareNoCase(L"EXE") == 0) - { - _afterPart = kAfterPart; - basePart = name.Left(dotPos); - } - } - - int numLetters = 1; - bool splitStyle = false; - if (basePart.Right(numLetters) == L"1") - { - while (numLetters < basePart.Length()) - { - if (basePart[basePart.Length() - numLetters - 1] != '0') - break; - numLetters++; - } - } - else - return false; - _unchangedPart = basePart.Left(basePart.Length() - numLetters); - _changedPart = basePart.Right(numLetters); - return true; - } - - UString GetNextName() - { - UString newName; - // if (_newStyle || !_first) - { - int i; - int numLetters = _changedPart.Length(); - for (i = numLetters - 1; i >= 0; i--) - { - wchar_t c = _changedPart[i]; - if (c == L'9') - { - c = L'0'; - newName = c + newName; - if (i == 0) - newName = UString(L'1') + newName; - continue; - } - c++; - newName = UString(c) + newName; - i--; - for (; i >= 0; i--) - newName = _changedPart[i] + newName; - break; - } - _changedPart = newName; - } - _first = false; - return _unchangedPart + _changedPart + _afterPart; - } -}; - -#endif - -STDMETHODIMP CHandler::Open(IInStream *stream, - const UInt64 *maxCheckStartPosition, - IArchiveOpenCallback *openArchiveCallback) -{ - COM_TRY_BEGIN - Close(); - #ifndef _SFX - _fileInfoPopIDs.Clear(); - #endif - try - { - CMyComPtr openArchiveCallbackTemp = openArchiveCallback; - #ifdef _7Z_VOL - CVolumeName seqName; - - CMyComPtr openVolumeCallback; - #endif - - #ifndef _NO_CRYPTO - CMyComPtr getTextPassword; - if (openArchiveCallback) - { - openArchiveCallbackTemp.QueryInterface( - IID_ICryptoGetTextPassword, &getTextPassword); - } - #endif - #ifdef _7Z_VOL - if (openArchiveCallback) - { - openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); - } - for (;;) - { - CMyComPtr inStream; - if (!_volumes.IsEmpty()) - { - if (!openVolumeCallback) - break; - if(_volumes.Size() == 1) - { - UString baseName; - { - NCOM::CPropVariant prop; - RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); - if (prop.vt != VT_BSTR) - break; - baseName = prop.bstrVal; - } - seqName.InitName(baseName); - } - - UString fullName = seqName.GetNextName(); - HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); - if (result == S_FALSE) - break; - if (result != S_OK) - return result; - if (!stream) - break; - } - else - inStream = stream; - - CInArchive archive; - RINOK(archive.Open(inStream, maxCheckStartPosition)); - - _volumes.Add(CVolume()); - CVolume &volume = _volumes.Back(); - CArchiveDatabaseEx &database = volume.Database; - volume.Stream = inStream; - volume.StartRef2Index = _refs.Size(); - - HRESULT result = archive.ReadDatabase(database - #ifndef _NO_CRYPTO - , getTextPassword - #endif - ); - if (result != S_OK) - { - _volumes.Clear(); - return result; - } - database.Fill(); - for(int i = 0; i < database.Files.Size(); i++) - { - CRef refNew; - refNew.VolumeIndex = _volumes.Size() - 1; - refNew.ItemIndex = i; - _refs.Add(refNew); - /* - const CFileItem &file = database.Files[i]; - int j; - */ - /* - for (j = _refs.Size() - 1; j >= 0; j--) - { - CRef2 &ref2 = _refs[j]; - const CRef &ref = ref2.Refs.Back(); - const CVolume &volume2 = _volumes[ref.VolumeIndex]; - const CArchiveDatabaseEx &database2 = volume2.Database; - const CFileItem &file2 = database2.Files[ref.ItemIndex]; - if (file2.Name.CompareNoCase(file.Name) == 0) - { - if (!file.IsStartPosDefined) - continue; - if (file.StartPos != ref2.StartPos + ref2.UnPackSize) - continue; - ref2.Refs.Add(refNew); - break; - } - } - */ - /* - j = -1; - if (j < 0) - { - CRef2 ref2New; - ref2New.Refs.Add(refNew); - j = _refs.Add(ref2New); - } - CRef2 &ref2 = _refs[j]; - ref2.UnPackSize += file.UnPackSize; - ref2.PackSize += database.GetFilePackSize(i); - if (ref2.Refs.Size() == 1 && file.IsStartPosDefined) - ref2.StartPos = file.StartPos; - */ - } - if (database.Files.Size() != 1) - break; - const CFileItem &file = database.Files.Front(); - if (!file.IsStartPosDefined) - break; - } - #else - CInArchive archive; - RINOK(archive.Open(stream, maxCheckStartPosition)); - HRESULT result = archive.ReadDatabase( - EXTERNAL_CODECS_VARS - _database - #ifndef _NO_CRYPTO - , getTextPassword - #endif - ); - RINOK(result); - _database.Fill(); - _inStream = stream; - #endif - } - catch(...) - { - Close(); - return S_FALSE; - } - // _inStream = stream; - #ifndef _SFX - FillPopIDs(); - #endif - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Close() -{ - COM_TRY_BEGIN - #ifdef _7Z_VOL - _volumes.Clear(); - _refs.Clear(); - #else - _inStream.Release(); - _database.Clear(); - #endif - return S_OK; - COM_TRY_END -} - -#ifdef _7Z_VOL -STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) -{ - if (index != 0) - return E_INVALIDARG; - *stream = 0; - CMultiStream *streamSpec = new CMultiStream; - CMyComPtr streamTemp = streamSpec; - - UInt64 pos = 0; - const UString *fileName; - for (int i = 0; i < _refs.Size(); i++) - { - const CRef &ref = _refs[i]; - const CVolume &volume = _volumes[ref.VolumeIndex]; - const CArchiveDatabaseEx &database = volume.Database; - const CFileItem &file = database.Files[ref.ItemIndex]; - if (i == 0) - fileName = &file.Name; - else - if (fileName->Compare(file.Name) != 0) - return S_FALSE; - if (!file.IsStartPosDefined) - return S_FALSE; - if (file.StartPos != pos) - return S_FALSE; - CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex]; - if (folderIndex == kNumNoIndex) - { - if (file.UnPackSize != 0) - return E_FAIL; - continue; - } - if (database.NumUnPackStreamsVector[folderIndex] != 1) - return S_FALSE; - const CFolder &folder = database.Folders[folderIndex]; - if (folder.Coders.Size() != 1) - return S_FALSE; - const CCoderInfo &coder = folder.Coders.Front(); - if (coder.NumInStreams != 1 || coder.NumOutStreams != 1) - return S_FALSE; - if (coder.MethodID != k_Copy) - return S_FALSE; - - pos += file.UnPackSize; - CMultiStream::CSubStreamInfo subStreamInfo; - subStreamInfo.Stream = volume.Stream; - subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0); - subStreamInfo.Size = file.UnPackSize; - streamSpec->Streams.Add(subStreamInfo); - } - streamSpec->Init(); - *stream = streamTemp.Detach(); - return S_OK; -} -#endif - - -#ifdef __7Z_SET_PROPERTIES -#ifdef EXTRACT_ONLY - -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) -{ - COM_TRY_BEGIN - #ifdef COMPRESS_MT - const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); - _numThreads = numProcessors; - #endif - - for (int i = 0; i < numProperties; i++) - { - UString name = names[i]; - name.MakeUpper(); - if (name.IsEmpty()) - return E_INVALIDARG; - const PROPVARIANT &value = values[i]; - UInt32 number; - int index = ParseStringToUInt32(name, number); - if (index == 0) - { - if(name.Left(2).CompareNoCase(L"MT") == 0) - { - #ifdef COMPRESS_MT - RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); - #endif - continue; - } - else - return E_INVALIDARG; - } - } - return S_OK; - COM_TRY_END -} - -#endif -#endif - -IMPL_ISetCompressCodecsInfo - -}}