Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2007-01-20 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:49 +0300
commitd9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch)
treec722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Archive/7z/7zHandlerOut.cpp
parent804edc5756fede54dbb1aefda6d39d306111938d (diff)
4.44 beta
Diffstat (limited to 'CPP/7zip/Archive/7z/7zHandlerOut.cpp')
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandlerOut.cpp1148
1 files changed, 1148 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
new file mode 100755
index 00000000..8be88c38
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -0,0 +1,1148 @@
+// 7z/OutHandler.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zOut.h"
+#include "7zUpdate.h"
+#include "7zMethods.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringToInt.h"
+#include "../../IPassword.h"
+#include "../../ICoder.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/ParseProperties.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace N7z {
+
+#ifdef COMPRESS_LZMA
+static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+static CMethodID k_LZMA2 = { { 0x3, 0x1, 0x2 }, 3 };
+#endif
+
+#ifdef COMPRESS_PPMD
+static CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
+#endif
+
+#ifdef COMPRESS_BCJ_X86
+static CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
+#endif
+
+#ifdef COMPRESS_BCJ2
+static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
+#endif
+
+#ifdef COMPRESS_COPY
+static CMethodID k_Copy = { { 0x0 }, 1 };
+#endif
+
+#ifdef COMPRESS_DEFLATE
+#ifndef COMPRESS_DEFLATE_ENCODER
+#define COMPRESS_DEFLATE_ENCODER
+#endif
+#endif
+
+#ifdef COMPRESS_DEFLATE_ENCODER
+static CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
+#endif
+
+#ifdef COMPRESS_BZIP2
+#ifndef COMPRESS_BZIP2_ENCODER
+#define COMPRESS_BZIP2_ENCODER
+#endif
+#endif
+
+#ifdef COMPRESS_BZIP2_ENCODER
+static CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
+#endif
+
+const wchar_t *kCopyMethod = L"Copy";
+const wchar_t *kLZMAMethodName = L"LZMA";
+const wchar_t *kLZMA2MethodName = L"LZMA2";
+const wchar_t *kBZip2MethodName = L"BZip2";
+const wchar_t *kPpmdMethodName = L"PPMd";
+const wchar_t *kDeflateMethodName = L"Deflate";
+const wchar_t *kDeflate64MethodName = L"Deflate64";
+
+static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
+static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
+
+static const UInt32 kLzmaAlgorithmX1 = 0;
+static const UInt32 kLzmaAlgorithmX5 = 1;
+
+static const UInt32 kLzmaDicSizeX1 = 1 << 16;
+static const UInt32 kLzmaDicSizeX3 = 1 << 20;
+static const UInt32 kLzmaDicSizeX5 = 1 << 22;
+static const UInt32 kLzmaDicSizeX7 = 1 << 24;
+static const UInt32 kLzmaDicSizeX9 = 1 << 26;
+
+static const UInt32 kLzmaFastBytesX1 = 32;
+static const UInt32 kLzmaFastBytesX7 = 64;
+
+static const UInt32 kPpmdMemSizeX1 = (1 << 22);
+static const UInt32 kPpmdMemSizeX5 = (1 << 24);
+static const UInt32 kPpmdMemSizeX7 = (1 << 26);
+static const UInt32 kPpmdMemSizeX9 = (192 << 20);
+
+static const UInt32 kPpmdOrderX1 = 4;
+static const UInt32 kPpmdOrderX5 = 6;
+static const UInt32 kPpmdOrderX7 = 16;
+static const UInt32 kPpmdOrderX9 = 32;
+
+static const UInt32 kDeflateFastBytesX1 = 32;
+static const UInt32 kDeflateFastBytesX7 = 64;
+static const UInt32 kDeflateFastBytesX9 = 128;
+
+static const UInt32 kDeflatePassesX1 = 1;
+static const UInt32 kDeflatePassesX7 = 3;
+static const UInt32 kDeflatePassesX9 = 10;
+
+static const UInt32 kBZip2NumPassesX1 = 1;
+static const UInt32 kBZip2NumPassesX7 = 2;
+static const UInt32 kBZip2NumPassesX9 = 7;
+
+static const UInt32 kBZip2DicSizeX1 = 100000;
+static const UInt32 kBZip2DicSizeX3 = 500000;
+static const UInt32 kBZip2DicSizeX5 = 900000;
+
+const wchar_t *kDefaultMethodName = kLZMAMethodName;
+
+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
+static const UInt32 kDictionaryForHeaders = 1 << 20;
+static const UInt32 kNumFastBytesForHeaders = 273;
+static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;
+
+static bool IsCopyMethod(const UString &methodName)
+ { return (methodName.CompareNoCase(kCopyMethod) == 0); }
+
+static bool IsLZMAMethod(const UString &methodName)
+{
+ return
+ (methodName.CompareNoCase(kLZMAMethodName) == 0) ||
+ (methodName.CompareNoCase(kLZMA2MethodName) == 0);
+}
+
+/*
+static bool IsLZMethod(const UString &methodName)
+ { return IsLZMAMethod(methodName); }
+*/
+
+static bool IsBZip2Method(const UString &methodName)
+ { return (methodName.CompareNoCase(kBZip2MethodName) == 0); }
+
+static bool IsPpmdMethod(const UString &methodName)
+ { return (methodName.CompareNoCase(kPpmdMethodName) == 0); }
+
+static bool IsDeflateMethod(const UString &methodName)
+ { return (methodName.CompareNoCase(kDeflateMethodName) == 0) ||
+ (methodName.CompareNoCase(kDeflate64MethodName) == 0); }
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kWindows;
+ return S_OK;
+}
+
+HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode,
+ IArchiveUpdateCallback *updateCallback)
+{
+ CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
+ if (!getTextPassword)
+ {
+ CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback);
+ udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
+ }
+
+ if (getTextPassword)
+ {
+ CMyComBSTR password;
+ Int32 passwordIsDefined;
+ RINOK(getTextPassword->CryptoGetTextPassword2(
+ &passwordIsDefined, &password));
+ methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
+ if (methodMode.PasswordIsDefined)
+ methodMode.Password = password;
+ }
+ else
+ methodMode.PasswordIsDefined = false;
+ return S_OK;
+}
+
+struct CNameToPropID
+{
+ PROPID PropID;
+ VARTYPE VarType;
+ const wchar_t *Name;
+};
+
+CNameToPropID g_NameToPropID[] =
+{
+ { NCoderPropID::kOrder, VT_UI4, L"O" },
+ { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
+ { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
+ { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },
+
+ { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },
+ { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },
+ { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
+ { NCoderPropID::kAlgorithm, VT_UI4, L"a" },
+ { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
+ { NCoderPropID::kNumThreads, VT_UI4, L"mt" }
+};
+
+bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType,
+ NCOM::CPropVariant &destProp)
+{
+ if (varType == srcProp.vt)
+ {
+ destProp = srcProp;
+ return true;
+ }
+ if (varType == VT_UI1)
+ {
+ if(srcProp.vt == VT_UI4)
+ {
+ UInt32 value = srcProp.ulVal;
+ if (value > 0xFF)
+ return false;
+ destProp = Byte(value);
+ return true;
+ }
+ }
+ return false;
+}
+
+const int kNumNameToPropIDItems = sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]);
+
+int FindPropIdFromStringName(const UString &name)
+{
+ for (int i = 0; i < kNumNameToPropIDItems; i++)
+ if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
+ return i;
+ return -1;
+}
+
+HRESULT CHandler::SetCompressionMethod(
+ CCompressionMethodMode &methodMode,
+ CCompressionMethodMode &headerMethod)
+{
+ HRESULT res = SetCompressionMethod(methodMode, _methods
+ #ifdef COMPRESS_MT
+ , _numThreads
+ #endif
+ );
+ RINOK(res);
+ methodMode.Binds = _binds;
+ if (_compressHeadersFull)
+ _compressHeaders = true;
+
+ if (_compressHeaders)
+ {
+ // headerMethod.Methods.Add(methodMode.Methods.Back());
+
+ CObjectVector<COneMethodInfo> headerMethodInfoVector;
+ COneMethodInfo oneMethodInfo;
+ oneMethodInfo.MethodName = kLZMAMethodName;
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kMatchFinder;
+ property.Value = kLzmaMatchFinderForHeaders;
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kAlgorithm;
+ property.Value = kAlgorithmForHeaders;
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kNumFastBytes;
+ property.Value = UInt32(kNumFastBytesForHeaders);
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kDictionarySize;
+ property.Value = UInt32(kDictionaryForHeaders);
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ headerMethodInfoVector.Add(oneMethodInfo);
+ HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector
+ #ifdef COMPRESS_MT
+ ,1
+ #endif
+ );
+ RINOK(res);
+ }
+ return S_OK;
+}
+
+static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID,
+ const NWindows::NCOM::CPropVariant &value)
+{
+ int j;
+ for (j = 0; j < oneMethodInfo.CoderProperties.Size(); j++)
+ if (oneMethodInfo.CoderProperties[j].PropID == propID)
+ break;
+ if (j != oneMethodInfo.CoderProperties.Size())
+ return;
+ CProperty property;
+ property.PropID = propID;
+ property.Value = value;
+ oneMethodInfo.CoderProperties.Add(property);
+}
+
+HRESULT CHandler::SetCompressionMethod(
+ CCompressionMethodMode &methodMode,
+ CObjectVector<COneMethodInfo> &methodsInfo
+ #ifdef COMPRESS_MT
+ , UInt32 numThreads
+ #endif
+ )
+{
+ #ifndef EXCLUDE_COM
+ /*
+ CObjectVector<CMethodInfo2> methodInfoVector;
+ if (!NRegistryInfo::EnumerateAllMethods(methodInfoVector))
+ return E_FAIL;
+ */
+ #endif
+
+
+ UInt32 level = _level;
+
+ if (methodsInfo.IsEmpty())
+ {
+ COneMethodInfo oneMethodInfo;
+ oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);
+ methodsInfo.Add(oneMethodInfo);
+ }
+
+ bool needSolid = false;
+ for(int i = 0; i < methodsInfo.Size(); i++)
+ {
+ COneMethodInfo &oneMethodInfo = methodsInfo[i];
+ if (oneMethodInfo.MethodName.IsEmpty())
+ oneMethodInfo.MethodName = kDefaultMethodName;
+
+ if (!IsCopyMethod(oneMethodInfo.MethodName))
+ needSolid = true;
+
+ if (IsLZMAMethod(oneMethodInfo.MethodName))
+ {
+ UInt32 dicSize =
+ (level >= 9 ? kLzmaDicSizeX9 :
+ (level >= 7 ? kLzmaDicSizeX7 :
+ (level >= 5 ? kLzmaDicSizeX5 :
+ (level >= 3 ? kLzmaDicSizeX3 :
+ kLzmaDicSizeX1))));
+
+ UInt32 algorithm =
+ (level >= 5 ? kLzmaAlgorithmX5 :
+ kLzmaAlgorithmX1);
+
+ UInt32 fastBytes =
+ (level >= 7 ? kLzmaFastBytesX7 :
+ kLzmaFastBytesX1);
+
+ const wchar_t *matchFinder =
+ (level >= 5 ? kLzmaMatchFinderX5 :
+ kLzmaMatchFinderX1);
+
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algorithm);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
+ #ifdef COMPRESS_MT
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
+ #endif
+ }
+ else if (IsDeflateMethod(oneMethodInfo.MethodName))
+ {
+ UInt32 fastBytes =
+ (level >= 9 ? kDeflateFastBytesX9 :
+ (level >= 7 ? kDeflateFastBytesX7 :
+ kDeflateFastBytesX1));
+
+ UInt32 numPasses =
+ (level >= 9 ? kDeflatePassesX9 :
+ (level >= 7 ? kDeflatePassesX7 :
+ kDeflatePassesX1));
+
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
+ }
+ else if (IsBZip2Method(oneMethodInfo.MethodName))
+ {
+ UInt32 numPasses =
+ (level >= 9 ? kBZip2NumPassesX9 :
+ (level >= 7 ? kBZip2NumPassesX7 :
+ kBZip2NumPassesX1));
+
+ UInt32 dicSize =
+ (level >= 5 ? kBZip2DicSizeX5 :
+ (level >= 3 ? kBZip2DicSizeX3 :
+ kBZip2DicSizeX1));
+
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
+ #ifdef COMPRESS_MT
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
+ #endif
+ }
+ else if (IsPpmdMethod(oneMethodInfo.MethodName))
+ {
+ UInt32 useMemSize =
+ (level >= 9 ? kPpmdMemSizeX9 :
+ (level >= 7 ? kPpmdMemSizeX7 :
+ (level >= 5 ? kPpmdMemSizeX5 :
+ kPpmdMemSizeX1)));
+
+ UInt32 order =
+ (level >= 9 ? kPpmdOrderX9 :
+ (level >= 7 ? kPpmdOrderX7 :
+ (level >= 5 ? kPpmdOrderX5 :
+ kPpmdOrderX1)));
+
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
+ }
+
+
+ CMethodFull methodFull;
+ methodFull.NumInStreams = 1;
+ methodFull.NumOutStreams = 1;
+
+ bool defined = false;
+
+ #ifdef COMPRESS_LZMA
+ if (oneMethodInfo.MethodName.CompareNoCase(L"LZMA") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_LZMA;
+ }
+ #endif
+
+ #ifdef COMPRESS_PPMD
+ if (oneMethodInfo.MethodName.CompareNoCase(L"PPMD") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_PPMD;
+ }
+ #endif
+
+ #ifdef COMPRESS_BCJ_X86
+ if (oneMethodInfo.MethodName.CompareNoCase(L"BCJ") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_BCJ_X86;
+ }
+ #endif
+
+ #ifdef COMPRESS_BCJ2
+ if (oneMethodInfo.MethodName.CompareNoCase(L"BCJ2") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_BCJ2;
+ methodFull.NumInStreams = 4;
+ methodFull.NumOutStreams = 1;
+ }
+ #endif
+
+ #ifdef COMPRESS_DEFLATE_ENCODER
+ if (oneMethodInfo.MethodName.CompareNoCase(L"Deflate") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_Deflate;
+ }
+ #endif
+
+ #ifdef COMPRESS_BZIP2_ENCODER
+ if (oneMethodInfo.MethodName.CompareNoCase(L"BZip2") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_BZip2;
+ }
+ #endif
+
+ #ifdef COMPRESS_COPY
+ if (oneMethodInfo.MethodName.CompareNoCase(L"Copy") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_Copy;
+ }
+
+ #endif
+
+ #ifndef EXCLUDE_COM
+
+ if (!defined)
+ {
+ CMethodInfo2 methodInfo;
+ if (!GetMethodInfo(oneMethodInfo.MethodName, methodInfo))
+ return E_INVALIDARG;
+ if (!methodInfo.EncoderIsAssigned)
+ return E_INVALIDARG;
+
+ methodFull.MethodID = methodInfo.MethodID;
+ methodFull.NumInStreams = methodInfo.NumInStreams;
+ methodFull.NumOutStreams = methodInfo.NumOutStreams;
+
+ methodFull.EncoderClassID = methodInfo.Encoder;
+ methodFull.FilePath = methodInfo.FilePath;
+ defined = true;
+ }
+
+ #endif
+ if (!defined)
+ return E_INVALIDARG;
+
+ methodFull.CoderProperties = oneMethodInfo.CoderProperties;
+ methodMode.Methods.Add(methodFull);
+
+ if (!_numSolidBytesDefined)
+ {
+ for (int j = 0; j < methodFull.CoderProperties.Size(); j++)
+ {
+ const CProperty &prop = methodFull.CoderProperties[j];
+ if ((prop.PropID == NCoderPropID::kDictionarySize ||
+ prop.PropID == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)
+ {
+ _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;
+ const UInt64 kMinSize = (1 << 24);
+ if (_numSolidBytes < kMinSize)
+ _numSolidBytes = kMinSize;
+ _numSolidBytesDefined = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!needSolid && !_numSolidBytesDefined)
+ {
+ _numSolidBytesDefined = true;
+ _numSolidBytes = 0;
+ }
+ return S_OK;
+}
+
+static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, CArchiveFileTime &filetime, bool &filetimeIsDefined)
+{
+ filetimeIsDefined = false;
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(index, propID, &propVariant));
+ if (propVariant.vt == VT_FILETIME)
+ {
+ filetime = propVariant.filetime;
+ filetimeIsDefined = true;
+ }
+ else if (propVariant.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ COM_TRY_BEGIN
+
+ const CArchiveDatabaseEx *database = 0;
+ #ifdef _7Z_VOL
+ if(_volumes.Size() > 1)
+ return E_FAIL;
+ const CVolume *volume = 0;
+ if (_volumes.Size() == 1)
+ {
+ volume = &_volumes.Front();
+ database = &volume->Database;
+ }
+ #else
+ if (_inStream != 0)
+ database = &_database;
+ #endif
+
+ // CRecordVector<bool> compressStatuses;
+ CObjectVector<CUpdateItem> updateItems;
+ // CRecordVector<UInt32> copyIndices;
+
+ // CMyComPtr<IUpdateCallback2> updateCallback2;
+ // updateCallback->QueryInterface(&updateCallback2);
+
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ Int32 newData;
+ Int32 newProperties;
+ UInt32 indexInArchive;
+ if (!updateCallback)
+ return E_FAIL;
+ RINOK(updateCallback->GetUpdateItemInfo(i,
+ &newData, &newProperties, &indexInArchive));
+ CUpdateItem updateItem;
+ updateItem.NewProperties = IntToBool(newProperties);
+ updateItem.NewData = IntToBool(newData);
+ updateItem.IndexInArchive = indexInArchive;
+ updateItem.IndexInClient = i;
+ updateItem.IsAnti = false;
+ updateItem.Size = 0;
+
+ if (updateItem.IndexInArchive != -1)
+ {
+ const CFileItem &fileItem = database->Files[updateItem.IndexInArchive];
+ updateItem.Name = fileItem.Name;
+ updateItem.IsDirectory = fileItem.IsDirectory;
+ updateItem.Size = fileItem.UnPackSize;
+ updateItem.IsAnti = fileItem.IsAnti;
+
+ updateItem.CreationTime = fileItem.CreationTime;
+ updateItem.IsCreationTimeDefined = fileItem.IsCreationTimeDefined;
+ updateItem.LastWriteTime = fileItem.LastWriteTime;
+ updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined;
+ updateItem.LastAccessTime = fileItem.LastAccessTime;
+ updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined;
+ }
+
+ if (updateItem.NewProperties)
+ {
+ bool nameIsDefined;
+ bool folderStatusIsDefined;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ updateItem.AttributesAreDefined = false;
+ else if (propVariant.vt != VT_UI4)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.Attributes = propVariant.ulVal;
+ updateItem.AttributesAreDefined = true;
+ }
+ }
+
+ RINOK(GetTime(updateCallback, i, kpidCreationTime, updateItem.CreationTime, updateItem.IsCreationTimeDefined));
+ RINOK(GetTime(updateCallback, i, kpidLastWriteTime, updateItem.LastWriteTime , updateItem.IsLastWriteTimeDefined));
+ RINOK(GetTime(updateCallback, i, kpidLastAccessTime, updateItem.LastAccessTime, updateItem.IsLastAccessTimeDefined));
+
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ nameIsDefined = false;
+ else if (propVariant.vt != VT_BSTR)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal);
+ nameIsDefined = true;
+ }
+ }
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ folderStatusIsDefined = false;
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE);
+ folderStatusIsDefined = true;
+ }
+ }
+
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ updateItem.IsAnti = false;
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE);
+ }
+
+ if (updateItem.IsAnti)
+ {
+ updateItem.AttributesAreDefined = false;
+
+ updateItem.IsCreationTimeDefined = false;
+ updateItem.IsLastWriteTimeDefined = false;
+ updateItem.IsLastAccessTimeDefined = false;
+
+ updateItem.Size = 0;
+ }
+
+ if (!folderStatusIsDefined && updateItem.AttributesAreDefined)
+ updateItem.SetDirectoryStatusFromAttributes();
+ }
+
+ if (updateItem.NewData)
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant));
+ if (propVariant.vt != VT_UI8)
+ return E_INVALIDARG;
+ updateItem.Size = (UInt64)propVariant.uhVal.QuadPart;
+ if (updateItem.Size != 0 && updateItem.IsAnti)
+ return E_INVALIDARG;
+ }
+ updateItems.Add(updateItem);
+ }
+
+ CCompressionMethodMode methodMode, headerMethod;
+ RINOK(SetCompressionMethod(methodMode, headerMethod));
+ #ifdef COMPRESS_MT
+ methodMode.NumThreads = _numThreads;
+ headerMethod.NumThreads = 1;
+ #endif
+
+ RINOK(SetPassword(methodMode, updateCallback));
+
+ bool useAdditionalHeaderStreams = true;
+ bool compressMainHeader = false;
+
+ if (_compressHeadersFull)
+ {
+ useAdditionalHeaderStreams = false;
+ compressMainHeader = true;
+ }
+ if (methodMode.PasswordIsDefined)
+ {
+ useAdditionalHeaderStreams = false;
+ compressMainHeader = true;
+ if(_encryptHeaders)
+ RINOK(SetPassword(headerMethod, updateCallback));
+ }
+
+ if (numItems < 2)
+ compressMainHeader = false;
+
+ CUpdateOptions options;
+ options.Method = &methodMode;
+ options.HeaderMethod = (_compressHeaders ||
+ (methodMode.PasswordIsDefined && _encryptHeaders)) ?
+ &headerMethod : 0;
+ options.UseFilters = _level != 0 && _autoFilter;
+ options.MaxFilter = _level >= 8;
+
+ options.HeaderOptions.UseAdditionalHeaderStreams = useAdditionalHeaderStreams;
+ options.HeaderOptions.CompressMainHeader = compressMainHeader;
+ options.HeaderOptions.WriteModified = WriteModified;
+ options.HeaderOptions.WriteCreated = WriteCreated;
+ options.HeaderOptions.WriteAccessed = WriteAccessed;
+
+ options.NumSolidFiles = _numSolidFiles;
+ options.NumSolidBytes = _numSolidBytes;
+ options.SolidExtension = _solidExtension;
+ options.RemoveSfxBlock = _removeSfxBlock;
+ options.VolumeMode = _volumeMode;
+ return Update(
+ #ifdef _7Z_VOL
+ volume ? volume->Stream: 0,
+ volume ? database: 0,
+ #else
+ _inStream,
+ database,
+ #endif
+ updateItems, outStream, updateCallback, options);
+ COM_TRY_END
+}
+
+static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
+{
+ stream = 0;
+ int index = ParseStringToUInt32(srcString, coder);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.Delete(0, index);
+ if (srcString[0] == 'S')
+ {
+ srcString.Delete(0);
+ int index = ParseStringToUInt32(srcString, stream);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.Delete(0, index);
+ }
+ return S_OK;
+}
+
+static HRESULT GetBindInfo(UString &srcString, CBind &bind)
+{
+ RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));
+ if (srcString[0] != ':')
+ return E_INVALIDARG;
+ srcString.Delete(0);
+ RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));
+ if (!srcString.IsEmpty())
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+static void SplitParams(const UString &srcString, UStringVector &subStrings)
+{
+ subStrings.Clear();
+ UString name;
+ int len = srcString.Length();
+ if (len == 0)
+ return;
+ for (int i = 0; i < len; i++)
+ {
+ wchar_t c = srcString[i];
+ if (c == L':')
+ {
+ subStrings.Add(name);
+ name.Empty();
+ }
+ else
+ name += c;
+ }
+ subStrings.Add(name);
+}
+
+static void SplitParam(const UString &param, UString &name, UString &value)
+{
+ int eqPos = param.Find(L'=');
+ if (eqPos >= 0)
+ {
+ name = param.Left(eqPos);
+ value = param.Mid(eqPos + 1);
+ return;
+ }
+ for(int i = 0; i < param.Length(); i++)
+ {
+ wchar_t c = param[i];
+ if (c >= L'0' && c <= L'9')
+ {
+ name = param.Left(i);
+ value = param.Mid(i);
+ return;
+ }
+ }
+ name = param;
+}
+
+HRESULT CHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
+{
+ CProperty property;
+ if (name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0)
+ {
+ UInt32 dicSize;
+ RINOK(ParsePropDictionaryValue(value, dicSize));
+ if (name.CompareNoCase(L"D") == 0)
+ property.PropID = NCoderPropID::kDictionarySize;
+ else
+ property.PropID = NCoderPropID::kUsedMemorySize;
+ property.Value = dicSize;
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ else
+ {
+ int index = FindPropIdFromStringName(name);
+ if (index < 0)
+ return E_INVALIDARG;
+
+ const CNameToPropID &nameToPropID = g_NameToPropID[index];
+ property.PropID = nameToPropID.PropID;
+
+ NCOM::CPropVariant propValue;
+
+
+ if (nameToPropID.VarType == VT_BSTR)
+ propValue = value;
+ else
+ {
+ UInt32 number;
+ if (ParseStringToUInt32(value, number) == value.Length())
+ propValue = number;
+ else
+ propValue = value;
+ }
+
+ if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value))
+ return E_INVALIDARG;
+
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ return S_OK;
+}
+
+HRESULT CHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
+{
+ UStringVector params;
+ SplitParams(srcString, params);
+ if (params.Size() > 0)
+ oneMethodInfo.MethodName = params[0];
+ for (int i = 1; i < params.Size(); i++)
+ {
+ const UString &param = params[i];
+ UString name, value;
+ SplitParam(param, name, value);
+ RINOK(SetParam(oneMethodInfo, name, value));
+ }
+ return S_OK;
+}
+
+HRESULT CHandler::SetSolidSettings(const UString &s)
+{
+ UString s2 = s;
+ s2.MakeUpper();
+ if (s2.IsEmpty() || s2.Compare(L"ON") == 0)
+ {
+ InitSolid();
+ return S_OK;
+ }
+ if (s2.Compare(L"OFF") == 0)
+ {
+ _numSolidFiles = 1;
+ return S_OK;
+ }
+ for (int i = 0; i < s2.Length();)
+ {
+ const wchar_t *start = ((const wchar_t *)s2) + i;
+ const wchar_t *end;
+ UInt64 v = ConvertStringToUInt64(start, &end);
+ if (start == end)
+ {
+ if (s2[i++] != 'E')
+ return E_INVALIDARG;
+ _solidExtension = true;
+ continue;
+ }
+ i += (int)(end - start);
+ if (i == s2.Length())
+ return E_INVALIDARG;
+ wchar_t c = s2[i++];
+ switch(c)
+ {
+ case 'F':
+ if (v < 1)
+ v = 1;
+ _numSolidFiles = v;
+ break;
+ case 'B':
+ _numSolidBytes = v;
+ _numSolidBytesDefined = true;
+ break;
+ case 'K':
+ _numSolidBytes = (v << 10);
+ _numSolidBytesDefined = true;
+ break;
+ case 'M':
+ _numSolidBytes = (v << 20);
+ _numSolidBytesDefined = true;
+ break;
+ case 'G':
+ _numSolidBytes = (v << 30);
+ _numSolidBytesDefined = true;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CHandler::SetSolidSettings(const PROPVARIANT &value)
+{
+ switch(value.vt)
+ {
+ case VT_EMPTY:
+ InitSolid();
+ return S_OK;
+ case VT_BSTR:
+ return SetSolidSettings(value.bstrVal);
+ default:
+ return E_INVALIDARG;
+ }
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+ COM_TRY_BEGIN
+ _methods.Clear();
+ _binds.Clear();
+ Init();
+ #ifdef COMPRESS_MT
+ const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
+ #endif
+
+ UInt32 mainDicSize = 0xFFFFFFFF;
+ UInt32 mainDicMethodIndex = 0xFFFFFFFF;
+
+ UInt32 minNumber = 0;
+
+ for (int i = 0; i < numProperties; i++)
+ {
+ UString name = names[i];
+ name.MakeUpper();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ const PROPVARIANT &value = values[i];
+
+ if (name[0] == 'X')
+ {
+ name.Delete(0);
+ _level = 9;
+ RINOK(ParsePropValue(name, value, _level));
+ continue;
+ }
+
+ if (name[0] == 'B')
+ {
+ name.Delete(0);
+ CBind bind;
+ RINOK(GetBindInfo(name, bind));
+ _binds.Add(bind);
+ continue;
+ }
+
+ if (name[0] == L'S')
+ {
+ name.Delete(0);
+ if (name.IsEmpty())
+ {
+ RINOK(SetSolidSettings(value));
+ }
+ else
+ {
+ RINOK(SetSolidSettings(name));
+ }
+ continue;
+ }
+
+
+ UInt32 number;
+ int index = ParseStringToUInt32(name, number);
+ UString realName = name.Mid(index);
+ 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 if (name.CompareNoCase(L"RSFX") == 0)
+ {
+ RINOK(SetBoolProperty(_removeSfxBlock, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"F") == 0)
+ {
+ RINOK(SetBoolProperty(_autoFilter, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"HC") == 0)
+ {
+ RINOK(SetBoolProperty(_compressHeaders, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"HCF") == 0)
+ {
+ RINOK(SetBoolProperty(_compressHeadersFull, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"HE") == 0)
+ {
+ RINOK(SetBoolProperty(_encryptHeaders, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"TM") == 0)
+ {
+ RINOK(SetBoolProperty(WriteModified, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"TC") == 0)
+ {
+ RINOK(SetBoolProperty(WriteCreated, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"TA") == 0)
+ {
+ RINOK(SetBoolProperty(WriteAccessed, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"V") == 0)
+ {
+ RINOK(SetBoolProperty(_volumeMode, value));
+ continue;
+ }
+ number = 0;
+ }
+ if (number > 10000)
+ return E_FAIL;
+ if (number < minNumber)
+ return E_INVALIDARG;
+ number -= minNumber;
+ for(int j = _methods.Size(); j <= (int)number; j++)
+ {
+ COneMethodInfo oneMethodInfo;
+ _methods.Add(oneMethodInfo);
+ }
+
+ COneMethodInfo &oneMethodInfo = _methods[number];
+
+ if (realName.Length() == 0)
+ {
+ if (value.vt != VT_BSTR)
+ return E_INVALIDARG;
+
+ // oneMethodInfo.MethodName = UnicodeStringToMultiByte(UString(value.bstrVal));
+ RINOK(SetParams(oneMethodInfo, value.bstrVal));
+ }
+ else
+ {
+ CProperty property;
+ if (realName.Left(1).CompareNoCase(L"D") == 0)
+ {
+ UInt32 dicSize;
+ RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));
+ property.PropID = NCoderPropID::kDictionarySize;
+ property.Value = dicSize;
+ oneMethodInfo.CoderProperties.Add(property);
+ if (number <= mainDicMethodIndex)
+ mainDicSize = dicSize;
+ }
+ else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
+ {
+ UInt32 dicSize;
+ RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
+ property.PropID = NCoderPropID::kUsedMemorySize;
+ property.Value = dicSize;
+ oneMethodInfo.CoderProperties.Add(property);
+ if (number <= mainDicMethodIndex)
+ mainDicSize = dicSize;
+ }
+ else
+ {
+ int index = FindPropIdFromStringName(realName);
+ if (index < 0)
+ return E_INVALIDARG;
+
+ const CNameToPropID &nameToPropID = g_NameToPropID[index];
+ property.PropID = nameToPropID.PropID;
+
+ if (!ConvertProperty(value, nameToPropID.VarType, property.Value))
+ return E_INVALIDARG;
+
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ }
+ }
+
+ return S_OK;
+ COM_TRY_END
+}
+
+}}