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:
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipHandlerOut.cpp')
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandlerOut.cpp281
1 files changed, 170 insertions, 111 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index 8a8de511..8ecf7942 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -46,6 +46,30 @@ static bool IsSimpleAsciiString(const wchar_t *s)
}
}
+
+static int FindZipMethod(const char *s, const char * const *names, unsigned num)
+{
+ for (unsigned i = 0; i < num; i++)
+ {
+ const char *name = names[i];
+ if (name && StringsAreEqualNoCase_Ascii(s, name))
+ return i;
+ }
+ return -1;
+}
+
+static int FindZipMethod(const char *s)
+{
+ int k = FindZipMethod(s, kMethodNames1, kNumMethodNames1);
+ if (k >= 0)
+ return k;
+ k = FindZipMethod(s, kMethodNames2, kNumMethodNames2);
+ if (k >= 0)
+ return kMethodNames2Start + k;
+ return -1;
+}
+
+
#define COM_TRY_BEGIN2 try {
#define COM_TRY_END2 } \
catch(const CSystemException &e) { return e.ErrorCode; } \
@@ -63,6 +87,7 @@ static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propI
return S_OK;
}
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *callback)
{
@@ -75,31 +100,46 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
CObjectVector<CUpdateItem> updateItems;
+ updateItems.ClearAndReserve(numItems);
+
bool thereAreAesUpdates = false;
UInt64 largestSize = 0;
bool largestSizeDefined = false;
+ UString name;
+ CUpdateItem ui;
+
for (UInt32 i = 0; i < numItems; i++)
{
- CUpdateItem ui;
Int32 newData;
Int32 newProps;
- UInt32 indexInArchive;
+ UInt32 indexInArc;
+
if (!callback)
return E_FAIL;
- RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+
+ RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc));
+
+ name.Empty();
+ ui.Clear();
+
ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData);
- ui.IndexInArc = indexInArchive;
+ ui.IndexInArc = indexInArc;
ui.IndexInClient = i;
- bool existInArchive = (indexInArchive != (UInt32)(Int32)-1);
- if (existInArchive && newData)
- if (m_Items[indexInArchive].IsAesEncrypted())
+
+ bool existInArchive = (indexInArc != (UInt32)(Int32)-1);
+ if (existInArchive)
+ {
+ const CItemEx &inputItem = m_Items[indexInArc];
+ if (inputItem.IsAesEncrypted())
thereAreAesUpdates = true;
+ if (!IntToBool(newProps))
+ ui.IsDir = inputItem.IsDir();
+ }
if (IntToBool(newProps))
{
- UString name;
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidAttrib, &prop));
@@ -115,12 +155,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidPath, &prop));
if (prop.vt == VT_EMPTY)
- name.Empty();
+ {
+ // name.Empty();
+ }
else if (prop.vt != VT_BSTR)
return E_INVALIDARG;
else
name = prop.bstrVal;
}
+
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidIsDir, &prop));
@@ -153,7 +196,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
FileTimeToDosTime(localFileTime, ui.Time);
}
- name = NItemName::MakeLegalName(name);
+ NItemName::ReplaceSlashes_OsToUnix(name);
+
bool needSlash = ui.IsDir;
const wchar_t kSlash = L'/';
if (!name.IsEmpty())
@@ -188,11 +232,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.Name.Len() >= (1 << 16))
return E_INVALIDARG;
- ui.IndexInClient = i;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidComment, &prop));
+ if (prop.vt == VT_EMPTY)
+ {
+ // ui.Comment.Free();
+ }
+ else if (prop.vt != VT_BSTR)
+ return E_INVALIDARG;
+ else
+ {
+ UString s = prop.bstrVal;
+ AString a;
+ if (ui.IsUtf8)
+ ConvertUnicodeToUTF8(s, a);
+ else
+ {
+ bool defaultCharWasUsed;
+ a = UnicodeStringToMultiByte(s, codePage, '_', defaultCharWasUsed);
+ }
+ if (a.Len() >= (1 << 16))
+ return E_INVALIDARG;
+ ui.Comment.CopyFrom((const Byte *)(const char *)a, a.Len());
+ }
+ }
+
+
/*
if (existInArchive)
{
- const CItemEx &itemInfo = m_Items[indexInArchive];
+ const CItemEx &itemInfo = m_Items[indexInArc];
// ui.Commented = itemInfo.IsCommented();
ui.Commented = false;
if (ui.Commented)
@@ -205,6 +275,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
ui.Commented = false;
*/
}
+
+
if (IntToBool(newData))
{
UInt64 size = 0;
@@ -220,12 +292,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
largestSizeDefined = true;
}
ui.Size = size;
-
- // ui.Size -= ui.Size / 2;
}
+
updateItems.Add(ui);
}
+
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
{
CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback);
@@ -261,16 +333,52 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
}
- Byte mainMethod;
- if (m_MainMethod < 0)
- mainMethod = (Byte)(((_props.Level == 0) ?
- NFileHeader::NCompressionMethod::kStored :
- NFileHeader::NCompressionMethod::kDeflated));
+
+ int mainMethod = m_MainMethod;
+
+ if (mainMethod < 0)
+ {
+ if (!_props._methods.IsEmpty())
+ {
+ const AString &methodName = _props._methods.Front().MethodName;
+ if (!methodName.IsEmpty())
+ {
+ mainMethod = FindZipMethod(methodName);
+ if (mainMethod < 0)
+ {
+ CMethodId methodId;
+ UInt32 numStreams;
+ if (!FindMethod(EXTERNAL_CODECS_VARS methodName, methodId, numStreams))
+ return E_NOTIMPL;
+ if (numStreams != 1)
+ return E_NOTIMPL;
+ if (methodId == kMethodId_BZip2)
+ mainMethod = NFileHeader::NCompressionMethod::kBZip2;
+ else
+ {
+ if (methodId < kMethodId_ZipBase)
+ return E_NOTIMPL;
+ methodId -= kMethodId_ZipBase;
+ if (methodId > 0xFF)
+ return E_NOTIMPL;
+ mainMethod = (int)methodId;
+ }
+ }
+ }
+ }
+ }
+
+ if (mainMethod < 0)
+ mainMethod = (Byte)(((_props.GetLevel() == 0) ?
+ NFileHeader::NCompressionMethod::kStore :
+ NFileHeader::NCompressionMethod::kDeflate));
else
- mainMethod = (Byte)m_MainMethod;
- options.MethodSequence.Add(mainMethod);
- if (mainMethod != NFileHeader::NCompressionMethod::kStored)
- options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
+ mainMethod = (Byte)mainMethod;
+
+ options.MethodSequence.Add((Byte)mainMethod);
+
+ if (mainMethod != NFileHeader::NCompressionMethod::kStore)
+ options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStore);
return Update(
EXTERNAL_CODECS_VARS
@@ -281,28 +389,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END2
}
-struct CMethodIndexToName
-{
- unsigned Method;
- const char *Name;
-};
-static const CMethodIndexToName k_SupportedMethods[] =
-{
- { NFileHeader::NCompressionMethod::kStored, "copy" },
- { NFileHeader::NCompressionMethod::kDeflated, "deflate" },
- { NFileHeader::NCompressionMethod::kDeflated64, "deflate64" },
- { NFileHeader::NCompressionMethod::kBZip2, "bzip2" },
- { NFileHeader::NCompressionMethod::kLZMA, "lzma" },
- { NFileHeader::NCompressionMethod::kPPMd, "ppmd" }
-};
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitMethodProps();
- #ifndef _7ZIP_ST
- const UInt32 numProcessors = _props.NumThreads;
- #endif
for (UInt32 i = 0; i < numProps; i++)
{
@@ -313,82 +404,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
const PROPVARIANT &prop = values[i];
- if (name[0] == L'x')
- {
- UInt32 level = 9;
- RINOK(ParsePropToUInt32(name.Ptr(1), prop, level));
- _props.Level = level;
- _props.MethodInfo.AddProp_Level(level);
- }
- else if (name == L"m")
- {
- if (prop.vt == VT_BSTR)
- {
- UString m = prop.bstrVal, m2;
- m.MakeLower_Ascii();
- int colonPos = m.Find(L':');
- if (colonPos >= 0)
- {
- m2 = m.Ptr(colonPos + 1);
- m.DeleteFrom(colonPos);
- }
- unsigned k;
- for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
- {
- const CMethodIndexToName &pair = k_SupportedMethods[k];
- if (m.IsEqualTo(pair.Name))
- {
- if (!m2.IsEmpty())
- {
- RINOK(_props.MethodInfo.ParseParamsFromString(m2));
- }
- m_MainMethod = pair.Method;
- break;
- }
- }
- if (k == ARRAY_SIZE(k_SupportedMethods))
- return E_INVALIDARG;
- }
- else if (prop.vt == VT_UI4)
- {
- unsigned k;
- for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
- {
- unsigned method = k_SupportedMethods[k].Method;
- if (prop.ulVal == method)
- {
- m_MainMethod = method;
- break;
- }
- }
- if (k == ARRAY_SIZE(k_SupportedMethods))
- return E_INVALIDARG;
- }
- else
- return E_INVALIDARG;
- }
- else if (name.IsPrefixedBy(L"em"))
+ if (name.IsEqualTo_Ascii_NoCase("em"))
{
if (prop.vt != VT_BSTR)
return E_INVALIDARG;
{
- UString m = prop.bstrVal;
- m.MakeLower_Ascii();
- if (m.IsPrefixedBy(L"aes"))
+ const wchar_t *m = prop.bstrVal;
+ if (IsString1PrefixedByString2_NoCase_Ascii(m, "aes"))
{
- m.DeleteFrontal(3);
- if (m == L"128")
+ m += 3;
+ if (StringsAreEqual_Ascii(m, "128"))
_props.AesKeyMode = 1;
- else if (m == L"192")
+ else if (StringsAreEqual_Ascii(m, "192"))
_props.AesKeyMode = 2;
- else if (m == L"256" || m.IsEmpty())
+ else if (StringsAreEqual_Ascii(m, "256") || m[0] == 0)
_props.AesKeyMode = 3;
else
return E_INVALIDARG;
_props.IsAesMode = true;
m_ForceAesMode = true;
}
- else if (m == L"zipcrypto")
+ else if (StringsAreEqualNoCase_Ascii(m, "ZipCrypto"))
{
_props.IsAesMode = false;
m_ForceAesMode = true;
@@ -397,13 +433,6 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
return E_INVALIDARG;
}
}
- else if (name.IsPrefixedBy(L"mt"))
- {
- #ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Ptr(2), prop, numProcessors, _props.NumThreads));
- _props.NumThreadsWasChanged = true;
- #endif
- }
else if (name.IsEqualTo("tc"))
{
RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra));
@@ -433,9 +462,39 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
}
else
{
- RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));
+ if (name.IsEqualTo_Ascii_NoCase("m") && prop.vt == VT_UI4)
+ {
+ UInt32 id = prop.ulVal;
+ if (id > 0xFF)
+ return E_INVALIDARG;
+ m_MainMethod = id;
+ }
+ else
+ {
+ RINOK(_props.SetProperty(name, prop));
+ }
+ // RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));
}
}
+
+ _props._methods.DeleteFrontal(_props.GetNumEmptyMethods());
+ if (_props._methods.Size() > 1)
+ return E_INVALIDARG;
+ if (_props._methods.Size() == 1)
+ {
+ const AString &methodName = _props._methods[0].MethodName;
+
+ if (!methodName.IsEmpty())
+ {
+ const char *end;
+ UInt32 id = ConvertStringToUInt32(methodName, &end);
+ if (*end == 0 && id <= 0xFF)
+ m_MainMethod = id;
+ else if (methodName.IsEqualTo_Ascii_NoCase("Copy")) // it's alias for "Store"
+ m_MainMethod = 0;
+ }
+ }
+
return S_OK;
}