Branch data Line data Source code
1 : : /* $NetBSD: vis.c,v 1.37 2008/07/25 22:29:23 dsl Exp $ */
2 : :
3 : : /*-
4 : : * Copyright (c) 1989, 1993
5 : : * The Regents of the University of California. All rights reserved.
6 : : *
7 : : * Redistribution and use in source and binary forms, with or without
8 : : * modification, are permitted provided that the following conditions
9 : : * are met:
10 : : * 1. Redistributions of source code must retain the above copyright
11 : : * notice, this list of conditions and the following disclaimer.
12 : : * 2. Redistributions in binary form must reproduce the above copyright
13 : : * notice, this list of conditions and the following disclaimer in the
14 : : * documentation and/or other materials provided with the distribution.
15 : : * 3. Neither the name of the University nor the names of its contributors
16 : : * may be used to endorse or promote products derived from this software
17 : : * without specific prior written permission.
18 : : *
19 : : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 : : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 : : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 : : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 : : * SUCH DAMAGE.
30 : : */
31 : :
32 : : /*-
33 : : * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
34 : : * All rights reserved.
35 : : *
36 : : * Redistribution and use in source and binary forms, with or without
37 : : * modification, are permitted provided that the following conditions
38 : : * are met:
39 : : * 1. Redistributions of source code must retain the above copyright
40 : : * notice, this list of conditions and the following disclaimer.
41 : : * 2. Redistributions in binary form must reproduce the above copyright
42 : : * notice, this list of conditions and the following disclaimer in the
43 : : * documentation and/or other materials provided with the distribution.
44 : : *
45 : : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
46 : : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
47 : : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
49 : : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50 : : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51 : : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52 : : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53 : : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55 : : * POSSIBILITY OF SUCH DAMAGE.
56 : : */
57 : :
58 : : #if 1
59 : : #include <config.h>
60 : : #include "roken.h"
61 : : #ifndef _DIAGASSERT
62 : : #define _DIAGASSERT(X)
63 : : #endif
64 : : #else /* heimdal */
65 : : #include <sys/cdefs.h>
66 : : #if defined(LIBC_SCCS) && !defined(lint)
67 : : __RCSID("$NetBSD: vis.c,v 1.37 2008/07/25 22:29:23 dsl Exp $");
68 : : #endif /* LIBC_SCCS and not lint */
69 : :
70 : : #include "namespace.h"
71 : : #endif /* heimdal */
72 : :
73 : : #include <sys/types.h>
74 : :
75 : : #include <assert.h>
76 : : #include <ctype.h>
77 : : #include <limits.h>
78 : : #include <stdio.h>
79 : : #include <string.h>
80 : : #include <vis.h>
81 : : #include <stdlib.h>
82 : :
83 : : #if 0
84 : : #ifdef __weak_alias
85 : : __weak_alias(strsvis,_strsvis)
86 : : __weak_alias(strsvisx,_strsvisx)
87 : : __weak_alias(strvis,_strvis)
88 : : __weak_alias(strvisx,_strvisx)
89 : : __weak_alias(svis,_svis)
90 : : __weak_alias(vis,_vis)
91 : : #endif
92 : : #endif
93 : :
94 : : #if !HAVE_VIS || !HAVE_SVIS
95 : : #include <ctype.h>
96 : : #include <limits.h>
97 : : #include <stdio.h>
98 : : #include <string.h>
99 : :
100 : : static char *do_svis(char *, int, int, int, const char *);
101 : :
102 : : #undef BELL
103 : : #if defined(__STDC__)
104 : : #define BELL '\a'
105 : : #else
106 : : #define BELL '\007'
107 : : #endif
108 : :
109 : : ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
110 : : rk_vis (char *, int, int, int);
111 : : ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
112 : : rk_svis (char *, int, int, int, const char *);
113 : : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
114 : : rk_strvis (char *, const char *, int);
115 : : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
116 : : rk_strsvis (char *, const char *, int, const char *);
117 : : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
118 : : rk_strvisx (char *, const char *, size_t, int);
119 : : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
120 : : rk_strsvisx (char *, const char *, size_t, int, const char *);
121 : :
122 : :
123 : : #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
124 : : #define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
125 : : #define issafe(c) (c == '\b' || c == BELL || c == '\r')
126 : : #define xtoa(c) "0123456789abcdef"[c]
127 : :
128 : : #define MAXEXTRAS 5
129 : :
130 : : #define MAKEEXTRALIST(flag, extra, orig_str) \
131 : : do { \
132 : : const char *orig = orig_str; \
133 : : const char *o = orig; \
134 : : char *e; \
135 : : while (*o++) \
136 : : continue; \
137 : : extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \
138 : : if (!extra) break; \
139 : : for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
140 : : continue; \
141 : : e--; \
142 : : if (flag & VIS_SP) *e++ = ' '; \
143 : : if (flag & VIS_TAB) *e++ = '\t'; \
144 : : if (flag & VIS_NL) *e++ = '\n'; \
145 : : if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
146 : : *e = '\0'; \
147 : : } while (/*CONSTCOND*/0)
148 : :
149 : : /*
150 : : * This is do_hvis, for HTTP style (RFC 1808)
151 : : */
152 : : static char *
153 : 0 : do_hvis(char *dst, int c, int flag, int nextc, const char *extra)
154 : : {
155 [ # # ][ # # ]: 0 : if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) {
[ # # ]
156 : 0 : *dst++ = '%';
157 : 0 : *dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
158 : 0 : *dst++ = xtoa((unsigned int)c & 0xf);
159 : : } else {
160 : 0 : dst = do_svis(dst, c, flag, nextc, extra);
161 : : }
162 : 0 : return dst;
163 : : }
164 : :
165 : : /*
166 : : * This is do_vis, the central code of vis.
167 : : * dst: Pointer to the destination buffer
168 : : * c: Character to encode
169 : : * flag: Flag word
170 : : * nextc: The character following 'c'
171 : : * extra: Pointer to the list of extra characters to be
172 : : * backslash-protected.
173 : : */
174 : : static char *
175 : 0 : do_svis(char *dst, int c, int flag, int nextc, const char *extra)
176 : : {
177 : : int isextra;
178 : 0 : isextra = strchr(extra, c) != NULL;
179 [ # # ][ # # ]: 0 : if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
180 : 0 : ((flag & VIS_SAFE) && issafe(c)))) {
181 : 0 : *dst++ = c;
182 : 0 : return dst;
183 : : }
184 [ # # ]: 0 : if (flag & VIS_CSTYLE) {
185 [ # # # # : 0 : switch (c) {
# # # # #
# ]
186 : : case '\n':
187 : 0 : *dst++ = '\\'; *dst++ = 'n';
188 : 0 : return dst;
189 : : case '\r':
190 : 0 : *dst++ = '\\'; *dst++ = 'r';
191 : 0 : return dst;
192 : : case '\b':
193 : 0 : *dst++ = '\\'; *dst++ = 'b';
194 : 0 : return dst;
195 : : case BELL:
196 : 0 : *dst++ = '\\'; *dst++ = 'a';
197 : 0 : return dst;
198 : : case '\v':
199 : 0 : *dst++ = '\\'; *dst++ = 'v';
200 : 0 : return dst;
201 : : case '\t':
202 : 0 : *dst++ = '\\'; *dst++ = 't';
203 : 0 : return dst;
204 : : case '\f':
205 : 0 : *dst++ = '\\'; *dst++ = 'f';
206 : 0 : return dst;
207 : : case ' ':
208 : 0 : *dst++ = '\\'; *dst++ = 's';
209 : 0 : return dst;
210 : : case '\0':
211 : 0 : *dst++ = '\\'; *dst++ = '0';
212 [ # # ][ # # ]: 0 : if (isoctal(nextc)) {
213 : 0 : *dst++ = '0';
214 : 0 : *dst++ = '0';
215 : : }
216 : 0 : return dst;
217 : : default:
218 [ # # ]: 0 : if (isgraph(c)) {
219 : 0 : *dst++ = '\\'; *dst++ = c;
220 : 0 : return dst;
221 : : }
222 : : }
223 : : }
224 [ # # ][ # # ]: 0 : if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
[ # # ]
225 : 0 : *dst++ = '\\';
226 : 0 : *dst++ = (u_char)(((unsigned int)(u_char)c >> 6) & 03) + '0';
227 : 0 : *dst++ = (u_char)(((unsigned int)(u_char)c >> 3) & 07) + '0';
228 : 0 : *dst++ = (u_char)( c & 07) + '0';
229 : : } else {
230 [ # # ]: 0 : if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\';
231 [ # # ]: 0 : if (c & 0200) {
232 : 0 : c &= 0177; *dst++ = 'M';
233 : : }
234 [ # # ]: 0 : if (iscntrl(c)) {
235 : 0 : *dst++ = '^';
236 [ # # ]: 0 : if (c == 0177)
237 : 0 : *dst++ = '?';
238 : : else
239 : 0 : *dst++ = c + '@';
240 : : } else {
241 : 0 : *dst++ = '-'; *dst++ = c;
242 : : }
243 : : }
244 : 0 : return dst;
245 : : }
246 : :
247 : :
248 : : /*
249 : : * svis - visually encode characters, also encoding the characters
250 : : * pointed to by `extra'
251 : : */
252 : : ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
253 : 0 : rk_svis(char *dst, int c, int flag, int nextc, const char *extra)
254 : : {
255 : 0 : char *nextra = NULL;
256 : :
257 : : _DIAGASSERT(dst != NULL);
258 : : _DIAGASSERT(extra != NULL);
259 [ # # ][ # # ]: 0 : MAKEEXTRALIST(flag, nextra, extra);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
260 [ # # ]: 0 : if (!nextra) {
261 : 0 : *dst = '\0'; /* can't create nextra, return "" */
262 : 0 : return dst;
263 : : }
264 [ # # ]: 0 : if (flag & VIS_HTTPSTYLE)
265 : 0 : dst = do_hvis(dst, c, flag, nextc, nextra);
266 : : else
267 : 0 : dst = do_svis(dst, c, flag, nextc, nextra);
268 : 0 : free(nextra);
269 : 0 : *dst = '\0';
270 : 0 : return dst;
271 : : }
272 : :
273 : :
274 : : /*
275 : : * strsvis, strsvisx - visually encode characters from src into dst
276 : : *
277 : : * Extra is a pointer to a \0-terminated list of characters to
278 : : * be encoded, too. These functions are useful e. g. to
279 : : * encode strings in such a way so that they are not interpreted
280 : : * by a shell.
281 : : *
282 : : * Dst must be 4 times the size of src to account for possible
283 : : * expansion. The length of dst, not including the trailing NULL,
284 : : * is returned.
285 : : *
286 : : * Strsvisx encodes exactly len bytes from src into dst.
287 : : * This is useful for encoding a block of data.
288 : : */
289 : :
290 : : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
291 : 0 : rk_strsvis(char *dst, const char *csrc, int flag, const char *extra)
292 : : {
293 : : int c;
294 : : char *start;
295 : 0 : char *nextra = NULL;
296 : 0 : const unsigned char *src = (const unsigned char *)csrc;
297 : :
298 : : _DIAGASSERT(dst != NULL);
299 : : _DIAGASSERT(src != NULL);
300 : : _DIAGASSERT(extra != NULL);
301 [ # # ][ # # ]: 0 : MAKEEXTRALIST(flag, nextra, extra);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
302 [ # # ]: 0 : if (!nextra) {
303 : 0 : *dst = '\0'; /* can't create nextra, return "" */
304 : 0 : return 0;
305 : : }
306 [ # # ]: 0 : if (flag & VIS_HTTPSTYLE) {
307 [ # # ]: 0 : for (start = dst; (c = *src++) != '\0'; /* empty */)
308 : 0 : dst = do_hvis(dst, c, flag, *src, nextra);
309 : : } else {
310 [ # # ]: 0 : for (start = dst; (c = *src++) != '\0'; /* empty */)
311 : 0 : dst = do_svis(dst, c, flag, *src, nextra);
312 : : }
313 : 0 : free(nextra);
314 : 0 : *dst = '\0';
315 : 0 : return (dst - start);
316 : : }
317 : :
318 : :
319 : : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
320 : 0 : rk_strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)
321 : : {
322 : : unsigned char c;
323 : : char *start;
324 : 0 : char *nextra = NULL;
325 : 0 : const unsigned char *src = (const unsigned char *)csrc;
326 : :
327 : : _DIAGASSERT(dst != NULL);
328 : : _DIAGASSERT(src != NULL);
329 : : _DIAGASSERT(extra != NULL);
330 [ # # ][ # # ]: 0 : MAKEEXTRALIST(flag, nextra, extra);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
331 [ # # ]: 0 : if (! nextra) {
332 : 0 : *dst = '\0'; /* can't create nextra, return "" */
333 : 0 : return 0;
334 : : }
335 : :
336 [ # # ]: 0 : if (flag & VIS_HTTPSTYLE) {
337 [ # # ]: 0 : for (start = dst; len > 0; len--) {
338 : 0 : c = *src++;
339 [ # # ]: 0 : dst = do_hvis(dst, c, flag, len ? *src : '\0', nextra);
340 : : }
341 : : } else {
342 [ # # ]: 0 : for (start = dst; len > 0; len--) {
343 : 0 : c = *src++;
344 [ # # ]: 0 : dst = do_svis(dst, c, flag, len ? *src : '\0', nextra);
345 : : }
346 : : }
347 : 0 : free(nextra);
348 : 0 : *dst = '\0';
349 : 0 : return (dst - start);
350 : : }
351 : : #endif
352 : :
353 : : #if !HAVE_VIS
354 : : /*
355 : : * vis - visually encode characters
356 : : */
357 : : ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
358 : 0 : rk_vis(char *dst, int c, int flag, int nextc)
359 : : {
360 : 0 : char *extra = NULL;
361 : 0 : unsigned char uc = (unsigned char)c;
362 : :
363 : : _DIAGASSERT(dst != NULL);
364 : :
365 [ # # ][ # # ]: 0 : MAKEEXTRALIST(flag, extra, "");
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
366 [ # # ]: 0 : if (! extra) {
367 : 0 : *dst = '\0'; /* can't create extra, return "" */
368 : 0 : return dst;
369 : : }
370 [ # # ]: 0 : if (flag & VIS_HTTPSTYLE)
371 : 0 : dst = do_hvis(dst, uc, flag, nextc, extra);
372 : : else
373 : 0 : dst = do_svis(dst, uc, flag, nextc, extra);
374 : 0 : free(extra);
375 : 0 : *dst = '\0';
376 : 0 : return dst;
377 : : }
378 : :
379 : :
380 : : /*
381 : : * strvis, strvisx - visually encode characters from src into dst
382 : : *
383 : : * Dst must be 4 times the size of src to account for possible
384 : : * expansion. The length of dst, not including the trailing NULL,
385 : : * is returned.
386 : : *
387 : : * Strvisx encodes exactly len bytes from src into dst.
388 : : * This is useful for encoding a block of data.
389 : : */
390 : : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
391 : 0 : rk_strvis(char *dst, const char *src, int flag)
392 : : {
393 : 0 : char *extra = NULL;
394 : : int rv;
395 : :
396 [ # # ][ # # ]: 0 : MAKEEXTRALIST(flag, extra, "");
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
397 [ # # ]: 0 : if (!extra) {
398 : 0 : *dst = '\0'; /* can't create extra, return "" */
399 : 0 : return 0;
400 : : }
401 : 0 : rv = strsvis(dst, src, flag, extra);
402 : 0 : free(extra);
403 : 0 : return rv;
404 : : }
405 : :
406 : :
407 : : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
408 : 0 : rk_strvisx(char *dst, const char *src, size_t len, int flag)
409 : : {
410 : 0 : char *extra = NULL;
411 : : int rv;
412 : :
413 [ # # ][ # # ]: 0 : MAKEEXTRALIST(flag, extra, "");
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
414 [ # # ]: 0 : if (!extra) {
415 : 0 : *dst = '\0'; /* can't create extra, return "" */
416 : 0 : return 0;
417 : : }
418 : 0 : rv = strsvisx(dst, src, len, flag, extra);
419 : 0 : free(extra);
420 : 0 : return rv;
421 : : }
422 : : #endif
|