mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 02:07:06 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
1285
CPP/7zip/Archive/Rar/RarHandler.cpp
Executable file → Normal file
1285
CPP/7zip/Archive/Rar/RarHandler.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
79
CPP/7zip/Archive/Rar/RarHandler.h
Executable file → Normal file
79
CPP/7zip/Archive/Rar/RarHandler.h
Executable file → Normal file
@@ -7,44 +7,85 @@
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "RarIn.h"
|
||||
#include "RarVolumeInStream.h"
|
||||
#include "RarItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
struct CInArcInfo
|
||||
{
|
||||
UInt32 Flags;
|
||||
Byte EncryptVersion;
|
||||
|
||||
UInt64 StartPos;
|
||||
UInt64 EndPos;
|
||||
UInt64 FileSize;
|
||||
|
||||
UInt32 EndFlags;
|
||||
UInt32 VolNumber;
|
||||
UInt32 DataCRC;
|
||||
|
||||
CInArcInfo(): EndFlags(0) {}
|
||||
|
||||
UInt64 GetPhySize() const { return EndPos - StartPos; }
|
||||
|
||||
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 IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 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); }
|
||||
|
||||
bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; }
|
||||
bool Is_DataCRC_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_DataCRC) != 0; }
|
||||
};
|
||||
|
||||
struct CArc
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 PhySize;
|
||||
// CByteBuffer Comment;
|
||||
|
||||
CArc(): PhySize(0) {}
|
||||
ISequentialInStream *CreateLimitedStream(UInt64 offset, UInt64 size) const;
|
||||
};
|
||||
|
||||
struct CRefItem
|
||||
{
|
||||
unsigned VolumeIndex;
|
||||
unsigned ItemIndex;
|
||||
unsigned NumItems;
|
||||
};
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CRecordVector<CRefItem> _refItems;
|
||||
CObjectVector<CItemEx> _items;
|
||||
CObjectVector<CInArchive> _archives;
|
||||
NArchive::NRar::CInArchiveInfo _archiveInfo;
|
||||
AString _errorMessage;
|
||||
CObjectVector<CItem> _items;
|
||||
CObjectVector<CArc> _arcs;
|
||||
NArchive::NRar::CInArcInfo _arcInfo;
|
||||
// AString _errorMessage;
|
||||
UInt32 _errorFlags;
|
||||
UInt32 _warningFlags;
|
||||
bool _isArc;
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
|
||||
UInt64 GetPackSize(int refIndex) const;
|
||||
|
||||
bool IsSolid(int refIndex)
|
||||
{
|
||||
const CItemEx &item = _items[_refItems[refIndex].ItemIndex];
|
||||
if (item.UnPackVersion < 20)
|
||||
{
|
||||
if (_archiveInfo.IsSolid())
|
||||
return (refIndex > 0);
|
||||
return false;
|
||||
}
|
||||
return item.IsSolid();
|
||||
}
|
||||
UInt64 GetPackSize(unsigned refIndex) const;
|
||||
bool IsSolid(unsigned refIndex) const;
|
||||
|
||||
/*
|
||||
void AddErrorMessage(const AString &s)
|
||||
{
|
||||
if (!_errorMessage.IsEmpty())
|
||||
_errorMessage += '\n';
|
||||
_errorMessage += s;
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT Open2(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Archive/Rar/Headers.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "RarHeader.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NRar{
|
||||
namespace NHeader{
|
||||
|
||||
Byte kMarker[kMarkerSize] = {0x52 + 1, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};
|
||||
|
||||
class CMarkerInitializer
|
||||
{
|
||||
public:
|
||||
CMarkerInitializer() { kMarker[0]--; };
|
||||
};
|
||||
|
||||
static CMarkerInitializer markerInitializer;
|
||||
|
||||
}}}
|
||||
67
CPP/7zip/Archive/Rar/RarHeader.h
Executable file → Normal file
67
CPP/7zip/Archive/Rar/RarHeader.h
Executable file → Normal file
@@ -3,16 +3,15 @@
|
||||
#ifndef __ARCHIVE_RAR_HEADER_H
|
||||
#define __ARCHIVE_RAR_HEADER_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "../../../Common/MyTypes.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
namespace NHeader {
|
||||
|
||||
const int kMarkerSize = 7;
|
||||
extern Byte kMarker[kMarkerSize];
|
||||
const unsigned kMarkerSize = 7;
|
||||
|
||||
const int kArchiveSolid = 0x1;
|
||||
const unsigned kArchiveSolid = 0x1;
|
||||
|
||||
namespace NBlockType
|
||||
{
|
||||
@@ -44,36 +43,40 @@ namespace NArchive
|
||||
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;
|
||||
const UInt16 kEndOfArc_Flags_NextVol = 1;
|
||||
const UInt16 kEndOfArc_Flags_DataCRC = 2;
|
||||
const UInt16 kEndOfArc_Flags_RevSpace = 4;
|
||||
const UInt16 kEndOfArc_Flags_VolNumber = 8;
|
||||
|
||||
const unsigned kHeaderSizeMin = 7;
|
||||
|
||||
const int kArchiveHeaderSize = 13;
|
||||
|
||||
const int kBlockHeadersAreEncrypted = 0x80;
|
||||
const unsigned kArchiveHeaderSize = 13;
|
||||
|
||||
const unsigned kBlockHeadersAreEncrypted = 0x80;
|
||||
}
|
||||
|
||||
namespace NFile
|
||||
{
|
||||
const int kSplitBefore = 1 << 0;
|
||||
const int kSplitAfter = 1 << 1;
|
||||
const int kEncrypted = 1 << 2;
|
||||
const int kComment = 1 << 3;
|
||||
const int kSolid = 1 << 4;
|
||||
const unsigned kSplitBefore = 1 << 0;
|
||||
const unsigned kSplitAfter = 1 << 1;
|
||||
const unsigned kEncrypted = 1 << 2;
|
||||
const unsigned kComment = 1 << 3;
|
||||
const unsigned kSolid = 1 << 4;
|
||||
|
||||
const int kDictBitStart = 5;
|
||||
const int kNumDictBits = 3;
|
||||
const int kDictMask = (1 << kNumDictBits) - 1;
|
||||
const int kDictDirectoryValue = 0x7;
|
||||
const unsigned kDictBitStart = 5;
|
||||
const unsigned kNumDictBits = 3;
|
||||
const unsigned kDictMask = (1 << kNumDictBits) - 1;
|
||||
const unsigned kDictDirectoryValue = 0x7;
|
||||
|
||||
const int kSize64Bits = 1 << 8;
|
||||
const int kUnicodeName = 1 << 9;
|
||||
const int kSalt = 1 << 10;
|
||||
const int kOldVersion = 1 << 11;
|
||||
const int kExtTime = 1 << 12;
|
||||
// const int kExtFlags = 1 << 13;
|
||||
// const int kSkipIfUnknown = 1 << 14;
|
||||
const unsigned kSize64Bits = 1 << 8;
|
||||
const unsigned kUnicodeName = 1 << 9;
|
||||
const unsigned kSalt = 1 << 10;
|
||||
const unsigned kOldVersion = 1 << 11;
|
||||
const unsigned kExtTime = 1 << 12;
|
||||
// const unsigned kExtFlags = 1 << 13;
|
||||
// const unsigned kSkipIfUnknown = 1 << 14;
|
||||
|
||||
const int kLongBlock = 1 << 15;
|
||||
const unsigned kLongBlock = 1 << 15;
|
||||
|
||||
/*
|
||||
struct CBlock
|
||||
@@ -134,17 +137,17 @@ namespace NFile
|
||||
};
|
||||
*/
|
||||
|
||||
const int kLabelFileAttribute = 0x08;
|
||||
const int kWinFileDirectoryAttributeMask = 0x10;
|
||||
const unsigned kLabelFileAttribute = 0x08;
|
||||
const unsigned kWinFileDirectoryAttributeMask = 0x10;
|
||||
|
||||
enum CHostOS
|
||||
{
|
||||
kHostMSDOS = 0,
|
||||
kHostOS2 = 1,
|
||||
kHostWin32 = 2,
|
||||
kHostUnix = 3,
|
||||
kHostMacOS = 4,
|
||||
kHostBeOS = 5
|
||||
kHostOS2 = 1,
|
||||
kHostWin32 = 2,
|
||||
kHostUnix = 3,
|
||||
kHostMacOS = 4,
|
||||
kHostBeOS = 5
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,478 +0,0 @@
|
||||
// Archive/RarIn.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/UTFConvert.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../Common/FindSignature.h"
|
||||
|
||||
#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)
|
||||
{
|
||||
throw CInArchiveException(cause);
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
try
|
||||
{
|
||||
Close();
|
||||
HRESULT res = Open2(inStream, searchHeaderSizeLimit);
|
||||
if (res == S_OK)
|
||||
return res;
|
||||
Close();
|
||||
return res;
|
||||
}
|
||||
catch(...) { Close(); throw; }
|
||||
}
|
||||
|
||||
void CInArchive::Close()
|
||||
{
|
||||
m_Stream.Release();
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize)
|
||||
{
|
||||
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)
|
||||
{
|
||||
size_t processed = size;
|
||||
if (ReadBytesSpec(data, &processed) != S_OK)
|
||||
return false;
|
||||
return processed == size;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
m_CryptoMode = false;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition));
|
||||
m_Position = m_StreamStartPosition;
|
||||
|
||||
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];
|
||||
|
||||
RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize));
|
||||
AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);
|
||||
|
||||
|
||||
UInt32 blockSize = Get16(buf + 5);
|
||||
|
||||
_header.EncryptVersion = 0;
|
||||
_header.Flags = Get16(buf + 3);
|
||||
|
||||
UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;
|
||||
if (_header.IsThereEncryptVer())
|
||||
{
|
||||
if (blockSize <= headerSize)
|
||||
return S_FALSE;
|
||||
RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));
|
||||
AddToSeekValue(1);
|
||||
_header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];
|
||||
headerSize += 1;
|
||||
}
|
||||
if (blockSize < headerSize ||
|
||||
buf[2] != NHeader::NBlockType::kArchiveHeader ||
|
||||
(UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF))
|
||||
return S_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 = _header;
|
||||
}
|
||||
|
||||
static void DecodeUnicodeFileName(const char *name, const Byte *encName,
|
||||
int encSize, wchar_t *unicodeName, int maxDecSize)
|
||||
{
|
||||
int encPos = 0;
|
||||
int decPos = 0;
|
||||
int flagBits = 0;
|
||||
Byte flags = 0;
|
||||
Byte highByte = encName[encPos++];
|
||||
while (encPos < encSize && decPos < maxDecSize)
|
||||
{
|
||||
if (flagBits == 0)
|
||||
{
|
||||
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:
|
||||
{
|
||||
int length = encName[encPos++];
|
||||
if (length & 0x80)
|
||||
{
|
||||
Byte correction = encName[encPos++];
|
||||
for (length = (length & 0x7f) + 2;
|
||||
length > 0 && decPos < maxDecSize; length--, decPos++)
|
||||
unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));
|
||||
}
|
||||
else
|
||||
for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++)
|
||||
unicodeName[decPos] = name[decPos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
flags <<= 2;
|
||||
flagBits -= 2;
|
||||
}
|
||||
unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;
|
||||
}
|
||||
|
||||
void CInArchive::ReadName(CItemEx &item, int nameSize)
|
||||
{
|
||||
item.UnicodeName.Empty();
|
||||
if (nameSize > 0)
|
||||
{
|
||||
m_NameBuffer.EnsureCapacity(nameSize + 1);
|
||||
char *buffer = (char *)m_NameBuffer;
|
||||
|
||||
for (int i = 0; i < nameSize; i++)
|
||||
buffer[i] = ReadByte();
|
||||
|
||||
int mainLen;
|
||||
for (mainLen = 0; mainLen < nameSize; mainLen++)
|
||||
if (buffer[mainLen] == '\0')
|
||||
break;
|
||||
buffer[mainLen] = '\0';
|
||||
item.Name = buffer;
|
||||
|
||||
if(item.HasUnicodeName())
|
||||
{
|
||||
if(mainLen < nameSize)
|
||||
{
|
||||
int unicodeNameSizeMax = MyMin(nameSize, (0x400));
|
||||
_unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1);
|
||||
DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1,
|
||||
nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax);
|
||||
item.UnicodeName = _unicodeNameBuffer;
|
||||
}
|
||||
else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))
|
||||
item.UnicodeName.Empty();
|
||||
}
|
||||
}
|
||||
else
|
||||
item.Name.Empty();
|
||||
}
|
||||
|
||||
Byte CInArchive::ReadByte()
|
||||
{
|
||||
if (m_CurPos >= m_PosLimit)
|
||||
throw CInArchiveException(CInArchiveException::kIncorrectArchive);
|
||||
return m_CurData[m_CurPos++];
|
||||
}
|
||||
|
||||
UInt16 CInArchive::ReadUInt16()
|
||||
{
|
||||
UInt16 value = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Byte b = ReadByte();
|
||||
value |= (UInt16(b) << (8 * i));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
UInt32 CInArchive::ReadUInt32()
|
||||
{
|
||||
UInt32 value = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Byte b = ReadByte();
|
||||
value |= (UInt32(b) << (8 * i));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void CInArchive::ReadTime(Byte mask, CRarTime &rarTime)
|
||||
{
|
||||
rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);
|
||||
int numDigits = (mask & 3);
|
||||
rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0;
|
||||
for (int i = 0; i < numDigits; i++)
|
||||
rarTime.SubTime[3 - numDigits + i] = ReadByte();
|
||||
}
|
||||
|
||||
void CInArchive::ReadHeaderReal(CItemEx &item)
|
||||
{
|
||||
item.Flags = m_BlockHeader.Flags;
|
||||
item.PackSize = ReadUInt32();
|
||||
item.Size = ReadUInt32();
|
||||
item.HostOS = ReadByte();
|
||||
item.FileCRC = ReadUInt32();
|
||||
item.MTime.DosTime = ReadUInt32();
|
||||
item.UnPackVersion = ReadByte();
|
||||
item.Method = ReadByte();
|
||||
int nameSize = ReadUInt16();
|
||||
item.Attrib = ReadUInt32();
|
||||
|
||||
item.MTime.LowSecond = 0;
|
||||
item.MTime.SubTime[0] =
|
||||
item.MTime.SubTime[1] =
|
||||
item.MTime.SubTime[2] = 0;
|
||||
|
||||
if((item.Flags & NHeader::NFile::kSize64Bits) != 0)
|
||||
{
|
||||
item.PackSize |= ((UInt64)ReadUInt32() << 32);
|
||||
item.Size |= ((UInt64)ReadUInt32() << 32);
|
||||
}
|
||||
|
||||
ReadName(item, nameSize);
|
||||
|
||||
if (item.HasSalt())
|
||||
for (int i = 0; i < sizeof(item.Salt); i++)
|
||||
item.Salt[i] = ReadByte();
|
||||
|
||||
// some rar archives have HasExtTime flag without field.
|
||||
if (m_CurPos < m_PosLimit && item.HasExtTime())
|
||||
{
|
||||
Byte accessMask = (Byte)(ReadByte() >> 4);
|
||||
Byte b = ReadByte();
|
||||
Byte modifMask = (Byte)(b >> 4);
|
||||
Byte createMask = (Byte)(b & 0xF);
|
||||
if ((modifMask & 8) != 0)
|
||||
ReadTime(modifMask, item.MTime);
|
||||
item.CTimeDefined = ((createMask & 8) != 0);
|
||||
if (item.CTimeDefined)
|
||||
{
|
||||
item.CTime.DosTime = ReadUInt32();
|
||||
ReadTime(createMask, item.CTime);
|
||||
}
|
||||
item.ATimeDefined = ((accessMask & 8) != 0);
|
||||
if (item.ATimeDefined)
|
||||
{
|
||||
item.ATime.DosTime = ReadUInt32();
|
||||
ReadTime(accessMask, item.ATime);
|
||||
}
|
||||
}
|
||||
|
||||
UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos;
|
||||
|
||||
item.Position = m_Position;
|
||||
item.MainPartSize = fileHeaderWithNameSize;
|
||||
item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);
|
||||
|
||||
if (m_CryptoMode)
|
||||
item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);
|
||||
else
|
||||
item.AlignSize = 0;
|
||||
AddToSeekValue(m_BlockHeader.HeadSize);
|
||||
}
|
||||
|
||||
void CInArchive::AddToSeekValue(UInt64 addValue)
|
||||
{
|
||||
m_Position += addValue;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage)
|
||||
{
|
||||
decryptionError = false;
|
||||
for (;;)
|
||||
{
|
||||
SeekInArchive(m_Position);
|
||||
if (!m_CryptoMode && (_header.Flags &
|
||||
NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
|
||||
{
|
||||
m_CryptoMode = false;
|
||||
if (getTextPassword == 0)
|
||||
return S_FALSE;
|
||||
if (!m_RarAES)
|
||||
{
|
||||
m_RarAESSpec = new NCrypto::NRar29::CDecoder;
|
||||
m_RarAES = m_RarAESSpec;
|
||||
}
|
||||
m_RarAESSpec->SetRar350Mode(_header.IsEncryptOld());
|
||||
|
||||
// Salt
|
||||
const UInt32 kSaltSize = 8;
|
||||
Byte salt[kSaltSize];
|
||||
if(!ReadBytesAndTestSize(salt, kSaltSize))
|
||||
return S_FALSE;
|
||||
m_Position += kSaltSize;
|
||||
RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))
|
||||
// Password
|
||||
CMyComBSTR password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password))
|
||||
UString unicodePassword(password);
|
||||
|
||||
CByteBuffer buffer;
|
||||
const UInt32 sizeInBytes = unicodePassword.Length() * 2;
|
||||
buffer.SetCapacity(sizeInBytes);
|
||||
for (int i = 0; i < unicodePassword.Length(); i++)
|
||||
{
|
||||
wchar_t c = unicodePassword[i];
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
|
||||
RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
|
||||
|
||||
const UInt32 kDecryptedBufferSize = (1 << 12);
|
||||
if (m_DecryptedData.GetCapacity() == 0)
|
||||
{
|
||||
const UInt32 kAlign = 16;
|
||||
m_DecryptedData.SetCapacity(kDecryptedBufferSize + kAlign);
|
||||
m_DecryptedDataAligned = (Byte *)((ptrdiff_t)((Byte *)m_DecryptedData + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1));
|
||||
}
|
||||
RINOK(m_RarAES->Init());
|
||||
size_t decryptedDataSizeT = kDecryptedBufferSize;
|
||||
RINOK(ReadStream(m_Stream, m_DecryptedDataAligned, &decryptedDataSizeT));
|
||||
m_DecryptedDataSize = (UInt32)decryptedDataSizeT;
|
||||
m_DecryptedDataSize = m_RarAES->Filter(m_DecryptedDataAligned, m_DecryptedDataSize);
|
||||
|
||||
m_CryptoMode = true;
|
||||
m_CryptoPos = 0;
|
||||
}
|
||||
|
||||
m_FileHeaderData.EnsureCapacity(7);
|
||||
size_t processed = 7;
|
||||
RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed));
|
||||
if (processed != 7)
|
||||
{
|
||||
if (processed != 0)
|
||||
errorMessage = k_UnexpectedEnd;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
m_CurData = (Byte *)m_FileHeaderData;
|
||||
m_CurPos = 0;
|
||||
m_PosLimit = 7;
|
||||
m_BlockHeader.CRC = ReadUInt16();
|
||||
m_BlockHeader.Type = ReadByte();
|
||||
m_BlockHeader.Flags = ReadUInt16();
|
||||
m_BlockHeader.HeadSize = ReadUInt16();
|
||||
|
||||
if (m_BlockHeader.HeadSize < 7)
|
||||
ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);
|
||||
|
||||
if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)
|
||||
return S_FALSE;
|
||||
|
||||
if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader)
|
||||
{
|
||||
m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);
|
||||
m_CurData = (Byte *)m_FileHeaderData;
|
||||
m_PosLimit = m_BlockHeader.HeadSize;
|
||||
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)
|
||||
ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
|
||||
|
||||
FinishCryptoBlock();
|
||||
m_CryptoMode = false;
|
||||
SeekInArchive(m_Position); // Move Position to compressed Data;
|
||||
AddToSeekValue(item.PackSize); // m_Position points to next header;
|
||||
return S_OK;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
else
|
||||
m_CryptoPos = 0;
|
||||
AddToSeekValue(m_BlockHeader.HeadSize);
|
||||
FinishCryptoBlock();
|
||||
m_CryptoMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CInArchive::SeekInArchive(UInt64 position)
|
||||
{
|
||||
m_Stream->Seek(position, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)
|
||||
{
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
SeekInArchive(position);
|
||||
streamSpec->SetStream(m_Stream);
|
||||
streamSpec->Init(size);
|
||||
return inStream.Detach();
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,123 +0,0 @@
|
||||
// RarIn.h
|
||||
|
||||
#ifndef __ARCHIVE_RAR_IN_H
|
||||
#define __ARCHIVE_RAR_IN_H
|
||||
|
||||
#include "Common/DynamicBuffer.h"
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
#include "../../Common/StreamObjects.h"
|
||||
|
||||
#include "../../Crypto/RarAes.h"
|
||||
|
||||
#include "RarHeader.h"
|
||||
#include "RarItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
class CInArchiveException
|
||||
{
|
||||
public:
|
||||
enum CCauseType
|
||||
{
|
||||
kUnexpectedEndOfArchive = 0,
|
||||
kArchiveHeaderCRCError,
|
||||
kFileHeaderCRCError,
|
||||
kIncorrectArchive
|
||||
}
|
||||
Cause;
|
||||
CInArchiveException(CCauseType cause) : Cause(cause) {}
|
||||
};
|
||||
|
||||
|
||||
struct CInArchiveInfo
|
||||
{
|
||||
UInt32 Flags;
|
||||
Byte EncryptVersion;
|
||||
UInt64 StartPosition;
|
||||
|
||||
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
|
||||
{
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
|
||||
UInt64 m_StreamStartPosition;
|
||||
|
||||
CInArchiveInfo _header;
|
||||
CDynamicBuffer<char> m_NameBuffer;
|
||||
CDynamicBuffer<wchar_t> _unicodeNameBuffer;
|
||||
|
||||
CByteBuffer _comment;
|
||||
|
||||
void ReadName(CItemEx &item, int nameSize);
|
||||
void ReadHeaderReal(CItemEx &item);
|
||||
|
||||
HRESULT ReadBytesSpec(void *data, size_t *size);
|
||||
bool ReadBytesAndTestSize(void *data, UInt32 size);
|
||||
|
||||
HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
|
||||
|
||||
void ThrowExceptionWithCode(CInArchiveException::CCauseType cause);
|
||||
void ThrowUnexpectedEndOfArchiveException();
|
||||
|
||||
void AddToSeekValue(UInt64 addValue);
|
||||
|
||||
CDynamicBuffer<Byte> m_FileHeaderData;
|
||||
|
||||
NHeader::NBlock::CBlock m_BlockHeader;
|
||||
|
||||
NCrypto::NRar29::CDecoder *m_RarAESSpec;
|
||||
CMyComPtr<ICompressFilter> m_RarAES;
|
||||
|
||||
Byte *m_CurData; // it must point to start of Rar::Block
|
||||
UInt32 m_CurPos;
|
||||
UInt32 m_PosLimit;
|
||||
Byte ReadByte();
|
||||
UInt16 ReadUInt16();
|
||||
UInt32 ReadUInt32();
|
||||
void ReadTime(Byte mask, CRarTime &rarTime);
|
||||
|
||||
CBuffer<Byte> m_DecryptedData;
|
||||
Byte *m_DecryptedDataAligned;
|
||||
UInt32 m_DecryptedDataSize;
|
||||
|
||||
bool m_CryptoMode;
|
||||
UInt32 m_CryptoPos;
|
||||
void FinishCryptoBlock()
|
||||
{
|
||||
if (m_CryptoMode)
|
||||
while ((m_CryptoPos & 0xF) != 0)
|
||||
{
|
||||
m_CryptoPos++;
|
||||
m_Position++;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
UInt64 m_Position;
|
||||
|
||||
HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
|
||||
void Close();
|
||||
HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage);
|
||||
|
||||
void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;
|
||||
|
||||
void SeekInArchive(UInt64 position);
|
||||
ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -1,55 +0,0 @@
|
||||
// RarItem.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "RarItem.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NRar{
|
||||
|
||||
bool CItem::IgnoreItem() const
|
||||
{
|
||||
switch(HostOS)
|
||||
{
|
||||
case NHeader::NFile::kHostMSDOS:
|
||||
case NHeader::NFile::kHostOS2:
|
||||
case NHeader::NFile::kHostWin32:
|
||||
return ((Attrib & NHeader::NFile::kLabelFileAttribute) != 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CItem::IsDir() const
|
||||
{
|
||||
if (GetDictSize() == NHeader::NFile::kDictDirectoryValue)
|
||||
return true;
|
||||
switch(HostOS)
|
||||
{
|
||||
case NHeader::NFile::kHostMSDOS:
|
||||
case NHeader::NFile::kHostOS2:
|
||||
case NHeader::NFile::kHostWin32:
|
||||
if ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt32 CItem::GetWinAttributes() const
|
||||
{
|
||||
UInt32 winAttributes;
|
||||
switch(HostOS)
|
||||
{
|
||||
case NHeader::NFile::kHostMSDOS:
|
||||
case NHeader::NFile::kHostOS2:
|
||||
case NHeader::NFile::kHostWin32:
|
||||
winAttributes = Attrib;
|
||||
break;
|
||||
default:
|
||||
winAttributes = 0; // must be converted from unix value;
|
||||
}
|
||||
if (IsDir())
|
||||
winAttributes |= NHeader::NFile::kWinFileDirectoryAttributeMask;
|
||||
return winAttributes;
|
||||
}
|
||||
|
||||
}}
|
||||
40
CPP/7zip/Archive/Rar/RarItem.h
Executable file → Normal file
40
CPP/7zip/Archive/Rar/RarItem.h
Executable file → Normal file
@@ -3,13 +3,12 @@
|
||||
#ifndef __ARCHIVE_RAR_ITEM_H
|
||||
#define __ARCHIVE_RAR_ITEM_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "Common/MyString.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "RarHeader.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NRar{
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
struct CRarTime
|
||||
{
|
||||
@@ -56,18 +55,35 @@ struct CItem
|
||||
UInt32 GetDictSize() const { return (Flags >> NHeader::NFile::kDictBitStart) & NHeader::NFile::kDictMask; }
|
||||
bool IsDir() const;
|
||||
bool IgnoreItem() const;
|
||||
UInt32 GetWinAttributes() const;
|
||||
|
||||
CItem(): CTimeDefined(false), ATimeDefined(false) {}
|
||||
};
|
||||
UInt32 GetWinAttrib() const;
|
||||
|
||||
class CItemEx: public CItem
|
||||
{
|
||||
public:
|
||||
UInt64 Position;
|
||||
UInt16 MainPartSize;
|
||||
unsigned MainPartSize;
|
||||
UInt16 CommentSize;
|
||||
UInt16 AlignSize;
|
||||
|
||||
// int BaseFileIndex;
|
||||
// bool IsAltStream;
|
||||
|
||||
UString GetName() const
|
||||
{
|
||||
if (( /* IsAltStream || */ HasUnicodeName()) && !UnicodeName.IsEmpty())
|
||||
return UnicodeName;
|
||||
return MultiByteToUnicodeString(Name, CP_OEMCP);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CTimeDefined = false;
|
||||
ATimeDefined = false;
|
||||
Name.Empty();
|
||||
UnicodeName.Empty();
|
||||
// IsAltStream = false;
|
||||
// BaseFileIndex = -1;
|
||||
}
|
||||
|
||||
CItem() { Clear(); }
|
||||
|
||||
UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; };
|
||||
// DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; };
|
||||
UInt64 GetCommentPosition() const { return Position + MainPartSize; };
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// RarRegister.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "RarHandler.h"
|
||||
static IInArchive *CreateArc() { return new NArchive::NRar::CHandler; }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"Rar", L"rar r00", 0, 3, {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}, 7, false, CreateArc, 0, };
|
||||
|
||||
REGISTER_ARC(Rar)
|
||||
@@ -1,78 +0,0 @@
|
||||
// RarVolumeInStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "RarVolumeInStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
void CFolderInStream::Init(
|
||||
CObjectVector<CInArchive> *archives,
|
||||
const CObjectVector<CItemEx> *items,
|
||||
const CRefItem &refItem)
|
||||
{
|
||||
_archives = archives;
|
||||
_items = items;
|
||||
_refItem = refItem;
|
||||
_curIndex = 0;
|
||||
CRCs.Clear();
|
||||
_fileIsOpen = false;
|
||||
}
|
||||
|
||||
HRESULT CFolderInStream::OpenStream()
|
||||
{
|
||||
while (_curIndex < _refItem.NumItems)
|
||||
{
|
||||
const CItemEx &item = (*_items)[_refItem.ItemIndex + _curIndex];
|
||||
_stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex].
|
||||
CreateLimitedStream(item.GetDataPosition(), item.PackSize));
|
||||
_curIndex++;
|
||||
_fileIsOpen = true;
|
||||
_crc = CRC_INIT_VAL;
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFolderInStream::CloseStream()
|
||||
{
|
||||
CRCs.Add(CRC_GET_DIGEST(_crc));
|
||||
_stream.Release();
|
||||
_fileIsOpen = false;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize = 0;
|
||||
while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
|
||||
{
|
||||
if (_fileIsOpen)
|
||||
{
|
||||
UInt32 localProcessedSize;
|
||||
RINOK(_stream->Read(
|
||||
((Byte *)data) + realProcessedSize, size, &localProcessedSize));
|
||||
_crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize);
|
||||
if (localProcessedSize == 0)
|
||||
{
|
||||
RINOK(CloseStream());
|
||||
continue;
|
||||
}
|
||||
realProcessedSize += localProcessedSize;
|
||||
size -= localProcessedSize;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(OpenStream());
|
||||
}
|
||||
}
|
||||
if (processedSize != 0)
|
||||
*processedSize = realProcessedSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,49 +0,0 @@
|
||||
// RarVolumeInStream.h
|
||||
|
||||
#ifndef __RAR_VOLUME_IN_STREAM_H
|
||||
#define __RAR_VOLUME_IN_STREAM_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "RarIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
struct CRefItem
|
||||
{
|
||||
int VolumeIndex;
|
||||
int ItemIndex;
|
||||
int NumItems;
|
||||
};
|
||||
|
||||
class CFolderInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
private:
|
||||
CObjectVector<CInArchive> *_archives;
|
||||
const CObjectVector<CItemEx> *_items;
|
||||
CRefItem _refItem;
|
||||
int _curIndex;
|
||||
UInt32 _crc;
|
||||
bool _fileIsOpen;
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
|
||||
HRESULT OpenStream();
|
||||
HRESULT CloseStream();
|
||||
public:
|
||||
void Init(CObjectVector<CInArchive> *archives,
|
||||
const CObjectVector<CItemEx> *items,
|
||||
const CRefItem &refItem);
|
||||
|
||||
CRecordVector<UInt32> CRCs;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
0
CPP/7zip/Archive/Rar/StdAfx.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Rar/StdAfx.cpp
Executable file → Normal file
2
CPP/7zip/Archive/Rar/StdAfx.h
Executable file → Normal file
2
CPP/7zip/Archive/Rar/StdAfx.h
Executable file → Normal file
@@ -3,6 +3,6 @@
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user