1 /* Copyright (C) 1993, 2000 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: sbcp.c,v 1.5 2002/02/21 22:24:53 giles Exp $ */
18 /* BCP and TBCP filters */
19 #include "stdio_.h"
20 #include "strimpl.h"
21 #include "sbcp.h"
22
23 #define CtrlA 0x01
24 #define CtrlC 0x03
25 #define CtrlD 0x04
26 #define CtrlE 0x05
27 #define CtrlQ 0x11
28 #define CtrlS 0x13
29 #define CtrlT 0x14
30 #define ESC 0x1b
31 #define CtrlBksl 0x1c
32
33 /* The following is not used yet. */
34 /*private const char *TBCP_end_protocol_string = "\033%-12345X"; */
35
36 /* ------ BCPEncode and TBCPEncode ------ */
37
38 /* Process a buffer */
39 private int
s_xBCPE_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last,const byte * escaped)40 s_xBCPE_process(stream_state * st, stream_cursor_read * pr,
41 stream_cursor_write * pw, bool last, const byte * escaped)
42 {
43 const byte *p = pr->ptr;
44 const byte *rlimit = pr->limit;
45 uint rcount = rlimit - p;
46 byte *q = pw->ptr;
47 uint wcount = pw->limit - q;
48 const byte *end = p + min(rcount, wcount);
49
50 while (p < end) {
51 byte ch = *++p;
52
53 if (ch <= 31 && escaped[ch]) {
54 if (p == rlimit) {
55 p--;
56 break;
57 }
58 *++q = CtrlA;
59 ch ^= 0x40;
60 if (--wcount < rcount)
61 end--;
62 }
63 *++q = ch;
64 }
65 pr->ptr = p;
66 pw->ptr = q;
67 return (p == rlimit ? 0 : 1);
68 }
69
70 /* Actual process procedures */
71 private int
s_BCPE_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)72 s_BCPE_process(stream_state * st, stream_cursor_read * pr,
73 stream_cursor_write * pw, bool last)
74 {
75 static const byte escaped[32] =
76 {
77 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
79 };
80
81 return s_xBCPE_process(st, pr, pw, last, escaped);
82 }
83 private int
s_TBCPE_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)84 s_TBCPE_process(stream_state * st, stream_cursor_read * pr,
85 stream_cursor_write * pw, bool last)
86 {
87 static const byte escaped[32] =
88 {
89 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0
91 };
92
93 return s_xBCPE_process(st, pr, pw, last, escaped);
94 }
95
96 /* Stream templates */
97 const stream_template s_BCPE_template =
98 {&st_stream_state, NULL, s_BCPE_process, 1, 2
99 };
100 const stream_template s_TBCPE_template =
101 {&st_stream_state, NULL, s_TBCPE_process, 1, 2
102 };
103
104 /* ------ BCPDecode and TBCPDecode ------ */
105
106 private_st_BCPD_state();
107
108 /* Initialize the state */
109 private int
s_BCPD_init(stream_state * st)110 s_BCPD_init(stream_state * st)
111 {
112 stream_BCPD_state *const ss = (stream_BCPD_state *) st;
113
114 ss->escaped = 0;
115 ss->matched = ss->copy_count = 0;
116 return 0;
117 }
118
119 /* Process a buffer */
120 private int
s_xBCPD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last,bool tagged)121 s_xBCPD_process(stream_state * st, stream_cursor_read * pr,
122 stream_cursor_write * pw, bool last, bool tagged)
123 {
124 stream_BCPD_state *const ss = (stream_BCPD_state *) st;
125 const byte *p = pr->ptr;
126 const byte *rlimit = pr->limit;
127 byte *q = pw->ptr;
128 byte *wlimit = pw->limit;
129 int copy_count = ss->copy_count;
130 int status;
131 bool escaped = ss->escaped;
132
133 for (;;) {
134 byte ch;
135
136 if (copy_count) {
137 if (q == wlimit) {
138 status = (p < rlimit ? 1 : 0);
139 break;
140 }
141 *++q = *++(ss->copy_ptr);
142 copy_count--;
143 continue;
144 }
145 if (p == rlimit) {
146 status = 0;
147 break;
148 }
149 ch = *++p;
150 if (ch <= 31)
151 switch (ch) {
152 case CtrlA:
153 if (escaped) {
154 status = ERRC;
155 goto out;
156 }
157 escaped = true;
158 continue;
159 case CtrlC:
160 status = (*ss->signal_interrupt) (st);
161 if (status < 0)
162 goto out;
163 continue;
164 case CtrlD:
165 if (escaped) {
166 status = ERRC;
167 goto out;
168 }
169 status = EOFC;
170 goto out;
171 case CtrlE:
172 continue;
173 case CtrlQ:
174 continue;
175 case CtrlS:
176 continue;
177 case CtrlT:
178 status = (*ss->request_status) (st);
179 if (status < 0)
180 goto out;
181 continue;
182 case CtrlBksl:
183 continue;
184 }
185 if (q == wlimit) {
186 p--;
187 status = 1;
188 break;
189 }
190 if (escaped) {
191 escaped = false;
192 switch (ch) {
193 case '[':
194 if (!tagged) {
195 status = ERRC;
196 goto out;
197 }
198 /* falls through */
199 case 'A':
200 case 'C':
201 case 'D':
202 case 'E':
203 case 'Q':
204 case 'S':
205 case 'T':
206 case '\\':
207 ch ^= 0x40;
208 break;
209 case 'M':
210 if (!tagged) {
211 status = ERRC;
212 goto out;
213 }
214 continue;
215 default:
216 status = ERRC;
217 goto out;
218 }
219 }
220 *++q = ch;
221 }
222 out:ss->copy_count = copy_count;
223 ss->escaped = escaped;
224 pr->ptr = p;
225 pw->ptr = q;
226 return status;
227 }
228
229 /* Actual process procedures */
230 private int
s_BCPD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)231 s_BCPD_process(stream_state * st, stream_cursor_read * pr,
232 stream_cursor_write * pw, bool last)
233 {
234 return s_xBCPD_process(st, pr, pw, last, false);
235 }
236 private int
s_TBCPD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)237 s_TBCPD_process(stream_state * st, stream_cursor_read * pr,
238 stream_cursor_write * pw, bool last)
239 {
240 return s_xBCPD_process(st, pr, pw, last, true);
241 }
242
243 /* Stream templates */
244 const stream_template s_BCPD_template =
245 {&st_BCPD_state, s_BCPD_init, s_BCPD_process, 1, 1,
246 NULL, NULL, s_BCPD_init
247 };
248 const stream_template s_TBCPD_template =
249 {&st_BCPD_state, s_BCPD_init, s_TBCPD_process, 1, 1,
250 NULL, NULL, s_BCPD_init
251 };
252