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.cpp60
1 files changed, 46 insertions, 14 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index c21b5605..a9b3eae5 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -53,7 +53,7 @@ static int FindZipMethod(const char *s, const char * const *names, unsigned num)
{
const char *name = names[i];
if (name && StringsAreEqualNoCase_Ascii(s, name))
- return i;
+ return (int)i;
}
return -1;
}
@@ -65,7 +65,7 @@ static int FindZipMethod(const char *s)
return k;
k = FindZipMethod(s, kMethodNames2, kNumMethodNames2);
if (k >= 0)
- return kMethodNames2Start + k;
+ return (int)kMethodNames2Start + k;
return -1;
}
@@ -75,7 +75,7 @@ static int FindZipMethod(const char *s)
catch(const CSystemException &e) { return e.ErrorCode; } \
catch(...) { return E_OUTOFMEMORY; }
-static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime)
+static HRESULT GetTime(IArchiveUpdateCallback *callback, unsigned index, PROPID propID, FILETIME &filetime)
{
filetime.dwHighDateTime = filetime.dwLowDateTime = 0;
NCOM::CPropVariant prop;
@@ -106,6 +106,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
UInt64 largestSize = 0;
bool largestSizeDefined = false;
+ #ifdef _WIN32
+ const UINT oemCP = GetOEMCP();
+ #endif
+
UString name;
CUpdateItem ui;
@@ -125,7 +129,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData);
- ui.IndexInArc = indexInArc;
+ ui.IndexInArc = (int)indexInArc;
ui.IndexInClient = i;
bool existInArchive = (indexInArc != (UInt32)(Int32)-1);
@@ -240,10 +244,25 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (needSlash)
name += kSlash;
- UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP;
-
+ const UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP;
bool tryUtf8 = true;
- if ((m_ForceLocal || !m_ForceUtf8) && codePage != CP_UTF8)
+
+ /*
+ Windows 10 allows users to set UTF-8 in Region Settings via option:
+ "Beta: Use Unicode UTF-8 for worldwide language support"
+ In that case Windows uses CP_UTF8 when we use CP_OEMCP.
+ 21.02 fixed:
+ we set UTF-8 mark for non-latin files for such UTF-8 mode in Windows.
+ we write additional Info-Zip Utf-8 FileName Extra for non-latin names/
+ */
+
+ if ((codePage != CP_UTF8) &&
+ #ifdef _WIN32
+ (m_ForceLocal || !m_ForceUtf8) && (oemCP != CP_UTF8)
+ #else
+ (m_ForceLocal && !m_ForceUtf8)
+ #endif
+ )
{
bool defaultCharWasUsed;
ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed);
@@ -251,13 +270,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
MultiByteToUnicodeString(ui.Name, codePage) != name));
}
+ const bool isNonLatin = !name.IsAscii();
+
if (tryUtf8)
{
- ui.IsUtf8 = !name.IsAscii();
+ ui.IsUtf8 = isNonLatin;
ConvertUnicodeToUTF8(name, ui.Name);
+
+ #ifndef _WIN32
+ if (ui.IsUtf8 && !CheckUTF8_AString(ui.Name))
+ {
+ // if it's non-Windows and there are non-UTF8 characters we clear UTF8-flag
+ ui.IsUtf8 = false;
+ }
+ #endif
}
+ else if (isNonLatin)
+ Convert_Unicode_To_UTF8_Buf(name, ui.Name_Utf);
- if (ui.Name.Len() >= (1 << 16))
+ if (ui.Name.Len() >= (1 << 16)
+ || ui.Name_Utf.Size() >= (1 << 16) - 128)
return E_INVALIDARG;
{
@@ -337,10 +369,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options._dataSizeReduceDefined = largestSizeDefined;
options.PasswordIsDefined = false;
- options.Password.Empty();
+ options.Password.Wipe_and_Empty();
if (getTextPassword)
{
- CMyComBSTR password;
+ CMyComBSTR_Wipe password;
Int32 passwordIsDefined;
RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password));
options.PasswordIsDefined = IntToBool(passwordIsDefined);
@@ -352,7 +384,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (!IsSimpleAsciiString(password))
return E_INVALIDARG;
if (password)
- options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP);
+ UnicodeStringToMultiByte2(options.Password, (LPCOLESTR)password, CP_OEMCP);
if (options.IsAesMode)
{
if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax)
@@ -496,7 +528,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
UInt32 id = prop.ulVal;
if (id > 0xFF)
return E_INVALIDARG;
- m_MainMethod = id;
+ m_MainMethod = (int)id;
}
else
{
@@ -518,7 +550,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
const char *end;
UInt32 id = ConvertStringToUInt32(methodName, &end);
if (*end == 0 && id <= 0xFF)
- m_MainMethod = id;
+ m_MainMethod = (int)id;
else if (methodName.IsEqualTo_Ascii_NoCase("Copy")) // it's alias for "Store"
m_MainMethod = 0;
}