/src/ghostpdl/base/sbcp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2021 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* BCP and TBCP filters */ |
18 | | #include "stdio_.h" |
19 | | #include "strimpl.h" |
20 | | #include "sbcp.h" |
21 | | |
22 | 327 | #define CtrlA 0x01 |
23 | 1.33k | #define CtrlC 0x03 |
24 | 49 | #define CtrlD 0x04 |
25 | 218 | #define CtrlE 0x05 |
26 | 282 | #define CtrlQ 0x11 |
27 | 517 | #define CtrlS 0x13 |
28 | 439 | #define CtrlT 0x14 |
29 | | #define ESC 0x1b |
30 | 466 | #define CtrlBksl 0x1c |
31 | | |
32 | | /* The following is not used yet. */ |
33 | | /*static const char *TBCP_end_protocol_string = "\033%-12345X";*/ |
34 | | |
35 | | /* ------ BCPEncode and TBCPEncode ------ */ |
36 | | |
37 | | /* Process a buffer */ |
38 | | static int |
39 | | s_xBCPE_process(stream_state * st, stream_cursor_read * pr, |
40 | | stream_cursor_write * pw, bool last, const byte * escaped) |
41 | 0 | { |
42 | 0 | const byte *p = pr->ptr; |
43 | 0 | const byte *rlimit = pr->limit; |
44 | 0 | uint rcount = rlimit - p; |
45 | 0 | byte *q = pw->ptr; |
46 | 0 | uint wcount = pw->limit - q; |
47 | 0 | const byte *end = p + min(rcount, wcount); |
48 | |
|
49 | 0 | while (p < end) { |
50 | 0 | byte ch = *++p; |
51 | |
|
52 | 0 | if (ch <= 31 && escaped[ch]) { |
53 | 0 | if (p == rlimit) { |
54 | 0 | p--; |
55 | 0 | break; |
56 | 0 | } |
57 | 0 | *++q = CtrlA; |
58 | 0 | ch ^= 0x40; |
59 | 0 | if (--wcount < rcount) |
60 | 0 | end--; |
61 | 0 | } |
62 | 0 | *++q = ch; |
63 | 0 | } |
64 | 0 | pr->ptr = p; |
65 | 0 | pw->ptr = q; |
66 | 0 | return (p == rlimit ? 0 : 1); |
67 | 0 | } |
68 | | |
69 | | /* Actual process procedures */ |
70 | | static int |
71 | | s_BCPE_process(stream_state * st, stream_cursor_read * pr, |
72 | | stream_cursor_write * pw, bool last) |
73 | 0 | { |
74 | 0 | static const byte escaped[32] = |
75 | 0 | { |
76 | 0 | 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
77 | 0 | 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 |
78 | 0 | }; |
79 | |
|
80 | 0 | return s_xBCPE_process(st, pr, pw, last, escaped); |
81 | 0 | } |
82 | | static int |
83 | | s_TBCPE_process(stream_state * st, stream_cursor_read * pr, |
84 | | stream_cursor_write * pw, bool last) |
85 | 0 | { |
86 | 0 | static const byte escaped[32] = |
87 | 0 | { |
88 | 0 | 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
89 | 0 | 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 |
90 | 0 | }; |
91 | |
|
92 | 0 | return s_xBCPE_process(st, pr, pw, last, escaped); |
93 | 0 | } |
94 | | |
95 | | /* Stream templates */ |
96 | | const stream_template s_BCPE_template = |
97 | | {&st_stream_state, NULL, s_BCPE_process, 1, 2 |
98 | | }; |
99 | | const stream_template s_TBCPE_template = |
100 | | {&st_stream_state, NULL, s_TBCPE_process, 1, 2 |
101 | | }; |
102 | | |
103 | | /* ------ BCPDecode and TBCPDecode ------ */ |
104 | | |
105 | | private_st_BCPD_state(); |
106 | | |
107 | | /* Initialize the state */ |
108 | | static int |
109 | | s_BCPD_init(stream_state * st) |
110 | 290 | { |
111 | 290 | stream_BCPD_state *const ss = (stream_BCPD_state *) st; |
112 | | |
113 | 290 | ss->escaped = 0; |
114 | 290 | ss->matched = ss->copy_count = 0; |
115 | 290 | return 0; |
116 | 290 | } |
117 | | |
118 | | /* Process a buffer */ |
119 | | static int |
120 | | s_xBCPD_process(stream_state * st, stream_cursor_read * pr, |
121 | | stream_cursor_write * pw, bool last, bool tagged) |
122 | 1.38k | { |
123 | 1.38k | stream_BCPD_state *const ss = (stream_BCPD_state *) st; |
124 | 1.38k | const byte *p = pr->ptr; |
125 | 1.38k | const byte *rlimit = pr->limit; |
126 | 1.38k | byte *q = pw->ptr; |
127 | 1.38k | byte *wlimit = pw->limit; |
128 | 1.38k | int copy_count = ss->copy_count; |
129 | 1.38k | int status; |
130 | 1.38k | bool escaped = ss->escaped; |
131 | | |
132 | 762k | for (;;) { |
133 | 762k | byte ch; |
134 | | |
135 | 762k | if (copy_count) { |
136 | 0 | if (q == wlimit) { |
137 | 0 | status = (p < rlimit ? 1 : 0); |
138 | 0 | break; |
139 | 0 | } |
140 | 0 | *++q = *++(ss->copy_ptr); |
141 | 0 | copy_count--; |
142 | 0 | continue; |
143 | 0 | } |
144 | 762k | if (p == rlimit) { |
145 | 983 | status = 0; |
146 | 983 | break; |
147 | 983 | } |
148 | 761k | ch = *++p; |
149 | 761k | if (ch <= 31) |
150 | 22.9k | switch (ch) { |
151 | 327 | case CtrlA: |
152 | 327 | if (escaped) { |
153 | 11 | status = ERRC; |
154 | 11 | goto out; |
155 | 11 | } |
156 | 316 | escaped = true; |
157 | 316 | continue; |
158 | 1.33k | case CtrlC: |
159 | 1.33k | status = (*ss->signal_interrupt) (st); |
160 | 1.33k | if (status < 0) |
161 | 0 | goto out; |
162 | 1.33k | continue; |
163 | 1.33k | case CtrlD: |
164 | 49 | if (escaped) { |
165 | 3 | status = ERRC; |
166 | 3 | goto out; |
167 | 3 | } |
168 | 46 | status = EOFC; |
169 | 46 | goto out; |
170 | 218 | case CtrlE: |
171 | 218 | continue; |
172 | 282 | case CtrlQ: |
173 | 282 | continue; |
174 | 517 | case CtrlS: |
175 | 517 | continue; |
176 | 439 | case CtrlT: |
177 | 439 | status = (*ss->request_status) (st); |
178 | 439 | if (status < 0) |
179 | 0 | goto out; |
180 | 439 | continue; |
181 | 466 | case CtrlBksl: |
182 | 466 | continue; |
183 | 22.9k | } |
184 | 757k | if (q == wlimit) { |
185 | 266 | p--; |
186 | 266 | status = 1; |
187 | 266 | break; |
188 | 266 | } |
189 | 757k | if (escaped) { |
190 | 296 | escaped = false; |
191 | 296 | switch (ch) { |
192 | 41 | case '[': |
193 | 41 | if (!tagged) { |
194 | 0 | status = ERRC; |
195 | 0 | goto out; |
196 | 0 | } |
197 | | /* falls through */ |
198 | 45 | case 'A': |
199 | 46 | case 'C': |
200 | 46 | case 'D': |
201 | 46 | case 'E': |
202 | 46 | case 'Q': |
203 | 46 | case 'S': |
204 | 46 | case 'T': |
205 | 60 | case '\\': |
206 | 60 | ch ^= 0x40; |
207 | 60 | break; |
208 | 162 | case 'M': |
209 | 162 | if (!tagged) { |
210 | 0 | status = ERRC; |
211 | 0 | goto out; |
212 | 0 | } |
213 | 162 | continue; |
214 | 162 | default: |
215 | 74 | status = ERRC; |
216 | 74 | goto out; |
217 | 296 | } |
218 | 296 | } |
219 | 757k | *++q = ch; |
220 | 757k | } |
221 | 1.38k | out:ss->copy_count = copy_count; |
222 | 1.38k | ss->escaped = escaped; |
223 | 1.38k | pr->ptr = p; |
224 | 1.38k | pw->ptr = q; |
225 | 1.38k | return status; |
226 | 1.38k | } |
227 | | |
228 | | /* Actual process procedures */ |
229 | | static int |
230 | | s_BCPD_process(stream_state * st, stream_cursor_read * pr, |
231 | | stream_cursor_write * pw, bool last) |
232 | 0 | { |
233 | 0 | return s_xBCPD_process(st, pr, pw, last, false); |
234 | 0 | } |
235 | | static int |
236 | | s_TBCPD_process(stream_state * st, stream_cursor_read * pr, |
237 | | stream_cursor_write * pw, bool last) |
238 | 1.38k | { |
239 | 1.38k | return s_xBCPD_process(st, pr, pw, last, true); |
240 | 1.38k | } |
241 | | |
242 | | /* Stream templates */ |
243 | | const stream_template s_BCPD_template = |
244 | | {&st_BCPD_state, s_BCPD_init, s_BCPD_process, 1, 1, |
245 | | NULL, NULL, s_BCPD_init |
246 | | }; |
247 | | const stream_template s_TBCPD_template = |
248 | | {&st_BCPD_state, s_BCPD_init, s_TBCPD_process, 1, 1, |
249 | | NULL, NULL, s_BCPD_init |
250 | | }; |