summaryrefslogtreecommitdiffstats
path: root/CPP/7zip/Archive/7z/7zHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/7z/7zHandler.cpp')
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandler.cpp482
1 files changed, 482 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
new file mode 100755
index 0000000..c404b9c
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -0,0 +1,482 @@
+// 7zHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+
+#ifndef __7Z_SET_PROPERTIES
+#include "../../../Windows/System.h"
+#endif
+
+#include "../Common/ItemNameUtils.h"
+
+#include "7zHandler.h"
+#include "7zProperties.h"
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+#include "../Common/ParseProperties.h"
+#endif
+#endif
+
+using namespace NWindows;
+
+extern UString ConvertMethodIdToString(UInt64 id);
+
+namespace NArchive {
+namespace N7z {
+
+CHandler::CHandler()
+{
+ _crcSize = 4;
+
+ #ifndef _NO_CRYPTO
+ _passwordIsDefined = false;
+ #endif
+
+ #ifdef EXTRACT_ONLY
+ #ifdef __7Z_SET_PROPERTIES
+ _numThreads = NSystem::GetNumberOfProcessors();
+ #endif
+ #else
+ Init();
+ #endif
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _db.Files.Size();
+ 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},
+ { NULL, kpidPhySize, VT_UI8},
+ { NULL, kpidHeadersSize, VT_UI8},
+ { NULL, kpidOffset, VT_UI8}
+};
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+ switch(propID)
+ {
+ case kpidMethod:
+ {
+ UString resString;
+ CRecordVector<UInt64> ids;
+ int i;
+ for (i = 0; i < _db.Folders.Size(); i++)
+ {
+ const CFolder &f = _db.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 = _db.IsSolid(); break;
+ case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break;
+ case kpidHeadersSize: prop = _db.HeadersSize; break;
+ case kpidPhySize: prop = _db.PhySize; break;
+ case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+IMP_IInArchive_ArcProps
+
+#endif
+
+static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop)
+{
+ UInt64 value;
+ if (v.GetItem(index, value))
+ {
+ FILETIME ft;
+ ft.dwLowDateTime = (DWORD)value;
+ ft.dwHighDateTime = (DWORD)(value >> 32);
+ prop = ft;
+ }
+}
+
+#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_Delta = 3;
+static const UInt64 k_LZMA2 = 0x21;
+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 void AddHexToString(UString &res, Byte value)
+{
+ res += GetHex((Byte)(value >> 4));
+ res += GetHex((Byte)(value & 0xF));
+}
+
+#endif
+
+bool CHandler::IsEncrypted(UInt32 index2) const
+{
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ return _db.Folders[folderIndex].IsEncrypted();
+ return false;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+
+ /*
+ const CRef2 &ref2 = _refs[index];
+ if (ref2.Refs.IsEmpty())
+ return E_FAIL;
+ const CRef &ref = ref2.Refs.Front();
+ */
+
+ const CFileItem &item = _db.Files[index];
+ UInt32 index2 = index;
+
+ switch(propID)
+ {
+ case kpidPath:
+ if (!item.Name.IsEmpty())
+ prop = NItemName::GetOSName(item.Name);
+ break;
+ case kpidIsDir: prop = item.IsDir; break;
+ case kpidSize:
+ {
+ prop = item.Size;
+ // prop = ref2.Size;
+ break;
+ }
+ case kpidPackSize:
+ {
+ // prop = ref2.PackSize;
+ {
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
+ prop = _db.GetFolderFullPackSize(folderIndex);
+ /*
+ else
+ prop = (UInt64)0;
+ */
+ }
+ else
+ prop = (UInt64)0;
+ }
+ break;
+ }
+ case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; }
+ case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break;
+ case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break;
+ case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break;
+ case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break;
+ case kpidCRC: if (item.CrcDefined) prop = item.Crc; break;
+ case kpidEncrypted: prop = IsEncrypted(index2); break;
+ case kpidIsAnti: prop = _db.IsItemAnti(index2); break;
+ #ifndef _SFX
+ case kpidMethod:
+ {
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ const CFolder &folderInfo = _db.Folders[folderIndex];
+ UString methodsString;
+ for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
+ {
+ const CCoderInfo &coder = folderInfo.Coders[i];
+ if (!methodsString.IsEmpty())
+ methodsString += L' ';
+
+ UString methodName, propsString;
+ bool methodIsKnown = FindMethod(
+ EXTERNAL_CODECS_VARS
+ coder.MethodID, methodName);
+
+ if (!methodIsKnown)
+ methodsString += ConvertMethodIdToString(coder.MethodID);
+ else
+ {
+ methodsString += methodName;
+ if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1)
+ propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1);
+ else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5)
+ {
+ UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
+ propsString = GetStringForSizeValue(dicSize);
+ }
+ else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)
+ {
+ Byte p = coder.Props[0];
+ UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));
+ propsString = GetStringForSizeValue(dicSize);
+ }
+ else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)
+ {
+ Byte order = *(const Byte *)coder.Props;
+ propsString = L'o';
+ propsString += ConvertUInt32ToString(order);
+ propsString += L":mem";
+ UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
+ propsString += GetStringForSizeValue(dicSize);
+ }
+ else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)
+ {
+ const Byte *data = (const Byte *)coder.Props;
+ Byte firstByte = *data++;
+ UInt32 numCyclesPower = firstByte & 0x3F;
+ propsString = ConvertUInt32ToString(numCyclesPower);
+ /*
+ if ((firstByte & 0xC0) != 0)
+ {
+ UInt32 saltSize = (firstByte >> 7) & 1;
+ UInt32 ivSize = (firstByte >> 6) & 1;
+ if (coder.Props.GetCapacity() >= 2)
+ {
+ Byte secondByte = *data++;
+ saltSize += (secondByte >> 4);
+ ivSize += (secondByte & 0x0F);
+ }
+ }
+ */
+ }
+ }
+ if (!propsString.IsEmpty())
+ {
+ methodsString += L':';
+ methodsString += propsString;
+ }
+ else if (coder.Props.GetCapacity() > 0)
+ {
+ methodsString += L":[";
+ for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++)
+ {
+ if (bi > 5 && bi + 1 < coder.Props.GetCapacity())
+ {
+ methodsString += L"..";
+ break;
+ }
+ else
+ AddHexToString(methodsString, coder.Props[bi]);
+ }
+ methodsString += L']';
+ }
+ }
+ prop = methodsString;
+ }
+ }
+ break;
+ case kpidBlock:
+ {
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ prop = (UInt32)folderIndex;
+ }
+ break;
+ case kpidPackedSize0:
+ case kpidPackedSize1:
+ case kpidPackedSize2:
+ case kpidPackedSize3:
+ case kpidPackedSize4:
+ {
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ const CFolder &folderInfo = _db.Folders[folderIndex];
+ if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
+ folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
+ {
+ prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
+ }
+ else
+ prop = (UInt64)0;
+ }
+ else
+ prop = (UInt64)0;
+ }
+ break;
+ #endif
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ #ifndef _SFX
+ _fileInfoPopIDs.Clear();
+ #endif
+ try
+ {
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+ if (openArchiveCallback)
+ {
+ openArchiveCallbackTemp.QueryInterface(
+ IID_ICryptoGetTextPassword, &getTextPassword);
+ }
+ #endif
+ CInArchive archive;
+ RINOK(archive.Open(stream, maxCheckStartPosition));
+ #ifndef _NO_CRYPTO
+ _passwordIsDefined = false;
+ UString password;
+ #endif
+ HRESULT result = archive.ReadDatabase(
+ EXTERNAL_CODECS_VARS
+ _db
+ #ifndef _NO_CRYPTO
+ , getTextPassword, _passwordIsDefined
+ #endif
+ );
+ RINOK(result);
+ _db.Fill();
+ _inStream = stream;
+ }
+ catch(...)
+ {
+ Close();
+ return S_FALSE;
+ }
+ // _inStream = stream;
+ #ifndef _SFX
+ FillPopIDs();
+ #endif
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ COM_TRY_BEGIN
+ _inStream.Release();
+ _db.Clear();
+ return S_OK;
+ COM_TRY_END
+}
+
+#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
+
+IMPL_ISetCompressCodecsInfo
+
+}}