mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 08:07:06 -06:00
4.58 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
bd1fa36322
commit
3901bf0ab8
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
ui.Attributes = prop.ulVal;
|
||||
}
|
||||
|
||||
{
|
||||
NCOM::CPropVariant propVariant;
|
||||
RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &propVariant));
|
||||
if (propVariant.vt != VT_FILETIME)
|
||||
return E_INVALIDARG;
|
||||
utcFileTime = propVariant.filetime;
|
||||
}
|
||||
{
|
||||
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))
|
||||
|
||||
{
|
||||
// return E_INVALIDARG;
|
||||
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));
|
||||
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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); }
|
||||
|
||||
}}
|
||||
|
||||
@@ -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) {}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user