diff options
Diffstat (limited to 'lib/roken/vis.c')
| -rw-r--r-- | lib/roken/vis.c | 395 | 
1 files changed, 241 insertions, 154 deletions
| diff --git a/lib/roken/vis.c b/lib/roken/vis.c index 1114223a2974..19ff29d95ca8 100644 --- a/lib/roken/vis.c +++ b/lib/roken/vis.c @@ -1,4 +1,4 @@ -/*	$NetBSD: vis.c,v 1.4 2003/08/07 09:15:32 agc Exp $	*/ +/*	$NetBSD: vis.c,v 1.37 2008/07/25 22:29:23 dsl Exp $	*/  /*-   * Copyright (c) 1989, 1993 @@ -30,7 +30,8 @@   */  /*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. + * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc. + * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without   * modification, are permitted provided that the following conditions @@ -40,47 +41,35 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - *    may be used to endorse or promote products derived from this software - *    without specific prior written permission.   * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.   */ -  #if 1 -#ifdef HAVE_CONFIG_H  #include <config.h> -RCSID("$Id: vis.c 21005 2007-06-08 01:54:35Z lha $"); -#endif  #include "roken.h"  #ifndef _DIAGASSERT  #define _DIAGASSERT(X)  #endif -#else +#else /* heimdal */  #include <sys/cdefs.h> -#if !defined(lint) -__RCSID("$NetBSD: vis.c,v 1.4 2003/08/07 09:15:32 agc Exp $"); -#endif /* not lint */ -#endif +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: vis.c,v 1.37 2008/07/25 22:29:23 dsl Exp $"); +#endif /* LIBC_SCCS and not lint */ -#if 0  #include "namespace.h" -#endif +#endif /* heimdal */ +  #include <sys/types.h>  #include <assert.h> @@ -89,6 +78,7 @@ __RCSID("$NetBSD: vis.c,v 1.4 2003/08/07 09:15:32 agc Exp $");  #include <stdio.h>  #include <string.h>  #include <vis.h> +#include <stdlib.h>  #if 0  #ifdef __weak_alias @@ -101,6 +91,14 @@ __weak_alias(vis,_vis)  #endif  #endif +#if !HAVE_VIS || !HAVE_SVIS +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> + +static char *do_svis(char *, int, int, int, const char *); +  #undef BELL  #if defined(__STDC__)  #define BELL '\a' @@ -108,39 +106,64 @@ __weak_alias(vis,_vis)  #define BELL '\007'  #endif -char ROKEN_LIB_FUNCTION -	*rk_vis (char *, int, int, int); -char ROKEN_LIB_FUNCTION -	*rk_svis (char *, int, int, int, const char *); -int ROKEN_LIB_FUNCTION +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +	rk_vis (char *, int, int, int); +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL +	rk_svis (char *, int, int, int, const char *); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL  	rk_strvis (char *, const char *, int); -int ROKEN_LIB_FUNCTION +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL  	rk_strsvis (char *, const char *, int, const char *); -int ROKEN_LIB_FUNCTION +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL  	rk_strvisx (char *, const char *, size_t, int); -int ROKEN_LIB_FUNCTION +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL  	rk_strsvisx (char *, const char *, size_t, int, const char *);  #define isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')  #define iswhite(c)	(c == ' ' || c == '\t' || c == '\n')  #define issafe(c)	(c == '\b' || c == BELL || c == '\r') +#define xtoa(c)		"0123456789abcdef"[c] -#define MAXEXTRAS       5 - +#define MAXEXTRAS	5 -#define MAKEEXTRALIST(flag, extra)					      \ +#define MAKEEXTRALIST(flag, extra, orig_str)				      \  do {									      \ -	char *pextra = extra;						      \ -	if (flag & VIS_SP) *pextra++ = ' ';				      \ -	if (flag & VIS_TAB) *pextra++ = '\t';				      \ -	if (flag & VIS_NL) *pextra++ = '\n';				      \ -	if ((flag & VIS_NOSLASH) == 0) *pextra++ = '\\';		      \ -	*pextra = '\0';							      \ +	const char *orig = orig_str;					      \ +	const char *o = orig;						      \ +	char *e;							      \ +	while (*o++)							      \ +		continue;						      \ +	extra = malloc((size_t)((o - orig) + MAXEXTRAS));		      \ +	if (!extra) break;						      \ +	for (o = orig, e = extra; (*e++ = *o++) != '\0';)		      \ +		continue;						      \ +	e--;								      \ +	if (flag & VIS_SP) *e++ = ' ';					      \ +	if (flag & VIS_TAB) *e++ = '\t';				      \ +	if (flag & VIS_NL) *e++ = '\n';					      \ +	if ((flag & VIS_NOSLASH) == 0) *e++ = '\\';			      \ +	*e = '\0';							      \  } while (/*CONSTCOND*/0)  /* - * This is SVIS, the central macro of vis. + * This is do_hvis, for HTTP style (RFC 1808) + */ +static char * +do_hvis(char *dst, int c, int flag, int nextc, const char *extra) +{ +	if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { +		*dst++ = '%'; +		*dst++ = xtoa(((unsigned int)c >> 4) & 0xf); +		*dst++ = xtoa((unsigned int)c & 0xf); +	} else { +		dst = do_svis(dst, c, flag, nextc, extra); +	} +	return dst; +} + +/* + * This is do_vis, the central code of vis.   * dst:	      Pointer to the destination buffer   * c:	      Character to encode   * flag:      Flag word @@ -148,90 +171,103 @@ do {									      \   * extra:     Pointer to the list of extra characters to be   *	      backslash-protected.   */ -#define SVIS(dst, c, flag, nextc, extra)				   \ -do {									   \ -	int isextra, isc;						   \ -	isextra = strchr(extra, c) != NULL;				   \ -	if (!isextra &&							   \ -	    isascii((unsigned char)c) &&				   \ -	    (isgraph((unsigned char)c) || iswhite(c) ||			   \ -	    ((flag & VIS_SAFE) && issafe(c)))) {			   \ -		*dst++ = c;						   \ -		break;							   \ -	}								   \ -	isc = 0;							   \ -	if (flag & VIS_CSTYLE) {					   \ -		switch (c) {						   \ -		case '\n':						   \ -			isc = 1; *dst++ = '\\'; *dst++ = 'n';		   \ -			break;						   \ -		case '\r':						   \ -			isc = 1; *dst++ = '\\'; *dst++ = 'r';		   \ -			break;						   \ -		case '\b':						   \ -			isc = 1; *dst++ = '\\'; *dst++ = 'b';		   \ -			break;						   \ -		case BELL:						   \ -			isc = 1; *dst++ = '\\'; *dst++ = 'a';		   \ -			break;						   \ -		case '\v':						   \ -			isc = 1; *dst++ = '\\'; *dst++ = 'v';		   \ -			break;						   \ -		case '\t':						   \ -			isc = 1; *dst++ = '\\'; *dst++ = 't';		   \ -			break;						   \ -		case '\f':						   \ -			isc = 1; *dst++ = '\\'; *dst++ = 'f';		   \ -			break;						   \ -		case ' ':						   \ -			isc = 1; *dst++ = '\\'; *dst++ = 's';		   \ -			break;						   \ -		case '\0':						   \ -			isc = 1; *dst++ = '\\'; *dst++ = '0';		   \ -			if (isoctal(nextc)) {				   \ -				*dst++ = '0';				   \ -				*dst++ = '0';				   \ -			}						   \ -		}							   \ -	}								   \ -	if (isc) break;							   \ -	if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {	   \ -		*dst++ = '\\';						   \ -		*dst++ = (u_char)(((unsigned)(u_char)c >> 6) & 03) + '0';  \ -		*dst++ = (u_char)(((unsigned)(u_char)c >> 3) & 07) + '0';  \ -		*dst++ =			     (c	      & 07) + '0'; \ -	} else {							   \ -		if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\';		   \ -		if (c & 0200) {						   \ -			c &= 0177; *dst++ = 'M';			   \ -		}							   \ -		if (iscntrl((unsigned char)c)) {			   \ -			*dst++ = '^';					   \ -			if (c == 0177)					   \ -				*dst++ = '?';				   \ -			else						   \ -				*dst++ = c + '@';			   \ -		} else {						   \ -			*dst++ = '-'; *dst++ = c;			   \ -		}							   \ -	}								   \ -} while (/*CONSTCOND*/0) +static char * +do_svis(char *dst, int c, int flag, int nextc, const char *extra) +{ +	int isextra; +	isextra = strchr(extra, c) != NULL; +	if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || +	    ((flag & VIS_SAFE) && issafe(c)))) { +		*dst++ = c; +		return dst; +	} +	if (flag & VIS_CSTYLE) { +		switch (c) { +		case '\n': +			*dst++ = '\\'; *dst++ = 'n'; +			return dst; +		case '\r': +			*dst++ = '\\'; *dst++ = 'r'; +			return dst; +		case '\b': +			*dst++ = '\\'; *dst++ = 'b'; +			return dst; +		case BELL: +			*dst++ = '\\'; *dst++ = 'a'; +			return dst; +		case '\v': +			*dst++ = '\\'; *dst++ = 'v'; +			return dst; +		case '\t': +			*dst++ = '\\'; *dst++ = 't'; +			return dst; +		case '\f': +			*dst++ = '\\'; *dst++ = 'f'; +			return dst; +		case ' ': +			*dst++ = '\\'; *dst++ = 's'; +			return dst; +		case '\0': +			*dst++ = '\\'; *dst++ = '0'; +			if (isoctal(nextc)) { +				*dst++ = '0'; +				*dst++ = '0'; +			} +			return dst; +		default: +			if (isgraph(c)) { +				*dst++ = '\\'; *dst++ = c; +				return dst; +			} +		} +	} +	if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { +		*dst++ = '\\'; +		*dst++ = (u_char)(((unsigned int)(u_char)c >> 6) & 03) + '0'; +		*dst++ = (u_char)(((unsigned int)(u_char)c >> 3) & 07) + '0'; +		*dst++ = (u_char)(			 c       & 07) + '0'; +	} else { +		if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; +		if (c & 0200) { +			c &= 0177; *dst++ = 'M'; +		} +		if (iscntrl(c)) { +			*dst++ = '^'; +			if (c == 0177) +				*dst++ = '?'; +			else +				*dst++ = c + '@'; +		} else { +			*dst++ = '-'; *dst++ = c; +		} +	} +	return dst; +}  /*   * svis - visually encode characters, also encoding the characters - * 	  pointed to by `extra' + *	  pointed to by `extra'   */ - -char * ROKEN_LIB_FUNCTION +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL  rk_svis(char *dst, int c, int flag, int nextc, const char *extra)  { +	char *nextra = NULL; +  	_DIAGASSERT(dst != NULL);  	_DIAGASSERT(extra != NULL); - -	SVIS(dst, c, flag, nextc, extra); +	MAKEEXTRALIST(flag, nextra, extra); +	if (!nextra) { +		*dst = '\0';		/* can't create nextra, return "" */ +		return dst; +	} +	if (flag & VIS_HTTPSTYLE) +		dst = do_hvis(dst, c, flag, nextc, nextra); +	else +		dst = do_svis(dst, c, flag, nextc, nextra); +	free(nextra);  	*dst = '\0'; -	return(dst); +	return dst;  } @@ -242,94 +278,145 @@ rk_svis(char *dst, int c, int flag, int nextc, const char *extra)   *	be encoded, too. These functions are useful e. g. to   *	encode strings in such a way so that they are not interpreted   *	by a shell. - *	 + *   *	Dst must be 4 times the size of src to account for possible   *	expansion.  The length of dst, not including the trailing NULL, - *	is returned.  + *	is returned.   *   *	Strsvisx encodes exactly len bytes from src into dst.   *	This is useful for encoding a block of data.   */ -int ROKEN_LIB_FUNCTION -rk_strsvis(char *dst, const char *src, int flag, const char *extra) +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strsvis(char *dst, const char *csrc, int flag, const char *extra)  { -	char c; +	int c;  	char *start; +	char *nextra = NULL; +	const unsigned char *src = (const unsigned char *)csrc;  	_DIAGASSERT(dst != NULL);  	_DIAGASSERT(src != NULL);  	_DIAGASSERT(extra != NULL); - -	for (start = dst; (c = *src++) != '\0'; /* empty */) -	    SVIS(dst, c, flag, *src, extra); +	MAKEEXTRALIST(flag, nextra, extra); +	if (!nextra) { +		*dst = '\0';		/* can't create nextra, return "" */ +		return 0; +	} +	if (flag & VIS_HTTPSTYLE) { +		for (start = dst; (c = *src++) != '\0'; /* empty */) +			dst = do_hvis(dst, c, flag, *src, nextra); +	} else { +		for (start = dst; (c = *src++) != '\0'; /* empty */) +			dst = do_svis(dst, c, flag, *src, nextra); +	} +	free(nextra);  	*dst = '\0';  	return (dst - start);  } -int ROKEN_LIB_FUNCTION -rk_strsvisx(char *dst, const char *src, size_t len, int flag, const char *extra) +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)  { -	char c; +	unsigned char c;  	char *start; +	char *nextra = NULL; +	const unsigned char *src = (const unsigned char *)csrc;  	_DIAGASSERT(dst != NULL);  	_DIAGASSERT(src != NULL);  	_DIAGASSERT(extra != NULL); +	MAKEEXTRALIST(flag, nextra, extra); +	if (! nextra) { +		*dst = '\0';		/* can't create nextra, return "" */ +		return 0; +	} -	for (start = dst; len > 0; len--) { -		c = *src++; -		SVIS(dst, c, flag, len ? *src : '\0', extra); +	if (flag & VIS_HTTPSTYLE) { +		for (start = dst; len > 0; len--) { +			c = *src++; +			dst = do_hvis(dst, c, flag, len ? *src : '\0', nextra); +		} +	} else { +		for (start = dst; len > 0; len--) { +			c = *src++; +			dst = do_svis(dst, c, flag, len ? *src : '\0', nextra); +		}  	} +	free(nextra);  	*dst = '\0';  	return (dst - start);  } +#endif - +#if !HAVE_VIS  /*   * vis - visually encode characters   */ -char * ROKEN_LIB_FUNCTION +ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL  rk_vis(char *dst, int c, int flag, int nextc)  { -	char extra[MAXEXTRAS]; +	char *extra = NULL; +	unsigned char uc = (unsigned char)c;  	_DIAGASSERT(dst != NULL); -	MAKEEXTRALIST(flag, extra); -	SVIS(dst, c, flag, nextc, extra); +	MAKEEXTRALIST(flag, extra, ""); +	if (! extra) { +		*dst = '\0';		/* can't create extra, return "" */ +		return dst; +	} +	if (flag & VIS_HTTPSTYLE) +		dst = do_hvis(dst, uc, flag, nextc, extra); +	else +		dst = do_svis(dst, uc, flag, nextc, extra); +	free(extra);  	*dst = '\0'; -	return (dst); +	return dst;  }  /*   * strvis, strvisx - visually encode characters from src into dst - *	 + *   *	Dst must be 4 times the size of src to account for possible   *	expansion.  The length of dst, not including the trailing NULL, - *	is returned.  + *	is returned.   *   *	Strvisx encodes exactly len bytes from src into dst.   *	This is useful for encoding a block of data.   */ - -int ROKEN_LIB_FUNCTION +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL  rk_strvis(char *dst, const char *src, int flag)  { -	char extra[MAXEXTRAS]; +	char *extra = NULL; +	int rv; -	MAKEEXTRALIST(flag, extra); -	return (rk_strsvis(dst, src, flag, extra)); +	MAKEEXTRALIST(flag, extra, ""); +	if (!extra) { +		*dst = '\0';		/* can't create extra, return "" */ +		return 0; +	} +	rv = strsvis(dst, src, flag, extra); +	free(extra); +	return rv;  } -int ROKEN_LIB_FUNCTION +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL  rk_strvisx(char *dst, const char *src, size_t len, int flag)  { -	char extra[MAXEXTRAS]; +	char *extra = NULL; +	int rv; -	MAKEEXTRALIST(flag, extra); -	return (rk_strsvisx(dst, src, len, flag, extra)); +	MAKEEXTRALIST(flag, extra, ""); +	if (!extra) { +		*dst = '\0';		/* can't create extra, return "" */ +		return 0; +	} +	rv = strsvisx(dst, src, len, flag, extra); +	free(extra); +	return rv;  } +#endif | 
