summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2002-03-23 17:38:27 +0000
committerchristos <christos@NetBSD.org>2002-03-23 17:38:27 +0000
commite20c30d79415b1fdd55b176fcda19dcfc4e899d4 (patch)
tree39dea70bd3fa4aa27f22f321186d0927a3c4b82e
parent4498b37c8b676e3e369f23111c13ab341a3d3a90 (diff)
- Add VIS_HTTPSTYLE from FreeBSD.
- svis, strsvis, strsvisx were not reversible, because they did not encode \\ unless it was passed in the extras array. - Fix documentation to match the proper signature of the functions.
-rw-r--r--lib/libc/gen/unvis.337
-rw-r--r--lib/libc/gen/unvis.c46
-rw-r--r--lib/libc/gen/vis.322
-rw-r--r--lib/libc/gen/vis.c96
4 files changed, 162 insertions, 39 deletions
diff --git a/lib/libc/gen/unvis.3 b/lib/libc/gen/unvis.3
index 68b348749bb..7aa1b67c853 100644
--- a/lib/libc/gen/unvis.3
+++ b/lib/libc/gen/unvis.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: unvis.3,v 1.13 2002/02/07 09:24:05 ross Exp $
+.\" $NetBSD: unvis.3,v 1.14 2002/03/23 17:38:27 christos Exp $
.\"
.\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -45,14 +45,17 @@
.Sh SYNOPSIS
.Fd #include \*[Lt]vis.h\*[Gt]
.Ft int
-.Fn unvis "char *cp" "char c" "int *astate" "int flag"
+.Fn unvis "char *cp" "int c" "int *astate" "int flag"
.Ft int
-.Fn strunvis "char *dst" "char *src"
+.Fn strunvis "char *dst" "const char *src"
+.Ft int
+.Fn strunvisx "char *dst" "const char *src" "int flag"
.Sh DESCRIPTION
The
-.Fn unvis
-and
+.Fn unvis ,
.Fn strunvis
+and
+.Fn strunvisx
functions
are used to decode a visual representation of characters, as produced
by the
@@ -92,6 +95,17 @@ should be equal to the size of
(that is, no expansion takes place during decoding).
.Pp
The
+.Fn strunvisx
+function does the same as the
+.Fn strunvis
+function,
+but it allows you to add a flag that specifies the style the string
+.Ar src
+is encoded with.
+Currently, the only supported flag is
+.Dv VIS_HTTPSTYLE .
+.Pp
+The
.Fn unvis
function implements a state machine that can be used to decode an
arbitrary stream of bytes.
@@ -132,6 +146,14 @@ one more time with flag set to
.Dv UNVIS_END
to extract any remaining character (the character passed in is ignored).
.Pp
+The
+.Ar flag
+argument is also used to specify the encoding style of the source.
+If set to
+.Dv VIS_HTTPSTYLE ,
+.Fn unvis
+will decode URI strings as specified in RFC 1808.
+.Pp
The following code fragment illustrates a proper use of
.Fn unvis .
.Bd -literal -offset indent
@@ -162,6 +184,11 @@ if (unvis(\*[Am]out, (char)0, \*[Am]state, UNVIS_END) == UNVIS_VALID)
.Xr unvis 1 ,
.Xr vis 1 ,
.Xr vis 3
+.Rs
+.%A R. Fielding
+.%T Relative Uniform Resource Locators
+.%O RFC1808
+.Re
.Sh HISTORY
The
.Fn unvis
diff --git a/lib/libc/gen/unvis.c b/lib/libc/gen/unvis.c
index 4f2f526382e..747863b98f0 100644
--- a/lib/libc/gen/unvis.c
+++ b/lib/libc/gen/unvis.c
@@ -1,4 +1,4 @@
-/* $NetBSD: unvis.c,v 1.21 2002/01/31 22:43:38 tv Exp $ */
+/* $NetBSD: unvis.c,v 1.22 2002/03/23 17:38:27 christos Exp $ */
/*-
* Copyright (c) 1989, 1993
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: unvis.c,v 1.21 2002/01/31 22:43:38 tv Exp $");
+__RCSID("$NetBSD: unvis.c,v 1.22 2002/03/23 17:38:27 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -73,8 +73,11 @@ __warn_references(unvis,
#define S_CTRL 4 /* control char started (^) */
#define S_OCTAL2 5 /* octal digit 2 */
#define S_OCTAL3 6 /* octal digit 3 */
+#define S_HEX1 7 /* hex digit */
+#define S_HEX2 8 /* hex digit 2 */
#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10))
int
unvis(cp, c, astate, flag)
@@ -99,7 +102,8 @@ __unvis13(cp, c, astate, flag)
_DIAGASSERT(astate != NULL);
if (flag & UNVIS_END) {
- if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
+ if (*astate == S_OCTAL2 || *astate == S_OCTAL3
+ || *astate == S_HEX2) {
*astate = S_GROUND;
return (UNVIS_VALID);
}
@@ -114,6 +118,10 @@ __unvis13(cp, c, astate, flag)
*astate = S_START;
return (0);
}
+ if ((flag & VIS_HTTPSTYLE) && c == '%') {
+ *astate = S_HEX1;
+ return (0);
+ }
*cp = c;
return (UNVIS_VALID);
@@ -236,7 +244,24 @@ __unvis13(cp, c, astate, flag)
* we were done, push back passed char
*/
return (UNVIS_VALIDPUSH);
-
+ case S_HEX1:
+ if (isxdigit(c)) {
+ *cp = xtod(c);
+ *astate = S_HEX2;
+ return (0);
+ }
+ /*
+ * no - done with current sequence, push back passed char
+ */
+ *astate = S_GROUND;
+ return (UNVIS_VALIDPUSH);
+ case S_HEX2:
+ *astate = S_GROUND;
+ if (isxdigit(c)) {
+ *cp = xtod(c) | (*cp << 4);
+ return (UNVIS_VALID);
+ }
+ return (UNVIS_VALIDPUSH);
default:
/*
* decoder in unknown state - (probably uninitialized)
@@ -254,9 +279,10 @@ __unvis13(cp, c, astate, flag)
*/
int
-strunvis(dst, src)
+strunvisx(dst, src, flag)
char *dst;
const char *src;
+ int flag;
{
char c;
char *start = dst;
@@ -267,7 +293,7 @@ strunvis(dst, src)
while ((c = *src++) != '\0') {
again:
- switch (__unvis13(dst, c, &state, 0)) {
+ switch (__unvis13(dst, c, &state, flag)) {
case UNVIS_VALID:
dst++;
break;
@@ -286,4 +312,12 @@ strunvis(dst, src)
*dst = '\0';
return (dst - start);
}
+
+int
+strunvis(dst, src)
+ char *dst;
+ const char *src;
+{
+ return strunvisx(dst, src, 0);
+}
#endif
diff --git a/lib/libc/gen/vis.3 b/lib/libc/gen/vis.3
index 5b845ab24e0..af88b6ce19f 100644
--- a/lib/libc/gen/vis.3
+++ b/lib/libc/gen/vis.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: vis.3,v 1.15 2002/02/07 07:00:18 ross Exp $
+.\" $NetBSD: vis.3,v 1.16 2002/03/23 17:38:27 christos Exp $
.\"
.\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -205,11 +205,15 @@ warning on the use of the
.Dv VIS_NOSLASH
flag below).
.Pp
-There are three forms of encoding.
+There are four forms of encoding.
All forms use the backslash character
.Ql \e
to introduce a special
-sequence; two backslashes are used to represent a real backslash.
+sequence; two backslashes are used to represent a real backslash,
+except
+.Dv VIS_HTTPSTYLE
+that uses
+.Ql $ .
These are the visual formats:
.Bl -tag -width VIS_CSTYLE
.It (default)
@@ -293,6 +297,13 @@ Use a three digit octal sequence. The form is
where
.Em d
represents an octal digit.
+.It Dv VIS_HTTPSTYLE
+Use URI encoding as described in RFC 1808.
+The form is
+.Ql %xx
+where
+.Em x
+represents a hexadecimal digit.
.El
.Pp
There is one additional flag,
@@ -310,6 +321,11 @@ ambiguous and non-invertible.
.Xr unvis 1 ,
.Xr vis 1 ,
.Xr unvis 3
+.Rs
+.%A R. Fielding
+.%T Relative Uniform Resource Locators
+.%O RFC1808
+.Re
.Sh HISTORY
The
.Fa vis ,
diff --git a/lib/libc/gen/vis.c b/lib/libc/gen/vis.c
index 17a6625f5f3..9021147c8a7 100644
--- a/lib/libc/gen/vis.c
+++ b/lib/libc/gen/vis.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vis.c,v 1.21 2002/01/31 22:43:39 tv Exp $ */
+/* $NetBSD: vis.c,v 1.22 2002/03/23 17:38:27 christos Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: vis.c,v 1.21 2002/01/31 22:43:39 tv Exp $");
+__RCSID("$NetBSD: vis.c,v 1.22 2002/03/23 17:38:27 christos Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
@@ -44,6 +44,7 @@ __RCSID("$NetBSD: vis.c,v 1.21 2002/01/31 22:43:39 tv Exp $");
#include <assert.h>
#include <vis.h>
+#include <stdlib.h>
#ifdef __weak_alias
__weak_alias(strsvis,_strsvis)
@@ -70,20 +71,43 @@ __weak_alias(vis,_vis)
#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 MAKEEXTRALIST(flag, extra) \
+#define MAKEEXTRALIST(flag, extra, orig) \
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 *o = orig; \
+ char *e; \
+ while (*o++) \
+ continue; \
+ extra = alloca((size_t)((o - orig) + MAXEXTRAS)); \
+ 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 HVIS, the macro of vis used to HTTP style (RFC 1808)
+ */
+#define HVIS(dst, c, flag, nextc, extra) \
+do \
+ if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \
+ *dst++ = '%'; \
+ *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \
+ *dst++ = xtoa((unsigned int)c & 0xf); \
+ } else { \
+ SVIS(dst, c, flag, nextc, extra); \
+ } \
+while (/*CONSTCOND*/0)
+
/*
* This is SVIS, the central macro of vis.
* dst: Pointer to the destination buffer
@@ -171,10 +195,14 @@ svis(dst, c, flag, nextc, extra)
int c, flag, nextc;
const char *extra;
{
+ char *nextra;
_DIAGASSERT(dst != NULL);
_DIAGASSERT(extra != NULL);
-
- SVIS(dst, c, flag, nextc, extra);
+ MAKEEXTRALIST(flag, nextra, extra);
+ if (flag & VIS_HTTPSTYLE)
+ HVIS(dst, c, flag, nextc, nextra);
+ else
+ SVIS(dst, c, flag, nextc, nextra);
*dst = '\0';
return(dst);
}
@@ -204,13 +232,19 @@ strsvis(dst, src, flag, extra)
{
char c;
char *start;
+ char *nextra;
_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 (flag & VIS_HTTPSTYLE) {
+ for (start = dst; (c = *src++) != '\0'; /* empty */)
+ HVIS(dst, c, flag, *src, nextra);
+ } else {
+ for (start = dst; (c = *src++) != '\0'; /* empty */)
+ SVIS(dst, c, flag, *src, nextra);
+ }
*dst = '\0';
return (dst - start);
}
@@ -226,14 +260,23 @@ strsvisx(dst, src, len, flag, extra)
{
char c;
char *start;
+ char *nextra;
_DIAGASSERT(dst != NULL);
_DIAGASSERT(src != NULL);
_DIAGASSERT(extra != NULL);
-
- for (start = dst; len > 0; len--) {
- c = *src++;
- SVIS(dst, c, flag, len ? *src : '\0', extra);
+ MAKEEXTRALIST(flag, nextra, extra);
+
+ if (flag & VIS_HTTPSTYLE) {
+ for (start = dst; len > 0; len--) {
+ c = *src++;
+ HVIS(dst, c, flag, len ? *src : '\0', nextra);
+ }
+ } else {
+ for (start = dst; len > 0; len--) {
+ c = *src++;
+ SVIS(dst, c, flag, len ? *src : '\0', nextra);
+ }
}
*dst = '\0';
return (dst - start);
@@ -249,12 +292,15 @@ vis(dst, c, flag, nextc)
int c, flag, nextc;
{
- char extra[MAXEXTRAS];
+ char *extra;
_DIAGASSERT(dst != NULL);
- MAKEEXTRALIST(flag, extra);
- SVIS(dst, c, flag, nextc, extra);
+ MAKEEXTRALIST(flag, extra, "");
+ if (flag & VIS_HTTPSTYLE)
+ HVIS(dst, c, flag, nextc, extra);
+ else
+ SVIS(dst, c, flag, nextc, extra);
*dst = '\0';
return (dst);
}
@@ -276,9 +322,9 @@ strvis(dst, src, flag)
const char *src;
int flag;
{
- char extra[MAXEXTRAS];
+ char *extra;
- MAKEEXTRALIST(flag, extra);
+ MAKEEXTRALIST(flag, extra, "");
return (strsvis(dst, src, flag, extra));
}
@@ -290,9 +336,9 @@ strvisx(dst, src, len, flag)
size_t len;
int flag;
{
- char extra[MAXEXTRAS];
+ char *extra;
- MAKEEXTRALIST(flag, extra);
+ MAKEEXTRALIST(flag, extra, "");
return (strsvisx(dst, src, len, flag, extra));
}
#endif