From 3901bf0ab88106a5b031cba7bc18d60cdebf7eef Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Mon, 5 May 2008 00:00:00 +0000 Subject: 4.58 beta --- CPP/7zip/Archive/Zip/ZipAddCommon.cpp | 2 +- CPP/7zip/Archive/Zip/ZipHandler.cpp | 64 ++++++++---- CPP/7zip/Archive/Zip/ZipHandler.h | 7 ++ CPP/7zip/Archive/Zip/ZipHandlerOut.cpp | 171 ++++++++++++++++++++++----------- CPP/7zip/Archive/Zip/ZipHeader.h | 18 +++- CPP/7zip/Archive/Zip/ZipIn.cpp | 12 +-- CPP/7zip/Archive/Zip/ZipItem.cpp | 34 +++++++ CPP/7zip/Archive/Zip/ZipItem.h | 48 ++++++--- CPP/7zip/Archive/Zip/ZipOut.cpp | 17 +++- CPP/7zip/Archive/Zip/ZipUpdate.cpp | 14 ++- CPP/7zip/Archive/Zip/ZipUpdate.h | 8 +- 11 files changed, 292 insertions(+), 103 deletions(-) (limited to 'CPP/7zip/Archive/Zip') 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 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 getTextPassword; if (!getTextPassword) { - CMyComPtr udateCallBack2(updateCallback); + CMyComPtr 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 &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( -- cgit v1.2.3