mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-11 00:07:09 -06:00
15.06
This commit is contained in:
committed by
Kornel Lesiński
parent
54490d51d5
commit
cba375916f
2683
CPP/7zip/Archive/Rar/Rar5Handler.cpp
Normal file
2683
CPP/7zip/Archive/Rar/Rar5Handler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
410
CPP/7zip/Archive/Rar/Rar5Handler.h
Normal file
410
CPP/7zip/Archive/Rar/Rar5Handler.h
Normal file
@@ -0,0 +1,410 @@
|
||||
// Rar5Handler.h
|
||||
|
||||
#ifndef __RAR5_HANDLER_H
|
||||
#define __RAR5_HANDLER_H
|
||||
|
||||
#include "../../../../C/Blake2.h"
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar5 {
|
||||
|
||||
namespace NHeaderFlags
|
||||
{
|
||||
const unsigned kExtra = 1 << 0;
|
||||
const unsigned kData = 1 << 1;
|
||||
// const unsigned kUnknown = 1 << 2;
|
||||
const unsigned kPrevVol = 1 << 3;
|
||||
const unsigned kNextVol = 1 << 4;
|
||||
// const unsigned kIsChild = 1 << 5;
|
||||
// const unsigned kPreserveChild = 1 << 6;
|
||||
}
|
||||
|
||||
namespace NHeaderType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kArc = 1,
|
||||
kFile,
|
||||
kService,
|
||||
kArcEncrypt,
|
||||
kEndOfArc
|
||||
};
|
||||
}
|
||||
|
||||
namespace NArcFlags
|
||||
{
|
||||
const unsigned kVol = 1 << 0;
|
||||
const unsigned kVolNumber = 1 << 1;
|
||||
const unsigned kSolid = 1 << 2;
|
||||
// const unsigned kRecovery = 1 << 3;
|
||||
// const unsigned kLocked = 1 << 4;
|
||||
}
|
||||
|
||||
const unsigned kArcExtraRecordType_Locator = 1;
|
||||
|
||||
namespace NLocatorFlags
|
||||
{
|
||||
const unsigned kQuickOpen = 1 << 0;
|
||||
const unsigned kRecovery = 1 << 1;
|
||||
}
|
||||
|
||||
namespace NFileFlags
|
||||
{
|
||||
const unsigned kIsDir = 1 << 0;
|
||||
const unsigned kUnixTime = 1 << 1;
|
||||
const unsigned kCrc32 = 1 << 2;
|
||||
const unsigned kUnknownSize = 1 << 3;
|
||||
}
|
||||
|
||||
namespace NMethodFlags
|
||||
{
|
||||
// const unsigned kVersionMask = 0x3F;
|
||||
const unsigned kSolid = 1 << 6;
|
||||
}
|
||||
|
||||
namespace NArcEndFlags
|
||||
{
|
||||
const unsigned kMoreVols = 1 << 0;
|
||||
}
|
||||
|
||||
enum EHostOS
|
||||
{
|
||||
kHost_Windows = 0,
|
||||
kHost_Unix
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ---------- Extra ----------
|
||||
|
||||
namespace NExtraRecordType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kCrypto = 1,
|
||||
kHash,
|
||||
kTime,
|
||||
kVersion,
|
||||
kLink,
|
||||
kUnixOwner,
|
||||
kSubdata
|
||||
};
|
||||
}
|
||||
|
||||
// const unsigned kCryptoAlgo_AES = 0;
|
||||
|
||||
namespace NCryptoFlags
|
||||
{
|
||||
const unsigned kPswCheck = 1 << 0;
|
||||
const unsigned kUseMAC = 1 << 1;
|
||||
}
|
||||
|
||||
struct CCryptoInfo
|
||||
{
|
||||
UInt64 Algo;
|
||||
UInt64 Flags;
|
||||
Byte Cnt;
|
||||
|
||||
bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; }
|
||||
bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; }
|
||||
bool Parse(const Byte *p, size_t size);
|
||||
};
|
||||
|
||||
const unsigned kHashID_Blake2sp = 0;
|
||||
|
||||
namespace NTimeRecord
|
||||
{
|
||||
enum
|
||||
{
|
||||
k_Index_MTime = 0,
|
||||
k_Index_CTime,
|
||||
k_Index_ATime
|
||||
};
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const unsigned kUnixTime = 1 << 0;
|
||||
const unsigned kMTime = 1 << 1;
|
||||
// const unsigned kCTime = 1 << 2;
|
||||
// const unsigned kATime = 1 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
namespace NLinkType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kUnixSymLink = 1,
|
||||
kWinSymLink,
|
||||
kWinJunction,
|
||||
kHardLink,
|
||||
kFileCopy
|
||||
};
|
||||
}
|
||||
|
||||
namespace NLinkFlags
|
||||
{
|
||||
const unsigned kTargetIsDir = 1 << 0;
|
||||
}
|
||||
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt32 CommonFlags;
|
||||
UInt32 Flags;
|
||||
|
||||
Byte RecordType;
|
||||
bool Version_Defined;
|
||||
|
||||
int ACL;
|
||||
|
||||
AString Name;
|
||||
|
||||
int VolIndex;
|
||||
int NextItem;
|
||||
|
||||
UInt32 UnixMTime;
|
||||
UInt32 CRC;
|
||||
UInt32 Attrib;
|
||||
UInt32 Method;
|
||||
|
||||
CByteBuffer Extra;
|
||||
|
||||
UInt64 Size;
|
||||
UInt64 PackSize;
|
||||
UInt64 HostOS;
|
||||
|
||||
UInt64 DataPos;
|
||||
UInt64 Version;
|
||||
|
||||
CItem() { Clear(); }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CommonFlags = 0;
|
||||
Flags = 0;
|
||||
|
||||
VolIndex = 0;
|
||||
NextItem = -1;
|
||||
|
||||
Version_Defined = false;
|
||||
Version = 0;
|
||||
|
||||
Name.Empty();
|
||||
Extra.Free();
|
||||
ACL = -1;
|
||||
}
|
||||
|
||||
bool IsSplitBefore() const { return (CommonFlags & NHeaderFlags::kPrevVol) != 0; }
|
||||
bool IsSplitAfter() const { return (CommonFlags & NHeaderFlags::kNextVol) != 0; }
|
||||
bool IsSplit() const { return (CommonFlags & (NHeaderFlags::kPrevVol | NHeaderFlags::kNextVol)) != 0; }
|
||||
|
||||
bool IsDir() const { return (Flags & NFileFlags::kIsDir) != 0; }
|
||||
bool Has_UnixMTime() const { return (Flags & NFileFlags::kUnixTime) != 0; }
|
||||
bool Has_CRC() const { return (Flags & NFileFlags::kCrc32) != 0; }
|
||||
bool Is_UnknownSize() const { return (Flags & NFileFlags::kUnknownSize) != 0; }
|
||||
|
||||
bool IsNextForItem(const CItem &prev) const
|
||||
{
|
||||
return !IsDir() && !prev.IsDir() && IsSplitBefore() && prev.IsSplitAfter() && (Name == prev.Name);
|
||||
// && false;
|
||||
}
|
||||
|
||||
bool IsSolid() const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; }
|
||||
unsigned GetAlgoVersion() const { return (unsigned)Method & 0x3F; }
|
||||
unsigned GetMethod() const { return ((unsigned)Method >> 7) & 0x7; }
|
||||
UInt32 GetDictSize() const { return (((UInt32)Method >> 10) & 0xF); }
|
||||
|
||||
bool IsService() const { return RecordType == NHeaderType::kService; }
|
||||
|
||||
bool Is_STM() const { return IsService() && Name == "STM"; }
|
||||
bool Is_CMT() const { return IsService() && Name == "CMT"; }
|
||||
bool Is_ACL() const { return IsService() && Name == "ACL"; }
|
||||
// bool Is_QO() const { return IsService() && Name == "QO"; }
|
||||
|
||||
int FindExtra(unsigned type, unsigned &recordDataSize) const;
|
||||
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
unsigned size;
|
||||
return FindExtra(NExtraRecordType::kCrypto, size) >= 0;
|
||||
}
|
||||
|
||||
int FindExtra_Blake() const
|
||||
{
|
||||
unsigned size = 0;
|
||||
int offset = FindExtra(NExtraRecordType::kHash, size);
|
||||
if (offset >= 0
|
||||
&& size == BLAKE2S_DIGEST_SIZE + 1
|
||||
&& Extra[(unsigned)offset] == kHashID_Blake2sp)
|
||||
return offset + 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bool NeedUse_as_CopyLink() const { return PackSize == 0 && Is_CopyLink(); }
|
||||
|
||||
bool GetAltStreamName(AString &name) const;
|
||||
|
||||
UInt32 GetWinAttrib() const
|
||||
{
|
||||
UInt32 a;
|
||||
switch (HostOS)
|
||||
{
|
||||
case kHost_Windows: a = Attrib; break;
|
||||
case kHost_Unix: a = (Attrib << 16); break;
|
||||
default: a = 0;
|
||||
}
|
||||
// if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
return a;
|
||||
}
|
||||
|
||||
UInt64 GetDataPosition() const { return DataPos; }
|
||||
};
|
||||
|
||||
|
||||
struct CInArcInfo
|
||||
{
|
||||
UInt64 Flags;
|
||||
UInt64 VolNumber;
|
||||
UInt64 StartPos;
|
||||
UInt64 EndPos;
|
||||
|
||||
UInt64 EndFlags;
|
||||
bool EndOfArchive_was_Read;
|
||||
|
||||
bool IsEncrypted;
|
||||
|
||||
// CByteBuffer Extra;
|
||||
|
||||
/*
|
||||
struct CLocator
|
||||
{
|
||||
UInt64 Flags;
|
||||
UInt64 QuickOpen;
|
||||
UInt64 Recovery;
|
||||
|
||||
bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; }
|
||||
bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; }
|
||||
};
|
||||
|
||||
int FindExtra(unsigned type, unsigned &recordDataSize) const;
|
||||
bool FindExtra_Locator(CLocator &locator) const;
|
||||
*/
|
||||
|
||||
CInArcInfo():
|
||||
Flags(0),
|
||||
VolNumber(0),
|
||||
StartPos(0),
|
||||
EndPos(0),
|
||||
EndFlags(0),
|
||||
EndOfArchive_was_Read(false),
|
||||
IsEncrypted(false)
|
||||
{}
|
||||
|
||||
/*
|
||||
void Clear()
|
||||
{
|
||||
Flags = 0;
|
||||
VolNumber = 0;
|
||||
StartPos = 0;
|
||||
EndPos = 0;
|
||||
EndFlags = 0;
|
||||
EndOfArchive_was_Read = false;
|
||||
Extra.Free();
|
||||
}
|
||||
*/
|
||||
|
||||
UInt64 GetPhySize() const { return EndPos - StartPos; }
|
||||
|
||||
bool AreMoreVolumes() const { return (EndFlags & NArcEndFlags::kMoreVols) != 0; }
|
||||
|
||||
bool IsVolume() const { return (Flags & NArcFlags::kVol) != 0; }
|
||||
bool IsSolid() const { return (Flags & NArcFlags::kSolid) != 0; }
|
||||
bool Is_VolNumber_Defined() const { return (Flags & NArcFlags::kVolNumber) != 0; }
|
||||
|
||||
UInt64 GetVolIndex() const { return Is_VolNumber_Defined() ? VolNumber : 0; }
|
||||
};
|
||||
|
||||
|
||||
struct CRefItem
|
||||
{
|
||||
unsigned Item;
|
||||
unsigned Last;
|
||||
int Parent;
|
||||
int Link;
|
||||
};
|
||||
|
||||
|
||||
struct CArc
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
CInArcInfo Info;
|
||||
};
|
||||
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveGetRawProps,
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
CRecordVector<CRefItem> _refs;
|
||||
CObjectVector<CItem> _items;
|
||||
private:
|
||||
CObjectVector<CArc> _arcs;
|
||||
CObjectVector<CByteBuffer> _acls;
|
||||
|
||||
UInt32 _errorFlags;
|
||||
// UInt32 _warningFlags;
|
||||
bool _isArc;
|
||||
CByteBuffer _comment;
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
|
||||
UInt64 GetPackSize(unsigned refIndex) const;
|
||||
|
||||
void FillLinks();
|
||||
|
||||
HRESULT Open2(IInStream *stream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openCallback);
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
|
||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IArchiveGetRawProps(;)
|
||||
|
||||
DECL_ISetCompressCodecsInfo
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
#include "../Common/OutStreamWithCRC.h"
|
||||
|
||||
#include "RarVol.h"
|
||||
#include "RarHandler.h"
|
||||
|
||||
using namespace NWindows;
|
||||
@@ -44,6 +45,8 @@ namespace NRar {
|
||||
|
||||
static const Byte kMarker[NHeader::kMarkerSize] = SIGNATURE;
|
||||
|
||||
const unsigned kPasswordLen_MAX = 127;
|
||||
|
||||
bool CItem::IgnoreItem() const
|
||||
{
|
||||
switch (HostOS)
|
||||
@@ -131,7 +134,7 @@ class CInArchive
|
||||
CByteBuffer _comment;
|
||||
CByteBuffer m_FileHeaderData;
|
||||
NHeader::NBlock::CBlock m_BlockHeader;
|
||||
NCrypto::NRar29::CDecoder *m_RarAESSpec;
|
||||
NCrypto::NRar3::CDecoder *m_RarAESSpec;
|
||||
CMyComPtr<ICompressFilter> m_RarAES;
|
||||
CBuffer<Byte> m_DecryptedData;
|
||||
Byte *m_DecryptedDataAligned;
|
||||
@@ -362,6 +365,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
|
||||
_ttt_ .DosTime = Get32(p); p += 4; size -= 4; \
|
||||
READ_TIME(_mask_, _ttt_); } \
|
||||
|
||||
|
||||
bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
|
||||
{
|
||||
const Byte *pStart = p;
|
||||
@@ -500,7 +504,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
}
|
||||
if (!m_RarAES)
|
||||
{
|
||||
m_RarAESSpec = new NCrypto::NRar29::CDecoder;
|
||||
m_RarAESSpec = new NCrypto::NRar3::CDecoder;
|
||||
m_RarAES = m_RarAESSpec;
|
||||
}
|
||||
m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());
|
||||
@@ -518,7 +522,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen(password);
|
||||
CByteBuffer buffer(len * 2);
|
||||
if (len > kPasswordLen_MAX)
|
||||
len = kPasswordLen_MAX;
|
||||
|
||||
CByteArr buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = password[i];
|
||||
@@ -526,7 +533,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
|
||||
RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
|
||||
m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2);
|
||||
|
||||
const UInt32 kDecryptedBufferSize = (1 << 12);
|
||||
if (m_DecryptedData.Size() == 0)
|
||||
@@ -990,121 +997,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static bool IsDigit(wchar_t c)
|
||||
{
|
||||
return c >= L'0' && c <= L'9';
|
||||
}
|
||||
|
||||
class CVolumeName
|
||||
{
|
||||
bool _first;
|
||||
bool _newStyle;
|
||||
UString _unchangedPart;
|
||||
UString _changedPart;
|
||||
UString _afterPart;
|
||||
public:
|
||||
CVolumeName(): _newStyle(true) {};
|
||||
|
||||
bool InitName(const UString &name, bool newStyle)
|
||||
{
|
||||
_first = true;
|
||||
_newStyle = newStyle;
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
UString basePart = name;
|
||||
|
||||
if (dotPos >= 0)
|
||||
{
|
||||
UString ext = name.Ptr(dotPos + 1);
|
||||
if (ext.IsEqualTo_Ascii_NoCase("rar"))
|
||||
{
|
||||
_afterPart = name.Ptr(dotPos);
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
_afterPart.SetFromAscii(".rar");
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (!_newStyle)
|
||||
{
|
||||
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;
|
||||
_changedPart = ext;
|
||||
_unchangedPart = name.Left(dotPos + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_newStyle)
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_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;
|
||||
}
|
||||
|
||||
/*
|
||||
void MakeBeforeFirstName()
|
||||
{
|
||||
unsigned len = _changedPart.Len();
|
||||
_changedPart.Empty();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
_changedPart += L'0';
|
||||
}
|
||||
*/
|
||||
|
||||
UString GetNextName()
|
||||
{
|
||||
if (_newStyle || !_first)
|
||||
{
|
||||
unsigned i = _changedPart.Len();
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = _changedPart[--i];
|
||||
if (c == L'9')
|
||||
{
|
||||
c = L'0';
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
if (i == 0)
|
||||
{
|
||||
_changedPart.InsertAtFront(L'1');
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_first = false;
|
||||
return _unchangedPart + _changedPart + _afterPart;
|
||||
}
|
||||
};
|
||||
|
||||
static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
|
||||
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
|
||||
{
|
||||
areThereNonZeros = false;
|
||||
numZeros = 0;
|
||||
@@ -1136,7 +1030,6 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
{
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
|
||||
|
||||
CVolumeName seqName;
|
||||
|
||||
@@ -1145,8 +1038,8 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
|
||||
if (openCallback)
|
||||
{
|
||||
openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
|
||||
openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||
openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||
}
|
||||
|
||||
CInArchive archive;
|
||||
@@ -1363,108 +1256,91 @@ struct CMethodItem
|
||||
};
|
||||
|
||||
|
||||
class CFolderInStream:
|
||||
class CVolsInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
private:
|
||||
const CObjectVector<CArc> *_archives;
|
||||
UInt64 _rem;
|
||||
ISequentialInStream *_stream;
|
||||
const CObjectVector<CArc> *_arcs;
|
||||
const CObjectVector<CItem> *_items;
|
||||
CRefItem _refItem;
|
||||
unsigned _curIndex;
|
||||
UInt32 _crc;
|
||||
bool _fileIsOpen;
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
bool _calcCrc;
|
||||
|
||||
HRESULT OpenStream();
|
||||
HRESULT CloseStream();
|
||||
public:
|
||||
void Init(const CObjectVector<CArc> *archives,
|
||||
const CObjectVector<CItem> *items,
|
||||
const CRefItem &refItem);
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
CRecordVector<UInt32> CRCs;
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
void Init(const CObjectVector<CArc> *arcs,
|
||||
const CObjectVector<CItem> *items,
|
||||
const CRefItem &refItem)
|
||||
{
|
||||
_arcs = arcs;
|
||||
_items = items;
|
||||
_refItem = refItem;
|
||||
_curIndex = 0;
|
||||
_stream = NULL;
|
||||
CrcIsOK = true;
|
||||
}
|
||||
|
||||
bool CrcIsOK;
|
||||
};
|
||||
|
||||
|
||||
ISequentialInStream* CArc::CreateLimitedStream(UInt64 offset, UInt64 size) const
|
||||
{
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
Stream->Seek(offset, STREAM_SEEK_SET, NULL);
|
||||
streamSpec->SetStream(Stream);
|
||||
streamSpec->Init(size);
|
||||
return inStream.Detach();
|
||||
}
|
||||
|
||||
void CFolderInStream::Init(
|
||||
const CObjectVector<CArc> *archives,
|
||||
const CObjectVector<CItem> *items,
|
||||
const CRefItem &refItem)
|
||||
{
|
||||
_archives = archives;
|
||||
_items = items;
|
||||
_refItem = refItem;
|
||||
_curIndex = 0;
|
||||
CRCs.Clear();
|
||||
_fileIsOpen = false;
|
||||
}
|
||||
|
||||
HRESULT CFolderInStream::OpenStream()
|
||||
{
|
||||
while (_curIndex < _refItem.NumItems)
|
||||
{
|
||||
const CItem &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)
|
||||
STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
UInt32 realProcessedSize = 0;
|
||||
while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (_fileIsOpen)
|
||||
if (!_stream)
|
||||
{
|
||||
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;
|
||||
if (_curIndex >= _refItem.NumItems)
|
||||
break;
|
||||
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
|
||||
IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream;
|
||||
RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
_stream = s;
|
||||
_calcCrc = (CrcIsOK && item.IsSplitAfter());
|
||||
_crc = CRC_INIT_VAL;
|
||||
_rem = item.PackSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(OpenStream());
|
||||
UInt32 cur = size;
|
||||
if (cur > _rem)
|
||||
cur = (UInt32)_rem;
|
||||
UInt32 num = cur;
|
||||
HRESULT res = _stream->Read(data, cur, &cur);
|
||||
if (_calcCrc)
|
||||
_crc = CrcUpdate(_crc, data, cur);
|
||||
realProcessedSize += cur;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
data = (Byte *)data + cur;
|
||||
size -= cur;
|
||||
_rem -= cur;
|
||||
if (_rem == 0)
|
||||
{
|
||||
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
|
||||
_curIndex++;
|
||||
if (_calcCrc && CRC_GET_DIGEST(_crc) != item.FileCRC)
|
||||
CrcIsOK = false;
|
||||
_stream = NULL;
|
||||
}
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
if (realProcessedSize != 0)
|
||||
return S_OK;
|
||||
if (cur == 0 && num != 0)
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
if (processedSize != 0)
|
||||
*processedSize = realProcessedSize;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1526,13 +1402,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
CFilterCoder *filterStreamSpec = new CFilterCoder(false);
|
||||
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
|
||||
|
||||
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
|
||||
NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressFilter> rar20CryptoDecoder;
|
||||
NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressFilter> rar29CryptoDecoder;
|
||||
NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressFilter> rar3CryptoDecoder;
|
||||
|
||||
CFolderInStream *folderInStreamSpec = NULL;
|
||||
CMyComPtr<ISequentialInStream> folderInStream;
|
||||
CVolsInStream *volsInStreamSpec = NULL;
|
||||
CMyComPtr<ISequentialInStream> volsInStream;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
@@ -1602,26 +1478,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
outStreamSpec->Init();
|
||||
realOutStream.Release();
|
||||
|
||||
/*
|
||||
for (unsigned partIndex = 0; partIndex < 1; partIndex++)
|
||||
if (!volsInStream)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
|
||||
// item redefinition
|
||||
const CItem &item = _items[refItem.ItemIndex + partIndex];
|
||||
|
||||
CInArchive &archive = _arcs[refItem.VolumeIndex + partIndex];
|
||||
|
||||
inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),
|
||||
item.PackSize));
|
||||
*/
|
||||
if (!folderInStream)
|
||||
{
|
||||
folderInStreamSpec = new CFolderInStream;
|
||||
folderInStream = folderInStreamSpec;
|
||||
volsInStreamSpec = new CVolsInStream;
|
||||
volsInStream = volsInStreamSpec;
|
||||
}
|
||||
|
||||
folderInStreamSpec->Init(&_arcs, &_items, refItem);
|
||||
volsInStreamSpec->Init(&_arcs, &_items, refItem);
|
||||
|
||||
UInt64 packSize = currentPackSize;
|
||||
|
||||
@@ -1632,29 +1495,29 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
// CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
|
||||
if (item.UnPackVersion >= 29)
|
||||
{
|
||||
if (!rar29CryptoDecoder)
|
||||
if (!rar3CryptoDecoder)
|
||||
{
|
||||
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
|
||||
rar29CryptoDecoder = rar29CryptoDecoderSpec;
|
||||
rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder;
|
||||
rar3CryptoDecoder = rar3CryptoDecoderSpec;
|
||||
}
|
||||
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
||||
rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
||||
/*
|
||||
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
|
||||
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||
RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||
&cryptoProperties));
|
||||
*/
|
||||
RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||
filterStreamSpec->Filter = rar29CryptoDecoder;
|
||||
RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
|
||||
filterStreamSpec->Filter = rar3CryptoDecoder;
|
||||
}
|
||||
else if (item.UnPackVersion >= 20)
|
||||
{
|
||||
if (!rar20CryptoDecoder)
|
||||
{
|
||||
rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
|
||||
rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder;
|
||||
rar20CryptoDecoder = rar20CryptoDecoderSpec;
|
||||
}
|
||||
filterStreamSpec->Filter = rar20CryptoDecoder;
|
||||
@@ -1666,49 +1529,66 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
continue;
|
||||
}
|
||||
|
||||
RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||
// RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
|
||||
|
||||
if (!getTextPassword)
|
||||
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
|
||||
if (getTextPassword)
|
||||
|
||||
if (!getTextPassword)
|
||||
{
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
|
||||
// if (getTextPassword)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
||||
|
||||
if (item.UnPackVersion >= 29)
|
||||
{
|
||||
UString unicodePassword;
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen(password);
|
||||
CByteBuffer buffer(len * 2);
|
||||
if (len > kPasswordLen_MAX)
|
||||
len = kPasswordLen_MAX;
|
||||
CByteArr buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = password[i];
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
|
||||
rar3CryptoDecoderSpec->SetPassword((const Byte *)buffer, len * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
AString oemPassword;
|
||||
if (password)
|
||||
oemPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()));
|
||||
{
|
||||
UString unicode = (LPCOLESTR)password;
|
||||
if (unicode.Len() > kPasswordLen_MAX)
|
||||
unicode.DeleteFrom(kPasswordLen_MAX);
|
||||
oemPassword = UnicodeStringToMultiByte(unicode, CP_OEMCP);
|
||||
}
|
||||
rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len());
|
||||
}
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));
|
||||
}
|
||||
*/
|
||||
|
||||
filterStreamSpec->SetInStream(folderInStream);
|
||||
filterStreamSpec->SetInStream(volsInStream);
|
||||
filterStreamSpec->SetOutStreamSize(NULL);
|
||||
inStream = filterStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
inStream = folderInStream;
|
||||
inStream = volsInStream;
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressCoder> commonCoder;
|
||||
@@ -1766,7 +1646,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
|
||||
if (solidStart)
|
||||
{
|
||||
isSolid = false;
|
||||
isSolid = 0;
|
||||
solidStart = false;
|
||||
}
|
||||
|
||||
@@ -1786,46 +1666,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
if (item.IsEncrypted())
|
||||
filterStreamSpec->ReleaseInStream();
|
||||
if (result == S_FALSE)
|
||||
{
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
|
||||
continue;
|
||||
}
|
||||
if (result != S_OK)
|
||||
return result;
|
||||
|
||||
const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
|
||||
int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kCRCError;
|
||||
outStream.Release();
|
||||
|
||||
/*
|
||||
if (refItem.NumItems == 1 &&
|
||||
!item.IsSplitBefore() && !item.IsSplitAfter())
|
||||
*/
|
||||
if (result != S_OK)
|
||||
{
|
||||
const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
|
||||
bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(crcOK ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kCRCError));
|
||||
if (result == S_FALSE)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (result == E_NOTIMPL)
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
bool crcOK = true;
|
||||
for (unsigned partIndex = 0; partIndex < refItem.NumItems; partIndex++)
|
||||
{
|
||||
const CItem &item = _items[refItem.ItemIndex + partIndex];
|
||||
if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])
|
||||
{
|
||||
crcOK = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(crcOK ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kCRCError));
|
||||
}
|
||||
*/
|
||||
RINOK(extractCallback->SetOperationResult(opRes));
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
129
CPP/7zip/Archive/Rar/RarVol.h
Normal file
129
CPP/7zip/Archive/Rar/RarVol.h
Normal file
@@ -0,0 +1,129 @@
|
||||
// RarVol.h
|
||||
|
||||
#ifndef __ARCHIVE_RAR_VOL_H
|
||||
#define __ARCHIVE_RAR_VOL_H
|
||||
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "RarHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRar {
|
||||
|
||||
inline bool IsDigit(wchar_t c)
|
||||
{
|
||||
return c >= L'0' && c <= L'9';
|
||||
}
|
||||
|
||||
class CVolumeName
|
||||
{
|
||||
bool _first;
|
||||
bool _newStyle;
|
||||
UString _unchangedPart;
|
||||
UString _changedPart;
|
||||
UString _afterPart;
|
||||
public:
|
||||
CVolumeName(): _newStyle(true) {};
|
||||
|
||||
bool InitName(const UString &name, bool newStyle = true)
|
||||
{
|
||||
_first = true;
|
||||
_newStyle = newStyle;
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
UString basePart = name;
|
||||
|
||||
if (dotPos >= 0)
|
||||
{
|
||||
UString ext = name.Ptr(dotPos + 1);
|
||||
if (ext.IsEqualTo_Ascii_NoCase("rar"))
|
||||
{
|
||||
_afterPart = name.Ptr(dotPos);
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
_afterPart.SetFromAscii(".rar");
|
||||
basePart = name.Left(dotPos);
|
||||
}
|
||||
else if (!_newStyle)
|
||||
{
|
||||
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;
|
||||
_changedPart = ext;
|
||||
_unchangedPart = name.Left(dotPos + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_newStyle)
|
||||
{
|
||||
_afterPart.Empty();
|
||||
_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;
|
||||
}
|
||||
|
||||
/*
|
||||
void MakeBeforeFirstName()
|
||||
{
|
||||
unsigned len = _changedPart.Len();
|
||||
_changedPart.Empty();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
_changedPart += L'0';
|
||||
}
|
||||
*/
|
||||
|
||||
UString GetNextName()
|
||||
{
|
||||
if (_newStyle || !_first)
|
||||
{
|
||||
unsigned i = _changedPart.Len();
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = _changedPart[--i];
|
||||
if (c == L'9')
|
||||
{
|
||||
c = L'0';
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
if (i == 0)
|
||||
{
|
||||
_changedPart.InsertAtFront(L'1');
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
_changedPart.ReplaceOneCharAtPos(i, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_first = false;
|
||||
return _unchangedPart + _changedPart + _afterPart;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user