From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- .../7zstub/src/7zip/Archive/7z/7zHandler.cpp | 757 +++++++++++++++++++++ 1 file changed, 757 insertions(+) create mode 100644 other-licenses/7zstub/src/7zip/Archive/7z/7zHandler.cpp (limited to 'other-licenses/7zstub/src/7zip/Archive/7z/7zHandler.cpp') diff --git a/other-licenses/7zstub/src/7zip/Archive/7z/7zHandler.cpp b/other-licenses/7zstub/src/7zip/Archive/7z/7zHandler.cpp new file mode 100644 index 000000000..b6f492aea --- /dev/null +++ b/other-licenses/7zstub/src/7zip/Archive/7z/7zHandler.cpp @@ -0,0 +1,757 @@ +// 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 + +using namespace NWindows; + +namespace NArchive { +namespace N7z { + +CHandler::CHandler() +{ + #ifdef COMPRESS_MT + _numThreads = NWindows::NSystem::GetNumberOfProcessors(); + #endif + #ifndef EXTRACT_ONLY + Init(); + #endif + #ifndef EXCLUDE_COM + LoadMethodMap(); + #endif +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + COM_TRY_BEGIN + *numItems = + #ifdef _7Z_VOL + _refs.Size(); + #else + *numItems = _database.Files.Size(); + #endif + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + value->vt = VT_EMPTY; + return S_OK; +} + +#ifdef _SFX + +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType) +{ + return E_NOTIMPL; +} + +#endif + + +STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) +{ + *numProperties = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType) +{ + return E_NOTIMPL; +} + + +static void MySetFileTime(bool timeDefined, FILETIME unixTime, + NWindows::NCOM::CPropVariant &propVariant) +{ + if (timeDefined) + propVariant = unixTime; +} + +/* +inline static wchar_t GetHex(Byte value) +{ + return (value < 10) ? ('0' + value) : ('A' + (value - 10)); +} + +static UString ConvertBytesToHexString(const Byte *data, UInt32 size) +{ + UString result; + for (UInt32 i = 0; i < size; i++) + { + Byte b = data[i]; + result += GetHex(b >> 4); + result += GetHex(b & 0xF); + } + return result; +} +*/ + + +#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 CMethodID k_Copy = { { 0x0 }, 1 }; +static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; +static CMethodID k_BCJ = { { 0x3, 0x3, 0x1, 0x3 }, 4 }; +static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 }; +static CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 }; +static CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 }; +static CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 }; + +static inline char GetHex(Byte value) +{ + return (value < 10) ? ('0' + value) : ('A' + (value - 10)); +} +static inline UString GetHex2(Byte value) +{ + UString result; + result += GetHex(value >> 4); + result += GetHex(value & 0xF); + return result; +} + +#endif + +static inline UInt32 GetUInt32FromMemLE(const Byte *p) +{ + return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant propVariant; + + /* + 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()) + propVariant = NItemName::GetOSName(item.Name); + break; + } + case kpidIsFolder: + propVariant = item.IsDirectory; + break; + case kpidSize: + { + propVariant = item.UnPackSize; + // propVariant = ref2.UnPackSize; + break; + } + case kpidPosition: + { + /* + if (ref2.Refs.Size() > 1) + propVariant = ref2.StartPos; + else + */ + if (item.IsStartPosDefined) + propVariant = item.StartPos; + break; + } + case kpidPackedSize: + { + // propVariant = ref2.PackSize; + { + CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + { + if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2) + propVariant = _database.GetFolderFullPackSize(folderIndex); + /* + else + propVariant = UInt64(0); + */ + } + else + propVariant = UInt64(0); + } + break; + } + case kpidLastAccessTime: + MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, propVariant); + break; + case kpidCreationTime: + MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, propVariant); + break; + case kpidLastWriteTime: + MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, propVariant); + break; + case kpidAttributes: + if (item.AreAttributesDefined) + propVariant = item.Attributes; + break; + case kpidCRC: + if (item.IsFileCRCDefined) + propVariant = item.FileCRC; + 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' '; + CMethodInfo methodInfo; + + bool methodIsKnown; + + for (int j = 0; j < coderInfo.AltCoders.Size(); j++) + { + if (j > 0) + methodsString += L"|"; + const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders[j]; + + UString methodName; + #ifdef NO_REGISTRY + + methodIsKnown = true; + if (altCoderInfo.MethodID == k_Copy) + methodName = L"Copy"; + else if (altCoderInfo.MethodID == k_LZMA) + methodName = L"LZMA"; + else if (altCoderInfo.MethodID == k_BCJ) + methodName = L"BCJ"; + else if (altCoderInfo.MethodID == k_BCJ2) + methodName = L"BCJ2"; + else if (altCoderInfo.MethodID == k_PPMD) + methodName = L"PPMD"; + else if (altCoderInfo.MethodID == k_Deflate) + methodName = L"Deflate"; + else if (altCoderInfo.MethodID == k_BZip2) + methodName = L"BZip2"; + else + methodIsKnown = false; + + #else + + methodIsKnown = GetMethodInfo( + altCoderInfo.MethodID, methodInfo); + methodName = methodInfo.Name; + + #endif + + if (methodIsKnown) + { + methodsString += methodName; + if (altCoderInfo.MethodID == k_LZMA) + { + if (altCoderInfo.Properties.GetCapacity() >= 5) + { + methodsString += L":"; + UInt32 dicSize = GetUInt32FromMemLE( + ((const Byte *)altCoderInfo.Properties + 1)); + methodsString += GetStringForSizeValue(dicSize); + } + } + else if (altCoderInfo.MethodID == k_PPMD) + { + if (altCoderInfo.Properties.GetCapacity() >= 5) + { + Byte order = *(const Byte *)altCoderInfo.Properties; + methodsString += L":o"; + methodsString += ConvertUInt32ToString(order); + methodsString += L":mem"; + UInt32 dicSize = GetUInt32FromMemLE( + ((const Byte *)altCoderInfo.Properties + 1)); + methodsString += GetStringForSizeValue(dicSize); + } + } + else + { + if (altCoderInfo.Properties.GetCapacity() > 0) + { + methodsString += L":["; + for (size_t bi = 0; bi < altCoderInfo.Properties.GetCapacity(); bi++) + { + if (bi > 2 && bi + 1 < altCoderInfo.Properties.GetCapacity()) + { + methodsString += L".."; + break; + } + else + methodsString += GetHex2(altCoderInfo.Properties[bi]); + } + methodsString += L"]"; + } + } + } + else + { + methodsString += altCoderInfo.MethodID.ConvertToString(); + } + } + } + propVariant = methodsString; + } + } + break; + case kpidBlock: + { + CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + propVariant = (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)) + { + propVariant = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); + } + else + propVariant = UInt64(0); + } + else + propVariant = UInt64(0); + } + break; + #endif + case kpidIsAnti: + propVariant = item.IsAnti; + break; + } + propVariant.Detach(value); + return S_OK; + COM_TRY_END +} + +static const wchar_t *kExt = L"7z"; +static const wchar_t *kAfterPart = L".7z"; + +#ifdef _7Z_VOL + +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); + } + while(true) + { + CMyComPtr inStream; + if (!_volumes.IsEmpty()) + { + if (!openVolumeCallback) + break; + if(_volumes.Size() == 1) + { + UString baseName; + { + NCOM::CPropVariant propVariant; + RINOK(openVolumeCallback->GetProperty(kpidName, &propVariant)); + if (propVariant.vt != VT_BSTR) + break; + baseName = propVariant.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(_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; + const CAltCoderInfo &altCoder = coder.AltCoders.Front(); + if (altCoder.MethodID.IDSize != 1 || altCoder.MethodID.ID[0] != 0) + 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 + const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); + _numThreads = numProcessors; + + 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) + { + RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); + continue; + } + else + return E_INVALIDARG; + } + } + return S_OK; + COM_TRY_END +} + +#endif +#endif + +}} -- cgit v1.2.3