mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 06:06:59 -06:00
9.19
This commit is contained in:
committed by
Kornel Lesiński
parent
c65230d858
commit
b75af1bba6
@@ -7,6 +7,7 @@
|
||||
#include "Common/StringConvert.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/PropVariantUtils.h"
|
||||
#include "Windows/Time.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
@@ -46,6 +47,20 @@ static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
|
||||
|
||||
static const wchar_t *kUnknownOS = L"Unknown";
|
||||
|
||||
static const CUInt32PCharPair 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" }
|
||||
};
|
||||
|
||||
static const STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
@@ -70,6 +85,7 @@ static const STATPROPSTG kProps[] =
|
||||
|
||||
static const STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidCharacts, VT_BSTR},
|
||||
{ NULL, kpidSolid, VT_BOOL},
|
||||
{ NULL, kpidNumBlocks, VT_UI4},
|
||||
// { NULL, kpidEncrypted, VT_BOOL},
|
||||
@@ -98,6 +114,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
switch(propID)
|
||||
{
|
||||
case kpidSolid: prop = _archiveInfo.IsSolid(); break;
|
||||
case kpidCharacts: FLAGS_TO_PROP(k_Flags, _archiveInfo.Flags, prop); break;
|
||||
// case kpidEncrypted: prop = _archiveInfo.IsEncrypted(); break; // it's for encrypted names.
|
||||
case kpidIsVolume: prop = _archiveInfo.IsVolume(); break;
|
||||
case kpidNumVolumes: prop = (UInt32)_archives.Size(); break;
|
||||
@@ -325,19 +342,19 @@ public:
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
IArchiveOpenCallback *openCallback)
|
||||
{
|
||||
{
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;
|
||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
|
||||
|
||||
CVolumeName seqName;
|
||||
|
||||
UInt64 totalBytes = 0;
|
||||
UInt64 curBytes = 0;
|
||||
|
||||
if (openArchiveCallback != NULL)
|
||||
if (openCallback)
|
||||
{
|
||||
openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
|
||||
openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
@@ -379,12 +396,12 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
inStream = stream;
|
||||
|
||||
UInt64 endPos = 0;
|
||||
if (openArchiveCallback != NULL)
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
if (openCallback)
|
||||
{
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
totalBytes += endPos;
|
||||
RINOK(openArchiveCallback->SetTotal(NULL, &totalBytes));
|
||||
RINOK(openCallback->SetTotal(NULL, &totalBytes));
|
||||
}
|
||||
|
||||
NArchive::NRar::CInArchive archive;
|
||||
@@ -396,15 +413,16 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
CItemEx item;
|
||||
for (;;)
|
||||
{
|
||||
if (archive.m_Position > endPos)
|
||||
{
|
||||
AddErrorMessage("Unexpected end of archive");
|
||||
break;
|
||||
}
|
||||
bool decryptionError;
|
||||
AString errorMessageLoc;
|
||||
HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc);
|
||||
if (errorMessageLoc)
|
||||
{
|
||||
if (!_errorMessage.IsEmpty())
|
||||
_errorMessage += '\n';
|
||||
_errorMessage += errorMessageLoc;
|
||||
}
|
||||
AddErrorMessage(errorMessageLoc);
|
||||
if (result == S_FALSE)
|
||||
{
|
||||
if (decryptionError && _items.IsEmpty())
|
||||
@@ -434,11 +452,11 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
_refItems.Add(refItem);
|
||||
}
|
||||
_items.Add(item);
|
||||
if (openArchiveCallback != NULL && _items.Size() % 100 == 0)
|
||||
if (openCallback && _items.Size() % 100 == 0)
|
||||
{
|
||||
UInt64 numFiles = _items.Size();
|
||||
UInt64 numBytes = curBytes + item.Position;
|
||||
RINOK(openArchiveCallback->SetCompleted(&numFiles, &numBytes));
|
||||
RINOK(openCallback->SetCompleted(&numFiles, &numBytes));
|
||||
}
|
||||
}
|
||||
curBytes += endPos;
|
||||
@@ -450,13 +468,13 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
IArchiveOpenCallback *openCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
try
|
||||
{
|
||||
HRESULT res = Open2(stream, maxCheckStartPosition, openArchiveCallback);
|
||||
HRESULT res = Open2(stream, maxCheckStartPosition, openCallback);
|
||||
if (res != S_OK)
|
||||
Close();
|
||||
return res;
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
#define __RAR_HANDLER_H
|
||||
|
||||
#include "../IArchive.h"
|
||||
#include "RarIn.h"
|
||||
#include "RarVolumeInStream.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "RarIn.h"
|
||||
#include "RarVolumeInStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
@@ -17,17 +18,6 @@ class CHandler:
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
|
||||
DECL_ISetCompressCodecsInfo
|
||||
|
||||
private:
|
||||
CRecordVector<CRefItem> _refItems;
|
||||
CObjectVector<CItemEx> _items;
|
||||
CObjectVector<CInArchive> _archives;
|
||||
@@ -37,7 +27,6 @@ private:
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
|
||||
UInt64 GetPackSize(int refIndex) const;
|
||||
// NArchive::NRar::CInArchive _archive;
|
||||
|
||||
bool IsSolid(int refIndex)
|
||||
{
|
||||
@@ -50,10 +39,26 @@ private:
|
||||
}
|
||||
return item.IsSolid();
|
||||
}
|
||||
void AddErrorMessage(const AString &s)
|
||||
{
|
||||
if (!_errorMessage.IsEmpty())
|
||||
_errorMessage += '\n';
|
||||
_errorMessage += s;
|
||||
}
|
||||
|
||||
HRESULT Open2(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback);
|
||||
IArchiveOpenCallback *openCallback);
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
|
||||
DECL_ISetCompressCodecsInfo
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
#include "Common/Types.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NRar{
|
||||
namespace NHeader{
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
namespace NHeader {
|
||||
|
||||
const int kMarkerSize = 7;
|
||||
extern Byte kMarker[kMarkerSize];
|
||||
@@ -43,32 +43,13 @@ namespace NArchive
|
||||
const UInt16 kBlockEncryption = 0x80;
|
||||
const UInt16 kFirstVolume = 0x100; // (set only by RAR 3.0 and later)
|
||||
const UInt16 kEncryptVer = 0x200; // RAR 3.6 there is EncryptVer Byte in End of MainHeader
|
||||
|
||||
const int kHeaderSizeMin = 7;
|
||||
|
||||
struct CBlock
|
||||
{
|
||||
UInt16 CRC;
|
||||
Byte Type;
|
||||
UInt16 Flags;
|
||||
UInt16 Size;
|
||||
UInt16 Reserved1;
|
||||
UInt32 Reserved2;
|
||||
// UInt16 GetRealCRC() const;
|
||||
};
|
||||
const int kHeaderSizeMin = 7;
|
||||
|
||||
const int kArchiveHeaderSize = 13;
|
||||
|
||||
const int kBlockHeadersAreEncrypted = 0x80;
|
||||
|
||||
struct CHeader360: public CBlock
|
||||
{
|
||||
Byte EncryptVersion;
|
||||
bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
|
||||
bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
|
||||
bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
|
||||
UInt32 GetBaseSize() const { return kArchiveHeaderSize + (IsEncryptOld() ? 0 : 1); }
|
||||
};
|
||||
}
|
||||
|
||||
namespace NFile
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/UTFConvert.h"
|
||||
@@ -14,9 +15,16 @@
|
||||
|
||||
#include "RarIn.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
#define Get64(p) GetUi64(p)
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
|
||||
static const char *k_UnexpectedEnd = "Unexpected end of archive";
|
||||
static const char *k_DecryptionError = "Decryption Error";
|
||||
|
||||
void CInArchive::ThrowExceptionWithCode(
|
||||
CInArchiveException::CCauseType cause)
|
||||
{
|
||||
@@ -42,140 +50,80 @@ void CInArchive::Close()
|
||||
m_Stream.Release();
|
||||
}
|
||||
|
||||
|
||||
static inline bool TestMarkerCandidate(const void *aTestBytes)
|
||||
HRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize)
|
||||
{
|
||||
for (UInt32 i = 0; i < NHeader::kMarkerSize; i++)
|
||||
if (((const Byte *)aTestBytes)[i] != NHeader::kMarker[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
RINOK(FindSignatureInStream(stream,
|
||||
NHeader::kMarker, NHeader::kMarkerSize,
|
||||
searchHeaderSizeLimit, m_ArchiveStartPosition));
|
||||
m_Stream = stream;
|
||||
m_Position = m_ArchiveStartPosition + NHeader::kMarkerSize;
|
||||
return m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
void CInArchive::ThrowUnexpectedEndOfArchiveException()
|
||||
{
|
||||
ThrowExceptionWithCode(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
if (m_CryptoMode)
|
||||
{
|
||||
size_t size = *resSize;
|
||||
*resSize = 0;
|
||||
const Byte *bufData = m_DecryptedDataAligned;
|
||||
UInt32 bufSize = m_DecryptedDataSize;
|
||||
size_t i;
|
||||
for (i = 0; i < size && m_CryptoPos < bufSize; i++)
|
||||
((Byte *)data)[i] = bufData[m_CryptoPos++];
|
||||
*resSize = i;
|
||||
return S_OK;
|
||||
}
|
||||
return ReadStream(m_Stream, data, resSize);
|
||||
}
|
||||
|
||||
bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
|
||||
{
|
||||
if (m_CryptoMode)
|
||||
{
|
||||
const Byte *bufData = m_DecryptedDataAligned;
|
||||
UInt32 bufSize = m_DecryptedDataSize;
|
||||
UInt32 i;
|
||||
for (i = 0; i < size && m_CryptoPos < bufSize; i++)
|
||||
((Byte *)data)[i] = bufData[m_CryptoPos++];
|
||||
return (i == size);
|
||||
}
|
||||
return (ReadStream_FALSE(m_Stream, data, size) == S_OK);
|
||||
size_t processed = size;
|
||||
if (ReadBytesSpec(data, &processed) != S_OK)
|
||||
return false;
|
||||
return processed == size;
|
||||
}
|
||||
|
||||
void CInArchive::ReadBytesAndTestResult(void *data, UInt32 size)
|
||||
{
|
||||
if(!ReadBytesAndTestSize(data,size))
|
||||
ThrowUnexpectedEndOfArchiveException();
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t realProcessedSize = size;
|
||||
HRESULT result = ReadStream(m_Stream, data, &realProcessedSize);
|
||||
if (processedSize != NULL)
|
||||
*processedSize = (UInt32)realProcessedSize;
|
||||
AddToSeekValue(realProcessedSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
static UInt32 CrcUpdateUInt16(UInt32 crc, UInt16 v)
|
||||
{
|
||||
crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF));
|
||||
crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF));
|
||||
return crc;
|
||||
}
|
||||
|
||||
static UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 v)
|
||||
{
|
||||
crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF));
|
||||
crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF));
|
||||
crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 16) & 0xFF));
|
||||
crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 24) & 0xFF));
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
m_CryptoMode = false;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition));
|
||||
m_Position = m_StreamStartPosition;
|
||||
|
||||
RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit));
|
||||
UInt64 arcStartPos;
|
||||
RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
|
||||
searchHeaderSizeLimit, arcStartPos));
|
||||
m_Position = arcStartPos + NHeader::kMarkerSize;
|
||||
RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
|
||||
Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1];
|
||||
|
||||
Byte buf[NHeader::NArchive::kArchiveHeaderSize];
|
||||
UInt32 processedSize;
|
||||
ReadBytes(buf, sizeof(buf), &processedSize);
|
||||
if (processedSize != sizeof(buf))
|
||||
return S_FALSE;
|
||||
m_CurData = buf;
|
||||
m_CurPos = 0;
|
||||
m_PosLimit = sizeof(buf);
|
||||
RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize));
|
||||
AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);
|
||||
|
||||
m_ArchiveHeader.CRC = ReadUInt16();
|
||||
m_ArchiveHeader.Type = ReadByte();
|
||||
m_ArchiveHeader.Flags = ReadUInt16();
|
||||
m_ArchiveHeader.Size = ReadUInt16();
|
||||
m_ArchiveHeader.Reserved1 = ReadUInt16();
|
||||
m_ArchiveHeader.Reserved2 = ReadUInt32();
|
||||
m_ArchiveHeader.EncryptVersion = 0;
|
||||
|
||||
UInt32 crc = CRC_INIT_VAL;
|
||||
crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.Type);
|
||||
crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Flags);
|
||||
crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Size);
|
||||
crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Reserved1);
|
||||
crc = CrcUpdateUInt32(crc, m_ArchiveHeader.Reserved2);
|
||||
UInt32 blockSize = Get16(buf + 5);
|
||||
|
||||
if (m_ArchiveHeader.IsThereEncryptVer() && m_ArchiveHeader.Size > NHeader::NArchive::kArchiveHeaderSize)
|
||||
_header.EncryptVersion = 0;
|
||||
_header.Flags = Get16(buf + 3);
|
||||
|
||||
UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;
|
||||
if (_header.IsThereEncryptVer())
|
||||
{
|
||||
ReadBytes(&m_ArchiveHeader.EncryptVersion, 1, &processedSize);
|
||||
if (processedSize != 1)
|
||||
if (blockSize <= headerSize)
|
||||
return S_FALSE;
|
||||
crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.EncryptVersion);
|
||||
RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));
|
||||
AddToSeekValue(1);
|
||||
_header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];
|
||||
headerSize += 1;
|
||||
}
|
||||
|
||||
if(m_ArchiveHeader.CRC != (CRC_GET_DIGEST(crc) & 0xFFFF))
|
||||
ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError);
|
||||
if (m_ArchiveHeader.Type != NHeader::NBlockType::kArchiveHeader)
|
||||
if (blockSize < headerSize ||
|
||||
buf[2] != NHeader::NBlockType::kArchiveHeader ||
|
||||
(UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF))
|
||||
return S_FALSE;
|
||||
m_ArchiveCommentPosition = m_Position;
|
||||
m_SeekOnArchiveComment = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CInArchive::SkipArchiveComment()
|
||||
{
|
||||
if (!m_SeekOnArchiveComment)
|
||||
return;
|
||||
AddToSeekValue(m_ArchiveHeader.Size - m_ArchiveHeader.GetBaseSize());
|
||||
m_SeekOnArchiveComment = false;
|
||||
size_t commentSize = blockSize - headerSize;
|
||||
_comment.SetCapacity(commentSize);
|
||||
RINOK(ReadStream_FALSE(stream, _comment, commentSize));
|
||||
AddToSeekValue(commentSize);
|
||||
m_Stream = stream;
|
||||
_header.StartPosition = arcStartPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
|
||||
{
|
||||
archiveInfo.StartPosition = m_ArchiveStartPosition;
|
||||
archiveInfo.Flags = m_ArchiveHeader.Flags;
|
||||
archiveInfo.CommentPosition = m_ArchiveCommentPosition;
|
||||
archiveInfo.CommentSize = (UInt16)(m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize);
|
||||
archiveInfo = _header;
|
||||
}
|
||||
|
||||
static void DecodeUnicodeFileName(const char *name, const Byte *encName,
|
||||
@@ -375,26 +323,21 @@ void CInArchive::AddToSeekValue(UInt64 addValue)
|
||||
HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage)
|
||||
{
|
||||
decryptionError = false;
|
||||
if (m_SeekOnArchiveComment)
|
||||
SkipArchiveComment();
|
||||
for (;;)
|
||||
{
|
||||
if (!SeekInArchive(m_Position))
|
||||
return S_FALSE;
|
||||
if (!m_CryptoMode && (m_ArchiveHeader.Flags &
|
||||
SeekInArchive(m_Position);
|
||||
if (!m_CryptoMode && (_header.Flags &
|
||||
NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
|
||||
{
|
||||
m_CryptoMode = false;
|
||||
if (getTextPassword == 0)
|
||||
return S_FALSE;
|
||||
if(!SeekInArchive(m_Position))
|
||||
return S_FALSE;
|
||||
if (!m_RarAES)
|
||||
{
|
||||
m_RarAESSpec = new NCrypto::NRar29::CDecoder;
|
||||
m_RarAES = m_RarAESSpec;
|
||||
}
|
||||
m_RarAESSpec->SetRar350Mode(m_ArchiveHeader.IsEncryptOld());
|
||||
m_RarAESSpec->SetRar350Mode(_header.IsEncryptOld());
|
||||
|
||||
// Salt
|
||||
const UInt32 kSaltSize = 8;
|
||||
@@ -438,9 +381,12 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
|
||||
}
|
||||
|
||||
m_FileHeaderData.EnsureCapacity(7);
|
||||
if (!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7))
|
||||
size_t processed = 7;
|
||||
RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed));
|
||||
if (processed != 7)
|
||||
{
|
||||
errorMessage = "Unexpected end of archive";
|
||||
if (processed != 0)
|
||||
errorMessage = k_UnexpectedEnd;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
@@ -463,7 +409,12 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
|
||||
m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);
|
||||
m_CurData = (Byte *)m_FileHeaderData;
|
||||
m_PosLimit = m_BlockHeader.HeadSize;
|
||||
ReadBytesAndTestResult(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7);
|
||||
if (!ReadBytesAndTestSize(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7))
|
||||
{
|
||||
errorMessage = k_UnexpectedEnd;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
ReadHeaderReal(item);
|
||||
if ((CrcCalc(m_CurData + 2,
|
||||
m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC)
|
||||
@@ -478,19 +429,25 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
|
||||
if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10))
|
||||
{
|
||||
decryptionError = true;
|
||||
errorMessage = k_DecryptionError;
|
||||
return S_FALSE;
|
||||
}
|
||||
if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)
|
||||
{
|
||||
m_FileHeaderData.EnsureCapacity(7 + 4);
|
||||
m_CurData = (Byte *)m_FileHeaderData;
|
||||
ReadBytesAndTestResult(m_CurData + m_CurPos, 4); // test it
|
||||
if (!ReadBytesAndTestSize(m_CurData + m_CurPos, 4))
|
||||
{
|
||||
errorMessage = k_UnexpectedEnd;
|
||||
return S_FALSE;
|
||||
}
|
||||
m_PosLimit = 7 + 4;
|
||||
UInt32 dataSize = ReadUInt32();
|
||||
AddToSeekValue(dataSize);
|
||||
if (m_CryptoMode && dataSize > (1 << 27))
|
||||
{
|
||||
decryptionError = true;
|
||||
errorMessage = k_DecryptionError;
|
||||
return S_FALSE;
|
||||
}
|
||||
m_CryptoPos = m_BlockHeader.HeadSize;
|
||||
@@ -503,11 +460,9 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
|
||||
}
|
||||
}
|
||||
|
||||
bool CInArchive::SeekInArchive(UInt64 position)
|
||||
void CInArchive::SeekInArchive(UInt64 position)
|
||||
{
|
||||
UInt64 newPosition;
|
||||
m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition);
|
||||
return newPosition == position;
|
||||
m_Stream->Seek(position, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)
|
||||
|
||||
@@ -33,18 +33,20 @@ public:
|
||||
CInArchiveException(CCauseType cause) : Cause(cause) {}
|
||||
};
|
||||
|
||||
class CInArchiveInfo
|
||||
|
||||
struct CInArchiveInfo
|
||||
{
|
||||
public:
|
||||
UInt32 Flags;
|
||||
Byte EncryptVersion;
|
||||
UInt64 StartPosition;
|
||||
UInt16 Flags;
|
||||
UInt64 CommentPosition;
|
||||
UInt16 CommentSize;
|
||||
|
||||
bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
|
||||
bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
|
||||
bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; }
|
||||
bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; }
|
||||
bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
|
||||
bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
|
||||
bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
@@ -52,23 +54,19 @@ class CInArchive
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
|
||||
UInt64 m_StreamStartPosition;
|
||||
UInt64 m_Position;
|
||||
UInt64 m_ArchiveStartPosition;
|
||||
|
||||
NHeader::NArchive::CHeader360 m_ArchiveHeader;
|
||||
CInArchiveInfo _header;
|
||||
CDynamicBuffer<char> m_NameBuffer;
|
||||
CDynamicBuffer<wchar_t> _unicodeNameBuffer;
|
||||
bool m_SeekOnArchiveComment;
|
||||
UInt64 m_ArchiveCommentPosition;
|
||||
|
||||
CByteBuffer _comment;
|
||||
|
||||
void ReadName(CItemEx &item, int nameSize);
|
||||
void ReadHeaderReal(CItemEx &item);
|
||||
|
||||
HRESULT ReadBytes(void *data, UInt32 size, UInt32 *aProcessedSize);
|
||||
HRESULT ReadBytesSpec(void *data, size_t *size);
|
||||
bool ReadBytesAndTestSize(void *data, UInt32 size);
|
||||
void ReadBytesAndTestResult(void *data, UInt32 size);
|
||||
|
||||
HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
|
||||
HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
|
||||
|
||||
void ThrowExceptionWithCode(CInArchiveException::CCauseType cause);
|
||||
@@ -108,15 +106,15 @@ class CInArchive
|
||||
}
|
||||
|
||||
public:
|
||||
UInt64 m_Position;
|
||||
|
||||
HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
|
||||
void Close();
|
||||
HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage);
|
||||
|
||||
void SkipArchiveComment();
|
||||
|
||||
void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;
|
||||
|
||||
bool SeekInArchive(UInt64 position);
|
||||
void SeekInArchive(UInt64 position);
|
||||
ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user