1 /* Copyright 2015 the unarr project authors (see AUTHORS file).
2    License: LGPLv3 */
3 
4 #ifndef rar_rar_h
5 #define rar_rar_h
6 
7 #include "../common/unarr-imp.h"
8 
9 #include "lzss.h"
10 #include "../lzmasdk/Ppmd7.h"
11 #include <limits.h>
12 
smin(size_t a,size_t b)13 static inline size_t smin(size_t a, size_t b) { return a < b ? a : b; }
14 
15 typedef struct ar_archive_rar_s ar_archive_rar;
16 
17 /***** parse-rar *****/
18 
19 #define FILE_SIGNATURE_SIZE 7
20 
21 enum block_types {
22     TYPE_FILE_SIGNATURE = 0x72, TYPE_MAIN_HEADER = 0x73, TYPE_FILE_ENTRY = 0x74,
23     TYPE_NEWSUB = 0x7A, TYPE_END_OF_ARCHIVE = 0x7B,
24 };
25 
26 enum archive_flags {
27     MHD_VOLUME = 1 << 0, MHD_COMMENT = 1 << 1, MHD_LOCK = 1 << 2,
28     MHD_SOLID = 1 << 3, MHD_PACK_COMMENT = 1 << 4, MHD_AV = 1 << 5,
29     MHD_PROTECT = 1 << 6, MHD_PASSWORD = 1 << 7, MHD_FIRSTVOLUME = 1 << 8,
30     MHD_ENCRYPTVER = 1 << 9,
31     MHD_LONG_BLOCK = 1 << 15,
32 };
33 
34 enum entry_flags {
35     LHD_SPLIT_BEFORE = 1 << 0, LHD_SPLIT_AFTER = 1 << 1, LHD_PASSWORD = 1 << 2,
36     LHD_COMMENT = 1 << 3, LHD_SOLID = 1 << 4,
37     LHD_DIRECTORY = (1 << 5) | (1 << 6) | (1 << 7),
38     LHD_LARGE = 1 << 8, LHD_UNICODE = 1 << 9, LHD_SALT = 1 << 10,
39     LHD_VERSION = 1 << 11, LHD_EXTTIME = 1 << 12, LHD_EXTFLAGS = 1 << 13,
40     LHD_LONG_BLOCK = 1 << 15,
41 };
42 
43 enum compression_method {
44     METHOD_STORE = 0x30,
45     METHOD_FASTEST = 0x31, METHOD_FAST = 0x32, METHOD_NORMAL = 0x33,
46     METHOD_GOOD = 0x34, METHOD_BEST = 0x35,
47 };
48 
49 struct rar_header {
50     uint16_t crc;
51     uint8_t type;
52     uint16_t flags;
53     uint16_t size;
54     uint64_t datasize;
55 };
56 
57 struct rar_entry {
58     uint64_t size;
59     uint8_t os;
60     uint32_t crc;
61     uint32_t dosdate;
62     uint8_t version;
63     uint8_t method;
64     uint16_t namelen;
65     uint32_t attrs;
66 };
67 
68 struct ar_archive_rar_entry {
69     uint8_t version;
70     uint8_t method;
71     uint32_t crc;
72     uint16_t header_size;
73     bool solid;
74     char *name;
75 };
76 
77 bool rar_parse_header(ar_archive *ar, struct rar_header *header);
78 bool rar_check_header_crc(ar_archive *ar);
79 bool rar_parse_header_entry(ar_archive_rar *rar, struct rar_header *header, struct rar_entry *entry);
80 const char *rar_get_name(ar_archive *ar);
81 
82 /***** filter-rar *****/
83 
84 struct RARVirtualMachine;
85 struct RARProgramCode;
86 struct RARFilter;
87 
88 struct ar_archive_rar_filters {
89     struct RARVirtualMachine *vm;
90     struct RARProgramCode *progs;
91     struct RARFilter *stack;
92     size_t filterstart;
93     uint32_t lastfilternum;
94     size_t lastend;
95     uint8_t *bytes;
96     size_t bytes_ready;
97 };
98 
99 bool rar_parse_filter(ar_archive_rar *rar, const uint8_t *bytes, uint16_t length, uint8_t flags);
100 bool rar_run_filters(ar_archive_rar *rar);
101 void rar_clear_filters(struct ar_archive_rar_filters *filters);
102 
103 /***** huffman-rar *****/
104 
105 struct huffman_code {
106     struct {
107         int branches[2];
108     } *tree;
109     int numentries;
110     int capacity;
111     int minlength;
112     int maxlength;
113     struct {
114         int length;
115         int value;
116     } *table;
117     int tablesize;
118 };
119 
120 bool rar_new_node(struct huffman_code *code);
121 bool rar_add_value(struct huffman_code *code, int value, int codebits, int length);
122 bool rar_create_code(struct huffman_code *code, uint8_t *lengths, int numsymbols);
123 bool rar_make_table(struct huffman_code *code);
124 void rar_free_code(struct huffman_code *code);
125 
rar_is_leaf_node(struct huffman_code * code,int node)126 static inline bool rar_is_leaf_node(struct huffman_code *code, int node) { return code->tree[node].branches[0] == code->tree[node].branches[1]; }
127 
128 /***** uncompress-rar *****/
129 
130 #define LZSS_WINDOW_SIZE   0x400000
131 #define LZSS_OVERFLOW_SIZE 288
132 
133 #define MAINCODE_SIZE      299
134 #define OFFSETCODE_SIZE    60
135 #define LOWOFFSETCODE_SIZE 17
136 #define LENGTHCODE_SIZE    28
137 #define HUFFMAN_TABLE_SIZE MAINCODE_SIZE + OFFSETCODE_SIZE + LOWOFFSETCODE_SIZE + LENGTHCODE_SIZE
138 
139 struct ByteReader {
140     IByteIn super;
141     ar_archive_rar *rar;
142 };
143 
144 struct CPpmdRAR_RangeDec {
145     IPpmd7_RangeDec super;
146     UInt32 Range;
147     UInt32 Code;
148     UInt32 Low;
149     IByteIn *Stream;
150 };
151 
152 struct ar_archive_rar_uncomp_v3 {
153     struct huffman_code maincode;
154     struct huffman_code offsetcode;
155     struct huffman_code lowoffsetcode;
156     struct huffman_code lengthcode;
157     uint8_t lengthtable[HUFFMAN_TABLE_SIZE];
158     uint32_t lastlength;
159     uint32_t lastoffset;
160     uint32_t oldoffset[4];
161     uint32_t lastlowoffset;
162     uint32_t numlowoffsetrepeats;
163 
164     bool is_ppmd_block;
165     int ppmd_escape;
166     CPpmd7 ppmd7_context;
167     struct CPpmdRAR_RangeDec range_dec;
168     struct ByteReader bytein;
169 
170     struct ar_archive_rar_filters filters;
171 };
172 
173 #define MAINCODE_SIZE_20        298
174 #define OFFSETCODE_SIZE_20      48
175 #define LENGTHCODE_SIZE_20      28
176 #define HUFFMAN_TABLE_SIZE_20   4 * 257
177 
178 struct AudioState {
179     int8_t weight[5];
180     int16_t delta[4];
181     int8_t lastdelta;
182     int error[11];
183     int count;
184     uint8_t lastbyte;
185 };
186 
187 struct ar_archive_rar_uncomp_v2 {
188     struct huffman_code maincode;
189     struct huffman_code offsetcode;
190     struct huffman_code lengthcode;
191     struct huffman_code audiocode[4];
192     uint8_t lengthtable[HUFFMAN_TABLE_SIZE_20];
193     uint32_t lastoffset;
194     uint32_t lastlength;
195     uint32_t oldoffset[4];
196     uint32_t oldoffsetindex;
197 
198     bool audioblock;
199     uint8_t channel;
200     uint8_t numchannels;
201     struct AudioState audiostate[4];
202     int8_t channeldelta;
203 };
204 
205 struct ar_archive_rar_uncomp {
206     uint8_t version;
207 
208     LZSS lzss;
209     size_t bytes_ready;
210     bool start_new_table;
211 
212     union {
213         struct ar_archive_rar_uncomp_v3 v3;
214         struct ar_archive_rar_uncomp_v2 v2;
215     } state;
216 
217     struct StreamBitReader {
218         uint64_t bits;
219         int available;
220         bool at_eof;
221     } br;
222 };
223 
224 bool rar_uncompress_part(ar_archive_rar *rar, void *buffer, size_t buffer_size);
225 int64_t rar_expand(ar_archive_rar *rar, int64_t end);
226 void rar_clear_uncompress(struct ar_archive_rar_uncomp *uncomp);
br_clear_leftover_bits(struct ar_archive_rar_uncomp * uncomp)227 static inline void br_clear_leftover_bits(struct ar_archive_rar_uncomp *uncomp) { uncomp->br.available &= ~0x07; }
228 
229 /***** rar *****/
230 
231 struct ar_archive_rar_progress {
232     size_t data_left;
233     size_t bytes_done;
234     uint32_t crc;
235 };
236 
237 struct ar_archive_rar_solid {
238     size_t size_total;
239     bool part_done;
240     bool restart;
241 };
242 
243 struct ar_archive_rar_s {
244     ar_archive super;
245     uint16_t archive_flags;
246     struct ar_archive_rar_entry entry;
247     struct ar_archive_rar_uncomp uncomp;
248     struct ar_archive_rar_progress progress;
249     struct ar_archive_rar_solid solid;
250 };
251 
252 #endif
253