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')
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandlerOut.cpp171
1 files changed, 114 insertions, 57 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index 453c37a3..2846c988 100755
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -66,138 +66,179 @@ static bool IsAsciiString(const UString &s)
catch(const CSystemException &e) { return e.ErrorCode; } \
catch(...) { return E_OUTOFMEMORY; }
+static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime)
+{
+ filetime.dwHighDateTime = filetime.dwLowDateTime = 0;
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_FILETIME)
+ filetime = prop.filetime;
+ else if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
- IArchiveUpdateCallback *updateCallback)
+ IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN2
CObjectVector<CUpdateItem> updateItems;
for(UInt32 i = 0; i < numItems; i++)
{
- CUpdateItem updateItem;
+ CUpdateItem ui;
Int32 newData;
Int32 newProperties;
UInt32 indexInArchive;
- if (!updateCallback)
+ if (!callback)
return E_FAIL;
- RINOK(updateCallback->GetUpdateItemInfo(i,
+ RINOK(callback->GetUpdateItemInfo(i,
&newData, // 1 - compress 0 - copy
&newProperties,
&indexInArchive));
- updateItem.NewProperties = IntToBool(newProperties);
- updateItem.NewData = IntToBool(newData);
- updateItem.IndexInArchive = indexInArchive;
- updateItem.IndexInClient = i;
+ ui.NewProperties = IntToBool(newProperties);
+ ui.NewData = IntToBool(newData);
+ ui.IndexInArchive = indexInArchive;
+ ui.IndexInClient = i;
// bool existInArchive = (indexInArchive != UInt32(-1));
if (IntToBool(newProperties))
{
- FILETIME utcFileTime;
UString name;
bool isDirectoryStatusDefined;
{
- NCOM::CPropVariant propVariant;
- RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));
- if (propVariant.vt == VT_EMPTY)
- updateItem.Attributes = 0;
- else if (propVariant.vt != VT_UI4)
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidAttributes, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.Attributes = 0;
+ else if (prop.vt != VT_UI4)
return E_INVALIDARG;
else
- updateItem.Attributes = propVariant.ulVal;
- }
- {
- NCOM::CPropVariant propVariant;
- RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &propVariant));
- if (propVariant.vt != VT_FILETIME)
- return E_INVALIDARG;
- utcFileTime = propVariant.filetime;
+ ui.Attributes = prop.ulVal;
}
+
{
- NCOM::CPropVariant propVariant;
- RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant));
- if (propVariant.vt == VT_EMPTY)
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidPath, &prop));
+ if (prop.vt == VT_EMPTY)
name.Empty();
- else if (propVariant.vt != VT_BSTR)
+ else if (prop.vt != VT_BSTR)
return E_INVALIDARG;
else
- name = propVariant.bstrVal;
+ name = prop.bstrVal;
}
{
- NCOM::CPropVariant propVariant;
- RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant));
- if (propVariant.vt == VT_EMPTY)
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidIsFolder, &prop));
+ if (prop.vt == VT_EMPTY)
isDirectoryStatusDefined = false;
- else if (propVariant.vt != VT_BOOL)
+ else if (prop.vt != VT_BOOL)
return E_INVALIDARG;
else
{
- updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE);
+ ui.IsDirectory = (prop.boolVal != VARIANT_FALSE);
isDirectoryStatusDefined = true;
}
}
- FILETIME localFileTime;
- if(!FileTimeToLocalFileTime(&utcFileTime, &localFileTime))
- return E_INVALIDARG;
- if(!FileTimeToDosTime(localFileTime, updateItem.Time))
+
+ {
+ CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidTimeType, &prop));
+ if (prop.vt == VT_UI4)
+ ui.NtfsTimeIsDefined = (prop.ulVal == NFileTimeType::kWindows);
+ else
+ ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra;
+ }
+ RINOK(GetTime(callback, i, kpidLastWriteTime, ui.NtfsMTime));
+ RINOK(GetTime(callback, i, kpidLastAccessTime, ui.NtfsATime));
+ RINOK(GetTime(callback, i, kpidCreationTime, ui.NtfsCTime));
+
{
- // return E_INVALIDARG;
+ FILETIME localFileTime = { 0, 0 };
+ if (ui.NtfsMTime.dwHighDateTime != 0 ||
+ ui.NtfsMTime.dwLowDateTime != 0)
+ if (!FileTimeToLocalFileTime(&ui.NtfsMTime, &localFileTime))
+ return E_INVALIDARG;
+ FileTimeToDosTime(localFileTime, ui.Time);
}
if (!isDirectoryStatusDefined)
- updateItem.IsDirectory = ((updateItem.Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
+ ui.IsDirectory = ((ui.Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
name = NItemName::MakeLegalName(name);
- bool needSlash = updateItem.IsDirectory;
+ bool needSlash = ui.IsDirectory;
const wchar_t kSlash = L'/';
if (!name.IsEmpty())
{
if (name[name.Length() - 1] == kSlash)
{
- if (!updateItem.IsDirectory)
+ if (!ui.IsDirectory)
return E_INVALIDARG;
needSlash = false;
}
}
if (needSlash)
name += kSlash;
- updateItem.Name = UnicodeStringToMultiByte(name, CP_OEMCP);
- if (updateItem.Name.Length() > 0xFFFF)
+
+ bool tryUtf8 = true;
+ if (m_ForseLocal || !m_ForseUtf8)
+ {
+ bool defaultCharWasUsed;
+ ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed);
+ tryUtf8 = (!m_ForseLocal && defaultCharWasUsed);
+ }
+
+ if (tryUtf8)
+ {
+ bool needUtf = false;
+ for (int i = 0; i < name.Length(); i++)
+ if ((unsigned)name[i] >= 0x80)
+ {
+ needUtf = true;
+ break;
+ }
+ ui.IsUtf8 = needUtf;
+ if (!ConvertUnicodeToUTF8(name, ui.Name))
+ return E_INVALIDARG;
+ }
+
+ if (ui.Name.Length() > 0xFFFF)
return E_INVALIDARG;
- updateItem.IndexInClient = i;
+ ui.IndexInClient = i;
/*
if(existInArchive)
{
const CItemEx &itemInfo = m_Items[indexInArchive];
- // updateItem.Commented = itemInfo.IsCommented();
- updateItem.Commented = false;
- if(updateItem.Commented)
+ // ui.Commented = itemInfo.IsCommented();
+ ui.Commented = false;
+ if(ui.Commented)
{
- updateItem.CommentRange.Position = itemInfo.GetCommentPosition();
- updateItem.CommentRange.Size = itemInfo.CommentSize;
+ ui.CommentRange.Position = itemInfo.GetCommentPosition();
+ ui.CommentRange.Size = itemInfo.CommentSize;
}
}
else
- updateItem.Commented = false;
+ ui.Commented = false;
*/
}
if (IntToBool(newData))
{
UInt64 size;
{
- NCOM::CPropVariant propVariant;
- RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant));
- if (propVariant.vt != VT_UI8)
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
return E_INVALIDARG;
- size = propVariant.uhVal.QuadPart;
+ size = prop.uhVal.QuadPart;
}
- updateItem.Size = size;
+ ui.Size = size;
}
- updateItems.Add(updateItem);
+ updateItems.Add(ui);
}
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
if (!getTextPassword)
{
- CMyComPtr<IArchiveUpdateCallback> udateCallBack2(updateCallback);
+ CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback);
udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
}
CCompressionMethodMode options;
@@ -281,7 +322,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return Update(
EXTERNAL_CODECS_VARS
m_Items, updateItems, outStream,
- m_ArchiveIsOpen ? &m_Archive : NULL, &options, updateCallback);
+ m_ArchiveIsOpen ? &m_Archive : NULL, &options, callback);
COM_TRY_END2
}
@@ -406,6 +447,22 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
RINOK(ParsePropValue(name.Mid(1), prop, num));
m_Algo = num;
}
+ else if (name.CompareNoCase(L"TC") == 0)
+ return SetBoolProperty(m_WriteNtfsTimeExtra, prop);
+ else if (name.CompareNoCase(L"CL") == 0)
+ {
+ RINOK(SetBoolProperty(m_ForseLocal, prop));
+ if (m_ForseLocal)
+ m_ForseUtf8 = false;
+ return S_OK;
+ }
+ else if (name.CompareNoCase(L"CU") == 0)
+ {
+ RINOK(SetBoolProperty(m_ForseUtf8, prop));
+ if (m_ForseUtf8)
+ m_ForseLocal = false;
+ return S_OK;
+ }
else
return E_INVALIDARG;
}