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>2008-05-05 04:00:00 +0400
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:55 +0300
commit3901bf0ab88106a5b031cba7bc18d60cdebf7eef (patch)
tree808a2489abed822223b118b64e0553db80af6087 /CPP/7zip/Archive/Zip
parentbd1fa36322ac27f5715433b388742893d6524516 (diff)
4.58 beta
Diffstat (limited to 'CPP/7zip/Archive/Zip')
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipAddCommon.cpp2
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.cpp64
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.h7
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandlerOut.cpp171
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHeader.h18
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.cpp12
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItem.cpp34
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItem.h48
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipOut.cpp17
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipUpdate.cpp14
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipUpdate.h8
11 files changed, 292 insertions, 103 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
index 0344f776..0f76b04a 100755
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
@@ -43,7 +43,7 @@ static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
resultCRC = CRC_GET_DIGEST(crc);
return S_OK;
}
- crc = CrcUpdate(crc, buffer, realProcessedSize);
+ crc = CrcUpdate(crc, buffer, (size_t)realProcessedSize);
}
}
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index c3576eeb..7d478a36 100755
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -81,6 +81,9 @@ STATPROPSTG kProps[] =
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackedSize, VT_UI8},
{ NULL, kpidLastWriteTime, VT_FILETIME},
+ { NULL, kpidCreationTime, VT_FILETIME},
+ { NULL, kpidLastAccessTime, VT_FILETIME},
+
{ NULL, kpidAttributes, VT_UI4},
{ NULL, kpidEncrypted, VT_BOOL},
@@ -150,17 +153,18 @@ CHandler::CHandler():
InitMethodProperties();
}
-static void StringToProp(const CByteBuffer &data, UINT codePage, NWindows::NCOM::CPropVariant &prop)
+static AString BytesToString(const CByteBuffer &data)
{
- int size = (int)data.GetCapacity();
- if (size <= 0)
- return;
AString s;
- char *p = s.GetBuffer(size + 1);
- memcpy(p, (const Byte *)data, size);
- p[size] = '\0';
- s.ReleaseBuffer();
- prop = MultiByteToUnicodeString(s, codePage);
+ int size = (int)data.GetCapacity();
+ if (size > 0)
+ {
+ char *p = s.GetBuffer(size + 1);
+ memcpy(p, (const Byte *)data, size);
+ p[size] = '\0';
+ s.ReleaseBuffer();
+ }
+ return s;
}
IMP_IInArchive_Props
@@ -173,10 +177,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
switch(propID)
{
case kpidComment:
- {
- StringToProp(m_Archive.m_ArchiveInfo.Comment, CP_ACP, prop);
+ prop = MultiByteToUnicodeString(BytesToString(m_Archive.m_ArchiveInfo.Comment), CP_ACP);
break;
- }
}
prop.Detach(value);
COM_TRY_END
@@ -197,8 +199,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
switch(propID)
{
case kpidPath:
- prop = NItemName::GetOSName2(
- MultiByteToUnicodeString(item.Name, item.GetCodePage()));
+ prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name));
break;
case kpidIsFolder:
prop = item.IsDirectory();
@@ -209,16 +210,39 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPackedSize:
prop = item.PackSize;
break;
+ case kpidTimeType:
+ FILETIME utcFileTime;
+ if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kTagTime, utcFileTime))
+ prop = (UInt32)NFileTimeType::kWindows;
+ break;
+ case kpidCreationTime:
+ {
+ FILETIME ft;
+ if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft))
+ prop = ft;
+ break;
+ }
+ case kpidLastAccessTime:
+ {
+ FILETIME ft;
+ if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft))
+ prop = ft;
+ break;
+ }
case kpidLastWriteTime:
{
- FILETIME localFileTime, utcFileTime;
- if (DosTimeToFileTime(item.Time, localFileTime))
+ FILETIME utcFileTime;
+ if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utcFileTime))
{
- if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ FILETIME localFileTime;
+ if (DosTimeToFileTime(item.Time, localFileTime))
+ {
+ if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+ else
utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
}
- else
- utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
prop = utcFileTime;
break;
}
@@ -230,7 +254,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
case kpidComment:
{
- StringToProp(item.Comment, item.GetCodePage(), prop);
+ prop = item.GetUnicodeString(BytesToString(item.Comment));
break;
}
case kpidCRC:
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h
index 28f44196..c8fa392c 100755
--- a/CPP/7zip/Archive/Zip/ZipHandler.h
+++ b/CPP/7zip/Archive/Zip/ZipHandler.h
@@ -59,6 +59,10 @@ private:
bool m_IsAesMode;
Byte m_AesKeyMode;
+ bool m_WriteNtfsTimeExtra;
+ bool m_ForseLocal;
+ bool m_ForseUtf8;
+
#ifdef COMPRESS_MT
UInt32 _numThreads;
#endif
@@ -77,6 +81,9 @@ private:
m_NumMatchFinderCyclesDefined = false;
m_IsAesMode = false;
m_AesKeyMode = 3; // aes-256
+ m_WriteNtfsTimeExtra = false;
+ m_ForseLocal = false;
+ m_ForseUtf8 = false;
#ifdef COMPRESS_MT
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
#endif
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;
}
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h
index 98ad17a3..0c978a7c 100755
--- a/CPP/7zip/Archive/Zip/ZipHeader.h
+++ b/CPP/7zip/Archive/Zip/ZipHeader.h
@@ -86,11 +86,23 @@ namespace NFileHeader
enum
{
kZip64 = 0x01,
+ kNTFS = 0x0A,
kStrongEncrypt = 0x17,
kWzAES = 0x9901
};
}
+ namespace NNtfsExtra
+ {
+ const UInt16 kTagTime = 1;
+ enum
+ {
+ kMTime = 0,
+ kATime = 1,
+ kCTime = 2
+ };
+ }
+
const UInt32 kLocalBlockSize = 26;
/*
struct CLocalBlock
@@ -156,13 +168,11 @@ namespace NFileHeader
namespace NFlags
{
- const int kNumUsedBits = 4;
- const int kUsedBitsMask = (1 << kNumUsedBits) - 1;
-
const int kEncrypted = 1 << 0;
const int kDescriptorUsedMask = 1 << 3;
const int kStrongEncrypted = 1 << 6;
-
+ const int kUtf8 = 1 << 11;
+
const int kImplodeDictionarySizeMask = 1 << 1;
const int kImplodeLiteralsOnMask = 1 << 2;
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index b579f9b4..f8e81c59 100755
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -114,10 +114,10 @@ bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit)
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
{
- UInt32 realProcessedSize;
- HRESULT result = ReadStream(m_Stream, data, size, &realProcessedSize);
+ size_t realProcessedSize = size;
+ HRESULT result = ReadStream(m_Stream, data, &realProcessedSize);
if(processedSize != NULL)
- *processedSize = realProcessedSize;
+ *processedSize = (UInt32)realProcessedSize;
m_Position += realProcessedSize;
return result;
}
@@ -304,7 +304,7 @@ HRESULT CInArchive::ReadLocalItem(CItemEx &item)
{
item.ExtractVersion.Version = ReadByte();
item.ExtractVersion.HostOS = ReadByte();
- item.Flags = ReadUInt16(); // & NFileHeader::NFlags::kUsedBitsMask;
+ item.Flags = ReadUInt16();
item.CompressionMethod = ReadUInt16();
item.Time = ReadUInt32();
item.FileCRC = ReadUInt32();
@@ -467,7 +467,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item)
item.MadeByVersion.HostOS = ReadByte();
item.ExtractVersion.Version = ReadByte();
item.ExtractVersion.HostOS = ReadByte();
- item.Flags = ReadUInt16(); // & NFileHeader::NFlags::kUsedBitsMask;
+ item.Flags = ReadUInt16();
item.CompressionMethod = ReadUInt16();
item.Time = ReadUInt32();
item.FileCRC = ReadUInt32();
@@ -772,7 +772,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
return S_FALSE;
UInt16 thisDiskNumber16 = ReadUInt16();
- if (!isZip64 || thisDiskNumber16)
+ if (!isZip64 || thisDiskNumber16 != 0xFFFF)
thisDiskNumber = thisDiskNumber16;
UInt16 startCDDiskNumber16 = ReadUInt16();
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
index 480a1abb..484696f5 100755
--- a/CPP/7zip/Archive/Zip/ZipItem.cpp
+++ b/CPP/7zip/Archive/Zip/ZipItem.cpp
@@ -5,6 +5,7 @@
#include "ZipHeader.h"
#include "ZipItem.h"
#include "../Common/ItemNameUtils.h"
+#include "../../../../C/CpuArch.h"
namespace NArchive {
namespace NZip {
@@ -19,6 +20,37 @@ bool operator!=(const CVersion &v1, const CVersion &v2)
return !(v1 == v2);
}
+bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const
+{
+ ft.dwHighDateTime = ft.dwLowDateTime = 0;
+ UInt32 size = (UInt32)Data.GetCapacity();
+ if (ID != NFileHeader::NExtraID::kNTFS || size < 32)
+ return false;
+ const Byte *p = (const Byte *)Data;
+ p += 4; // for reserved
+ size -= 4;
+ while (size > 4)
+ {
+ UInt16 tag = GetUi16(p);
+ UInt32 attrSize = GetUi16(p + 2);
+ p += 4;
+ size -= 4;
+ if (attrSize > size)
+ attrSize = size;
+
+ if (tag == NFileHeader::NNtfsExtra::kTagTime && attrSize >= 24)
+ {
+ p += 8 * index;
+ ft.dwLowDateTime = GetUi32(p);
+ ft.dwHighDateTime = GetUi32(p + 4);
+ return true;
+ }
+ p += attrSize;
+ size -= attrSize;
+ }
+ return false;
+}
+
bool CLocalItem::IsImplodeBigDictionary() const
{
if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded)
@@ -126,5 +158,7 @@ void CLocalItem::SetBitMask(int bitMask, bool enable)
void CLocalItem::SetEncrypted(bool encrypted)
{ SetBitMask(NFileHeader::NFlags::kEncrypted, encrypted); }
+void CLocalItem::SetUtf8(bool isUtf8)
+ { SetBitMask(NFileHeader::NFlags::kUtf8, isUtf8); }
}}
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
index 350e81b6..8d7cc3b4 100755
--- a/CPP/7zip/Archive/Zip/ZipItem.h
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -6,6 +6,8 @@
#include "Common/Types.h"
#include "Common/MyString.h"
#include "Common/Buffer.h"
+#include "Common/UTFConvert.h"
+#include "Common/StringConvert.h"
#include "ZipHeader.h"
@@ -25,6 +27,7 @@ struct CExtraSubBlock
{
UInt16 ID;
CByteBuffer Data;
+ bool ExtractNtfsTime(int index, FILETIME &ft) const;
};
struct CWzAesExtraField
@@ -137,6 +140,17 @@ struct CExtraBlock
return GetWzAesField(aesField);
}
+ bool GetNtfsTime(int index, FILETIME &ft) const
+ {
+ for (int i = 0; i < SubBlocks.Size(); i++)
+ {
+ const CExtraSubBlock &sb = SubBlocks[i];
+ if (sb.ID == NFileHeader::NExtraID::kNTFS)
+ return sb.ExtractNtfsTime(index, ft);
+ }
+ return false;
+ }
+
/*
bool HasStrongCryptoField() const
{
@@ -147,14 +161,9 @@ struct CExtraBlock
void RemoveUnknownSubBlocks()
{
- for (int i = SubBlocks.Size() - 1; i >= 0;)
- {
- const CExtraSubBlock &subBlock = SubBlocks[i];
- if (subBlock.ID != NFileHeader::NExtraID::kWzAES)
+ for (int i = SubBlocks.Size() - 1; i >= 0; i--)
+ if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES)
SubBlocks.Delete(i);
- else
- i--;
- }
}
};
@@ -173,6 +182,8 @@ public:
AString Name;
CExtraBlock LocalExtra;
+
+ bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; };
@@ -186,6 +197,16 @@ public:
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
+ UString GetUnicodeString(const AString &s) const
+ {
+ UString res;
+ if (IsUtf8())
+ if (!ConvertUTF8ToUnicode(s, res))
+ res.Empty();
+ if (res.IsEmpty())
+ res = MultiByteToUnicodeString(s, GetCodePage());
+ return res;
+ }
private:
void SetFlagBits(int startBitNumber, int numBits, int value);
@@ -193,11 +214,9 @@ private:
public:
void ClearFlags() { Flags = 0; }
void SetEncrypted(bool encrypted);
+ void SetUtf8(bool isUtf8);
- WORD GetCodePage() const
- {
- return CP_OEMCP;
- }
+ WORD GetCodePage() const { return CP_OEMCP; }
};
class CItem: public CLocalItem
@@ -209,11 +228,16 @@ public:
UInt64 LocalHeaderPosition;
+ FILETIME NtfsMTime;
+ FILETIME NtfsATime;
+ FILETIME NtfsCTime;
+
CExtraBlock CentralExtra;
CByteBuffer Comment;
bool FromLocal;
bool FromCentral;
+ bool NtfsTimeIsDefined;
bool IsDirectory() const;
UInt32 GetWinAttributes() const;
@@ -235,7 +259,7 @@ public:
|| MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS
) ? CP_OEMCP : CP_ACP);
}
- CItem() : FromLocal(false), FromCentral(false) {}
+ CItem() : FromLocal(false), FromCentral(false), NtfsTimeIsDefined(false) {}
};
}}
diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp
index d5e6895e..fd89b1e8 100755
--- a/CPP/7zip/Archive/Zip/ZipOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipOut.cpp
@@ -172,7 +172,8 @@ void COutArchive::WriteCentralHeader(const CItem &item)
WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
WriteUInt16((UInt16)item.Name.Length());
UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
- UInt16 centralExtraSize = (UInt16)(isZip64 ? (4 + zip64ExtraSize) : 0);
+ const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8);
+ UInt16 centralExtraSize = (UInt16)(isZip64 ? (4 + zip64ExtraSize) : 0) + (item.NtfsTimeIsDefined ? (4 + kNtfsExtraSize) : 0);
centralExtraSize = (UInt16)(centralExtraSize + item.CentralExtra.GetSize());
WriteUInt16(centralExtraSize); // test it;
WriteUInt16((UInt16)item.Comment.GetCapacity());
@@ -192,6 +193,20 @@ void COutArchive::WriteCentralHeader(const CItem &item)
if(isPosition64)
WriteUInt64(item.LocalHeaderPosition);
}
+ if (item.NtfsTimeIsDefined)
+ {
+ WriteUInt16(NFileHeader::NExtraID::kNTFS);
+ WriteUInt16(kNtfsExtraSize);
+ WriteUInt32(0); // reserved
+ WriteUInt16(NFileHeader::NNtfsExtra::kTagTime);
+ WriteUInt16(8 * 3);
+ WriteUInt32(item.NtfsMTime.dwLowDateTime);
+ WriteUInt32(item.NtfsMTime.dwHighDateTime);
+ WriteUInt32(item.NtfsATime.dwLowDateTime);
+ WriteUInt32(item.NtfsATime.dwHighDateTime);
+ WriteUInt32(item.NtfsCTime.dwLowDateTime);
+ WriteUInt32(item.NtfsCTime.dwHighDateTime);
+ }
WriteExtra(item.CentralExtra);
if (item.Comment.GetCapacity() > 0)
WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity());
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index 6cfa64e2..2ec08981 100755
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -69,12 +69,19 @@ static void SetFileHeader(
item.UnPackSize = updateItem.Size;
bool isDirectory;
+ item.ClearFlags();
+
if (updateItem.NewProperties)
{
isDirectory = updateItem.IsDirectory;
item.Name = updateItem.Name;
+ item.SetUtf8(updateItem.IsUtf8);
item.ExternalAttributes = updateItem.Attributes;
item.Time = updateItem.Time;
+ item.NtfsMTime = updateItem.NtfsMTime;
+ item.NtfsATime = updateItem.NtfsATime;
+ item.NtfsCTime = updateItem.NtfsCTime;
+ item.NtfsTimeIsDefined = updateItem.NtfsTimeIsDefined;
}
else
isDirectory = item.IsDirectory();
@@ -86,7 +93,6 @@ static void SetFileHeader(
item.ExtractVersion.HostOS = kExtractHostOS;
item.InternalAttributes = 0; // test it
- item.ClearFlags();
item.SetEncrypted(!isDirectory && options.PasswordIsDefined);
if (isDirectory)
{
@@ -341,7 +347,13 @@ static HRESULT UpdateItemOldData(COutArchive &archive,
// item.ExternalAttributes = updateItem.Attributes;
// Test it
item.Name = updateItem.Name;
+ item.SetUtf8(updateItem.IsUtf8);
item.Time = updateItem.Time;
+ item.NtfsMTime = updateItem.NtfsMTime;
+ item.NtfsATime = updateItem.NtfsATime;
+ item.NtfsCTime = updateItem.NtfsCTime;
+ item.NtfsTimeIsDefined = updateItem.NtfsTimeIsDefined;
+
item.CentralExtra.RemoveUnknownSubBlocks();
item.LocalExtra.RemoveUnknownSubBlocks();
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h
index 168eedd6..5e67bead 100755
--- a/CPP/7zip/Archive/Zip/ZipUpdate.h
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.h
@@ -27,6 +27,8 @@ struct CUpdateItem
bool NewData;
bool NewProperties;
bool IsDirectory;
+ bool NtfsTimeIsDefined;
+ bool IsUtf8;
int IndexInArchive;
int IndexInClient;
UInt32 Attributes;
@@ -35,7 +37,11 @@ struct CUpdateItem
AString Name;
// bool Commented;
// CUpdateRange CommentRange;
- CUpdateItem(): Size(0) {}
+ FILETIME NtfsMTime;
+ FILETIME NtfsATime;
+ FILETIME NtfsCTime;
+
+ CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}
};
HRESULT Update(