File indexing completed on 2025-02-02 04:26:01

0001 /* Copyright 2015 the unarr project authors (see AUTHORS file).
0002    License: LGPLv3 */
0003 
0004 #ifndef rar_rar_h
0005 #define rar_rar_h
0006 
0007 #include "../common/unarr-imp.h"
0008 
0009 #include "lzss.h"
0010 #include "../lzmasdk/Ppmd7.h"
0011 #include <limits.h>
0012 
0013 static inline size_t smin(size_t a, size_t b) { return a < b ? a : b; }
0014 
0015 typedef struct ar_archive_rar_s ar_archive_rar;
0016 
0017 /***** parse-rar *****/
0018 
0019 #define FILE_SIGNATURE_SIZE 7
0020 
0021 enum block_types {
0022     TYPE_FILE_SIGNATURE = 0x72, TYPE_MAIN_HEADER = 0x73, TYPE_FILE_ENTRY = 0x74,
0023     TYPE_NEWSUB = 0x7A, TYPE_END_OF_ARCHIVE = 0x7B,
0024 };
0025 
0026 enum archive_flags {
0027     MHD_VOLUME = 1 << 0, MHD_COMMENT = 1 << 1, MHD_LOCK = 1 << 2,
0028     MHD_SOLID = 1 << 3, MHD_PACK_COMMENT = 1 << 4, MHD_AV = 1 << 5,
0029     MHD_PROTECT = 1 << 6, MHD_PASSWORD = 1 << 7, MHD_FIRSTVOLUME = 1 << 8,
0030     MHD_ENCRYPTVER = 1 << 9,
0031     MHD_LONG_BLOCK = 1 << 15,
0032 };
0033 
0034 enum entry_flags {
0035     LHD_SPLIT_BEFORE = 1 << 0, LHD_SPLIT_AFTER = 1 << 1, LHD_PASSWORD = 1 << 2,
0036     LHD_COMMENT = 1 << 3, LHD_SOLID = 1 << 4,
0037     LHD_DIRECTORY = (1 << 5) | (1 << 6) | (1 << 7),
0038     LHD_LARGE = 1 << 8, LHD_UNICODE = 1 << 9, LHD_SALT = 1 << 10,
0039     LHD_VERSION = 1 << 11, LHD_EXTTIME = 1 << 12, LHD_EXTFLAGS = 1 << 13,
0040     LHD_LONG_BLOCK = 1 << 15,
0041 };
0042 
0043 enum compression_method {
0044     METHOD_STORE = 0x30,
0045     METHOD_FASTEST = 0x31, METHOD_FAST = 0x32, METHOD_NORMAL = 0x33,
0046     METHOD_GOOD = 0x34, METHOD_BEST = 0x35,
0047 };
0048 
0049 struct rar_header {
0050     uint16_t crc;
0051     uint8_t type;
0052     uint16_t flags;
0053     uint16_t size;
0054     uint64_t datasize;
0055 };
0056 
0057 struct rar_entry {
0058     uint64_t size;
0059     uint8_t os;
0060     uint32_t crc;
0061     uint32_t dosdate;
0062     uint8_t version;
0063     uint8_t method;
0064     uint16_t namelen;
0065     uint32_t attrs;
0066 };
0067 
0068 struct ar_archive_rar_entry {
0069     uint8_t version;
0070     uint8_t method;
0071     uint32_t crc;
0072     uint16_t header_size;
0073     bool solid;
0074     char *name;
0075 };
0076 
0077 bool rar_parse_header(ar_archive *ar, struct rar_header *header);
0078 bool rar_check_header_crc(ar_archive *ar);
0079 bool rar_parse_header_entry(ar_archive_rar *rar, struct rar_header *header, struct rar_entry *entry);
0080 const char *rar_get_name(ar_archive *ar);
0081 
0082 /***** filter-rar *****/
0083 
0084 struct RARVirtualMachine;
0085 struct RARProgramCode;
0086 struct RARFilter;
0087 
0088 struct ar_archive_rar_filters {
0089     struct RARVirtualMachine *vm;
0090     struct RARProgramCode *progs;
0091     struct RARFilter *stack;
0092     size_t filterstart;
0093     uint32_t lastfilternum;
0094     size_t lastend;
0095     uint8_t *bytes;
0096     size_t bytes_ready;
0097 };
0098 
0099 bool rar_parse_filter(ar_archive_rar *rar, const uint8_t *bytes, uint16_t length, uint8_t flags);
0100 bool rar_run_filters(ar_archive_rar *rar);
0101 void rar_clear_filters(struct ar_archive_rar_filters *filters);
0102 
0103 /***** huffman-rar *****/
0104 
0105 struct huffman_code {
0106     struct {
0107         int branches[2];
0108     } *tree;
0109     int numentries;
0110     int capacity;
0111     int minlength;
0112     int maxlength;
0113     struct {
0114         int length;
0115         int value;
0116     } *table;
0117     int tablesize;
0118 };
0119 
0120 bool rar_new_node(struct huffman_code *code);
0121 bool rar_add_value(struct huffman_code *code, int value, int codebits, int length);
0122 bool rar_create_code(struct huffman_code *code, uint8_t *lengths, int numsymbols);
0123 bool rar_make_table(struct huffman_code *code);
0124 void rar_free_code(struct huffman_code *code);
0125 
0126 static inline bool rar_is_leaf_node(struct huffman_code *code, int node) { return code->tree[node].branches[0] == code->tree[node].branches[1]; }
0127 
0128 /***** uncompress-rar *****/
0129 
0130 #define LZSS_WINDOW_SIZE   0x400000
0131 #define LZSS_OVERFLOW_SIZE 288
0132 
0133 #define MAINCODE_SIZE      299
0134 #define OFFSETCODE_SIZE    60
0135 #define LOWOFFSETCODE_SIZE 17
0136 #define LENGTHCODE_SIZE    28
0137 #define HUFFMAN_TABLE_SIZE MAINCODE_SIZE + OFFSETCODE_SIZE + LOWOFFSETCODE_SIZE + LENGTHCODE_SIZE
0138 
0139 struct ByteReader {
0140     IByteIn super;
0141     ar_archive_rar *rar;
0142 };
0143 
0144 struct CPpmdRAR_RangeDec {
0145     IPpmd7_RangeDec super;
0146     UInt32 Range;
0147     UInt32 Code;
0148     UInt32 Low;
0149     IByteIn *Stream;
0150 };
0151 
0152 struct ar_archive_rar_uncomp_v3 {
0153     struct huffman_code maincode;
0154     struct huffman_code offsetcode;
0155     struct huffman_code lowoffsetcode;
0156     struct huffman_code lengthcode;
0157     uint8_t lengthtable[HUFFMAN_TABLE_SIZE];
0158     uint32_t lastlength;
0159     uint32_t lastoffset;
0160     uint32_t oldoffset[4];
0161     uint32_t lastlowoffset;
0162     uint32_t numlowoffsetrepeats;
0163 
0164     bool is_ppmd_block;
0165     int ppmd_escape;
0166     CPpmd7 ppmd7_context;
0167     struct CPpmdRAR_RangeDec range_dec;
0168     struct ByteReader bytein;
0169 
0170     struct ar_archive_rar_filters filters;
0171 };
0172 
0173 #define MAINCODE_SIZE_20        298
0174 #define OFFSETCODE_SIZE_20      48
0175 #define LENGTHCODE_SIZE_20      28
0176 #define HUFFMAN_TABLE_SIZE_20   4 * 257
0177 
0178 struct AudioState {
0179     int8_t weight[5];
0180     int16_t delta[4];
0181     int8_t lastdelta;
0182     int error[11];
0183     int count;
0184     uint8_t lastbyte;
0185 };
0186 
0187 struct ar_archive_rar_uncomp_v2 {
0188     struct huffman_code maincode;
0189     struct huffman_code offsetcode;
0190     struct huffman_code lengthcode;
0191     struct huffman_code audiocode[4];
0192     uint8_t lengthtable[HUFFMAN_TABLE_SIZE_20];
0193     uint32_t lastoffset;
0194     uint32_t lastlength;
0195     uint32_t oldoffset[4];
0196     uint32_t oldoffsetindex;
0197 
0198     bool audioblock;
0199     uint8_t channel;
0200     uint8_t numchannels;
0201     struct AudioState audiostate[4];
0202     int8_t channeldelta;
0203 };
0204 
0205 struct ar_archive_rar_uncomp {
0206     uint8_t version;
0207 
0208     LZSS lzss;
0209     size_t bytes_ready;
0210     bool start_new_table;
0211 
0212     union {
0213         struct ar_archive_rar_uncomp_v3 v3;
0214         struct ar_archive_rar_uncomp_v2 v2;
0215     } state;
0216 
0217     struct StreamBitReader {
0218         uint64_t bits;
0219         int available;
0220         bool at_eof;
0221     } br;
0222 };
0223 
0224 bool rar_uncompress_part(ar_archive_rar *rar, void *buffer, size_t buffer_size);
0225 int64_t rar_expand(ar_archive_rar *rar, int64_t end);
0226 void rar_clear_uncompress(struct ar_archive_rar_uncomp *uncomp);
0227 static inline void br_clear_leftover_bits(struct ar_archive_rar_uncomp *uncomp) { uncomp->br.available &= ~0x07; }
0228 
0229 /***** rar *****/
0230 
0231 struct ar_archive_rar_progress {
0232     size_t data_left;
0233     size_t bytes_done;
0234     uint32_t crc;
0235 };
0236 
0237 struct ar_archive_rar_solid {
0238     size_t size_total;
0239     bool part_done;
0240     bool restart;
0241 };
0242 
0243 struct ar_archive_rar_s {
0244     ar_archive super;
0245     uint16_t archive_flags;
0246     struct ar_archive_rar_entry entry;
0247     struct ar_archive_rar_uncomp uncomp;
0248     struct ar_archive_rar_progress progress;
0249     struct ar_archive_rar_solid solid;
0250 };
0251 
0252 #endif