mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 22:06:59 -06:00
17.00
This commit is contained in:
@@ -50,22 +50,59 @@ static const Byte kMarker[kMarkerSize] = SIGNATURE;
|
||||
|
||||
static const size_t kCommentSize_Max = (size_t)1 << 16;
|
||||
|
||||
|
||||
static const char * const kHostOS[] =
|
||||
{
|
||||
"Windows"
|
||||
, "Unix"
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair k_ArcFlags[] =
|
||||
|
||||
static const char * const k_ArcFlags[] =
|
||||
{
|
||||
{ 0, "Volume" },
|
||||
{ 1, "VolumeField" },
|
||||
{ 2, "Solid" },
|
||||
{ 3, "Recovery" },
|
||||
{ 4, "Lock" }
|
||||
"Volume"
|
||||
, "VolumeField"
|
||||
, "Solid"
|
||||
, "Recovery"
|
||||
, "Lock" // 4
|
||||
};
|
||||
|
||||
|
||||
static const char * const k_FileFlags[] =
|
||||
{
|
||||
"Dir"
|
||||
, "UnixTime"
|
||||
, "CRC"
|
||||
, "UnknownSize"
|
||||
};
|
||||
|
||||
|
||||
static const char * const g_ExtraTypes[] =
|
||||
{
|
||||
"0"
|
||||
, "Crypto"
|
||||
, "Hash"
|
||||
, "Time"
|
||||
, "Version"
|
||||
, "Link"
|
||||
, "UnixOwner"
|
||||
, "Subdata"
|
||||
};
|
||||
|
||||
|
||||
static const char * const g_LinkTypes[] =
|
||||
{
|
||||
"0"
|
||||
, "UnixSymLink"
|
||||
, "WinSymLink"
|
||||
, "WinJunction"
|
||||
, "HardLink"
|
||||
, "FileCopy"
|
||||
};
|
||||
|
||||
|
||||
static const char g_ExtraTimeFlags[] = { 'u', 'M', 'C', 'A', 'n' };
|
||||
|
||||
|
||||
template <unsigned alignMask>
|
||||
struct CAlignedBuffer
|
||||
@@ -106,7 +143,8 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
|
||||
{
|
||||
Byte b = p[i];
|
||||
if (i < 10)
|
||||
*val |= (UInt64)(b & 0x7F) << (7 * i++);
|
||||
*val |= (UInt64)(b & 0x7F) << (7 * i);
|
||||
i++;
|
||||
if ((b & 0x80) == 0)
|
||||
return i;
|
||||
}
|
||||
@@ -114,7 +152,54 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
|
||||
}
|
||||
|
||||
|
||||
int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
|
||||
bool CLinkInfo::Parse(const Byte *p, unsigned size)
|
||||
{
|
||||
const Byte *pStart = p;
|
||||
unsigned num = ReadVarInt(p, size, &Type);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
num = ReadVarInt(p, size, &Flags);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
UInt64 len;
|
||||
num = ReadVarInt(p, size, &len);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
if (size != len)
|
||||
return false;
|
||||
|
||||
NameLen = (unsigned)len;
|
||||
NameOffset = (unsigned)(p - pStart);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void AddHex64(AString &s, UInt64 v)
|
||||
{
|
||||
char sz[32];
|
||||
sz[0] = '0';
|
||||
sz[1] = 'x';
|
||||
ConvertUInt64ToHex(v, sz + 2);
|
||||
s += sz;
|
||||
}
|
||||
|
||||
|
||||
static void PrintType(AString &s, const char * const table[], unsigned num, UInt64 val)
|
||||
{
|
||||
char sz[32];
|
||||
const char *p = NULL;
|
||||
if (val < num)
|
||||
p = table[(unsigned)val];
|
||||
if (!p)
|
||||
{
|
||||
ConvertUInt64ToString(val, sz);
|
||||
p = sz;
|
||||
}
|
||||
s += p;
|
||||
}
|
||||
|
||||
|
||||
int CItem::FindExtra(unsigned extraID, unsigned &recordDataSize) const
|
||||
{
|
||||
recordDataSize = 0;
|
||||
size_t offset = 0;
|
||||
@@ -137,8 +222,8 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
|
||||
rem = (size_t)size;
|
||||
}
|
||||
{
|
||||
UInt64 type2;
|
||||
unsigned num = ReadVarInt(Extra + offset, rem, &type2);
|
||||
UInt64 id;
|
||||
unsigned num = ReadVarInt(Extra + offset, rem, &id);
|
||||
if (num == 0)
|
||||
return -1;
|
||||
offset += num;
|
||||
@@ -147,12 +232,12 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
|
||||
// There was BUG in RAR 5.21- : it stored (size-1) instead of (size)
|
||||
// for Subdata record in Service header.
|
||||
// That record always was last in bad archives, so we can fix that case.
|
||||
if (type2 == NExtraRecordType::kSubdata
|
||||
if (id == NExtraID::kSubdata
|
||||
&& RecordType == NHeaderType::kService
|
||||
&& rem + 1 == Extra.Size() - offset)
|
||||
rem++;
|
||||
|
||||
if (type2 == type)
|
||||
if (id == extraID)
|
||||
{
|
||||
recordDataSize = (unsigned)rem;
|
||||
return (int)offset;
|
||||
@@ -164,19 +249,118 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
|
||||
}
|
||||
|
||||
|
||||
void CItem::PrintInfo(AString &s) const
|
||||
{
|
||||
size_t offset = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
size_t rem = Extra.Size() - offset;
|
||||
if (rem == 0)
|
||||
return;
|
||||
|
||||
{
|
||||
UInt64 size;
|
||||
unsigned num = ReadVarInt(Extra + offset, rem, &size);
|
||||
if (num == 0)
|
||||
return;
|
||||
offset += num;
|
||||
rem -= num;
|
||||
if (size > rem)
|
||||
break;
|
||||
rem = (size_t)size;
|
||||
}
|
||||
{
|
||||
UInt64 id;
|
||||
{
|
||||
unsigned num = ReadVarInt(Extra + offset, rem, &id);
|
||||
if (num == 0)
|
||||
break;
|
||||
offset += num;
|
||||
rem -= num;
|
||||
}
|
||||
|
||||
// There was BUG in RAR 5.21- : it stored (size-1) instead of (size)
|
||||
// for Subdata record in Service header.
|
||||
// That record always was last in bad archives, so we can fix that case.
|
||||
if (id == NExtraID::kSubdata
|
||||
&& RecordType == NHeaderType::kService
|
||||
&& rem + 1 == Extra.Size() - offset)
|
||||
rem++;
|
||||
|
||||
s.Add_Space_if_NotEmpty();
|
||||
PrintType(s, g_ExtraTypes, ARRAY_SIZE(g_ExtraTypes), id);
|
||||
|
||||
if (id == NExtraID::kTime)
|
||||
{
|
||||
const Byte *p = Extra + offset;
|
||||
UInt64 flags;
|
||||
unsigned num = ReadVarInt(p, rem, &flags);
|
||||
if (num != 0)
|
||||
{
|
||||
s += ':';
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_ExtraTimeFlags); i++)
|
||||
if ((flags & ((UInt64)1 << i)) != 0)
|
||||
s += g_ExtraTimeFlags[i];
|
||||
flags &= ~(((UInt64)1 << ARRAY_SIZE(g_ExtraTimeFlags)) - 1);
|
||||
if (flags != 0)
|
||||
{
|
||||
s += '_';
|
||||
AddHex64(s, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (id == NExtraID::kLink)
|
||||
{
|
||||
CLinkInfo linkInfo;
|
||||
if (linkInfo.Parse(Extra + offset, (unsigned)rem))
|
||||
{
|
||||
s += ':';
|
||||
PrintType(s, g_LinkTypes, ARRAY_SIZE(g_LinkTypes), linkInfo.Type);
|
||||
UInt64 flags = linkInfo.Flags;
|
||||
if (flags != 0)
|
||||
{
|
||||
s += ':';
|
||||
if (flags & NLinkFlags::kTargetIsDir)
|
||||
{
|
||||
s += 'D';
|
||||
flags &= ~((UInt64)NLinkFlags::kTargetIsDir);
|
||||
}
|
||||
if (flags != 0)
|
||||
{
|
||||
s += '_';
|
||||
AddHex64(s, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offset += rem;
|
||||
}
|
||||
}
|
||||
|
||||
s.Add_OptSpaced("ERROR");
|
||||
}
|
||||
|
||||
|
||||
bool CCryptoInfo::Parse(const Byte *p, size_t size)
|
||||
{
|
||||
Algo = 0;
|
||||
Flags = 0;
|
||||
Cnt = 0;
|
||||
|
||||
unsigned num = ReadVarInt(p, size, &Algo);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
num = ReadVarInt(p, size, &Flags);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
if (size > 0)
|
||||
Cnt = p[0];
|
||||
|
||||
if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0))
|
||||
return false;
|
||||
|
||||
Cnt = p[0];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -184,7 +368,7 @@ bool CCryptoInfo::Parse(const Byte *p, size_t size)
|
||||
bool CItem::FindExtra_Version(UInt64 &version) const
|
||||
{
|
||||
unsigned size;
|
||||
int offset = FindExtra(NExtraRecordType::kVersion, size);
|
||||
int offset = FindExtra(NExtraID::kVersion, size);
|
||||
if (offset < 0)
|
||||
return false;
|
||||
const Byte *p = Extra + (unsigned)offset;
|
||||
@@ -202,26 +386,12 @@ bool CItem::FindExtra_Version(UInt64 &version) const
|
||||
bool CItem::FindExtra_Link(CLinkInfo &link) const
|
||||
{
|
||||
unsigned size;
|
||||
int offset = FindExtra(NExtraRecordType::kLink, size);
|
||||
int offset = FindExtra(NExtraID::kLink, size);
|
||||
if (offset < 0)
|
||||
return false;
|
||||
const Byte *p = Extra + (unsigned)offset;
|
||||
|
||||
unsigned num = ReadVarInt(p, size, &link.Type);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
num = ReadVarInt(p, size, &link.Flags);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
UInt64 len;
|
||||
num = ReadVarInt(p, size, &len);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
if (size != len)
|
||||
if (!link.Parse(Extra + (unsigned)offset, size))
|
||||
return false;
|
||||
|
||||
link.NameLen = (unsigned)len;
|
||||
link.NameOffset = (unsigned)(p - Extra);
|
||||
link.NameOffset += offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -268,14 +438,14 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop)
|
||||
|
||||
UString unicode;
|
||||
if (ConvertUTF8ToUnicode(s, unicode))
|
||||
prop = NItemName::GetOSName(unicode);
|
||||
prop = NItemName::GetOsPath(unicode);
|
||||
}
|
||||
|
||||
bool CItem::GetAltStreamName(AString &name) const
|
||||
{
|
||||
name.Empty();
|
||||
unsigned size;
|
||||
int offset = FindExtra(NExtraRecordType::kSubdata, size);
|
||||
int offset = FindExtra(NExtraID::kSubdata, size);
|
||||
if (offset < 0)
|
||||
return false;
|
||||
name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size);
|
||||
@@ -578,7 +748,7 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h)
|
||||
|
||||
|
||||
/*
|
||||
int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const
|
||||
int CInArcInfo::FindExtra(unsigned extraID, unsigned &recordDataSize) const
|
||||
{
|
||||
recordDataSize = 0;
|
||||
size_t offset = 0;
|
||||
@@ -601,14 +771,14 @@ int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const
|
||||
rem = (size_t)size;
|
||||
}
|
||||
{
|
||||
UInt64 type2;
|
||||
unsigned num = ReadVarInt(Extra + offset, rem, &type2);
|
||||
UInt64 id;
|
||||
unsigned num = ReadVarInt(Extra + offset, rem, &id);
|
||||
if (num == 0)
|
||||
return -1;
|
||||
offset += num;
|
||||
rem -= num;
|
||||
|
||||
if (type2 == type)
|
||||
if (id == extraID)
|
||||
{
|
||||
recordDataSize = (unsigned)rem;
|
||||
return (int)offset;
|
||||
@@ -929,7 +1099,7 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool
|
||||
}
|
||||
|
||||
unsigned cryptoSize = 0;
|
||||
int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
|
||||
int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);
|
||||
|
||||
if (cryptoOffset >= 0)
|
||||
{
|
||||
@@ -1023,7 +1193,7 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
|
||||
// if (res == S_OK)
|
||||
{
|
||||
unsigned cryptoSize = 0;
|
||||
int cryptoOffset = lastItem.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
|
||||
int cryptoOffset = lastItem.FindExtra(NExtraID::kCrypto, cryptoSize);
|
||||
NCrypto::NRar5::CDecoder *crypto = NULL;
|
||||
|
||||
if (cryptoOffset >= 0)
|
||||
@@ -1190,7 +1360,7 @@ static const Byte kProps[] =
|
||||
kpidCRC,
|
||||
kpidHostOS,
|
||||
kpidMethod,
|
||||
|
||||
kpidCharacts,
|
||||
kpidSymLink,
|
||||
kpidHardLink,
|
||||
kpidCopyLink,
|
||||
@@ -1308,8 +1478,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
if (/* &_missingVol || */ !_missingVolName.IsEmpty())
|
||||
{
|
||||
UString s;
|
||||
s.SetFromAscii("Missing volume : ");
|
||||
UString s ("Missing volume : ");
|
||||
s += _missingVolName;
|
||||
prop = s;
|
||||
}
|
||||
@@ -1339,13 +1508,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
if (arcInfo->IsVolume())
|
||||
{
|
||||
char sz[32];
|
||||
ConvertUInt64ToString(arcInfo->GetVolIndex() + 1, sz);
|
||||
unsigned len = MyStringLen(sz);
|
||||
AString s = "part";
|
||||
for (; len < 2; len++)
|
||||
AString s ("part");
|
||||
UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1;
|
||||
if (v < 10)
|
||||
s += '0';
|
||||
s += sz;
|
||||
s.Add_UInt32(v);
|
||||
s += ".rar";
|
||||
prop = s;
|
||||
}
|
||||
@@ -1452,7 +1619,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
|
||||
static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop)
|
||||
{
|
||||
unsigned size;
|
||||
int offset = item.FindExtra(NExtraRecordType::kTime, size);
|
||||
int offset = item.FindExtra(NExtraID::kTime, size);
|
||||
if (offset < 0)
|
||||
return;
|
||||
|
||||
@@ -1470,29 +1637,43 @@ static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CProp
|
||||
return;
|
||||
|
||||
unsigned numStamps = 0;
|
||||
unsigned curStamp = 0;
|
||||
unsigned i;
|
||||
for (i = 0; i < 3; i++)
|
||||
if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
|
||||
{
|
||||
if (i == stampIndex)
|
||||
curStamp = numStamps;
|
||||
numStamps++;
|
||||
unsigned stampSizeLog = ((flags & NTimeRecord::NFlags::kUnixTime) != 0) ? 2 : 3;
|
||||
|
||||
if ((numStamps << stampSizeLog) != size)
|
||||
return;
|
||||
|
||||
numStamps = 0;
|
||||
for (i = 0; i < stampIndex; i++)
|
||||
if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
|
||||
numStamps++;
|
||||
|
||||
p += (numStamps << stampSizeLog);
|
||||
}
|
||||
|
||||
FILETIME ft;
|
||||
|
||||
if ((flags & NTimeRecord::NFlags::kUnixTime) != 0)
|
||||
NWindows::NTime::UnixTimeToFileTime(Get32(p), ft);
|
||||
{
|
||||
curStamp *= 4;
|
||||
if (curStamp + 4 > size)
|
||||
return;
|
||||
const Byte *p2 = p + curStamp;
|
||||
UInt64 val = NTime::UnixTimeToFileTime64(Get32(p2));
|
||||
numStamps *= 4;
|
||||
if ((flags & NTimeRecord::NFlags::kUnixNs) != 0 && numStamps * 2 <= size)
|
||||
{
|
||||
const UInt32 ns = Get32(p2 + numStamps) & 0x3FFFFFFF;
|
||||
if (ns < 1000000000)
|
||||
val += ns / 100;
|
||||
}
|
||||
ft.dwLowDateTime = (DWORD)val;
|
||||
ft.dwHighDateTime = (DWORD)(val >> 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
ft.dwLowDateTime = Get32(p);
|
||||
ft.dwHighDateTime = Get32(p + 4);
|
||||
curStamp *= 8;
|
||||
if (curStamp + 8 > size)
|
||||
return;
|
||||
const Byte *p2 = p + curStamp;
|
||||
ft.dwLowDateTime = Get32(p2);
|
||||
ft.dwHighDateTime = Get32(p2 + 4);
|
||||
}
|
||||
|
||||
prop = ft;
|
||||
@@ -1537,19 +1718,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
break;
|
||||
if (item.Version_Defined)
|
||||
{
|
||||
wchar_t temp[32];
|
||||
char temp[32];
|
||||
// temp[0] = ';';
|
||||
// ConvertUInt64ToString(item.Version, temp + 1);
|
||||
// unicodeName += temp;
|
||||
ConvertUInt64ToString(item.Version, temp);
|
||||
UString s2 = L"[VER]" WSTRING_PATH_SEPARATOR;
|
||||
UString s2 ("[VER]" STRING_PATH_SEPARATOR);
|
||||
s2 += temp;
|
||||
s2.Add_PathSepar();
|
||||
unicodeName.Insert(0, s2);
|
||||
}
|
||||
}
|
||||
|
||||
NItemName::ConvertToOSName2(unicodeName);
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(unicodeName);
|
||||
prop = unicodeName;
|
||||
|
||||
break;
|
||||
@@ -1623,7 +1804,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
case kpidMethod:
|
||||
{
|
||||
char temp[64];
|
||||
char temp[128];
|
||||
unsigned algo = item.GetAlgoVersion();
|
||||
char *s = temp;
|
||||
if (algo != 0)
|
||||
@@ -1645,16 +1826,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
}
|
||||
|
||||
unsigned cryptoSize = 0;
|
||||
int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
|
||||
int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);
|
||||
if (cryptoOffset >= 0)
|
||||
{
|
||||
s = temp + strlen(temp);
|
||||
*s++ = ' ';
|
||||
strcpy(s, "AES:");
|
||||
|
||||
CCryptoInfo cryptoInfo;
|
||||
if (cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize))
|
||||
|
||||
bool isOK = cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize);
|
||||
|
||||
if (cryptoInfo.Algo == 0)
|
||||
s = MyStpCpy(s, "AES");
|
||||
else
|
||||
{
|
||||
s = MyStpCpy(s, "Crypto_");
|
||||
ConvertUInt64ToString(cryptoInfo.Algo, s);
|
||||
s += strlen(s);
|
||||
}
|
||||
|
||||
if (isOK)
|
||||
{
|
||||
*s++ = ':';
|
||||
ConvertUInt32ToString(cryptoInfo.Cnt, s);
|
||||
s += strlen(s);
|
||||
*s++ = ':';
|
||||
@@ -1666,6 +1859,35 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidCharacts:
|
||||
{
|
||||
AString s;
|
||||
|
||||
if (item.ACL >= 0)
|
||||
{
|
||||
s.Add_OptSpaced("ACL");
|
||||
}
|
||||
|
||||
UInt32 flags = item.Flags;
|
||||
// flags &= ~(6); // we don't need compression related bits here.
|
||||
|
||||
if (flags != 0)
|
||||
{
|
||||
AString s2 = FlagsToString(k_FileFlags, ARRAY_SIZE(k_FileFlags), flags);
|
||||
if (!s2.IsEmpty())
|
||||
{
|
||||
s.Add_OptSpaced(s2);
|
||||
}
|
||||
}
|
||||
|
||||
item.PrintInfo(s);
|
||||
|
||||
if (!s.IsEmpty())
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case kpidHostOS:
|
||||
if (item.HostOS < ARRAY_SIZE(kHostOS))
|
||||
prop = kHostOS[(size_t)item.HostOS];
|
||||
@@ -1788,7 +2010,7 @@ void CHandler::FillLinks()
|
||||
const CItem &item = _items[ref.Item];
|
||||
if (item.IsDir() || item.IsService() || item.PackSize != 0)
|
||||
continue;
|
||||
CItem::CLinkInfo linkInfo;
|
||||
CLinkInfo linkInfo;
|
||||
if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy)
|
||||
continue;
|
||||
link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen);
|
||||
|
||||
@@ -85,7 +85,7 @@ enum EHostOS
|
||||
|
||||
// ---------- Extra ----------
|
||||
|
||||
namespace NExtraRecordType
|
||||
namespace NExtraID
|
||||
{
|
||||
enum
|
||||
{
|
||||
@@ -99,7 +99,7 @@ namespace NExtraRecordType
|
||||
};
|
||||
}
|
||||
|
||||
// const unsigned kCryptoAlgo_AES = 0;
|
||||
const unsigned kCryptoAlgo_AES = 0;
|
||||
|
||||
namespace NCryptoFlags
|
||||
{
|
||||
@@ -133,8 +133,9 @@ namespace NTimeRecord
|
||||
{
|
||||
const unsigned kUnixTime = 1 << 0;
|
||||
const unsigned kMTime = 1 << 1;
|
||||
// const unsigned kCTime = 1 << 2;
|
||||
// const unsigned kATime = 1 << 3;
|
||||
const unsigned kCTime = 1 << 2;
|
||||
const unsigned kATime = 1 << 3;
|
||||
const unsigned kUnixNs = 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +157,17 @@ namespace NLinkFlags
|
||||
}
|
||||
|
||||
|
||||
struct CLinkInfo
|
||||
{
|
||||
UInt64 Type;
|
||||
UInt64 Flags;
|
||||
unsigned NameOffset;
|
||||
unsigned NameLen;
|
||||
|
||||
bool Parse(const Byte *p, unsigned size);
|
||||
};
|
||||
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt32 CommonFlags;
|
||||
@@ -230,18 +242,20 @@ struct CItem
|
||||
bool Is_ACL() const { return IsService() && Name == "ACL"; }
|
||||
// bool Is_QO() const { return IsService() && Name == "QO"; }
|
||||
|
||||
int FindExtra(unsigned type, unsigned &recordDataSize) const;
|
||||
int FindExtra(unsigned extraID, unsigned &recordDataSize) const;
|
||||
void PrintInfo(AString &s) const;
|
||||
|
||||
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
unsigned size;
|
||||
return FindExtra(NExtraRecordType::kCrypto, size) >= 0;
|
||||
return FindExtra(NExtraID::kCrypto, size) >= 0;
|
||||
}
|
||||
|
||||
int FindExtra_Blake() const
|
||||
{
|
||||
unsigned size = 0;
|
||||
int offset = FindExtra(NExtraRecordType::kHash, size);
|
||||
int offset = FindExtra(NExtraID::kHash, size);
|
||||
if (offset >= 0
|
||||
&& size == BLAKE2S_DIGEST_SIZE + 1
|
||||
&& Extra[(unsigned)offset] == kHashID_Blake2sp)
|
||||
@@ -251,14 +265,6 @@ struct CItem
|
||||
|
||||
bool FindExtra_Version(UInt64 &version) const;
|
||||
|
||||
struct CLinkInfo
|
||||
{
|
||||
UInt64 Type;
|
||||
UInt64 Flags;
|
||||
unsigned NameOffset;
|
||||
unsigned NameLen;
|
||||
};
|
||||
|
||||
bool FindExtra_Link(CLinkInfo &link) const;
|
||||
void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const;
|
||||
bool Is_CopyLink() const;
|
||||
@@ -313,7 +319,7 @@ struct CInArcInfo
|
||||
bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; }
|
||||
};
|
||||
|
||||
int FindExtra(unsigned type, unsigned &recordDataSize) const;
|
||||
int FindExtra(unsigned extraID, unsigned &recordDataSize) const;
|
||||
bool FindExtra_Locator(CLocator &locator) const;
|
||||
*/
|
||||
|
||||
|
||||
@@ -104,20 +104,18 @@ static const char * const kHostOS[] =
|
||||
, "BeOS"
|
||||
};
|
||||
|
||||
static const char *kUnknownOS = "Unknown";
|
||||
|
||||
static const CUInt32PCharPair k_Flags[] =
|
||||
static const char * const k_Flags[] =
|
||||
{
|
||||
{ 0, "Volume" },
|
||||
{ 1, "Comment" },
|
||||
{ 2, "Lock" },
|
||||
{ 3, "Solid" },
|
||||
{ 4, "NewVolName" }, // pack_comment in old versuons
|
||||
{ 5, "Authenticity" },
|
||||
{ 6, "Recovery" },
|
||||
{ 7, "BlockEncryption" },
|
||||
{ 8, "FirstVolume" },
|
||||
{ 9, "EncryptVer" }
|
||||
"Volume"
|
||||
, "Comment"
|
||||
, "Lock"
|
||||
, "Solid"
|
||||
, "NewVolName" // pack_comment in old versuons
|
||||
, "Authenticity"
|
||||
, "Recovery"
|
||||
, "BlockEncryption"
|
||||
, "FirstVolume"
|
||||
, "EncryptVer" // 9
|
||||
};
|
||||
|
||||
enum EErrorType
|
||||
@@ -132,13 +130,13 @@ class CInArchive
|
||||
{
|
||||
IInStream *m_Stream;
|
||||
UInt64 m_StreamStartPosition;
|
||||
CBuffer<wchar_t> _unicodeNameBuffer;
|
||||
UString _unicodeNameBuffer;
|
||||
CByteBuffer _comment;
|
||||
CByteBuffer m_FileHeaderData;
|
||||
NHeader::NBlock::CBlock m_BlockHeader;
|
||||
NCrypto::NRar3::CDecoder *m_RarAESSpec;
|
||||
CMyComPtr<ICompressFilter> m_RarAES;
|
||||
CBuffer<Byte> m_DecryptedData;
|
||||
CByteBuffer m_DecryptedData;
|
||||
Byte *m_DecryptedDataAligned;
|
||||
UInt32 m_DecryptedDataSize;
|
||||
bool m_CryptoMode;
|
||||
@@ -272,14 +270,19 @@ bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
|
||||
return processed == size;
|
||||
}
|
||||
|
||||
static void DecodeUnicodeFileName(const Byte *name, const Byte *encName,
|
||||
|
||||
static unsigned DecodeUnicodeFileName(const Byte *name, const Byte *encName,
|
||||
unsigned encSize, wchar_t *unicodeName, unsigned maxDecSize)
|
||||
{
|
||||
unsigned encPos = 0;
|
||||
unsigned decPos = 0;
|
||||
unsigned flagBits = 0;
|
||||
Byte flags = 0;
|
||||
Byte highByte = encName[encPos++];
|
||||
|
||||
if (encPos >= encSize)
|
||||
return 0; // error
|
||||
const unsigned highBits = ((unsigned)encName[encPos++]) << 8;
|
||||
|
||||
while (encPos < encSize && decPos < maxDecSize)
|
||||
{
|
||||
if (flagBits == 0)
|
||||
@@ -287,40 +290,46 @@ static void DecodeUnicodeFileName(const Byte *name, const Byte *encName,
|
||||
flags = encName[encPos++];
|
||||
flagBits = 8;
|
||||
}
|
||||
switch (flags >> 6)
|
||||
{
|
||||
case 0:
|
||||
unicodeName[decPos++] = encName[encPos++];
|
||||
break;
|
||||
case 1:
|
||||
unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8));
|
||||
break;
|
||||
case 2:
|
||||
unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8));
|
||||
encPos += 2;
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
unsigned len = encName[encPos++];
|
||||
if (len & 0x80)
|
||||
{
|
||||
Byte correction = encName[encPos++];
|
||||
for (len = (len & 0x7f) + 2;
|
||||
len > 0 && decPos < maxDecSize; len--, decPos++)
|
||||
unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));
|
||||
}
|
||||
else
|
||||
for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++)
|
||||
unicodeName[decPos] = name[decPos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
flags <<= 2;
|
||||
|
||||
if (encPos >= encSize)
|
||||
break; // error
|
||||
unsigned len = encName[encPos++];
|
||||
|
||||
flagBits -= 2;
|
||||
const unsigned mode = (flags >> flagBits) & 3;
|
||||
|
||||
if (mode != 3)
|
||||
{
|
||||
if (mode == 1)
|
||||
len += highBits;
|
||||
else if (mode == 2)
|
||||
{
|
||||
if (encPos >= encSize)
|
||||
break; // error
|
||||
len += ((unsigned)encName[encPos++] << 8);
|
||||
}
|
||||
unicodeName[decPos++] = (wchar_t)len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len & 0x80)
|
||||
{
|
||||
if (encPos >= encSize)
|
||||
break; // error
|
||||
Byte correction = encName[encPos++];
|
||||
for (len = (len & 0x7f) + 2; len > 0 && decPos < maxDecSize; len--, decPos++)
|
||||
unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + highBits);
|
||||
}
|
||||
else
|
||||
for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++)
|
||||
unicodeName[decPos] = name[decPos];
|
||||
}
|
||||
}
|
||||
unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;
|
||||
|
||||
return decPos < maxDecSize ? decPos : maxDecSize - 1;
|
||||
}
|
||||
|
||||
|
||||
void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item)
|
||||
{
|
||||
item.UnicodeName.Empty();
|
||||
@@ -336,8 +345,8 @@ void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item)
|
||||
{
|
||||
i++;
|
||||
unsigned uNameSizeMax = MyMin(nameSize, (unsigned)0x400);
|
||||
_unicodeNameBuffer.AllocAtLeast(uNameSizeMax + 1);
|
||||
DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer, uNameSizeMax);
|
||||
unsigned len = DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer.GetBuf(uNameSizeMax), uNameSizeMax);
|
||||
_unicodeNameBuffer.ReleaseBuf_SetEnd(len);
|
||||
item.UnicodeName = _unicodeNameBuffer;
|
||||
}
|
||||
else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))
|
||||
@@ -818,7 +827,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidSolid: prop = _arcInfo.IsSolid(); break;
|
||||
case kpidCharacts:
|
||||
{
|
||||
AString s = FlagsToString(k_Flags, ARRAY_SIZE(k_Flags), _arcInfo.Flags);
|
||||
AString s (FlagsToString(k_Flags, ARRAY_SIZE(k_Flags), _arcInfo.Flags));
|
||||
// FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop);
|
||||
if (_arcInfo.Is_DataCRC_Defined())
|
||||
{
|
||||
@@ -871,8 +880,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
|
||||
if (/* &_missingVol || */ !_missingVolName.IsEmpty())
|
||||
{
|
||||
UString s;
|
||||
s.SetFromAscii("Missing volume : ");
|
||||
UString s ("Missing volume : ");
|
||||
s += _missingVolName;
|
||||
prop = s;
|
||||
}
|
||||
@@ -900,13 +908,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
if (_arcInfo.Is_VolNumber_Defined())
|
||||
{
|
||||
char sz[16];
|
||||
ConvertUInt32ToString((UInt32)_arcInfo.VolNumber + 1, sz);
|
||||
unsigned len = MyStringLen(sz);
|
||||
AString s = "part";
|
||||
for (; len < 2; len++)
|
||||
AString s ("part");
|
||||
UInt32 v = (UInt32)_arcInfo.VolNumber + 1;
|
||||
if (v < 10)
|
||||
s += '0';
|
||||
s += sz;
|
||||
s.Add_UInt32(v);
|
||||
s += ".rar";
|
||||
prop = s;
|
||||
}
|
||||
@@ -974,7 +980,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
u = mainItem->GetName();
|
||||
u += item.GetName();
|
||||
*/
|
||||
prop = (const wchar_t *)NItemName::WinNameToOSName(item.GetName());
|
||||
prop = (const wchar_t *)NItemName::WinPathToOsPath(item.GetName());
|
||||
break;
|
||||
}
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
@@ -1015,7 +1021,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
case kpidHostOS: prop = (item.HostOS < ARRAY_SIZE(kHostOS)) ? kHostOS[item.HostOS] : kUnknownOS; break;
|
||||
case kpidHostOS:
|
||||
TYPE_TO_PROP(kHostOS, item.HostOS, prop);
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -1324,7 +1332,13 @@ STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (_curIndex >= _refItem.NumItems)
|
||||
break;
|
||||
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
|
||||
IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream;
|
||||
unsigned volIndex = _refItem.VolumeIndex + _curIndex;
|
||||
if (volIndex >= _arcs->Size())
|
||||
{
|
||||
return S_OK;
|
||||
// return S_FALSE;
|
||||
}
|
||||
IInStream *s = (*_arcs)[volIndex].Stream;
|
||||
RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
_stream = s;
|
||||
_calcCrc = (CrcIsOK && item.IsSplitAfter());
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
}
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
_after.SetFromAscii(".rar");
|
||||
_after = ".rar";
|
||||
base.DeleteFrom(dotPos);
|
||||
}
|
||||
else if (!newStyle)
|
||||
@@ -76,8 +76,8 @@ public:
|
||||
|
||||
_after.Empty();
|
||||
_before = base;
|
||||
_before += L'.';
|
||||
_changed.SetFromAscii("r00");
|
||||
_before += '.';
|
||||
_changed = "r00";
|
||||
_needChangeForNext = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user