📄 7zhandlerout.cpp
字号:
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.UseAdditionalHeaderStreams = useAdditionalHeaderStreams;
options.CompressMainHeader = compressMainHeader;
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 int ParseStringToUInt32(const UString &srcString, UInt32 &number)
{
const wchar_t *start = srcString;
const wchar_t *end;
UInt64 number64 = ConvertStringToUInt64(start, &end);
if (number64 > 0xFFFFFFFF)
{
number = 0;
return 0;
}
number = (UInt32)number64;
return end - start;
}
static const int kLogarithmicSizeLimit = 32;
static const char kByteSymbol = 'B';
static const char kKiloByteSymbol = 'K';
static const char kMegaByteSymbol = 'M';
HRESULT ParseDictionaryValues(const UString &srcStringSpec, UInt32 &dicSize)
{
UString srcString = srcStringSpec;
srcString.MakeUpper();
const wchar_t *start = srcString;
const wchar_t *end;
UInt64 number = ConvertStringToUInt64(start, &end);
int numDigits = end - start;
if (numDigits == 0 || srcString.Length() > numDigits + 1)
return E_INVALIDARG;
if (srcString.Length() == numDigits)
{
if (number >= kLogarithmicSizeLimit)
return E_INVALIDARG;
dicSize = (UInt32)1 << (int)number;
return S_OK;
}
switch (srcString[numDigits])
{
case kByteSymbol:
if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
return E_INVALIDARG;
dicSize = (UInt32)number;
break;
case kKiloByteSymbol:
if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
return E_INVALIDARG;
dicSize = UInt32(number << 10);
break;
case kMegaByteSymbol:
if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
return E_INVALIDARG;
dicSize = UInt32(number << 20);
break;
default:
return E_INVALIDARG;
}
return S_OK;
}
static inline UINT GetCurrentFileCodePage()
{
return AreFileApisANSI() ? CP_ACP : CP_OEMCP;
}
static HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
{
switch(value.vt)
{
case VT_EMPTY:
dest = true;
break;
/*
case VT_UI4:
dest = (value.ulVal != 0);
break;
*/
case VT_BSTR:
{
UString valueString = value.bstrVal;
valueString.MakeUpper();
if (valueString.Compare(L"ON") == 0)
dest = true;
else if (valueString.Compare(L"OFF") == 0)
dest = false;
else
return E_INVALIDARG;
break;
}
default:
return E_INVALIDARG;
}
return S_OK;
}
/*
static HRESULT SetComplexProperty(bool &boolStatus, UInt32 &number,
const PROPVARIANT &value)
{
switch(value.vt)
{
case VT_EMPTY:
case VT_BSTR:
{
RINOK(SetBoolProperty(boolStatus, value));
return S_OK;
}
case VT_UI4:
boolStatus = true;
number = (value.ulVal);
break;
default:
return E_INVALIDARG;
}
return S_OK;
}
*/
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 ¶m, 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(ParseDictionaryValues(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 ¶m = 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 += 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)
{
UINT codePage = GetCurrentFileCodePage();
COM_TRY_BEGIN
_methods.Clear();
_binds.Clear();
Init();
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;
if (value.vt == VT_UI4)
{
if (!name.IsEmpty())
return E_INVALIDARG;
_level = value.ulVal;
}
else if (value.vt == VT_EMPTY)
{
if(!name.IsEmpty())
{
int index = ParseStringToUInt32(name, _level);
if (index != name.Length())
return E_INVALIDARG;
}
}
else
return E_INVALIDARG;
if (_level == 0)
{
_copyMode = true;
}
else if (_level < 5)
{
_defaultAlgorithm = kAlgorithmForFast;
_defaultDicSize = kDicSizeForFast;
_defaultMatchFinder = kMatchFinderForFast;
}
else if (_level < 7)
{
// normal;
}
else if(_level < 9)
{
_defaultAlgorithm = kAlgorithmForX7;
_defaultDicSize = kDicSizeForX7;
_defaultFastBytes = kFastBytesForX7;
}
else
{
_defaultAlgorithm = kAlgorithmForX9;
_defaultDicSize = kDicSizeForX9;
_defaultFastBytes = kFastBytesForX9;
_defaultMatchFinder = kMatchFinderForX9;
}
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.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"MT") == 0)
{
// _multiThreadMult = 200;
RINOK(SetBoolProperty(_multiThread, value));
// RINOK(SetComplexProperty(MultiThread, _multiThreadMult, 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.CompareNoCase(L"D") == 0 || realName.CompareNoCase(L"MEM") == 0)
{
UInt32 dicSize;
if (value.vt == VT_UI4)
{
UInt32 logDicSize = value.ulVal;
if (logDicSize >= 32)
return E_INVALIDARG;
dicSize = (UInt32)1 << logDicSize;
}
else if (value.vt == VT_BSTR)
{
RINOK(ParseDictionaryValues(value.bstrVal, dicSize));
}
else
return E_FAIL;
if (realName.CompareNoCase(L"D") == 0)
property.PropID = NCoderPropID::kDictionarySize;
else
property.PropID = NCoderPropID::kUsedMemorySize;
property.Value = dicSize;
oneMethodInfo.CoderProperties.Add(property);
}
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);
}
}
}
CheckAndSetSolidBytesLimit();
return S_OK;
COM_TRY_END
}
}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -