libclamunrar/headers.hpp
d39cb658
 #ifndef _RAR_HEADERS_
 #define _RAR_HEADERS_
 
 #define  SIZEOF_MARKHEAD3        7 // Size of RAR 4.x archive mark header.
 #define  SIZEOF_MAINHEAD14       7 // Size of RAR 1.4 main archive header.
 #define  SIZEOF_MAINHEAD3       13 // Size of RAR 4.x main archive header.
 #define  SIZEOF_FILEHEAD14      21 // Size of RAR 1.4 file header.
 #define  SIZEOF_FILEHEAD3       32 // Size of RAR 3.0 file header.
 #define  SIZEOF_SHORTBLOCKHEAD   7
 #define  SIZEOF_LONGBLOCKHEAD   11
 #define  SIZEOF_SUBBLOCKHEAD    14
 #define  SIZEOF_COMMHEAD        13
 #define  SIZEOF_PROTECTHEAD     26
 #define  SIZEOF_UOHEAD          18
 #define  SIZEOF_STREAMHEAD      26
 
 #define  VER_PACK               29
 #define  VER_PACK5              50 // It is stored as 0, but we subtract 50 when saving an archive.
 #define  VER_UNPACK             29
 #define  VER_UNPACK5            50 // It is stored as 0, but we add 50 when reading an archive.
 
 #define  MHD_VOLUME         0x0001U
 
 // Old style main archive comment embed into main archive header. Must not
 // be used in new archives anymore.
 #define  MHD_COMMENT        0x0002U
 
 #define  MHD_LOCK           0x0004U
 #define  MHD_SOLID          0x0008U
 #define  MHD_PACK_COMMENT   0x0010U
 #define  MHD_NEWNUMBERING   0x0010U
 #define  MHD_AV             0x0020U
 #define  MHD_PROTECT        0x0040U
 #define  MHD_PASSWORD       0x0080U
 #define  MHD_FIRSTVOLUME    0x0100U
 
 #define  LHD_SPLIT_BEFORE   0x0001U
 #define  LHD_SPLIT_AFTER    0x0002U
 #define  LHD_PASSWORD       0x0004U
 
 // Old style file comment embed into file header. Must not be used
 // in new archives anymore.
 #define  LHD_COMMENT        0x0008U
 
 // For non-file subheaders it denotes 'subblock having a parent file' flag.
 #define  LHD_SOLID          0x0010U
 
 
 #define  LHD_WINDOWMASK     0x00e0U
 #define  LHD_WINDOW64       0x0000U
 #define  LHD_WINDOW128      0x0020U
 #define  LHD_WINDOW256      0x0040U
 #define  LHD_WINDOW512      0x0060U
 #define  LHD_WINDOW1024     0x0080U
 #define  LHD_WINDOW2048     0x00a0U
 #define  LHD_WINDOW4096     0x00c0U
 #define  LHD_DIRECTORY      0x00e0U
 
 #define  LHD_LARGE          0x0100U
 #define  LHD_UNICODE        0x0200U
 #define  LHD_SALT           0x0400U
 #define  LHD_VERSION        0x0800U
 #define  LHD_EXTTIME        0x1000U
 
 #define  SKIP_IF_UNKNOWN    0x4000U
 #define  LONG_BLOCK         0x8000U
 
 #define  EARC_NEXT_VOLUME   0x0001U // Not last volume.
 #define  EARC_DATACRC       0x0002U // Store CRC32 of RAR archive (now is used only in volumes).
 #define  EARC_REVSPACE      0x0004U // Reserve space for end of REV file 7 byte record.
 #define  EARC_VOLNUMBER     0x0008U // Store a number of current volume.
 
 enum HEADER_TYPE {
   // RAR 5.0 header types.
   HEAD_MARK=0x00, HEAD_MAIN=0x01, HEAD_FILE=0x02, HEAD_SERVICE=0x03,
   HEAD_CRYPT=0x04, HEAD_ENDARC=0x05, HEAD_UNKNOWN=0xff,
 
   // RAR 1.5 - 4.x header types.
   HEAD3_MARK=0x72,HEAD3_MAIN=0x73,HEAD3_FILE=0x74,HEAD3_CMT=0x75,
   HEAD3_AV=0x76,HEAD3_OLDSERVICE=0x77,HEAD3_PROTECT=0x78,HEAD3_SIGN=0x79,
   HEAD3_SERVICE=0x7a,HEAD3_ENDARC=0x7b
 };
 
 
 // RAR 2.9 and earlier.
 enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103,
        NTACL_HEAD=0x104,STREAM_HEAD=0x105 };
 
 
 // Internal implementation, depends on archive format version.
 enum HOST_SYSTEM {
   // RAR 5.0 host OS
   HOST5_WINDOWS=0,HOST5_UNIX=1,
 
   // RAR 3.0 host OS.
   HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
   HOST_BEOS=5,HOST_MAX
 };
 
 // Unified archive format independent implementation.
 enum HOST_SYSTEM_TYPE {
   HSYS_WINDOWS, HSYS_UNIX, HSYS_UNKNOWN
 };
 
 
 // We also use these values in extra field, so do not modify them.
 enum FILE_SYSTEM_REDIRECT {
   FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
   FSREDIR_HARDLINK, FSREDIR_FILECOPY
 };
 
 
 #define SUBHEAD_TYPE_CMT      L"CMT"
 #define SUBHEAD_TYPE_QOPEN    L"QO"
 #define SUBHEAD_TYPE_ACL      L"ACL"
 #define SUBHEAD_TYPE_STREAM   L"STM"
 #define SUBHEAD_TYPE_UOWNER   L"UOW"
 #define SUBHEAD_TYPE_AV       L"AV"
 #define SUBHEAD_TYPE_RR       L"RR"
 #define SUBHEAD_TYPE_OS2EA    L"EA2"
 
 /* new file inherits a subblock when updating a host file */
 #define SUBHEAD_FLAGS_INHERITED    0x80000000
 
 #define SUBHEAD_FLAGS_CMT_UNICODE  0x00000001
 
 
 struct MarkHeader
 {
   byte Mark[8];
 
   // Following fields are virtual and not present in real blocks.
   uint HeadSize;
 };
 
 
 struct BaseBlock
 {
   uint HeadCRC;  // 'ushort' for RAR 1.5.
   HEADER_TYPE HeaderType; // 1 byte for RAR 1.5.
   uint Flags;    // 'ushort' for RAR 1.5.
   uint HeadSize; // 'ushort' for RAR 1.5, up to 2 MB for RAR 5.0.
 
   bool SkipIfUnknown;
 
   void Reset()
   {
     SkipIfUnknown=false;
   }
 };
 
 
 struct BlockHeader:BaseBlock
 {
   uint DataSize;
 };
 
 
 struct MainHeader:BaseBlock
 {
   ushort HighPosAV;
   uint PosAV;
   bool CommentInHeader;
   bool PackComment; // For RAR 1.4 archive format only.
   bool Locator;
   uint64 QOpenOffset;  // Offset of quick list record.
   uint64 QOpenMaxSize; // Maximum size of QOpen offset in locator extra field.
   uint64 RROffset;     // Offset of recovery record.
   uint64 RRMaxSize;    // Maximum size of RR offset in locator extra field.
   void Reset();
 };
 
 
 struct FileHeader:BlockHeader
 {
   byte HostOS;
   byte UnpVer;
   byte Method;
   union {
     uint FileAttr;
     uint SubFlags;
   };
   wchar FileName[NM];
 
   Array<byte> SubData;
 
   RarTime mtime;
   RarTime ctime;
   RarTime atime;
 
   int64 PackSize;
   int64 UnpSize;
   int64 MaxSize; // Reserve size bytes for vint of this size.
 
   HashValue FileHash;
 
   uint FileFlags;
 
   bool SplitBefore;
   bool SplitAfter;
 
   bool UnknownUnpSize;
 
   bool Encrypted;
   CRYPT_METHOD CryptMethod;
   bool SaltSet;
   byte Salt[SIZE_SALT50];
   byte InitV[SIZE_INITV];
   bool UsePswCheck;
   byte PswCheck[SIZE_PSWCHECK];
 
   // Use HMAC calculated from HashKey and checksum instead of plain checksum.
   bool UseHashKey;
 
   // Key to convert checksum to HMAC. Derived from password with PBKDF2
   // using additional iterations.
   byte HashKey[SHA256_DIGEST_SIZE];
 
   uint Lg2Count; // Log2 of PBKDF2 repetition count.
 
   bool Solid;
   bool Dir;
   bool CommentInHeader; // RAR 2.0 file comment.
   bool Version;   // name.ext;ver file name containing the version number.
   size_t WinSize;
   bool Inherited; // New file inherits a subblock when updating a host file (for subblocks only).
 
   // 'true' if file sizes use 8 bytes instead of 4. Not used in RAR 5.0.
   bool LargeFile;
   
   // 'true' for HEAD_SERVICE block, which is a child of preceding file block.
   // RAR 4.x uses 'solid' flag to indicate child subheader blocks in archives.
   bool SubBlock;
 
   HOST_SYSTEM_TYPE HSType;
 
   FILE_SYSTEM_REDIRECT RedirType;
   wchar RedirName[NM];
   bool DirTarget;
 
   bool UnixOwnerSet,UnixOwnerNumeric,UnixGroupNumeric;
   char UnixOwnerName[256],UnixGroupName[256];
 #ifdef _UNIX
   uid_t UnixOwnerID;
   gid_t UnixGroupID;
 #else // Need these Unix fields in Windows too for 'list' command.
   uint UnixOwnerID;
   uint UnixGroupID;
 #endif
 
   void Reset(size_t SubDataSize=0);
 
   bool CmpName(const wchar *Name)
   {
     return(wcscmp(FileName,Name)==0);
   }
 
   FileHeader& operator = (FileHeader &hd);
 };
 
 
 struct EndArcHeader:BaseBlock
 {
   // Optional CRC32 of entire archive up to start of EndArcHeader block.
   // Present in RAR 4.x archives if EARC_DATACRC flag is set.
   uint ArcDataCRC;  
   
   uint VolNumber; // Optional number of current volume.
 
   // 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
 
   bool NextVolume; // Not last volume.
   bool DataCRC;
   bool RevSpace;
   bool StoreVolNumber;
   void Reset()
   {
     BaseBlock::Reset();
     NextVolume=false;
     DataCRC=false;
     RevSpace=false;
     StoreVolNumber=false;
   }
 };
 
 
 struct CryptHeader:BaseBlock
 {
   bool UsePswCheck;
   uint Lg2Count; // Log2 of PBKDF2 repetition count.
   byte Salt[SIZE_SALT50];
   byte PswCheck[SIZE_PSWCHECK];
 };
 
 
 // SubBlockHeader and its successors were used in RAR 2.x format.
 // RAR 4.x uses FileHeader with HEAD_SERVICE HeaderType for subblocks.
 struct SubBlockHeader:BlockHeader
 {
   ushort SubType;
   byte Level;
 };
 
 
 struct CommentHeader:BaseBlock
 {
   ushort UnpSize;
   byte UnpVer;
   byte Method;
   ushort CommCRC;
 };
 
 
 struct ProtectHeader:BlockHeader
 {
   byte Version;
   ushort RecSectors;
   uint TotalBlocks;
   byte Mark[8];
 };
 
 
 struct UnixOwnersHeader:SubBlockHeader
 {
   ushort OwnerNameSize;
   ushort GroupNameSize;
 /* dummy */
   char OwnerName[256];
   char GroupName[256];
 };
 
 
 struct EAHeader:SubBlockHeader
 {
   uint UnpSize;
   byte UnpVer;
   byte Method;
   uint EACRC;
 };
 
 
 struct StreamHeader:SubBlockHeader
 {
   uint UnpSize;
   byte UnpVer;
   byte Method;
   uint StreamCRC;
   ushort StreamNameSize;
   char StreamName[260];
 };
 
 
 #endif