diff --git a/SabreTools.Library/FileTypes/CoreRarArchive.cs b/SabreTools.Library/FileTypes/CoreRarArchive.cs
index 34c31118..69a5967a 100644
--- a/SabreTools.Library/FileTypes/CoreRarArchive.cs
+++ b/SabreTools.Library/FileTypes/CoreRarArchive.cs
@@ -1,10 +1,119 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using SabreTools.Library.Data;
///
-/// http://www.rarlab.com/technote.htm#srvheaders
+/// This code is based on the header format described at http://www.rarlab.com/technote.htm#srvheaders
///
+///
+/// ---------------------------------------------
+/// vint
+///
+/// Variable length integer. Can include one or more bytes, where lower 7 bits of every byte contain integer data
+/// and highest bit in every byte is the continuation flag.If highest bit is 0, this is the last byte in sequence.
+/// So first byte contains 7 least significant bits of integer and continuation flag. Second byte, if present,
+/// contains next 7 bits and so on.
+///
+/// Currently RAR format uses vint to store up to 64 bit integers, resulting in 10 bytes maximum. This value may
+/// be increased in the future if necessary for some reason.
+///
+/// Sometimes RAR needs to pre-allocate space for vint before knowing its exact value. In such situation it can
+/// allocate more space than really necessary and then fill several leading bytes with 0x80 hexadecimal, which means
+/// 0 with continuation flag set.
+/// ----------------------------------------------
+/// General archive layout:
+///
+/// Self-extracting module(optional) (RAR assumes the maximum SFX module size to not exceed 1 MB, but this value
+/// can be increased in the future.
+/// RAR 5.0 signature (RAR 5.0 signature consists of 8 bytes: 0x52 0x61 0x72 0x21 0x1A 0x07 0x01 0x00.
+/// You need to search for this signature in supposed archive from beginning and up to maximum SFX
+/// module size. Just for comparison this is RAR 4.x 7 byte length signature: 0x52 0x61 0x72 0x21 0x1A 0x07 0x00.)
+/// Archive encryption header(optional)
+/// Main archive header
+/// Archive comment service header(optional)
+/// File header 1
+/// Service headers(NTFS ACL, streams, etc.) for preceding file(optional).
+/// ...
+/// File header N
+/// Service headers(NTFS ACL, streams, etc.) for preceding file(optional).
+/// Recovery record(optional).
+/// End of archive header.
+/// ----------------------------------------------
+/// General archive block format:
+///
+/// Header CRC32: uint32 (CRC32 of header data starting from Header size field and up to and including the optional extra area.)
+/// Header size: vint (Size of header data starting from Header type field and up to and including the optional extra area.
+/// This field must not be longer than 3 bytes in current implementation, resulting in 2 MB maximum header size.)
+/// Header type: vint (Type of archive header. Possible values are: )
+/// 1 Main archive header.
+/// 2 File header.
+/// 3 Service header.
+/// 4 Archive encryption header.
+/// 5 End of archive header.
+/// Header flags: vint (Flags common for all headers:)
+/// 0x0001 Extra area is present in the end of header.
+/// 0x0002 Data area is present in the end of header.
+/// 0x0004 Blocks with unknown type and this flag must be skipped when updating an archive.
+/// 0x0008 Data area is continuing from previous volume.
+/// 0x0010 Data area is continuing in next volume.
+/// 0x0020 Block depends on preceding file block.
+/// 0x0040 Preserve a child block if host block is modified.
+/// Extra area size: vint (Size of extra area. Optional field, present only if 0x0001 header flag is set.)
+/// Data size: vint (Size of data area. Optional field, present only if 0x0002 header flag is set.)
+/// ...: ... (Fields specific for current block type. See concrete block type descriptions for details)
+/// Extra data: ... (Optional area containing additional header fields, present only if 0x0001 header flag is set.)
+/// Data area: vint (Optional data area, present only if 0x0002 header flag is set. Used to store large data amounts, such as
+/// compressed file data. Not counted in Header CRC and Header size fields.
+/// ----------------------------------------------
+/// General extra area format
+///
+/// Size: vint (Size of record data starting from Type.)
+/// Type: vint (Record type. Different archive blocks have different associated extra area record types. Read the
+/// concrete archive block description for details. New record types can be added in the future, so unknown
+/// record types need to be skipped without interrupting an operation.)
+/// Data: ... (Record dependent data. May be missing if record consists only from size and type.)
+/// ----------------------------------------------
+/// Archive encryption header:
+///
+/// Header CRC32: uint32
+/// Header size: vint
+/// Header type: vint (4)
+/// Header flags: vint
+/// Encryption version: vint (Version of encryption algorithm. Now only 0 version(AES-256) is supported.)
+/// Encryption flags: vint
+/// 0x0001 Password check data is present.
+/// KDF count: 1 byte (Binary logarithm of iteration number for PBKDF2 function.RAR can refuse to process
+/// KDF count exceeding some threshold. Concrete value of threshold is a version dependent.)
+/// Salt: 16 bytes (Salt value used globally for all encrypted archive headers.)
+/// Check value: 12 bytes (Value used to verify the password validity. Present only if 0x0001 encryption
+/// flag is set.First 8 bytes are calculated using additional PBKDF2 rounds, 4 last bytes is the additional
+/// checksum. Together with the standard header CRC32 we have 64 bit checksum to reliably verify this field
+/// integrity and distinguish invalid password and damaged data. Further details can be found in UnRAR source code.)
+/// ----------------------------------------------
+/// Main archive header:
+///
+/// Header CRC32: uint32 (CRC32 of header data starting from Header size field and up to and including the optional extra area.)
+/// Header size: vint (Size of header data starting from Header type field and up to and including the optional extra area. This field must not be longer than 3 bytes in current implementation, resulting in 2 MB maximum header size.)
+/// Header type: vint (1)
+/// Header flags: vint (Flags common for all headers)
+/// Extra area size: vint (Size of extra area. Optional field, present only if 0x0001 header flag is set.)
+/// Archive flags: vint
+/// 0x0001 Volume.Archive is a part of multivolume set.
+/// 0x0002 Volume number field is present.This flag is present in all volumes except first.
+/// 0x0004 Solid archive.
+/// 0x0008 Recovery record is present.
+/// 0x0010 Locked archive.
+/// Volume number: vint (Optional field, present only if 0x0002 archive flag is set. Not present for first volume,
+/// 1 for second volume, 2 for third and so on.)
+/// Extra area: ... (Optional area containing additional header fields, present only if 0x0001 header flag is set.)
+/// [Extra area of main archive header can contain following record types
+/// Type Name Description
+/// 0x01 Locator Contains positions of different service blocks, so they can be accessed quickly, without scanning
+/// the entire archive.This record is optional.If it is missing, it is still necessary to scan the entire archive
+/// to verify presence of service blocks.]
+/// ----------------------------------------------
+///
namespace SabreTools.Library.FileTypes
{
public class CoreRarArchive
@@ -110,4 +219,71 @@ namespace SabreTools.Library.FileTypes
public uint ServiceSize; // vint
public byte[] ServiceData;
}
+
+ // BELOW ARE CONCRETE IMPLEMENTATIONS OF HEADER DETAILS
+
+ ///
+ /// General archive block format used by all RAR block types
+ ///
+ public class GeneralArchiveBlockFormat
+ {
+ public uint HeaderCRC32;
+ public uint HeaderSize; // vint
+ public HeaderType HeaderType;
+ public HeaderFlags HeaderFlags;
+ public ulong ExtraAreaSize; // vint
+ public ulong DataAreaSize; // vint
+ public byte[] ExtraArea;
+ public byte[] DataArea;
+ }
+
+ ///
+ /// General extra area format used by all RAR extra area records
+ ///
+ public class GeneralExtraAreaFormat
+ {
+ public ulong Size; // vint
+ public ulong Type; // vint
+ public byte[] Data;
+ }
+
+ ///
+ /// Encryption header only present in encrypted archives
+ ///
+ /// Every proceeding header is started from 16 byte AES-256
+ /// initialization vectors followed by encrypted header data
+ ///
+ public class ArchiveEncryptionHeader : GeneralArchiveBlockFormat
+ {
+ public new HeaderType HeaderType = HeaderType.ArchiveEncryptionHeader;
+ public ulong EncryptionVersion; // vint
+ public ulong EncryptionFlags; // vint
+ }
+
+ ///
+ /// Types of archive header
+ ///
+ public enum HeaderType : ulong // vint
+ {
+ MainArchiveHeader = 1,
+ FileHeader = 2,
+ ServiceHeader = 3,
+ ArchiveEncryptionHeader = 4,
+ EndOfArchiveHeader = 5,
+ }
+
+ ///
+ /// Flags common for all headers
+ ///
+ [Flags]
+ public enum HeaderFlags : ulong // vint
+ {
+ ExtraAreaIsPresentInEndOfHeader = 0x0001,
+ DataAreaIsPresentInEndOfHeader = 0x0002,
+ BlocksWithUnknownType = 0x0004, // this flag must be skipped when updating an archive
+ DataAreaIsContinuingFromPreviousVolume = 0x0008,
+ DataAreaIsContinuingInNextVolume = 0x0010,
+ BlockDependsOnPrecedingFileBlock = 0x0020,
+ PreserveChildBlockIfHostBlockIsModified = 0x0040,
+ }
}