diff options
Diffstat (limited to 'source/fitz/filter-basic.c')
-rw-r--r-- | source/fitz/filter-basic.c | 268 |
1 files changed, 165 insertions, 103 deletions
diff --git a/source/fitz/filter-basic.c b/source/fitz/filter-basic.c index 3a64ee93..5defe066 100644 --- a/source/fitz/filter-basic.c +++ b/source/fitz/filter-basic.c @@ -14,21 +14,34 @@ struct null_filter { fz_stream *chain; int remain; - int pos; + int offset; + unsigned char buffer[4096]; }; static int -read_null(fz_stream *stm, unsigned char *buf, int len) +next_null(fz_stream *stm, int max) { struct null_filter *state = stm->state; - int amount = fz_mini(len, state->remain); int n; - fz_seek(state->chain, state->pos, 0); - n = fz_read(state->chain, buf, amount); + if (state->remain == 0) + return EOF; + fz_seek(state->chain, state->offset, 0); + n = fz_available(state->chain, max); + if (n > state->remain) + n = state->remain; + if (n > sizeof(state->buffer)) + n = sizeof(state->buffer); + memcpy(state->buffer, state->chain->rp, n); + stm->rp = state->buffer; + stm->wp = stm->rp + n; + if (n == 0) + return EOF; + state->chain->rp += n; state->remain -= n; - state->pos += n; - return n; + state->offset += n; + stm->pos += n; + return *stm->rp++; } static void @@ -60,7 +73,7 @@ fz_open_null(fz_stream *chain, int len, int offset) state = fz_malloc_struct(ctx, struct null_filter); state->chain = chain; state->remain = len; - state->pos = offset; + state->offset = offset; } fz_catch(ctx) { @@ -68,7 +81,7 @@ fz_open_null(fz_stream *chain, int len, int offset) fz_rethrow(ctx); } - return fz_new_stream(ctx, state, read_null, close_null, rebind_null); + return fz_new_stream(ctx, state, next_null, close_null, rebind_null); } /* Concat filter concatenates several streams into one */ @@ -79,48 +92,51 @@ struct concat_filter int count; int current; int pad; /* 1 if we should add whitespace padding between streams */ - int ws; /* 1 if we should send a whitespace padding byte next */ + unsigned char ws_buf; fz_stream *chain[1]; }; static int -read_concat(fz_stream *stm, unsigned char *buf, int len) +next_concat(fz_stream *stm, int max) { struct concat_filter *state = (struct concat_filter *)stm->state; int n; - int read = 0; - if (len <= 0) - return 0; - - while (state->current != state->count && len > 0) + while (state->current < state->count) { - /* If we need to send a whitespace char, do that */ - if (state->ws) + /* Read the next block of underlying data. */ + if (stm->wp == state->chain[state->current]->wp) + state->chain[state->current]->rp = stm->wp; + n = fz_available(state->chain[state->current], max); + if (n) { - *buf++ = 32; - read++; - len--; - state->ws = 0; - continue; + stm->rp = state->chain[state->current]->rp; + stm->wp = state->chain[state->current]->wp; + stm->pos += n; + return *stm->rp++; } - /* Otherwise, read as much data as will fit in the buffer */ - n = fz_read(state->chain[state->current], buf, len); - read += n; - buf += n; - len -= n; - /* If we didn't read any, then we must have hit the end of - * our buffer space. Move to the next stream, and remember to - * pad. */ - if (n == 0) + else { - fz_close(state->chain[state->current]); + if (state->chain[state->current]->error) + { + stm->error = 1; + break; + } state->current++; - state->ws = state->pad; + fz_close(state->chain[state->current-1]); + if (state->pad) + { + stm->rp = &state->ws_buf; + stm->wp = stm->rp + 1; + stm->pos++; + return 32; + } } } - return read; + stm->rp = stm->wp; + + return EOF; } static void @@ -161,9 +177,9 @@ fz_open_concat(fz_context *ctx, int len, int pad) state->count = 0; state->current = 0; state->pad = pad; - state->ws = 0; /* We never send padding byte at the start */ + state->ws_buf = 32; - return fz_new_stream(ctx, state, read_concat, close_concat, rebind_concat); + return fz_new_stream(ctx, state, next_concat, close_concat, rebind_concat); } void @@ -185,6 +201,7 @@ struct fz_ahxd_s { fz_stream *chain; int eod; + unsigned char buffer[256]; }; static inline int iswhite(int a) @@ -213,23 +230,27 @@ static inline int unhex(int a) } static int -read_ahxd(fz_stream *stm, unsigned char *buf, int len) +next_ahxd(fz_stream *stm, int max) { fz_ahxd *state = stm->state; - unsigned char *p = buf; - unsigned char *ep = buf + len; + unsigned char *p = state->buffer; + unsigned char *ep; int a, b, c, odd; + if (max > sizeof(state->buffer)) + max = sizeof(state->buffer); + ep = p + max; + odd = 0; while (p < ep) { if (state->eod) - return p - buf; + break; c = fz_read_byte(state->chain); if (c < 0) - return p - buf; + break; if (ishex(c)) { @@ -250,14 +271,20 @@ read_ahxd(fz_stream *stm, unsigned char *buf, int len) if (odd) *p++ = (a << 4); state->eod = 1; + break; } else if (!iswhite(c)) { fz_throw(stm->ctx, FZ_ERROR_GENERIC, "bad data in ahxd: '%c'", c); } } + stm->rp = state->buffer; + stm->wp = p; + stm->pos += p - state->buffer; - return p - buf; + if (stm->rp != p) + return *stm->rp++; + return EOF; } static void @@ -294,7 +321,7 @@ fz_open_ahxd(fz_stream *chain) fz_rethrow(ctx); } - return fz_new_stream(ctx, state, read_ahxd, close_ahxd, rebind_ahxd); + return fz_new_stream(ctx, state, next_ahxd, close_ahxd, rebind_ahxd); } /* ASCII 85 Decode */ @@ -304,32 +331,32 @@ typedef struct fz_a85d_s fz_a85d; struct fz_a85d_s { fz_stream *chain; - unsigned char bp[4]; - unsigned char *rp, *wp; + unsigned char buffer[256]; int eod; }; static int -read_a85d(fz_stream *stm, unsigned char *buf, int len) +next_a85d(fz_stream *stm, int max) { fz_a85d *state = stm->state; - unsigned char *p = buf; - unsigned char *ep = buf + len; + unsigned char *p = state->buffer; + unsigned char *ep; int count = 0; int word = 0; int c; - while (state->rp < state->wp && p < ep) - *p++ = *state->rp++; + if (state->eod) + return EOF; + + if (max > sizeof(state->buffer)) + max = sizeof(state->buffer); + ep = p + max; while (p < ep) { - if (state->eod) - return p - buf; - c = fz_read_byte(state->chain); if (c < 0) - return p - buf; + break; if (c >= '!' && c <= 'u') { @@ -337,12 +364,10 @@ read_a85d(fz_stream *stm, unsigned char *buf, int len) { word = word * 85 + (c - '!'); - state->bp[0] = (word >> 24) & 0xff; - state->bp[1] = (word >> 16) & 0xff; - state->bp[2] = (word >> 8) & 0xff; - state->bp[3] = (word) & 0xff; - state->rp = state->bp; - state->wp = state->bp + 4; + *p++ = (word >> 24) & 0xff; + *p++ = (word >> 16) & 0xff; + *p++ = (word >> 8) & 0xff; + *p++ = (word) & 0xff; word = 0; count = 0; @@ -356,12 +381,10 @@ read_a85d(fz_stream *stm, unsigned char *buf, int len) else if (c == 'z' && count == 0) { - state->bp[0] = 0; - state->bp[1] = 0; - state->bp[2] = 0; - state->bp[3] = 0; - state->rp = state->bp; - state->wp = state->bp + 4; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 0; } else if (c == '~') @@ -381,39 +404,38 @@ read_a85d(fz_stream *stm, unsigned char *buf, int len) break; case 2: word = word * (85 * 85 * 85) + 0xffffff; - state->bp[0] = word >> 24; - state->rp = state->bp; - state->wp = state->bp + 1; + *p++ = word >> 24; break; case 3: word = word * (85 * 85) + 0xffff; - state->bp[0] = word >> 24; - state->bp[1] = word >> 16; - state->rp = state->bp; - state->wp = state->bp + 2; + *p++ = word >> 24; + *p++ = word >> 16; break; case 4: word = word * 85 + 0xff; - state->bp[0] = word >> 24; - state->bp[1] = word >> 16; - state->bp[2] = word >> 8; - state->rp = state->bp; - state->wp = state->bp + 3; + *p++ = word >> 24; + *p++ = word >> 16; + *p++ = word >> 8; break; } state->eod = 1; + break; } else if (!iswhite(c)) { fz_throw(stm->ctx, FZ_ERROR_GENERIC, "bad data in a85d: '%c'", c); } - - while (state->rp < state->wp && p < ep) - *p++ = *state->rp++; } - return p - buf; + stm->rp = state->buffer; + stm->wp = p; + stm->pos += p - state->buffer; + + if (p == stm->rp) + return EOF; + + return *stm->rp++; } static void @@ -443,8 +465,6 @@ fz_open_a85d(fz_stream *chain) { state = fz_malloc_struct(ctx, fz_a85d); state->chain = chain; - state->rp = state->bp; - state->wp = state->bp; state->eod = 0; } fz_catch(ctx) @@ -453,7 +473,7 @@ fz_open_a85d(fz_stream *chain) fz_rethrow(ctx); } - return fz_new_stream(ctx, state, read_a85d, close_a85d, rebind_a85d); + return fz_new_stream(ctx, state, next_a85d, close_a85d, rebind_a85d); } /* Run Length Decode */ @@ -464,25 +484,36 @@ struct fz_rld_s { fz_stream *chain; int run, n, c; + unsigned char buffer[256]; }; static int -read_rld(fz_stream *stm, unsigned char *buf, int len) +next_rld(fz_stream *stm, int max) { fz_rld *state = stm->state; - unsigned char *p = buf; - unsigned char *ep = buf + len; + unsigned char *p = state->buffer; + unsigned char *ep; + + if (state->run == 128) + return EOF; + + if (max > sizeof(state->buffer)) + max = sizeof(state->buffer); + ep = p + max; while (p < ep) { if (state->run == 128) - return p - buf; + break; if (state->n == 0) { state->run = fz_read_byte(state->chain); if (state->run < 0) + { state->run = 128; + break; + } if (state->run < 128) state->n = state->run + 1; if (state->run > 128) @@ -516,7 +547,14 @@ read_rld(fz_stream *stm, unsigned char *buf, int len) } } - return p - buf; + stm->rp = state->buffer; + stm->wp = p; + stm->pos += p - state->buffer; + + if (p == stm->rp) + return EOF; + + return *stm->rp++; } static void @@ -556,7 +594,7 @@ fz_open_rld(fz_stream *chain) fz_rethrow(ctx); } - return fz_new_stream(ctx, state, read_rld, close_rld, rebind_rld); + return fz_new_stream(ctx, state, next_rld, close_rld, rebind_rld); } /* RC4 Filter */ @@ -567,15 +605,27 @@ struct fz_arc4c_s { fz_stream *chain; fz_arc4 arc4; + unsigned char buffer[256]; }; static int -read_arc4(fz_stream *stm, unsigned char *buf, int len) +next_arc4(fz_stream *stm, int max) { fz_arc4c *state = stm->state; - int n = fz_read(state->chain, buf, len); - fz_arc4_encrypt(&state->arc4, buf, buf, n); - return n; + int n = fz_available(state->chain, max); + + if (n == 0) + return EOF; + if (n > sizeof(state->buffer)) + n = sizeof(state->buffer); + + stm->rp = state->buffer; + stm->wp = state->buffer + n; + fz_arc4_encrypt(&state->arc4, stm->rp, state->chain->rp, n); + state->chain->rp += n; + stm->pos += n; + + return *stm->rp++; } static void @@ -613,7 +663,7 @@ fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen) fz_rethrow(ctx); } - return fz_new_stream(ctx, state, read_arc4, close_arc4, rebind_arc4c); + return fz_new_stream(ctx, state, next_arc4, close_arc4, rebind_arc4c); } /* AES Filter */ @@ -628,14 +678,19 @@ struct fz_aesd_s int ivcount; unsigned char bp[16]; unsigned char *rp, *wp; + unsigned char buffer[256]; }; static int -read_aesd(fz_stream *stm, unsigned char *buf, int len) +next_aesd(fz_stream *stm, int max) { fz_aesd *state = stm->state; - unsigned char *p = buf; - unsigned char *ep = buf + len; + unsigned char *p = state->buffer; + unsigned char *ep; + + if (max > sizeof(state->buffer)) + max = sizeof(state->buffer); + ep = p + max; while (state->ivcount < 16) { @@ -652,7 +707,7 @@ read_aesd(fz_stream *stm, unsigned char *buf, int len) { int n = fz_read(state->chain, state->bp, 16); if (n == 0) - return p - buf; + break; else if (n < 16) fz_throw(stm->ctx, FZ_ERROR_GENERIC, "partial block in aes filter"); @@ -673,7 +728,14 @@ read_aesd(fz_stream *stm, unsigned char *buf, int len) *p++ = *state->rp++; } - return p - buf; + stm->rp = state->buffer; + stm->wp = p; + stm->pos += p - state->buffer; + + if (p == stm->rp) + return EOF; + + return *stm->rp++; } static void @@ -718,5 +780,5 @@ fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen) fz_rethrow(ctx); } - return fz_new_stream(ctx, state, read_aesd, close_aesd, rebind_aesd); + return fz_new_stream(ctx, state, next_aesd, close_aesd, rebind_aesd); } |