/* convenience of reusing procedures that take 1 state parameter */ static int zreadhexstring_at(i_ctx_t *i_ctx_p, os_ptr op, uint start, int odd) { stream *s; uint len, nread; byte *str; int odd_byte = odd; stream_cursor_write cw; int status; check_read_file(s, op - 1); /*check_write_type(*op, t_string); *//* done by caller */ str = op->value.bytes; len = r_size(op); cw.ptr = str + start - 1; cw.limit = str + len - 1; for (;;) { status = s_hex_process(&s->cursor.r, &cw, &odd_byte, hex_ignore_garbage); if (status == 1) { /* filled the string */ ref_assign_inline(op - 1, op); make_true(op); return 0; } else if (status != 0) /* error or EOF */ break; /* Didn't fill, keep going. */ status = spgetc(s); if (status < 0) break; sputback(s); } nread = cw.ptr + 1 - str; if (status != EOFC) { /* Error */ nread |= odd_byte << 24; return handle_read_status(i_ctx_p, status, op - 1, &nread, zreadhexstring_continue); } /* Reached end-of-file before filling the string. */ /* Return an appropriate substring. */ ref_assign_inline(op - 1, op); r_set_size(op - 1, nread); make_false(op); return 0; }
/* Process a buffer. */ static int s_exD_process(stream_state * st, stream_cursor_read * pr, stream_cursor_write * pw, bool last) { stream_exD_state *const ss = (stream_exD_state *) st; const byte *p = pr->ptr; byte *q = pw->ptr; int skip = ss->skip; int rcount = pr->limit - p; int wcount = pw->limit - q; int status = 0; int count = (wcount < rcount ? (status = 1, wcount) : rcount); if (ss->binary < 0) { /* * This is the very first time we're filling the buffer. */ const byte *const decoder = scan_char_decoder; int i; if (ss->pfb_state == 0 && !ss->keep_spaces) { /* * Skip '\t', '\r', '\n', ' ' at the beginning of the input stream, * because Adobe PS interpreters do this. Don't skip '\0' or '\f'. * Acrobat Reader doesn't skip spaces at all. */ for (; rcount; rcount--, p++) { byte c = p[1]; if(c != '\t' && c != char_CR && c != char_EOL && c != ' ') break; } pr->ptr = p; count = min(wcount, rcount); } /* * Determine whether this is ASCII or hex encoding. * Adobe's documentation doesn't actually specify the test * that eexec should use, but we believe the following * gives correct answers even on certain non-conforming * PostScript files encountered in practice: */ if (rcount < 8 && !last) return 0; ss->binary = 0; for (i = min(8, rcount); i > 0; i--) if (!(decoder[p[i]] <= 0xf || decoder[p[i]] == ctype_space) ) { ss->binary = 1; break; } } if (ss->binary) { /* * There is no need to pause at the end of the binary portion. * The padding bytes (which are in the text portion, in hexadecimal) * do their job, provided the write buffer is <= 256 bytes long. * This is (hopefully) ensured by the comment just above the * definition of s_exD_template. */ pr->ptr = p + count; } else { /* * We only ignore leading whitespace, in an attempt to * keep from reading beyond the end of the encrypted data; * but some badly coded files require us to ignore % also. */ stream_cursor_read r; const byte *start; hp: r = *pr; start = r.ptr; if (r.limit - r.ptr > ss->hex_left) r.limit = r.ptr + ss->hex_left; status = s_hex_process(&r, pw, &ss->odd, (ss->is_leading_space ? hex_ignore_leading_whitespace : hex_break_on_whitespace)); if (status == 2) { ss->is_leading_space = true; status = 1; } else ss->is_leading_space = false; pr->ptr = r.ptr; ss->hex_left -= r.ptr - start; /* * Check for having finished a prematurely decoded hex section of * a PFB file. */ if (ss->hex_left == 0) ss->binary = 1; count = pw->ptr - q; if (status < 0 && ss->odd < 0) { if (count) { --p; status = 0; /* reprocess error next time */ } else if (*p == '%') goto hp; /* ignore % */ } p = q; } if (skip >= count && skip != 0) { gs_type1_decrypt(q + 1, p + 1, count, (crypt_state *) & ss->cstate); ss->skip -= count; count = 0; status = 0; } else { gs_type1_decrypt(q + 1, p + 1, skip, (crypt_state *) & ss->cstate); count -= skip; gs_type1_decrypt(q + 1, p + 1 + skip, count, (crypt_state *) & ss->cstate); ss->skip = 0; } pw->ptr = q + count; return status; }