1 | #include "mupdf/fitz.h" |
2 | |
3 | #include <string.h> |
4 | |
5 | /* The null filter reads a specified amount of data from the substream. */ |
6 | |
7 | struct null_filter |
8 | { |
9 | fz_stream *chain; |
10 | size_t remain; |
11 | int64_t offset; |
12 | unsigned char buffer[4096]; |
13 | }; |
14 | |
15 | static int |
16 | next_null(fz_context *ctx, fz_stream *stm, size_t max) |
17 | { |
18 | struct null_filter *state = stm->state; |
19 | size_t n; |
20 | |
21 | if (state->remain == 0) |
22 | return EOF; |
23 | |
24 | fz_seek(ctx, state->chain, state->offset, 0); |
25 | n = fz_available(ctx, state->chain, max); |
26 | if (n == 0) |
27 | return EOF; |
28 | if (n > state->remain) |
29 | n = state->remain; |
30 | if (n > sizeof(state->buffer)) |
31 | n = sizeof(state->buffer); |
32 | |
33 | memcpy(state->buffer, state->chain->rp, n); |
34 | stm->rp = state->buffer; |
35 | stm->wp = stm->rp + n; |
36 | state->chain->rp += n; |
37 | state->remain -= n; |
38 | state->offset += n; |
39 | stm->pos += n; |
40 | return *stm->rp++; |
41 | } |
42 | |
43 | static void |
44 | close_null(fz_context *ctx, void *state_) |
45 | { |
46 | struct null_filter *state = (struct null_filter *)state_; |
47 | fz_drop_stream(ctx, state->chain); |
48 | fz_free(ctx, state); |
49 | } |
50 | |
51 | fz_stream * |
52 | fz_open_null_filter(fz_context *ctx, fz_stream *chain, int len, int64_t offset) |
53 | { |
54 | struct null_filter *state = fz_malloc_struct(ctx, struct null_filter); |
55 | state->chain = fz_keep_stream(ctx, chain); |
56 | state->remain = len; |
57 | state->offset = offset; |
58 | return fz_new_stream(ctx, state, next_null, close_null); |
59 | } |
60 | |
61 | /* The range filter copies data from specified ranges of the chained stream */ |
62 | |
63 | struct range_filter |
64 | { |
65 | fz_stream *chain; |
66 | fz_range *ranges; |
67 | int nranges; |
68 | int next_range; |
69 | size_t remain; |
70 | int64_t offset; |
71 | unsigned char buffer[4096]; |
72 | }; |
73 | |
74 | static int |
75 | next_range(fz_context *ctx, fz_stream *stm, size_t max) |
76 | { |
77 | struct range_filter *state = stm->state; |
78 | size_t n; |
79 | |
80 | while (state->remain == 0 && state->next_range < state->nranges) |
81 | { |
82 | fz_range *range = &state->ranges[state->next_range++]; |
83 | state->remain = range->length; |
84 | state->offset = range->offset; |
85 | } |
86 | |
87 | if (state->remain == 0) |
88 | return EOF; |
89 | fz_seek(ctx, state->chain, state->offset, 0); |
90 | n = fz_available(ctx, state->chain, max); |
91 | if (n > state->remain) |
92 | n = state->remain; |
93 | if (n > sizeof(state->buffer)) |
94 | n = sizeof(state->buffer); |
95 | memcpy(state->buffer, state->chain->rp, n); |
96 | stm->rp = state->buffer; |
97 | stm->wp = stm->rp + n; |
98 | if (n == 0) |
99 | return EOF; |
100 | state->chain->rp += n; |
101 | state->remain -= n; |
102 | state->offset += n; |
103 | stm->pos += n; |
104 | return *stm->rp++; |
105 | } |
106 | |
107 | static void |
108 | close_range(fz_context *ctx, void *state_) |
109 | { |
110 | struct range_filter *state = (struct range_filter *)state_; |
111 | fz_drop_stream(ctx, state->chain); |
112 | fz_free(ctx, state->ranges); |
113 | fz_free(ctx, state); |
114 | } |
115 | |
116 | fz_stream * |
117 | fz_open_range_filter(fz_context *ctx, fz_stream *chain, fz_range *ranges, int nranges) |
118 | { |
119 | struct range_filter *state = NULL; |
120 | |
121 | state = fz_malloc_struct(ctx, struct range_filter); |
122 | fz_try(ctx) |
123 | { |
124 | if (nranges > 0) |
125 | { |
126 | state->ranges = fz_calloc(ctx, nranges, sizeof(*ranges)); |
127 | memcpy(state->ranges, ranges, nranges * sizeof(*ranges)); |
128 | state->nranges = nranges; |
129 | state->next_range = 1; |
130 | state->remain = ranges[0].length; |
131 | state->offset = ranges[0].offset; |
132 | } |
133 | else |
134 | { |
135 | state->ranges = NULL; |
136 | state->nranges = 0; |
137 | state->next_range = 1; |
138 | state->remain = 0; |
139 | state->offset = 0; |
140 | } |
141 | state->chain = fz_keep_stream(ctx, chain); |
142 | } |
143 | fz_catch(ctx) |
144 | { |
145 | fz_free(ctx, state->ranges); |
146 | fz_free(ctx, state); |
147 | fz_rethrow(ctx); |
148 | } |
149 | |
150 | return fz_new_stream(ctx, state, next_range, close_range); |
151 | } |
152 | |
153 | /* |
154 | * The endstream filter reads a PDF substream, and starts to look for an 'endstream' token |
155 | * after the specified length. |
156 | */ |
157 | |
158 | #define END_CHECK_SIZE 32 |
159 | |
160 | struct endstream_filter |
161 | { |
162 | fz_stream *chain; |
163 | size_t remain, , size; |
164 | int64_t offset; |
165 | int warned; |
166 | unsigned char buffer[4096]; |
167 | }; |
168 | |
169 | static int |
170 | next_endstream(fz_context *ctx, fz_stream *stm, size_t max) |
171 | { |
172 | struct endstream_filter *state = stm->state; |
173 | size_t n, nbytes_in_buffer, size; |
174 | unsigned char *rp; |
175 | |
176 | if (state->remain == 0) |
177 | goto look_for_endstream; |
178 | |
179 | fz_seek(ctx, state->chain, state->offset, 0); |
180 | n = fz_available(ctx, state->chain, max); |
181 | if (n == 0) |
182 | return EOF; |
183 | if (n > state->remain) |
184 | n = state->remain; |
185 | if (n > sizeof(state->buffer)) |
186 | n = sizeof(state->buffer); |
187 | memcpy(state->buffer, state->chain->rp, n); |
188 | stm->rp = state->buffer; |
189 | stm->wp = stm->rp + n; |
190 | state->chain->rp += n; |
191 | state->remain -= n; |
192 | state->offset += n; |
193 | stm->pos += n; |
194 | return *stm->rp++; |
195 | |
196 | look_for_endstream: |
197 | /* We should distrust the stream length, and check for end |
198 | * marker before terminating the stream - this is to cope |
199 | * with files with duff "Length" values. */ |
200 | |
201 | /* Move any data left over in our buffer down to the start. |
202 | * Ordinarily, there won't be any, but this allows for the |
203 | * case where we were part way through matching a stream end |
204 | * marker when the buffer filled before. */ |
205 | nbytes_in_buffer = state->extras; |
206 | if (nbytes_in_buffer) |
207 | memmove(state->buffer, stm->rp, nbytes_in_buffer); |
208 | stm->rp = state->buffer; |
209 | stm->wp = stm->rp + nbytes_in_buffer; |
210 | |
211 | /* In most sane files, we'll get "\nendstream" instantly. We |
212 | * should only need (say) 32 bytes to be sure. For crap files |
213 | * where we overread regularly, don't harm performance by |
214 | * working in small chunks. */ |
215 | size = state->size * 2; |
216 | if (size > sizeof(state->buffer)) |
217 | size = sizeof(state->buffer); |
218 | state->size = size; |
219 | |
220 | /* Read enough data into our buffer to start looking for the 'endstream' token. */ |
221 | fz_seek(ctx, state->chain, state->offset, 0); |
222 | while (nbytes_in_buffer < size) |
223 | { |
224 | n = fz_available(ctx, state->chain, size - nbytes_in_buffer); |
225 | if (n == 0) |
226 | break; |
227 | if (n > size - nbytes_in_buffer) |
228 | n = size - nbytes_in_buffer; |
229 | memcpy(stm->wp, state->chain->rp, n); |
230 | stm->wp += n; |
231 | state->chain->rp += n; |
232 | nbytes_in_buffer += n; |
233 | state->offset += n; |
234 | } |
235 | |
236 | /* Look for the 'endstream' token. */ |
237 | rp = fz_memmem(state->buffer, nbytes_in_buffer, "endstream" , 9); |
238 | if (rp) |
239 | { |
240 | /* Include newline (CR|LF|CRLF) before 'endstream' token */ |
241 | if (rp > state->buffer && rp[-1] == '\n') --rp; |
242 | if (rp > state->buffer && rp[-1] == '\r') --rp; |
243 | n = rp - state->buffer; |
244 | stm->eof = 1; /* We're done, don't call us again! */ |
245 | } |
246 | else if (nbytes_in_buffer > 11) /* 11 covers enough data to detect "\r?\n?endstream" */ |
247 | n = nbytes_in_buffer - 11; /* no endstream, but there is more data */ |
248 | else |
249 | n = nbytes_in_buffer; /* no endstream, but at the end of the file */ |
250 | |
251 | /* We have at least n bytes before we hit an end marker */ |
252 | state->extras = nbytes_in_buffer - n; |
253 | stm->wp = stm->rp + n; |
254 | stm->pos += n; |
255 | |
256 | if (n == 0) |
257 | return EOF; |
258 | |
259 | if (!state->warned) |
260 | { |
261 | state->warned = 1; |
262 | fz_warn(ctx, "PDF stream Length incorrect" ); |
263 | } |
264 | return *stm->rp++; |
265 | } |
266 | |
267 | static void |
268 | close_endstream(fz_context *ctx, void *state_) |
269 | { |
270 | struct endstream_filter *state = (struct endstream_filter *)state_; |
271 | fz_drop_stream(ctx, state->chain); |
272 | fz_free(ctx, state); |
273 | } |
274 | |
275 | fz_stream * |
276 | fz_open_endstream_filter(fz_context *ctx, fz_stream *chain, int len, int64_t offset) |
277 | { |
278 | struct endstream_filter *state; |
279 | |
280 | if (len < 0) |
281 | len = 0; |
282 | |
283 | state = fz_malloc_struct(ctx, struct endstream_filter); |
284 | state->chain = fz_keep_stream(ctx, chain); |
285 | state->remain = len; |
286 | state->offset = offset; |
287 | state->extras = 0; |
288 | state->size = END_CHECK_SIZE >> 1; /* size is doubled first thing when used */ |
289 | |
290 | return fz_new_stream(ctx, state, next_endstream, close_endstream); |
291 | } |
292 | |
293 | /* Concat filter concatenates several streams into one */ |
294 | |
295 | struct concat_filter |
296 | { |
297 | int max; |
298 | int count; |
299 | int current; |
300 | int pad; /* 1 if we should add whitespace padding between streams */ |
301 | unsigned char ws_buf; |
302 | fz_stream *chain[1]; |
303 | }; |
304 | |
305 | static int |
306 | next_concat(fz_context *ctx, fz_stream *stm, size_t max) |
307 | { |
308 | struct concat_filter *state = (struct concat_filter *)stm->state; |
309 | size_t n; |
310 | |
311 | while (state->current < state->count) |
312 | { |
313 | /* Read the next block of underlying data. */ |
314 | if (stm->wp == state->chain[state->current]->wp) |
315 | state->chain[state->current]->rp = stm->wp; |
316 | n = fz_available(ctx, state->chain[state->current], max); |
317 | if (n) |
318 | { |
319 | stm->rp = state->chain[state->current]->rp; |
320 | stm->wp = state->chain[state->current]->wp; |
321 | stm->pos += n; |
322 | return *stm->rp++; |
323 | } |
324 | else |
325 | { |
326 | if (state->chain[state->current]->error) |
327 | { |
328 | stm->error = 1; |
329 | break; |
330 | } |
331 | state->current++; |
332 | fz_drop_stream(ctx, state->chain[state->current-1]); |
333 | if (state->pad) |
334 | { |
335 | stm->rp = (&state->ws_buf)+1; |
336 | stm->wp = stm->rp + 1; |
337 | stm->pos++; |
338 | return 32; |
339 | } |
340 | } |
341 | } |
342 | |
343 | stm->rp = stm->wp; |
344 | |
345 | return EOF; |
346 | } |
347 | |
348 | static void |
349 | close_concat(fz_context *ctx, void *state_) |
350 | { |
351 | struct concat_filter *state = (struct concat_filter *)state_; |
352 | int i; |
353 | |
354 | for (i = state->current; i < state->count; i++) |
355 | { |
356 | fz_drop_stream(ctx, state->chain[i]); |
357 | } |
358 | fz_free(ctx, state); |
359 | } |
360 | |
361 | fz_stream * |
362 | fz_open_concat(fz_context *ctx, int len, int pad) |
363 | { |
364 | struct concat_filter *state; |
365 | |
366 | state = fz_calloc(ctx, 1, sizeof(struct concat_filter) + (len-1)*sizeof(fz_stream *)); |
367 | state->max = len; |
368 | state->count = 0; |
369 | state->current = 0; |
370 | state->pad = pad; |
371 | state->ws_buf = 32; |
372 | |
373 | return fz_new_stream(ctx, state, next_concat, close_concat); |
374 | } |
375 | |
376 | void |
377 | fz_concat_push_drop(fz_context *ctx, fz_stream *concat, fz_stream *chain) |
378 | { |
379 | struct concat_filter *state = (struct concat_filter *)concat->state; |
380 | |
381 | if (state->count == state->max) |
382 | { |
383 | fz_drop_stream(ctx, chain); |
384 | fz_throw(ctx, FZ_ERROR_GENERIC, "Concat filter size exceeded" ); |
385 | } |
386 | |
387 | state->chain[state->count++] = chain; |
388 | } |
389 | |
390 | /* ASCII Hex Decode */ |
391 | |
392 | typedef struct fz_ahxd_s fz_ahxd; |
393 | |
394 | struct fz_ahxd_s |
395 | { |
396 | fz_stream *chain; |
397 | int eod; |
398 | unsigned char buffer[256]; |
399 | }; |
400 | |
401 | static inline int iswhite(int a) |
402 | { |
403 | switch (a) { |
404 | case '\n': case '\r': case '\t': case ' ': |
405 | case '\0': case '\f': case '\b': case 0177: |
406 | return 1; |
407 | } |
408 | return 0; |
409 | } |
410 | |
411 | static inline int ishex(int a) |
412 | { |
413 | return (a >= 'A' && a <= 'F') || |
414 | (a >= 'a' && a <= 'f') || |
415 | (a >= '0' && a <= '9'); |
416 | } |
417 | |
418 | static inline int unhex(int a) |
419 | { |
420 | if (a >= 'A' && a <= 'F') return a - 'A' + 0xA; |
421 | if (a >= 'a' && a <= 'f') return a - 'a' + 0xA; |
422 | if (a >= '0' && a <= '9') return a - '0'; |
423 | return 0; |
424 | } |
425 | |
426 | static int |
427 | next_ahxd(fz_context *ctx, fz_stream *stm, size_t max) |
428 | { |
429 | fz_ahxd *state = stm->state; |
430 | unsigned char *p = state->buffer; |
431 | unsigned char *ep; |
432 | int a, b, c, odd; |
433 | |
434 | if (max > sizeof(state->buffer)) |
435 | max = sizeof(state->buffer); |
436 | ep = p + max; |
437 | |
438 | odd = 0; |
439 | |
440 | while (p < ep) |
441 | { |
442 | if (state->eod) |
443 | break; |
444 | |
445 | c = fz_read_byte(ctx, state->chain); |
446 | if (c < 0) |
447 | break; |
448 | |
449 | if (ishex(c)) |
450 | { |
451 | if (!odd) |
452 | { |
453 | a = unhex(c); |
454 | odd = 1; |
455 | } |
456 | else |
457 | { |
458 | b = unhex(c); |
459 | *p++ = (a << 4) | b; |
460 | odd = 0; |
461 | } |
462 | } |
463 | else if (c == '>') |
464 | { |
465 | if (odd) |
466 | *p++ = (a << 4); |
467 | state->eod = 1; |
468 | break; |
469 | } |
470 | else if (!iswhite(c)) |
471 | { |
472 | fz_throw(ctx, FZ_ERROR_GENERIC, "bad data in ahxd: '%c'" , c); |
473 | } |
474 | } |
475 | stm->rp = state->buffer; |
476 | stm->wp = p; |
477 | stm->pos += p - state->buffer; |
478 | |
479 | if (stm->rp != p) |
480 | return *stm->rp++; |
481 | return EOF; |
482 | } |
483 | |
484 | static void |
485 | close_ahxd(fz_context *ctx, void *state_) |
486 | { |
487 | fz_ahxd *state = (fz_ahxd *)state_; |
488 | fz_drop_stream(ctx, state->chain); |
489 | fz_free(ctx, state); |
490 | } |
491 | |
492 | fz_stream * |
493 | fz_open_ahxd(fz_context *ctx, fz_stream *chain) |
494 | { |
495 | fz_ahxd *state = fz_malloc_struct(ctx, fz_ahxd); |
496 | state->chain = fz_keep_stream(ctx, chain); |
497 | state->eod = 0; |
498 | return fz_new_stream(ctx, state, next_ahxd, close_ahxd); |
499 | } |
500 | |
501 | /* ASCII 85 Decode */ |
502 | |
503 | typedef struct fz_a85d_s fz_a85d; |
504 | |
505 | struct fz_a85d_s |
506 | { |
507 | fz_stream *chain; |
508 | unsigned char buffer[256]; |
509 | int eod; |
510 | }; |
511 | |
512 | static int |
513 | next_a85d(fz_context *ctx, fz_stream *stm, size_t max) |
514 | { |
515 | fz_a85d *state = stm->state; |
516 | unsigned char *p = state->buffer; |
517 | unsigned char *ep; |
518 | int count = 0; |
519 | int word = 0; |
520 | int c; |
521 | |
522 | if (state->eod) |
523 | return EOF; |
524 | |
525 | if (max > sizeof(state->buffer)) |
526 | max = sizeof(state->buffer); |
527 | |
528 | ep = p + max; |
529 | while (p < ep) |
530 | { |
531 | c = fz_read_byte(ctx, state->chain); |
532 | if (c < 0) |
533 | break; |
534 | |
535 | if (c >= '!' && c <= 'u') |
536 | { |
537 | if (count == 4) |
538 | { |
539 | word = word * 85 + (c - '!'); |
540 | |
541 | *p++ = (word >> 24) & 0xff; |
542 | *p++ = (word >> 16) & 0xff; |
543 | *p++ = (word >> 8) & 0xff; |
544 | *p++ = (word) & 0xff; |
545 | |
546 | word = 0; |
547 | count = 0; |
548 | } |
549 | else |
550 | { |
551 | word = word * 85 + (c - '!'); |
552 | count ++; |
553 | } |
554 | } |
555 | |
556 | else if (c == 'z' && count == 0) |
557 | { |
558 | *p++ = 0; |
559 | *p++ = 0; |
560 | *p++ = 0; |
561 | *p++ = 0; |
562 | } |
563 | |
564 | else if (c == '~') |
565 | { |
566 | c = fz_read_byte(ctx, state->chain); |
567 | if (c != '>') |
568 | fz_warn(ctx, "bad eod marker in a85d" ); |
569 | |
570 | switch (count) { |
571 | case 0: |
572 | break; |
573 | case 1: |
574 | /* Specifically illegal in the spec, but adobe |
575 | * and gs both cope. See normal_87.pdf for a |
576 | * case where this matters. */ |
577 | fz_warn(ctx, "partial final byte in a85d" ); |
578 | break; |
579 | case 2: |
580 | word = word * (85 * 85 * 85) + 0xffffff; |
581 | *p++ = word >> 24; |
582 | break; |
583 | case 3: |
584 | word = word * (85 * 85) + 0xffff; |
585 | *p++ = word >> 24; |
586 | *p++ = word >> 16; |
587 | break; |
588 | case 4: |
589 | word = word * 85 + 0xff; |
590 | *p++ = word >> 24; |
591 | *p++ = word >> 16; |
592 | *p++ = word >> 8; |
593 | break; |
594 | } |
595 | state->eod = 1; |
596 | break; |
597 | } |
598 | |
599 | else if (!iswhite(c)) |
600 | { |
601 | fz_throw(ctx, FZ_ERROR_GENERIC, "bad data in a85d: '%c'" , c); |
602 | } |
603 | } |
604 | |
605 | stm->rp = state->buffer; |
606 | stm->wp = p; |
607 | stm->pos += p - state->buffer; |
608 | |
609 | if (p == stm->rp) |
610 | return EOF; |
611 | |
612 | return *stm->rp++; |
613 | } |
614 | |
615 | static void |
616 | close_a85d(fz_context *ctx, void *state_) |
617 | { |
618 | fz_a85d *state = (fz_a85d *)state_; |
619 | fz_drop_stream(ctx, state->chain); |
620 | fz_free(ctx, state); |
621 | } |
622 | |
623 | fz_stream * |
624 | fz_open_a85d(fz_context *ctx, fz_stream *chain) |
625 | { |
626 | fz_a85d *state = fz_malloc_struct(ctx, fz_a85d); |
627 | state->chain = fz_keep_stream(ctx, chain); |
628 | state->eod = 0; |
629 | return fz_new_stream(ctx, state, next_a85d, close_a85d); |
630 | } |
631 | |
632 | /* Run Length Decode */ |
633 | |
634 | typedef struct fz_rld_s fz_rld; |
635 | |
636 | struct fz_rld_s |
637 | { |
638 | fz_stream *chain; |
639 | int run, n, c; |
640 | unsigned char buffer[256]; |
641 | }; |
642 | |
643 | static int |
644 | next_rld(fz_context *ctx, fz_stream *stm, size_t max) |
645 | { |
646 | fz_rld *state = stm->state; |
647 | unsigned char *p = state->buffer; |
648 | unsigned char *ep; |
649 | |
650 | if (state->run == 128) |
651 | return EOF; |
652 | |
653 | if (max > sizeof(state->buffer)) |
654 | max = sizeof(state->buffer); |
655 | ep = p + max; |
656 | |
657 | while (p < ep) |
658 | { |
659 | if (state->run == 128) |
660 | break; |
661 | |
662 | if (state->n == 0) |
663 | { |
664 | state->run = fz_read_byte(ctx, state->chain); |
665 | if (state->run < 0) |
666 | { |
667 | state->run = 128; |
668 | break; |
669 | } |
670 | if (state->run < 128) |
671 | state->n = state->run + 1; |
672 | if (state->run > 128) |
673 | { |
674 | state->n = 257 - state->run; |
675 | state->c = fz_read_byte(ctx, state->chain); |
676 | if (state->c < 0) |
677 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode" ); |
678 | } |
679 | } |
680 | |
681 | if (state->run < 128) |
682 | { |
683 | while (p < ep && state->n) |
684 | { |
685 | int c = fz_read_byte(ctx, state->chain); |
686 | if (c < 0) |
687 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode" ); |
688 | *p++ = c; |
689 | state->n--; |
690 | } |
691 | } |
692 | |
693 | if (state->run > 128) |
694 | { |
695 | while (p < ep && state->n) |
696 | { |
697 | *p++ = state->c; |
698 | state->n--; |
699 | } |
700 | } |
701 | } |
702 | |
703 | stm->rp = state->buffer; |
704 | stm->wp = p; |
705 | stm->pos += p - state->buffer; |
706 | |
707 | if (p == stm->rp) |
708 | return EOF; |
709 | |
710 | return *stm->rp++; |
711 | } |
712 | |
713 | static void |
714 | close_rld(fz_context *ctx, void *state_) |
715 | { |
716 | fz_rld *state = (fz_rld *)state_; |
717 | fz_drop_stream(ctx, state->chain); |
718 | fz_free(ctx, state); |
719 | } |
720 | |
721 | fz_stream * |
722 | fz_open_rld(fz_context *ctx, fz_stream *chain) |
723 | { |
724 | fz_rld *state = fz_malloc_struct(ctx, fz_rld); |
725 | state->chain = fz_keep_stream(ctx, chain); |
726 | state->run = 0; |
727 | state->n = 0; |
728 | state->c = 0; |
729 | return fz_new_stream(ctx, state, next_rld, close_rld); |
730 | } |
731 | |
732 | /* RC4 Filter */ |
733 | |
734 | typedef struct fz_arc4c_s fz_arc4c; |
735 | |
736 | struct fz_arc4c_s |
737 | { |
738 | fz_stream *chain; |
739 | fz_arc4 arc4; |
740 | unsigned char buffer[256]; |
741 | }; |
742 | |
743 | static int |
744 | next_arc4(fz_context *ctx, fz_stream *stm, size_t max) |
745 | { |
746 | fz_arc4c *state = stm->state; |
747 | size_t n = fz_available(ctx, state->chain, max); |
748 | |
749 | if (n == 0) |
750 | return EOF; |
751 | if (n > sizeof(state->buffer)) |
752 | n = sizeof(state->buffer); |
753 | |
754 | stm->rp = state->buffer; |
755 | stm->wp = state->buffer + n; |
756 | fz_arc4_encrypt(&state->arc4, stm->rp, state->chain->rp, n); |
757 | state->chain->rp += n; |
758 | stm->pos += n; |
759 | |
760 | return *stm->rp++; |
761 | } |
762 | |
763 | static void |
764 | close_arc4(fz_context *ctx, void *state_) |
765 | { |
766 | fz_arc4c *state = (fz_arc4c *)state_; |
767 | fz_drop_stream(ctx, state->chain); |
768 | fz_free(ctx, state); |
769 | } |
770 | |
771 | fz_stream * |
772 | fz_open_arc4(fz_context *ctx, fz_stream *chain, unsigned char *key, unsigned keylen) |
773 | { |
774 | fz_arc4c *state = fz_malloc_struct(ctx, fz_arc4c); |
775 | state->chain = fz_keep_stream(ctx, chain); |
776 | fz_arc4_init(&state->arc4, key, keylen); |
777 | return fz_new_stream(ctx, state, next_arc4, close_arc4); |
778 | } |
779 | |
780 | /* AES Filter */ |
781 | |
782 | typedef struct fz_aesd_s fz_aesd; |
783 | |
784 | struct fz_aesd_s |
785 | { |
786 | fz_stream *chain; |
787 | fz_aes aes; |
788 | unsigned char iv[16]; |
789 | int ivcount; |
790 | unsigned char bp[16]; |
791 | unsigned char *rp, *wp; |
792 | unsigned char buffer[256]; |
793 | }; |
794 | |
795 | static int |
796 | next_aesd(fz_context *ctx, fz_stream *stm, size_t max) |
797 | { |
798 | fz_aesd *state = stm->state; |
799 | unsigned char *p = state->buffer; |
800 | unsigned char *ep; |
801 | |
802 | if (max > sizeof(state->buffer)) |
803 | max = sizeof(state->buffer); |
804 | ep = p + max; |
805 | |
806 | while (state->ivcount < 16) |
807 | { |
808 | int c = fz_read_byte(ctx, state->chain); |
809 | if (c < 0) |
810 | fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in aes filter" ); |
811 | state->iv[state->ivcount++] = c; |
812 | } |
813 | |
814 | while (state->rp < state->wp && p < ep) |
815 | *p++ = *state->rp++; |
816 | |
817 | while (p < ep) |
818 | { |
819 | size_t n = fz_read(ctx, state->chain, state->bp, 16); |
820 | if (n == 0) |
821 | break; |
822 | else if (n < 16) |
823 | fz_throw(ctx, FZ_ERROR_GENERIC, "partial block in aes filter" ); |
824 | |
825 | fz_aes_crypt_cbc(&state->aes, FZ_AES_DECRYPT, 16, state->iv, state->bp, state->bp); |
826 | state->rp = state->bp; |
827 | state->wp = state->bp + 16; |
828 | |
829 | /* strip padding at end of file */ |
830 | if (fz_is_eof(ctx, state->chain)) |
831 | { |
832 | int pad = state->bp[15]; |
833 | if (pad < 1 || pad > 16) |
834 | fz_throw(ctx, FZ_ERROR_GENERIC, "aes padding out of range: %d" , pad); |
835 | state->wp -= pad; |
836 | } |
837 | |
838 | while (state->rp < state->wp && p < ep) |
839 | *p++ = *state->rp++; |
840 | } |
841 | |
842 | stm->rp = state->buffer; |
843 | stm->wp = p; |
844 | stm->pos += p - state->buffer; |
845 | |
846 | if (p == stm->rp) |
847 | return EOF; |
848 | |
849 | return *stm->rp++; |
850 | } |
851 | |
852 | static void |
853 | close_aesd(fz_context *ctx, void *state_) |
854 | { |
855 | fz_aesd *state = (fz_aesd *)state_; |
856 | fz_drop_stream(ctx, state->chain); |
857 | fz_free(ctx, state); |
858 | } |
859 | |
860 | fz_stream * |
861 | fz_open_aesd(fz_context *ctx, fz_stream *chain, unsigned char *key, unsigned keylen) |
862 | { |
863 | fz_aesd *state = fz_malloc_struct(ctx, fz_aesd); |
864 | if (fz_aes_setkey_dec(&state->aes, key, keylen * 8)) |
865 | { |
866 | fz_free(ctx, state); |
867 | fz_throw(ctx, FZ_ERROR_GENERIC, "AES key init failed (keylen=%d)" , keylen * 8); |
868 | } |
869 | state->ivcount = 0; |
870 | state->rp = state->bp; |
871 | state->wp = state->bp; |
872 | state->chain = fz_keep_stream(ctx, chain); |
873 | return fz_new_stream(ctx, state, next_aesd, close_aesd); |
874 | } |
875 | |