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