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