MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vis.c
1 /* $NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos 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. 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.
18  *
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
29  * SUCH DAMAGE.
30  */
31 
32 /*-
33  * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
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.
44  *
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.
56  */
57 
58 #include "config.h"
59 
60 #if defined(LIBC_SCCS) && !defined(lint)
61 #endif /* LIBC_SCCS and not lint */
62 
63 /* XXXMYSQL : Make compiler happy. */
64 #ifdef _LIBC
65 #include "namespace.h"
66 #endif
67 
68 #include <sys/types.h>
69 
70 #include <assert.h>
71 /*
72  XXXMYSQL : Due to different versions of vis.h available,
73  use the one bundled with libedit.
74 */
75 #include "np/vis.h"
76 #include <errno.h>
77 #include <stdlib.h>
78 
79 #ifdef __weak_alias
80 __weak_alias(strvisx,_strvisx)
81 #endif
82 
83 #if !HAVE_VIS || !HAVE_SVIS
84 #include <ctype.h>
85 #include <limits.h>
86 #include <stdio.h>
87 #include <string.h>
88 
89 static char *do_svis(char *, size_t *, int, int, int, const char *);
90 
91 #undef BELL
92 #define BELL '\a'
93 
94 #ifndef isoctal
95 #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
96 #endif
97 #define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
98 #define issafe(c) (c == '\b' || c == BELL || c == '\r')
99 #define xtoa(c) "0123456789abcdef"[c]
100 #define XTOA(c) "0123456789ABCDEF"[c]
101 
102 #define MAXEXTRAS 5
103 
104 #define MAKEEXTRALIST(flag, extra, orig_str) \
105 do { \
106  const char *orig = orig_str; \
107  const char *o = orig; \
108  char *e; \
109  while (*o++) \
110  continue; \
111  extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \
112  if (!extra) break; \
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  * This is do_hvis, for HTTP style (RFC 1808)
125  */
126 static char *
127 do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
128 {
129 
130  if ((isascii(c) && isalnum(c))
131  /* safe */
132  || c == '$' || c == '-' || c == '_' || c == '.' || c == '+'
133  /* extra */
134  || c == '!' || c == '*' || c == '\'' || c == '(' || c == ')'
135  || c == ',') {
136  dst = do_svis(dst, dlen, c, flag, nextc, extra);
137  } else {
138  if (dlen) {
139  if (*dlen < 3)
140  return NULL;
141  *dlen -= 3;
142  }
143  *dst++ = '%';
144  *dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
145  *dst++ = xtoa((unsigned int)c & 0xf);
146  }
147 
148  return dst;
149 }
150 
151 /*
152  * This is do_mvis, for Quoted-Printable MIME (RFC 2045)
153  * NB: No handling of long lines or CRLF.
154  */
155 static char *
156 do_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
157 {
158  if ((c != '\n') &&
159  /* Space at the end of the line */
160  ((isspace(c) && (nextc == '\r' || nextc == '\n')) ||
161  /* Out of range */
162  (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||
163  /* Specific char to be escaped */
164  strchr("#$@[\\]^`{|}~", c) != NULL)) {
165  if (dlen) {
166  if (*dlen < 3)
167  return NULL;
168  *dlen -= 3;
169  }
170  *dst++ = '=';
171  *dst++ = XTOA(((unsigned int)c >> 4) & 0xf);
172  *dst++ = XTOA((unsigned int)c & 0xf);
173  } else {
174  dst = do_svis(dst, dlen, c, flag, nextc, extra);
175  }
176  return dst;
177 }
178 
179 /*
180  * This is do_vis, the central code of vis.
181  * dst: Pointer to the destination buffer
182  * c: Character to encode
183  * flag: Flag word
184  * nextc: The character following 'c'
185  * extra: Pointer to the list of extra characters to be
186  * backslash-protected.
187  */
188 static char *
189 do_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
190 {
191  int isextra;
192  size_t odlen = dlen ? *dlen : 0;
193 
194  isextra = strchr(extra, c) != NULL;
195 #define HAVE(x) \
196  do { \
197  if (dlen) { \
198  if (*dlen < (x)) \
199  goto out; \
200  *dlen -= (x); \
201  } \
202  } while (/*CONSTCOND*/0)
203  if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) ||
204  ((flag & VIS_SAFE) && issafe(c)))) {
205  HAVE(1);
206  *dst++ = c;
207  return dst;
208  }
209  if (flag & VIS_CSTYLE) {
210  HAVE(2);
211  switch (c) {
212  case '\n':
213  *dst++ = '\\'; *dst++ = 'n';
214  return dst;
215  case '\r':
216  *dst++ = '\\'; *dst++ = 'r';
217  return dst;
218  case '\b':
219  *dst++ = '\\'; *dst++ = 'b';
220  return dst;
221  case BELL:
222  *dst++ = '\\'; *dst++ = 'a';
223  return dst;
224  case '\v':
225  *dst++ = '\\'; *dst++ = 'v';
226  return dst;
227  case '\t':
228  *dst++ = '\\'; *dst++ = 't';
229  return dst;
230  case '\f':
231  *dst++ = '\\'; *dst++ = 'f';
232  return dst;
233  case ' ':
234  *dst++ = '\\'; *dst++ = 's';
235  return dst;
236  case '\0':
237  *dst++ = '\\'; *dst++ = '0';
238  if (isoctal(nextc)) {
239  HAVE(2);
240  *dst++ = '0';
241  *dst++ = '0';
242  }
243  return dst;
244  default:
245  if (isgraph(c)) {
246  *dst++ = '\\'; *dst++ = c;
247  return dst;
248  }
249  if (dlen)
250  *dlen = odlen;
251  }
252  }
253  if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
254  HAVE(4);
255  *dst++ = '\\';
256  *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0';
257  *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0';
258  *dst++ = (c & 07) + '0';
259  } else {
260  if ((flag & VIS_NOSLASH) == 0) {
261  HAVE(1);
262  *dst++ = '\\';
263  }
264 
265  if (c & 0200) {
266  HAVE(1);
267  c &= 0177; *dst++ = 'M';
268  }
269 
270  if (iscntrl(c)) {
271  HAVE(2);
272  *dst++ = '^';
273  if (c == 0177)
274  *dst++ = '?';
275  else
276  *dst++ = c + '@';
277  } else {
278  HAVE(2);
279  *dst++ = '-'; *dst++ = c;
280  }
281  }
282  return dst;
283 out:
284  *dlen = odlen;
285  return NULL;
286 }
287 
288 typedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *);
289 
290 /*
291  * Return the appropriate encoding function depending on the flags given.
292  */
293 static visfun_t
294 getvisfun(int flag)
295 {
296  if (flag & VIS_HTTPSTYLE)
297  return do_hvis;
298  if (flag & VIS_MIMESTYLE)
299  return do_mvis;
300  return do_svis;
301 }
302 
303 /*
304  * isnvis - visually encode characters, also encoding the characters
305  * pointed to by `extra'
306  */
307 static char *
308 isnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
309 {
310  char *nextra = NULL;
311  visfun_t f;
312 
313  _DIAGASSERT(dst != NULL);
314  _DIAGASSERT(extra != NULL);
315  MAKEEXTRALIST(flag, nextra, extra);
316  if (!nextra) {
317  if (dlen && *dlen == 0) {
318  errno = ENOSPC;
319  return NULL;
320  }
321  *dst = '\0'; /* can't create nextra, return "" */
322  return dst;
323  }
324  f = getvisfun(flag);
325  dst = (*f)(dst, dlen, c, flag, nextc, nextra);
326  free(nextra);
327  if (dst == NULL || (dlen && *dlen == 0)) {
328  errno = ENOSPC;
329  return NULL;
330  }
331  *dst = '\0';
332  return dst;
333 }
334 
335 char *
336 svis(char *dst, int c, int flag, int nextc, const char *extra)
337 {
338  return isnvis(dst, NULL, c, flag, nextc, extra);
339 }
340 
341 char *
342 snvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra)
343 {
344  return isnvis(dst, &dlen, c, flag, nextc, extra);
345 }
346 
347 
348 /*
349  * strsvis, strsvisx - visually encode characters from src into dst
350  *
351  * Extra is a pointer to a \0-terminated list of characters to
352  * be encoded, too. These functions are useful e. g. to
353  * encode strings in such a way so that they are not interpreted
354  * by a shell.
355  *
356  * Dst must be 4 times the size of src to account for possible
357  * expansion. The length of dst, not including the trailing NULL,
358  * is returned.
359  *
360  * Strsvisx encodes exactly len bytes from src into dst.
361  * This is useful for encoding a block of data.
362  */
363 static int
364 istrsnvis(char *dst, size_t *dlen, const char *csrc, int flag, const char *extra)
365 {
366  int c;
367  char *start;
368  char *nextra = NULL;
369  const unsigned char *src = (const unsigned char *)csrc;
370  visfun_t f;
371 
372  _DIAGASSERT(dst != NULL);
373  _DIAGASSERT(src != NULL);
374  _DIAGASSERT(extra != NULL);
375  MAKEEXTRALIST(flag, nextra, extra);
376  if (!nextra) {
377  *dst = '\0'; /* can't create nextra, return "" */
378  return 0;
379  }
380  f = getvisfun(flag);
381  for (start = dst; (c = *src++) != '\0'; /* empty */) {
382  dst = (*f)(dst, dlen, c, flag, *src, nextra);
383  if (dst == NULL) {
384  errno = ENOSPC;
385  return -1;
386  }
387  }
388  free(nextra);
389  if (dlen && *dlen == 0) {
390  errno = ENOSPC;
391  return -1;
392  }
393  *dst = '\0';
394  return (int)(dst - start);
395 }
396 
397 int
398 strsvis(char *dst, const char *csrc, int flag, const char *extra)
399 {
400  return istrsnvis(dst, NULL, csrc, flag, extra);
401 }
402 
403 int
404 strsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra)
405 {
406  return istrsnvis(dst, &dlen, csrc, flag, extra);
407 }
408 
409 static int
410 istrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag,
411  const char *extra)
412 {
413  unsigned char c;
414  char *start;
415  char *nextra = NULL;
416  const unsigned char *src = (const unsigned char *)csrc;
417  visfun_t f;
418 
419  _DIAGASSERT(dst != NULL);
420  _DIAGASSERT(src != NULL);
421  _DIAGASSERT(extra != NULL);
422  MAKEEXTRALIST(flag, nextra, extra);
423  if (! nextra) {
424  if (dlen && *dlen == 0) {
425  errno = ENOSPC;
426  return -1;
427  }
428  *dst = '\0'; /* can't create nextra, return "" */
429  return 0;
430  }
431 
432  f = getvisfun(flag);
433  for (start = dst; len > 0; len--) {
434  c = *src++;
435  dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra);
436  if (dst == NULL) {
437  errno = ENOSPC;
438  return -1;
439  }
440  }
441  free(nextra);
442  if (dlen && *dlen == 0) {
443  errno = ENOSPC;
444  return -1;
445  }
446  *dst = '\0';
447  return (int)(dst - start);
448 }
449 
450 int
451 strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)
452 {
453  return istrsnvisx(dst, NULL, csrc, len, flag, extra);
454 }
455 
456 int
457 strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag,
458  const char *extra)
459 {
460  return istrsnvisx(dst, &dlen, csrc, len, flag, extra);
461 }
462 #endif
463 
464 #if !HAVE_VIS
465 /*
466  * vis - visually encode characters
467  */
468 static char *
469 invis(char *dst, size_t *dlen, int c, int flag, int nextc)
470 {
471  char *extra = NULL;
472  unsigned char uc = (unsigned char)c;
473  visfun_t f;
474 
475  _DIAGASSERT(dst != NULL);
476 
477  MAKEEXTRALIST(flag, extra, "");
478  if (! extra) {
479  if (dlen && *dlen == 0) {
480  errno = ENOSPC;
481  return NULL;
482  }
483  *dst = '\0'; /* can't create extra, return "" */
484  return dst;
485  }
486  f = getvisfun(flag);
487  dst = (*f)(dst, dlen, uc, flag, nextc, extra);
488  free(extra);
489  if (dst == NULL || (dlen && *dlen == 0)) {
490  errno = ENOSPC;
491  return NULL;
492  }
493  *dst = '\0';
494  return dst;
495 }
496 
497 char *
498 vis(char *dst, int c, int flag, int nextc)
499 {
500  return invis(dst, NULL, c, flag, nextc);
501 }
502 
503 char *
504 nvis(char *dst, size_t dlen, int c, int flag, int nextc)
505 {
506  return invis(dst, &dlen, c, flag, nextc);
507 }
508 
509 
510 /*
511  * strvis, strvisx - visually encode characters from src into dst
512  *
513  * Dst must be 4 times the size of src to account for possible
514  * expansion. The length of dst, not including the trailing NULL,
515  * is returned.
516  *
517  * Strvisx encodes exactly len bytes from src into dst.
518  * This is useful for encoding a block of data.
519  */
520 static int
521 istrnvis(char *dst, size_t *dlen, const char *src, int flag)
522 {
523  char *extra = NULL;
524  int rv;
525 
526  MAKEEXTRALIST(flag, extra, "");
527  if (!extra) {
528  if (dlen && *dlen == 0) {
529  errno = ENOSPC;
530  return -1;
531  }
532  *dst = '\0'; /* can't create extra, return "" */
533  return 0;
534  }
535  rv = istrsnvis(dst, dlen, src, flag, extra);
536  free(extra);
537  return rv;
538 }
539 
540 int
541 strvis(char *dst, const char *src, int flag)
542 {
543  return istrnvis(dst, NULL, src, flag);
544 }
545 
546 int
547 strnvis(char *dst, size_t dlen, const char *src, int flag)
548 {
549  return istrnvis(dst, &dlen, src, flag);
550 }
551 
552 static int
553 istrnvisx(char *dst, size_t *dlen, const char *src, size_t len, int flag)
554 {
555  char *extra = NULL;
556  int rv;
557 
558  MAKEEXTRALIST(flag, extra, "");
559  if (!extra) {
560  if (dlen && *dlen == 0) {
561  errno = ENOSPC;
562  return -1;
563  }
564  *dst = '\0'; /* can't create extra, return "" */
565  return 0;
566  }
567  rv = istrsnvisx(dst, dlen, src, len, flag, extra);
568  free(extra);
569  return rv;
570 }
571 
572 int
573 strvisx(char *dst, const char *src, size_t len, int flag)
574 {
575  return istrnvisx(dst, NULL, src, len, flag);
576 }
577 
578 int
579 strnvisx(char *dst, size_t dlen, const char *src, size_t len, int flag)
580 {
581  return istrnvisx(dst, &dlen, src, len, flag);
582 }
583 
584 #endif