412 lines
8.0 KiB
C++
412 lines
8.0 KiB
C++
// 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;
|
|
UString _missingVolName;
|
|
|
|
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
|