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