1 /* $NetBSD: vis.c,v 1.40 2009/02/11 13:52:28 christos Exp $ */
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
33 * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
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.
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.
58 #include <sys/cdefs.h>
59 #if defined(LIBC_SCCS) && !defined(lint)
60 __RCSID("$NetBSD: vis.c,v 1.40 2009/02/11 13:52:28 christos Exp $");
61 #endif /* LIBC_SCCS and not lint */
63 #include "namespace.h"
64 #include <sys/types.h>
71 __weak_alias(strsvis
,_strsvis
)
72 __weak_alias(strsvisx
,_strsvisx
)
73 __weak_alias(strvis
,_strvis
)
74 __weak_alias(strvisx
,_strvisx
)
75 __weak_alias(svis
,_svis
)
76 __weak_alias(vis
,_vis
)
79 #if !HAVE_VIS || !HAVE_SVIS
85 static char *do_svis(char *, int, int, int, const char *);
90 #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
91 #define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
92 #define issafe(c) (c == '\b' || c == BELL || c == '\r')
93 #define xtoa(c) "0123456789abcdef"[c]
94 #define XTOA(c) "0123456789ABCDEF"[c]
98 #define MAKEEXTRALIST(flag, extra, orig_str) \
100 const char *orig = orig_str; \
101 const char *o = orig; \
105 extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \
107 for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
110 if (flag & VIS_SP) *e++ = ' '; \
111 if (flag & VIS_TAB) *e++ = '\t'; \
112 if (flag & VIS_NL) *e++ = '\n'; \
113 if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
115 } while (/*CONSTCOND*/0)
118 * This is do_hvis, for HTTP style (RFC 1808)
121 do_hvis(char *dst
, int c
, int flag
, int nextc
, const char *extra
)
124 if ((isascii(c
) && isalnum(c
))
126 || c
== '$' || c
== '-' || c
== '_' || c
== '.' || c
== '+'
128 || c
== '!' || c
== '*' || c
== '\'' || c
== '(' || c
== ')'
130 dst
= do_svis(dst
, c
, flag
, nextc
, extra
);
133 *dst
++ = xtoa(((unsigned int)c
>> 4) & 0xf);
134 *dst
++ = xtoa((unsigned int)c
& 0xf);
141 * This is do_mvis, for Quoted-Printable MIME (RFC 2045)
142 * NB: No handling of long lines or CRLF.
145 do_mvis(char *dst
, int c
, int flag
, int nextc
, const char *extra
)
148 /* Space at the end of the line */
149 ((isspace(c
) && (nextc
== '\r' || nextc
== '\n')) ||
151 (!isspace(c
) && (c
< 33 || (c
> 60 && c
< 62) || c
> 126)) ||
152 /* Specific char to be escaped */
153 strchr("#$@[\\]^`{|}~", c
) != NULL
)) {
155 *dst
++ = XTOA(((unsigned int)c
>> 4) & 0xf);
156 *dst
++ = XTOA((unsigned int)c
& 0xf);
158 dst
= do_svis(dst
, c
, flag
, nextc
, extra
);
164 * This is do_vis, the central code of vis.
165 * dst: Pointer to the destination buffer
166 * c: Character to encode
168 * nextc: The character following 'c'
169 * extra: Pointer to the list of extra characters to be
170 * backslash-protected.
173 do_svis(char *dst
, int c
, int flag
, int nextc
, const char *extra
)
176 isextra
= strchr(extra
, c
) != NULL
;
177 if (!isextra
&& isascii(c
) && (isgraph(c
) || iswhite(c
) ||
178 ((flag
& VIS_SAFE
) && issafe(c
)))) {
182 if (flag
& VIS_CSTYLE
) {
185 *dst
++ = '\\'; *dst
++ = 'n';
188 *dst
++ = '\\'; *dst
++ = 'r';
191 *dst
++ = '\\'; *dst
++ = 'b';
194 *dst
++ = '\\'; *dst
++ = 'a';
197 *dst
++ = '\\'; *dst
++ = 'v';
200 *dst
++ = '\\'; *dst
++ = 't';
203 *dst
++ = '\\'; *dst
++ = 'f';
206 *dst
++ = '\\'; *dst
++ = 's';
209 *dst
++ = '\\'; *dst
++ = '0';
210 if (isoctal(nextc
)) {
217 *dst
++ = '\\'; *dst
++ = c
;
222 if (isextra
|| ((c
& 0177) == ' ') || (flag
& VIS_OCTAL
)) {
224 *dst
++ = (u_char
)(((u_int32_t
)(u_char
)c
>> 6) & 03) + '0';
225 *dst
++ = (u_char
)(((u_int32_t
)(u_char
)c
>> 3) & 07) + '0';
226 *dst
++ = (c
& 07) + '0';
228 if ((flag
& VIS_NOSLASH
) == 0) *dst
++ = '\\';
230 c
&= 0177; *dst
++ = 'M';
239 *dst
++ = '-'; *dst
++ = c
;
245 typedef char *(*visfun_t
)(char *, int, int, int, const char *);
248 * Return the appropriate encoding function depending on the flags given.
253 if (flag
& VIS_HTTPSTYLE
)
255 if (flag
& VIS_MIMESTYLE
)
261 * svis - visually encode characters, also encoding the characters
262 * pointed to by `extra'
265 svis(char *dst
, int c
, int flag
, int nextc
, const char *extra
)
270 _DIAGASSERT(dst
!= NULL
);
271 _DIAGASSERT(extra
!= NULL
);
272 MAKEEXTRALIST(flag
, nextra
, extra
);
274 *dst
= '\0'; /* can't create nextra, return "" */
278 dst
= (*f
)(dst
, c
, flag
, nextc
, nextra
);
286 * strsvis, strsvisx - visually encode characters from src into dst
288 * Extra is a pointer to a \0-terminated list of characters to
289 * be encoded, too. These functions are useful e. g. to
290 * encode strings in such a way so that they are not interpreted
293 * Dst must be 4 times the size of src to account for possible
294 * expansion. The length of dst, not including the trailing NULL,
297 * Strsvisx encodes exactly len bytes from src into dst.
298 * This is useful for encoding a block of data.
301 strsvis(char *dst
, const char *csrc
, int flag
, const char *extra
)
306 const unsigned char *src
= (const unsigned char *)csrc
;
309 _DIAGASSERT(dst
!= NULL
);
310 _DIAGASSERT(src
!= NULL
);
311 _DIAGASSERT(extra
!= NULL
);
312 MAKEEXTRALIST(flag
, nextra
, extra
);
314 *dst
= '\0'; /* can't create nextra, return "" */
318 for (start
= dst
; (c
= *src
++) != '\0'; /* empty */)
319 dst
= (*f
)(dst
, c
, flag
, *src
, nextra
);
322 return (int)(dst
- start
);
327 strsvisx(char *dst
, const char *csrc
, size_t len
, int flag
, const char *extra
)
332 const unsigned char *src
= (const unsigned char *)csrc
;
335 _DIAGASSERT(dst
!= NULL
);
336 _DIAGASSERT(src
!= NULL
);
337 _DIAGASSERT(extra
!= NULL
);
338 MAKEEXTRALIST(flag
, nextra
, extra
);
340 *dst
= '\0'; /* can't create nextra, return "" */
345 for (start
= dst
; len
> 0; len
--) {
347 dst
= (*f
)(dst
, c
, flag
, len
> 1 ? *src
: '\0', nextra
);
351 return (int)(dst
- start
);
357 * vis - visually encode characters
360 vis(char *dst
, int c
, int flag
, int nextc
)
363 unsigned char uc
= (unsigned char)c
;
366 _DIAGASSERT(dst
!= NULL
);
368 MAKEEXTRALIST(flag
, extra
, "");
370 *dst
= '\0'; /* can't create extra, return "" */
374 dst
= (*f
)(dst
, uc
, flag
, nextc
, extra
);
382 * strvis, strvisx - visually encode characters from src into dst
384 * Dst must be 4 times the size of src to account for possible
385 * expansion. The length of dst, not including the trailing NULL,
388 * Strvisx encodes exactly len bytes from src into dst.
389 * This is useful for encoding a block of data.
392 strvis(char *dst
, const char *src
, int flag
)
397 MAKEEXTRALIST(flag
, extra
, "");
399 *dst
= '\0'; /* can't create extra, return "" */
402 rv
= strsvis(dst
, src
, flag
, extra
);
409 strvisx(char *dst
, const char *src
, size_t len
, int flag
)
414 MAKEEXTRALIST(flag
, extra
, "");
416 *dst
= '\0'; /* can't create extra, return "" */
419 rv
= strsvisx(dst
, src
, len
, flag
, extra
);