xref: /plan9/sys/src/cmd/gs/src/seexec.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1994, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: seexec.c,v 1.8 2002/09/02 22:09:15 ray Exp $ */
18 /* eexec filters */
19 #include "stdio_.h"		/* includes std.h */
20 #include "strimpl.h"
21 #include "sfilter.h"
22 #include "gscrypt1.h"
23 #include "scanchar.h"
24 
25 /* ------ eexecEncode ------ */
26 
27 /* Encoding is much simpler than decoding, because we don't */
28 /* worry about initial characters or hex vs. binary (the client */
29 /* has to take care of these aspects). */
30 
31 private_st_exE_state();
32 
33 /* Process a buffer */
34 private int
s_exE_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)35 s_exE_process(stream_state * st, stream_cursor_read * pr,
36 	      stream_cursor_write * pw, bool last)
37 {
38     stream_exE_state *const ss = (stream_exE_state *) st;
39     const byte *p = pr->ptr;
40     byte *q = pw->ptr;
41     uint rcount = pr->limit - p;
42     uint wcount = pw->limit - q;
43     uint count;
44     int status;
45 
46     if (rcount <= wcount)
47 	count = rcount, status = 0;
48     else
49 	count = wcount, status = 1;
50     gs_type1_encrypt(q + 1, p + 1, count, (crypt_state *)&ss->cstate);
51     pr->ptr += count;
52     pw->ptr += count;
53     return status;
54 }
55 
56 /* Stream template */
57 const stream_template s_exE_template = {
58     &st_exE_state, NULL, s_exE_process, 1, 2
59 };
60 
61 /* ------ eexecDecode ------ */
62 
63 private_st_exD_state();
64 
65 /* Set defaults. */
66 private void
s_exD_set_defaults(stream_state * st)67 s_exD_set_defaults(stream_state * st)
68 {
69     stream_exD_state *const ss = (stream_exD_state *) st;
70 
71     ss->binary = -1;		/* unknown */
72     ss->lenIV = 4;
73     ss->record_left = max_long;
74     ss->hex_left = max_long;
75     /* Clear pointers for GC */
76     ss->pfb_state = 0;
77 }
78 
79 /* Initialize the state for reading and decrypting. */
80 /* Decrypting streams are not positionable. */
81 private int
s_exD_init(stream_state * st)82 s_exD_init(stream_state * st)
83 {
84     stream_exD_state *const ss = (stream_exD_state *) st;
85 
86     ss->odd = -1;
87     ss->skip = ss->lenIV;
88     return 0;
89 }
90 
91 /* Process a buffer. */
92 private int
s_exD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)93 s_exD_process(stream_state * st, stream_cursor_read * pr,
94 	      stream_cursor_write * pw, bool last)
95 {
96     stream_exD_state *const ss = (stream_exD_state *) st;
97     const byte *p = pr->ptr;
98     byte *q = pw->ptr;
99     int skip = ss->skip;
100     int rcount = pr->limit - p;
101     int wcount = pw->limit - q;
102     int status = 0;
103     int count = (wcount < rcount ? (status = 1, wcount) : rcount);
104 
105     if (ss->binary < 0) {
106 	/*
107 	 * This is the very first time we're filling the buffer.
108 	 */
109 	const byte *const decoder = scan_char_decoder;
110 	int i;
111 
112         if (ss->pfb_state == 0) {
113 	    /*
114 	     * Skip '\t', '\r', '\n', ' ' at the beginning of the input stream,
115 	     * because Adobe interpreters do this. Don't skip '\0' or '\f'.
116 	     */
117 	    for (; rcount; rcount--, p++) {
118 		byte c = p[1];
119 		if(c != '\t' && c != char_CR && c != char_EOL && c != ' ')
120 		    break;
121 	    }
122 	    pr->ptr = p;
123 	    count = min(wcount, rcount);
124 	}
125 
126 	/*
127 	 * Determine whether this is ASCII or hex encoding.
128 	 * Adobe's documentation doesn't actually specify the test
129 	 * that eexec should use, but we believe the following
130 	 * gives correct answers even on certain non-conforming
131 	 * PostScript files encountered in practice:
132 	 */
133         if (rcount < 8 && !last)
134             return 0;
135 
136 	ss->binary = 0;
137 	for (i = min(8, rcount); i > 0; i--)
138 	    if (!(decoder[p[i]] <= 0xf ||
139 		  decoder[p[i]] == ctype_space)
140 		) {
141 		ss->binary = 1;
142 		if (ss->pfb_state != 0) {
143 		    /* Stop at the end of the .PFB binary data. */
144 		    ss->record_left = ss->pfb_state->record_left;
145 		}
146 		break;
147 	    }
148     }
149     if (ss->binary) {
150 	if (count > ss->record_left) {
151 	    count = ss->record_left;
152 	    status = 0;
153 	}
154 	/*
155 	 * We pause at the end of the .PFB binary data,
156 	 * in an attempt to keep from reading beyond the end of
157 	 * the encrypted data.
158 	 */
159 	if ((ss->record_left -= count) == 0)
160 	    ss->record_left = max_long;
161 	pr->ptr = p + count;
162     } else {
163 	/*
164 	 * We only ignore leading whitespace, in an attempt to
165 	 * keep from reading beyond the end of the encrypted data;
166 	 * but some badly coded files require us to ignore % also.
167 	 */
168 	stream_cursor_read r;
169 	const byte *start;
170 
171 hp:	r = *pr;
172 	start = r.ptr;
173 	if (r.limit - r.ptr > ss->hex_left)
174 	    r.limit = r.ptr + ss->hex_left;
175 	status = s_hex_process(&r, pw, &ss->odd,
176 			       hex_ignore_leading_whitespace);
177 	pr->ptr = r.ptr;
178 	ss->hex_left -= r.ptr - start;
179 	/*
180 	 * Check for having finished a prematurely decoded hex section of
181 	 * a PFB file.
182 	 */
183 	if (ss->hex_left == 0)
184 	    ss->binary = 1;
185 	count = pw->ptr - q;
186 	if (status < 0 && ss->odd < 0) {
187 	    if (count) {
188 		--p;
189 		status = 0;	/* reprocess error next time */
190 	    } else if (*p == '%')
191 		goto hp;	/* ignore % */
192 	}
193 	p = q;
194     }
195     if (skip >= count && skip != 0) {
196 	gs_type1_decrypt(q + 1, p + 1, count,
197 			 (crypt_state *) & ss->cstate);
198 	ss->skip -= count;
199 	count = 0;
200 	status = 0;
201     } else {
202 	gs_type1_decrypt(q + 1, p + 1, skip,
203 			 (crypt_state *) & ss->cstate);
204 	count -= skip;
205 	gs_type1_decrypt(q + 1, p + 1 + skip, count,
206 			 (crypt_state *) & ss->cstate);
207 	ss->skip = 0;
208     }
209     pw->ptr = q + count;
210     return status;
211 }
212 
213 /* Stream template */
214 /*
215  * The specification of eexec decoding requires that it never read more than
216  * 512 source bytes ahead.  The only reliable way to ensure this is to
217  * limit the size of the output buffer to 256.  We set it a little smaller
218  * so that it will stay under the limit even after adding min_in_size
219  * for a subsequent filter in a pipeline.  Note that we have to specify
220  * a size of at least 128 so that filter_read won't round it up.
221  */
222 const stream_template s_exD_template = {
223     &st_exD_state, s_exD_init, s_exD_process, 8, 200,
224     NULL, s_exD_set_defaults
225 };
226