vis.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* $NetBSD: vis.c,v 1.22 2002/03/23 17:38:27 christos Exp $ */
  2. /*-
  3. * Copyright (c) 1999 The NetBSD Foundation, Inc.
  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. #include <sys/cdefs.h>
  36. #if defined(LIBC_SCCS) && !defined(lint)
  37. __RCSID("$NetBSD: vis.c,v 1.22 2002/03/23 17:38:27 christos Exp $");
  38. #endif /* LIBC_SCCS and not lint */
  39. #include <sys/types.h>
  40. #include <assert.h>
  41. #include "np/vis.h"
  42. #include <stdlib.h>
  43. #include <stdint.h>
  44. #ifdef __weak_alias
  45. __weak_alias(strsvis,_strsvis)
  46. __weak_alias(strsvisx,_strsvisx)
  47. __weak_alias(strvis,_strvis)
  48. __weak_alias(strvisx,_strvisx)
  49. __weak_alias(svis,_svis)
  50. __weak_alias(vis,_vis)
  51. #endif
  52. #ifndef HAVE_VIS_H
  53. #include <ctype.h>
  54. #include <limits.h>
  55. #include <stdio.h>
  56. #include <string.h>
  57. #undef BELL
  58. #if defined(__STDC__)
  59. #define BELL '\a'
  60. #else
  61. #define BELL '\007'
  62. #endif
  63. #ifdef SOLARIS
  64. #include <alloca.h>
  65. #endif
  66. #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
  67. #define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
  68. #define issafe(c) (c == '\b' || c == BELL || c == '\r')
  69. #define xtoa(c) "0123456789abcdef"[c]
  70. #define MAXEXTRAS 5
  71. #define MAKEEXTRALIST(flag, extra, orig) \
  72. do { \
  73. const char *o = orig; \
  74. char *e; \
  75. while (*o++) \
  76. continue; \
  77. extra = alloca((size_t)((o - orig) + MAXEXTRAS)); \
  78. for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
  79. continue; \
  80. e--; \
  81. if (flag & VIS_SP) *e++ = ' '; \
  82. if (flag & VIS_TAB) *e++ = '\t'; \
  83. if (flag & VIS_NL) *e++ = '\n'; \
  84. if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
  85. *e = '\0'; \
  86. } while (/*CONSTCOND*/0)
  87. /*
  88. * This is HVIS, the macro of vis used to HTTP style (RFC 1808)
  89. */
  90. #define HVIS(dst, c, flag, nextc, extra) \
  91. do \
  92. if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \
  93. *dst++ = '%'; \
  94. *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \
  95. *dst++ = xtoa((unsigned int)c & 0xf); \
  96. } else { \
  97. SVIS(dst, c, flag, nextc, extra); \
  98. } \
  99. while (/*CONSTCOND*/0)
  100. /*
  101. * This is SVIS, the central macro of vis.
  102. * dst: Pointer to the destination buffer
  103. * c: Character to encode
  104. * flag: Flag word
  105. * nextc: The character following 'c'
  106. * extra: Pointer to the list of extra characters to be
  107. * backslash-protected.
  108. */
  109. #define SVIS(dst, c, flag, nextc, extra) \
  110. do { \
  111. int isextra, isc; \
  112. isextra = strchr(extra, c) != NULL; \
  113. if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \
  114. ((flag & VIS_SAFE) && issafe(c)))) { \
  115. *dst++ = c; \
  116. break; \
  117. } \
  118. isc = 0; \
  119. if (flag & VIS_CSTYLE) { \
  120. switch (c) { \
  121. case '\n': \
  122. isc = 1; *dst++ = '\\'; *dst++ = 'n'; \
  123. break; \
  124. case '\r': \
  125. isc = 1; *dst++ = '\\'; *dst++ = 'r'; \
  126. break; \
  127. case '\b': \
  128. isc = 1; *dst++ = '\\'; *dst++ = 'b'; \
  129. break; \
  130. case BELL: \
  131. isc = 1; *dst++ = '\\'; *dst++ = 'a'; \
  132. break; \
  133. case '\v': \
  134. isc = 1; *dst++ = '\\'; *dst++ = 'v'; \
  135. break; \
  136. case '\t': \
  137. isc = 1; *dst++ = '\\'; *dst++ = 't'; \
  138. break; \
  139. case '\f': \
  140. isc = 1; *dst++ = '\\'; *dst++ = 'f'; \
  141. break; \
  142. case ' ': \
  143. isc = 1; *dst++ = '\\'; *dst++ = 's'; \
  144. break; \
  145. case '\0': \
  146. isc = 1; *dst++ = '\\'; *dst++ = '0'; \
  147. if (isoctal(nextc)) { \
  148. *dst++ = '0'; \
  149. *dst++ = '0'; \
  150. } \
  151. } \
  152. } \
  153. if (isc) break; \
  154. if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \
  155. *dst++ = '\\'; \
  156. *dst++ = (u_char)(((uint32_t)(u_char)c >> 6) & 03) + '0'; \
  157. *dst++ = (u_char)(((uint32_t)(u_char)c >> 3) & 07) + '0'; \
  158. *dst++ = (c & 07) + '0'; \
  159. } else { \
  160. if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \
  161. if (c & 0200) { \
  162. c &= 0177; *dst++ = 'M'; \
  163. } \
  164. if (iscntrl(c)) { \
  165. *dst++ = '^'; \
  166. if (c == 0177) \
  167. *dst++ = '?'; \
  168. else \
  169. *dst++ = c + '@'; \
  170. } else { \
  171. *dst++ = '-'; *dst++ = c; \
  172. } \
  173. } \
  174. } while (/*CONSTCOND*/0)
  175. /*
  176. * svis - visually encode characters, also encoding the characters
  177. * pointed to by `extra'
  178. */
  179. char *
  180. svis(dst, c, flag, nextc, extra)
  181. char *dst;
  182. int c, flag, nextc;
  183. const char *extra;
  184. {
  185. char *nextra;
  186. _DIAGASSERT(dst != NULL);
  187. _DIAGASSERT(extra != NULL);
  188. MAKEEXTRALIST(flag, nextra, extra);
  189. if (flag & VIS_HTTPSTYLE)
  190. HVIS(dst, c, flag, nextc, nextra);
  191. else
  192. SVIS(dst, c, flag, nextc, nextra);
  193. *dst = '\0';
  194. return(dst);
  195. }
  196. /*
  197. * strsvis, strsvisx - visually encode characters from src into dst
  198. *
  199. * Extra is a pointer to a \0-terminated list of characters to
  200. * be encoded, too. These functions are useful e. g. to
  201. * encode strings in such a way so that they are not interpreted
  202. * by a shell.
  203. *
  204. * Dst must be 4 times the size of src to account for possible
  205. * expansion. The length of dst, not including the trailing NULL,
  206. * is returned.
  207. *
  208. * Strsvisx encodes exactly len bytes from src into dst.
  209. * This is useful for encoding a block of data.
  210. */
  211. int
  212. strsvis(dst, src, flag, extra)
  213. char *dst;
  214. const char *src;
  215. int flag;
  216. const char *extra;
  217. {
  218. char c;
  219. char *start;
  220. char *nextra;
  221. _DIAGASSERT(dst != NULL);
  222. _DIAGASSERT(src != NULL);
  223. _DIAGASSERT(extra != NULL);
  224. MAKEEXTRALIST(flag, nextra, extra);
  225. if (flag & VIS_HTTPSTYLE) {
  226. for (start = dst; (c = *src++) != '\0'; /* empty */)
  227. HVIS(dst, c, flag, *src, nextra);
  228. } else {
  229. for (start = dst; (c = *src++) != '\0'; /* empty */)
  230. SVIS(dst, c, flag, *src, nextra);
  231. }
  232. *dst = '\0';
  233. return (dst - start);
  234. }
  235. int
  236. strsvisx(dst, src, len, flag, extra)
  237. char *dst;
  238. const char *src;
  239. size_t len;
  240. int flag;
  241. const char *extra;
  242. {
  243. char c;
  244. char *start;
  245. char *nextra;
  246. _DIAGASSERT(dst != NULL);
  247. _DIAGASSERT(src != NULL);
  248. _DIAGASSERT(extra != NULL);
  249. MAKEEXTRALIST(flag, nextra, extra);
  250. if (flag & VIS_HTTPSTYLE) {
  251. for (start = dst; len > 0; len--) {
  252. c = *src++;
  253. HVIS(dst, c, flag, len ? *src : '\0', nextra);
  254. }
  255. } else {
  256. for (start = dst; len > 0; len--) {
  257. c = *src++;
  258. SVIS(dst, c, flag, len ? *src : '\0', nextra);
  259. }
  260. }
  261. *dst = '\0';
  262. return (dst - start);
  263. }
  264. /*
  265. * vis - visually encode characters
  266. */
  267. char *
  268. vis(dst, c, flag, nextc)
  269. char *dst;
  270. int c, flag, nextc;
  271. {
  272. char *extra;
  273. _DIAGASSERT(dst != NULL);
  274. MAKEEXTRALIST(flag, extra, "");
  275. if (flag & VIS_HTTPSTYLE)
  276. HVIS(dst, c, flag, nextc, extra);
  277. else
  278. SVIS(dst, c, flag, nextc, extra);
  279. *dst = '\0';
  280. return (dst);
  281. }
  282. /*
  283. * strvis, strvisx - visually encode characters from src into dst
  284. *
  285. * Dst must be 4 times the size of src to account for possible
  286. * expansion. The length of dst, not including the trailing NULL,
  287. * is returned.
  288. *
  289. * Strvisx encodes exactly len bytes from src into dst.
  290. * This is useful for encoding a block of data.
  291. */
  292. int
  293. strvis(dst, src, flag)
  294. char *dst;
  295. const char *src;
  296. int flag;
  297. {
  298. char *extra;
  299. MAKEEXTRALIST(flag, extra, "");
  300. return (strsvis(dst, src, flag, extra));
  301. }
  302. int
  303. strvisx(dst, src, len, flag)
  304. char *dst;
  305. const char *src;
  306. size_t len;
  307. int flag;
  308. {
  309. char *extra;
  310. MAKEEXTRALIST(flag, extra, "");
  311. return (strsvisx(dst, src, len, flag, extra));
  312. }
  313. #endif