mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 17:15:00 -06:00
15.05
This commit is contained in:
committed by
Kornel Lesiński
parent
0713a3ab80
commit
54490d51d5
@@ -89,7 +89,7 @@ UInt32 CItem::GetWinAttrib() const
|
||||
return a;
|
||||
}
|
||||
|
||||
static const char *kHostOS[] =
|
||||
static const char * const kHostOS[] =
|
||||
{
|
||||
"MS DOS"
|
||||
, "OS/2"
|
||||
@@ -354,7 +354,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
|
||||
}
|
||||
|
||||
#define READ_TIME(_mask_, _ttt_) \
|
||||
{ int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += size2, size -= size2; }
|
||||
{ int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += (unsigned)size2, size -= (unsigned)size2; }
|
||||
|
||||
#define READ_TIME_2(_mask_, _def_, _ttt_) \
|
||||
_def_ = ((_mask_ & 8) != 0); if (_def_) \
|
||||
@@ -421,7 +421,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
|
||||
{
|
||||
item.IsAltStream = true;
|
||||
item.Name.Empty();
|
||||
item.UnicodeName = L".ACL";
|
||||
item.UnicodeName.SetFromAscii(".ACL");
|
||||
}
|
||||
else if (item.Name == "STM" && size != 0 && (size & 1) == 0)
|
||||
{
|
||||
@@ -517,7 +517,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password))
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen((BSTR)password);
|
||||
len = MyStringLen(password);
|
||||
CByteBuffer buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
@@ -645,6 +645,8 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
error = k_ErrorType_Corrupted;
|
||||
ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset);
|
||||
}
|
||||
|
||||
ArcInfo.EndOfArchive_was_Read = true;
|
||||
}
|
||||
m_Position += processed;
|
||||
FinishCryptoBlock();
|
||||
@@ -668,7 +670,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item);
|
||||
if (okItem)
|
||||
{
|
||||
if (!CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize - item.CommentSize))
|
||||
if (!CheckHeaderCrc(m_FileHeaderData, (unsigned)m_BlockHeader.HeadSize - item.CommentSize))
|
||||
{
|
||||
error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
|
||||
return S_OK;
|
||||
@@ -802,8 +804,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
// FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop);
|
||||
if (_arcInfo.Is_DataCRC_Defined())
|
||||
{
|
||||
if (!s.IsEmpty())
|
||||
s += ' ';
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += "VolCRC";
|
||||
}
|
||||
prop = s;
|
||||
@@ -1008,27 +1009,28 @@ public:
|
||||
{
|
||||
_first = true;
|
||||
_newStyle = newStyle;
|
||||
int dotPos = name.ReverseFind('.');
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
UString basePart = name;
|
||||
|
||||
if (dotPos >= 0)
|
||||
{
|
||||
UString ext = name.Ptr(dotPos + 1);
|
||||
if (ext.IsEqualToNoCase(L"rar"))
|
||||
if (ext.IsEqualTo_Ascii_NoCase("rar"))
|
||||
{
|
||||
_afterPart = name.Ptr(dotPos);
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (ext.IsEqualToNoCase(L"exe"))
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
_afterPart = L".rar";
|
||||
_afterPart.SetFromAscii(".rar");
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (!_newStyle)
|
||||
{
|
||||
if (ext.IsEqualToNoCase(L"000") ||
|
||||
ext.IsEqualToNoCase(L"001") ||
|
||||
ext.IsEqualToNoCase(L"r00") ||
|
||||
ext.IsEqualToNoCase(L"r01"))
|
||||
if (ext.IsEqualTo_Ascii_NoCase("000") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("001") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("r00") ||
|
||||
ext.IsEqualTo_Ascii_NoCase("r01"))
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_first = false;
|
||||
@@ -1042,18 +1044,21 @@ public:
|
||||
if (!_newStyle)
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_unchangedPart = basePart + UString(L".");
|
||||
_changedPart = L"r00";
|
||||
_unchangedPart = basePart;
|
||||
_unchangedPart += L'.';
|
||||
_changedPart.SetFromAscii("r00");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (basePart.IsEmpty())
|
||||
return false;
|
||||
unsigned i = basePart.Len();
|
||||
|
||||
do
|
||||
if (!IsDigit(basePart[i - 1]))
|
||||
break;
|
||||
while (--i);
|
||||
|
||||
_unchangedPart = basePart.Left(i);
|
||||
_changedPart = basePart.Ptr(i);
|
||||
return true;
|
||||
@@ -1071,34 +1076,59 @@ public:
|
||||
|
||||
UString GetNextName()
|
||||
{
|
||||
UString newName;
|
||||
if (_newStyle || !_first)
|
||||
{
|
||||
for (int i = (int)_changedPart.Len() - 1; i >= 0; i--)
|
||||
unsigned i = _changedPart.Len();
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = _changedPart[i];
|
||||
wchar_t c = _changedPart[--i];
|
||||
if (c == L'9')
|
||||
{
|
||||
c = L'0';
|
||||
newName.InsertAtFront(c);
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
if (i == 0)
|
||||
newName.InsertAtFront(L'1');
|
||||
{
|
||||
_changedPart.InsertAtFront(L'1');
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
newName = UString(c) + newName;
|
||||
i--;
|
||||
for (; i >= 0; i--)
|
||||
newName.InsertAtFront(_changedPart[i]);
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
break;
|
||||
}
|
||||
_changedPart = newName;
|
||||
}
|
||||
|
||||
_first = false;
|
||||
return _unchangedPart + _changedPart + _afterPart;
|
||||
}
|
||||
};
|
||||
|
||||
static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
|
||||
{
|
||||
areThereNonZeros = false;
|
||||
numZeros = 0;
|
||||
const size_t kBufSize = 1 << 9;
|
||||
Byte buf[kBufSize];
|
||||
for (;;)
|
||||
{
|
||||
UInt32 size = 0;
|
||||
HRESULT(stream->Read(buf, kBufSize, &size));
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
if (buf[i] != 0)
|
||||
{
|
||||
areThereNonZeros = true;
|
||||
numZeros += i;
|
||||
return S_OK;
|
||||
}
|
||||
numZeros += size;
|
||||
if (numZeros > maxSize)
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openCallback)
|
||||
@@ -1174,6 +1204,7 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
RINOK(archive.Open(inStream, maxCheckStartPosition));
|
||||
_isArc = true;
|
||||
CItem item;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (archive.m_Position > endPos)
|
||||
@@ -1181,11 +1212,13 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
_errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
EErrorType error;
|
||||
// bool decryptionError;
|
||||
// AString errorMessageLoc;
|
||||
bool filled;
|
||||
HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error);
|
||||
|
||||
if (error != k_ErrorType_OK)
|
||||
{
|
||||
if (error == k_ErrorType_UnexpectedEnd)
|
||||
@@ -1198,16 +1231,33 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
// AddErrorMessage(errorMessageLoc);
|
||||
}
|
||||
RINOK(result);
|
||||
|
||||
if (!filled)
|
||||
{
|
||||
if (error == k_ErrorType_DecryptionError && _items.IsEmpty())
|
||||
return S_FALSE;
|
||||
|
||||
if (archive.ArcInfo.ExtraZeroTail_is_Possible())
|
||||
{
|
||||
/* if there is recovery record for multivolume archive,
|
||||
RAR adds 18 bytes (ZERO bytes) at the end for alignment.
|
||||
We must skip these bytes to prevent phySize warning. */
|
||||
RINOK(inStream->Seek(archive.ArcInfo.EndPos, STREAM_SEEK_SET, NULL));
|
||||
bool areThereNonZeros;
|
||||
UInt64 numZeros;
|
||||
const UInt64 maxSize = 1 << 12;
|
||||
RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize));
|
||||
if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)
|
||||
archive.ArcInfo.EndPos += numZeros;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (item.IgnoreItem())
|
||||
continue;
|
||||
|
||||
bool needAdd = true;
|
||||
|
||||
if (item.IsSplitBefore())
|
||||
{
|
||||
if (!_refItems.IsEmpty())
|
||||
@@ -1217,6 +1267,7 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
needAdd = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (needAdd)
|
||||
{
|
||||
CRefItem refItem;
|
||||
@@ -1225,7 +1276,9 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
refItem.VolumeIndex = _arcs.Size();
|
||||
_refItems.Add(refItem);
|
||||
}
|
||||
|
||||
_items.Add(item);
|
||||
|
||||
if (openCallback && _items.Size() % 100 == 0)
|
||||
{
|
||||
UInt64 numFiles = _items.Size();
|
||||
@@ -1256,7 +1309,7 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
|
||||
/*
|
||||
int baseFileIndex = -1;
|
||||
for (int i = 0; i < _refItems.Size(); i++)
|
||||
for (unsigned i = 0; i < _refItems.Size(); i++)
|
||||
{
|
||||
CItem &item = _items[_refItems[i].ItemIndex];
|
||||
if (item.IsAltStream)
|
||||
@@ -1430,7 +1483,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
unsigned lastIndex = 0;
|
||||
CRecordVector<int> importantIndexes;
|
||||
CRecordVector<unsigned> importantIndexes;
|
||||
CRecordVector<bool> extractStatuses;
|
||||
|
||||
for (UInt32 t = 0; t < numItems; t++)
|
||||
@@ -1470,7 +1523,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
CFilterCoder *filterStreamSpec = new CFilterCoder;
|
||||
CFilterCoder *filterStreamSpec = new CFilterCoder(false);
|
||||
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
|
||||
|
||||
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
|
||||
@@ -1576,22 +1629,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
// unpackedPos += 0;
|
||||
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
|
||||
if (item.UnPackVersion >= 29)
|
||||
{
|
||||
if (!rar29CryptoDecoder)
|
||||
{
|
||||
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
|
||||
rar29CryptoDecoder = rar29CryptoDecoderSpec;
|
||||
// RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));
|
||||
}
|
||||
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
||||
/*
|
||||
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
|
||||
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||
&cryptoProperties));
|
||||
RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||
*/
|
||||
RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||
filterStreamSpec->Filter = rar29CryptoDecoder;
|
||||
}
|
||||
else if (item.UnPackVersion >= 20)
|
||||
@@ -1600,7 +1656,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
{
|
||||
rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
|
||||
rar20CryptoDecoder = rar20CryptoDecoderSpec;
|
||||
// RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));
|
||||
}
|
||||
filterStreamSpec->Filter = rar20CryptoDecoder;
|
||||
}
|
||||
@@ -1610,8 +1665,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,
|
||||
&cryptoSetPassword));
|
||||
|
||||
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||
|
||||
if (!getTextPassword)
|
||||
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||
@@ -1624,7 +1679,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
UString unicodePassword;
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen((BSTR)password);
|
||||
len = MyStringLen(password);
|
||||
CByteBuffer buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
@@ -1646,14 +1701,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
{
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
|
||||
}
|
||||
|
||||
filterStreamSpec->SetInStream(folderInStream);
|
||||
filterStreamSpec->SetOutStreamSize(NULL);
|
||||
inStream = filterStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
inStream = folderInStream;
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressCoder> commonCoder;
|
||||
|
||||
switch(item.Method)
|
||||
{
|
||||
case '0':
|
||||
@@ -1679,14 +1738,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
mi.Coder.Release();
|
||||
if (item.UnPackVersion <= 40)
|
||||
{
|
||||
UInt32 methodID = 0x040300;
|
||||
UInt32 methodID = 0x40300;
|
||||
if (item.UnPackVersion < 20)
|
||||
methodID += 1;
|
||||
else if (item.UnPackVersion < 29)
|
||||
methodID += 2;
|
||||
else
|
||||
methodID += 3;
|
||||
RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false));
|
||||
RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, false, mi.Coder));
|
||||
}
|
||||
|
||||
if (mi.Coder == 0)
|
||||
@@ -1722,7 +1781,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
|
||||
HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);
|
||||
|
||||
if (item.IsEncrypted())
|
||||
filterStreamSpec->ReleaseInStream();
|
||||
if (result == S_FALSE)
|
||||
@@ -1771,15 +1832,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
IMPL_ISetCompressCodecsInfo
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Rar", "rar r00", 0, 3,
|
||||
NHeader::kMarkerSize, SIGNATURE,
|
||||
REGISTER_ARC_I(
|
||||
"Rar", "rar r00", 0, 3,
|
||||
kMarker,
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Rar)
|
||||
NULL)
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user