Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Mar 2001 20:28:02 +0100 (CET)
From:      Cyrille Lefevre <clefevre@poboxes.com>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/26005: MIME quoted-printable encoding added to vis/unvis + bug fix
Message-ID:  <200103221928.f2MJS2I22918@gits.dyndns.org>

next in thread | raw e-mail | index | archive | help

>Number:         26005
>Category:       bin
>Synopsis:       MIME quoted-printable encoding added to vis/unvis + bug fix
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Mar 22 11:30:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Cyrille Lefevre
>Release:        FreeBSD 4.3-BETA i386
>Organization:
ACME
>Environment:
System: FreeBSD gits 4.3-BETA FreeBSD 4.3-BETA #18: Sat Mar 17 02:17:40 CET 2001 root@:/disk2/4.x-stable/src/sys/compile/CUSTOM i386

>Description:
	MIME quoted-printable encoding added to vis/unvis.

	this allow you to read quoted-printable messages through
	the mail interface using !unvis -q which may be somewhat
	usefull.

	the bug fix is in the S_START case of unvis where
		*cp = isdigit(c) ? (c - '0') : (tolower(c) - 'a');
	must be
		*cp = isdigit(c) ? (c - '0') : (tolower(c) - 'a' + 10);

	also, added references to strunvisx in the unvis(3) manual page.

	the unvis(3) API has been change since characters from
	stdio are in and not char. following this rule, I get rid
	of all uneeded casts. I've checked all the source tree,
	unvis(3) is only used by unvis(1).

	new -h and -q flags added to unvis(1).

	well, I know that my english is very poor. so, the manual
	pages need to be reviewed. at least, the added parts.
>How-To-Repeat:
	validation tests are :

		vis -q /bin/ls | unvis -q | cmp - /bin/ls
		vis -q /bin/ls | mimencode -u -q | cmp - /bin/ls
		mimencode -q /bin/ls | unvis -q | cmp - /bin/ls

	mimencode come from the metamail port.
>Fix:

Index: include/vis.h
===================================================================
RCS file: /home/ncvs/src/include/vis.h,v
retrieving revision 1.6.2.1
diff -u -r1.6.2.1 vis.h
--- include/vis.h	2000/08/17 08:25:53	1.6.2.1
+++ include/vis.h	2001/03/21 23:39:51
@@ -47,24 +47,25 @@
 /*
  * to select alternate encoding format
  */
-#define	VIS_OCTAL	0x01	/* use octal \ddd format */
-#define	VIS_CSTYLE	0x02	/* use \[nrft0..] where appropriate */
+#define	VIS_OCTAL	0x001	/* use octal \ddd format */
+#define	VIS_CSTYLE	0x002	/* use \[nrft0..] where appropriate */
 
 /*
  * to alter set of characters encoded (default is to encode all
  * non-graphic except space, tab, and newline).
  */
-#define	VIS_SP		0x04	/* also encode space */
-#define	VIS_TAB		0x08	/* also encode tab */
-#define	VIS_NL		0x10	/* also encode newline */
+#define	VIS_SP		0x004	/* also encode space */
+#define	VIS_TAB		0x008	/* also encode tab */
+#define	VIS_NL		0x010	/* also encode newline */
 #define	VIS_WHITE	(VIS_SP | VIS_TAB | VIS_NL)
-#define	VIS_SAFE	0x20	/* only encode "unsafe" characters */
+#define	VIS_SAFE	0x020	/* only encode "unsafe" characters */
 
 /*
  * other
  */
-#define	VIS_NOSLASH	0x40	/* inhibit printing '\' */
-#define	VIS_HTTPSTYLE	0x80	/* http-style escape % HEX HEX */
+#define	VIS_NOSLASH	0x040	/* inhibit printing '\' */
+#define	VIS_HTTPSTYLE	0x080	/* http-style escape % HEX HEX */
+#define	VIS_QPSTYLE	0x100	/* quoted-printable-style escape = HEX HEX */
 
 /*
  * unvis return codes
@@ -86,8 +87,9 @@
 char	*vis __P((char *, int, int, int));
 int	strvis __P((char *, const char *, int));
 int	strvisx __P((char *, const char *, size_t, int));
+int	unvis __P((int *, int, int *, int));
 int	strunvis __P((char *, const char *));
-int	unvis __P((char *, int, int *, int));
+int	strunvisx __P((char *, const char *, int));
 __END_DECLS
 
 #endif /* !_VIS_H_ */
Index: usr.bin/vis/foldit.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/vis/foldit.c,v
retrieving revision 1.4
diff -u -r1.4 foldit.c
--- usr.bin/vis/foldit.c	1999/08/28 01:07:25	1.4
+++ usr.bin/vis/foldit.c	2001/03/21 04:19:54
@@ -40,7 +40,10 @@
 #endif /* not lint */
 
 #include <stdio.h>
+#include <vis.h>
 
+extern int eflags;
+
 int
 foldit(chunk, col, max)
 	char *chunk;
@@ -54,24 +57,34 @@
 again:
 	cp = chunk;
 	while (*cp) {
-		switch(*cp) {
-		case '\n':
-		case '\r':
-			col = 0;
-			break;
-		case '\t':
-			col = col + 8 &~ 07;
-			break;
-		case '\b':
-			col = col ? col - 1 : 0;
-			break;
-		default:
-			col++;
-		}
-		if (col > (max - 2)) {
-			printf("\\\n");
-			col = 0;
-			goto again;
+		if (eflags & VIS_QPSTYLE) {
+			if (*cp == '\n')
+				col = 0;
+			else if (++col > (max - 2)) {
+				printf ("=\n");
+				col = 0;
+				goto again;
+			}
+		} else {
+			switch(*cp) {
+			case '\n':
+			case '\r':
+				col = 0;
+				break;
+			case '\t':
+				col = col + 8 &~ 07;
+				break;
+			case '\b':
+				col = col ? col - 1 : 0;
+				break;
+			default:
+				col++;
+			}
+			if (col > (max - 2)) {
+				printf ("\\\n");
+				col = 0;
+				goto again;
+			}
 		}
 		cp++;
 	}
Index: usr.bin/vis/vis.1
===================================================================
RCS file: /home/ncvs/src/usr.bin/vis/vis.1,v
retrieving revision 1.6
diff -u -r1.6 vis.1
--- usr.bin/vis/vis.1	1999/08/28 01:07:25	1.6
+++ usr.bin/vis/vis.1	2001/03/22 02:31:39
@@ -40,7 +40,7 @@
 .Nd display non-printable characters in a visual format
 .Sh SYNOPSIS
 .Nm
-.Op Fl cbflnostw
+.Op Fl cbfhlnoqstw
 .Op Fl F Ar foldwidth
 .Op Ar
 .Sh DESCRIPTION
@@ -83,6 +83,12 @@
 .It Fl f
 Same as
 .Fl F .
+.It Fl h
+Request a format which displays non-printable characters using URI
+encoding sequences (%dd where dd is an hexadecimal number) as
+described in RFC 2396.  The
+.Fl b
+option is implied.
 .It Fl l
 Mark newlines with the visible sequence
 .Ql \e$ ,
@@ -106,6 +112,14 @@
 .It Fl o
 Request a format which displays non-printable characters as
 an octal number, \eddd.
+.It Fl q
+Request a format which displays non-printable characters in MIME
+quoted-printable sequences (=dd where dd is an hexadecimal number) as
+described in RFC 2045.  The
+.Fl b
+and
+.Fl F 77
+options are implied.
 .It Fl s
 Only characters considered unsafe to send to a terminal are encoded.
 This flag allows backspace, bell, and carriage return in addition
@@ -117,7 +131,24 @@
 .El
 .Sh SEE ALSO
 .Xr unvis 1 ,
-.Xr vis 3
+.Xr vis 3 ,
+.Xr unvis 3 .
+.Rs
+.%T Multipurpose Internet Mail Extensions (MIME) Part One
+.%R Format of Internet Message Bodies.
+.%A N. Freed
+.%A N. Borenstein
+.%D November 1996
+.%O RFC2045
+.Re
+.Rs
+.%T Relative Uniform Resource Locators (URI)
+.%R Generic Syntax
+.%A T. Berners-Lee
+.%A R. Fielding
+.%D August 1998
+.%O RFC2396
+.Re
 .Sh HISTORY
 The
 .Nm
Index: usr.bin/vis/vis.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/vis/vis.c,v
retrieving revision 1.6
diff -u -r1.6 vis.c
--- usr.bin/vis/vis.c	1999/08/28 01:07:25	1.6
+++ usr.bin/vis/vis.c	2001/03/22 03:48:21
@@ -67,7 +67,7 @@
 
 	(void) setlocale(LC_CTYPE, "");
 
-	while ((ch = getopt(argc, argv, "nwctsobfF:ld")) != -1)
+	while ((ch = getopt(argc, argv, "nwchqtsobfF:ld")) != -1)
 		switch((char)ch) {
 		case 'n':
 			none++;
@@ -78,6 +78,12 @@
 		case 'c':
 			eflags |= VIS_CSTYLE;
 			break;
+		case 'h':
+			eflags |= VIS_HTTPSTYLE;
+			break;
+		case 'q':
+			eflags |= VIS_QPSTYLE;
+			break;
 		case 't':
 			eflags |= VIS_TAB;
 			break;
@@ -112,6 +118,11 @@
 	argc -= optind;
 	argv += optind;
 
+	if (eflags & VIS_QPSTYLE) {
+		foldwidth = 77;
+		fold++;
+	}
+
 	if (*argv)
 		while (*argv) {
 			if ((fp=fopen(*argv, "r")) != NULL)
@@ -125,14 +136,13 @@
 	exit(0);
 }
 
-
 static void
 usage()
 {
 #ifdef DEBUG
-	fprintf(stderr, "usage: vis [-cbflnostwd] [-F foldwidth] [file ...]\n");
+	fprintf(stderr, "usage: vis [-cbfhlnoqstwd] [-F foldwidth] [file ...]\n");
 #else
-	fprintf(stderr, "usage: vis [-cbflnostw] [-F foldwidth] [file ...]\n");
+	fprintf(stderr, "usage: vis [-cbfhlnoqstw] [-F foldwidth] [file ...]\n");
 #endif
 	exit(1);
 }
@@ -156,7 +166,8 @@
 			if (c == '\\')
 				*cp++ = '\\';
 			*cp = '\0';
-		} else if (markeol && c == '\n') {
+		} else if (markeol && c == '\n' &&
+			   !(eflags & (VIS_HTTPSTYLE|VIS_QPSTYLE))) {
 			cp = buff;
 			if ((eflags & VIS_NOSLASH) == 0)
 				*cp++ = '\\';
@@ -164,7 +175,7 @@
 			*cp++ = '\n';
 			*cp = '\0';
 		} else
-			(void) vis(buff, (char)c, eflags, (char)rachar);
+			(void) vis(buff, c, eflags, rachar);
 
 		cp = buff;
 		if (fold) {
@@ -186,6 +197,11 @@
 	/*
 	 * terminate partial line with a hidden newline
 	 */
-	if (fold && *(cp-1) != '\n')
-		printf("\\\n");
+	if (fold && *(cp-1) != '\n') {
+		if (eflags & VIS_QPSTYLE)
+			putchar ('=');
+		else
+			putchar ('\\');
+		putchar ('\n');
+	}
 }
Index: usr.bin/unvis/unvis.1
===================================================================
RCS file: /home/ncvs/src/usr.bin/unvis/unvis.1,v
retrieving revision 1.5
diff -u -r1.5 unvis.1
--- usr.bin/unvis/unvis.1	1999/08/28 01:07:12	1.5
+++ usr.bin/unvis/unvis.1	2001/03/22 02:30:49
@@ -40,6 +40,7 @@
 .Nd "revert a visual representation of data back to original form"
 .Sh SYNOPSIS
 .Nm
+.Op Fl hq
 .Op Ar
 .Sh DESCRIPTION
 .Nm Unvis
@@ -47,10 +48,36 @@
 .Xr vis 1 .
 It reverts
 a visual representation of data back to its original form on standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl h
+Inputs are in URI encoded form (%dd where dd is an hexadecimal number)
+as described in RFC 2396.
+.It Fl q
+Inputs are in MIME quoted-printable from (=dd where dd is an
+hexadecimal number) as described in RFC 2045.
+.El
 .Sh SEE ALSO
 .Xr vis 1 ,
 .Xr unvis 3 ,
-.Xr vis 3
+.Xr vis 3 .
+.Rs
+.%T Multipurpose Internet Mail Extensions (MIME) Part One
+.%R Format of Internet Message Bodies.
+.%A N. Freed
+.%A N. Borenstein
+.%D November 1996
+.%O RFC2045
+.Re
+.Rs
+.%T Relative Uniform Resource Locators (URI)
+.%R Generic Syntax
+.%A T. Berners-Lee
+.%A R. Fielding
+.%D August 1998
+.%O RFC2396
+.Re
 .Sh HISTORY
 The
 .Nm
Index: usr.bin/unvis/unvis.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/unvis/unvis.c,v
retrieving revision 1.5
diff -u -r1.5 unvis.c
--- usr.bin/unvis/unvis.c	1999/08/28 01:07:13	1.5
+++ usr.bin/unvis/unvis.c	2001/03/21 05:53:52
@@ -50,6 +50,8 @@
 #include <unistd.h>
 #include <vis.h>
 
+int eflags;
+
 void process __P((FILE *, char *));
 static void usage __P((void));
 
@@ -60,8 +62,14 @@
 	FILE *fp;
 	int ch;
 
-	while ((ch = getopt(argc, argv, "")) != -1)
+	while ((ch = getopt(argc, argv, "hq")) != -1)
 		switch((char)ch) {
+		case 'h':   
+			eflags |= VIS_HTTPSTYLE;
+			break; 
+		case 'q':
+			eflags |= VIS_QPSTYLE;
+			break;
 		case '?':
 		default:
 			usage();
@@ -85,7 +93,7 @@
 static void
 usage()
 {
-	fprintf(stderr, "usage: unvis [file ...]\n");
+	fprintf(stderr, "usage: unvis [-hq] [file ...]\n");
 	exit(1);
 }
 
@@ -96,12 +104,12 @@
 {
 	register int offset = 0, c, ret;
 	int state = 0;
-	char outc;
+	int outc;
 
 	while ((c = getc(fp)) != EOF) {
 		offset++;
 	again:
-		switch(ret = unvis(&outc, (char)c, &state, 0)) {
+		switch(ret = unvis(&outc, c, &state, eflags)) {
 		case UNVIS_VALID:
 			putchar(outc);
 			break;
@@ -119,6 +127,6 @@
 			errx(1, "bad return value (%d), can't happen", ret);
 		}
 	}
-	if (unvis(&outc, (char)0, &state, UNVIS_END) == UNVIS_VALID)
+	if (unvis(&outc, 0, &state, UNVIS_END) == UNVIS_VALID)
 		putchar(outc);
 }
Index: lib/libc/gen/unvis.3
===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/unvis.3,v
retrieving revision 1.6.2.3
diff -u -r1.6.2.3 unvis.3
--- lib/libc/gen/unvis.3	2000/12/29 14:44:45	1.6.2.3
+++ lib/libc/gen/unvis.3	2001/03/22 02:29:27
@@ -47,32 +47,45 @@
 .Fn unvis "char *cp" "int c" "int *astate" "int flag"
 .Ft int 
 .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
 .Xr vis 3
 function, back into
-the original form.  Unvis is called with successive characters in
+the original form.  The
+.Fn unvis
+function is called with successive characters in
 .Ar c 
 until a valid
 sequence is recognized, at which time the decoded character is
 available at the character pointed to by
 .Ar cp .
-Strunvis decodes the
+The
+.Fn strunvis
+function decodes the
 characters pointed to by
 .Ar src
 into the buffer pointed to by
 .Ar dst .
+The
+.Fa flag
+parameter is used for altering the default range of
+characters considered for decoding.
 .Pp
 The
 .Fn strunvis
-function
-simply copies
+and
+.Fn strunvisx
+functions
+simply copy
 .Ar src
 to
 .Ar dst ,
@@ -124,9 +137,30 @@
 unknown state.  The decoder is placed into the starting state.
 .El
 .Pp
+Two forms of encoding style need to be specified to be recognized.
+Those forms are :
+.Bl -tag -width VIS_HTTPSTYLE
+.It Dv VIS_HTTPSTYLE
+Interpret URI encoded sequences as described in RFC 2396.
+Encoded values have the form
+.Ql %dd
+where
+.Em d
+represents an hexadecimal digit.
+.It Dv VIS_QPSTYLE
+Interpret MIME quoted-printable sequences as described in RFC 2045.
+Encoded values have the form
+.Ql =dd
+where
+.Em d
+represents an hexadecimal digit.
+.El
+.Pp
 When all bytes in the stream have been processed, call
 .Fn unvis
-one more time with flag set to
+one more time with
+.Fa flag
+set to
 .Dv UNVIS_END
 to extract any remaining character (the character passed in is ignored).
 .Pp
@@ -157,7 +191,26 @@
 	(void) putchar(out);
 .Ed
 .Sh SEE ALSO
-.Xr vis 1
+.Xr unvis 1 ,
+.Xr vis 1 ,
+.Xr strvis 3 ,
+.Xr vis 3 .
+.Rs
+.%T Multipurpose Internet Mail Extensions (MIME) Part One
+.%R Format of Internet Message Bodies.
+.%A N. Freed
+.%A N. Borenstein
+.%D November 1996
+.%O RFC2045
+.Re
+.Rs
+.%T Relative Uniform Resource Locators (URI)
+.%R Generic Syntax
+.%A T. Berners-Lee
+.%A R. Fielding
+.%D August 1998
+.%O RFC2396
+.Re
 .Sh HISTORY
 The
 .Fn unvis
Index: lib/libc/gen/unvis.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/unvis.c,v
retrieving revision 1.4.8.1
diff -u -r1.4.8.1 unvis.c
--- lib/libc/gen/unvis.c	2000/08/17 08:25:54	1.4.8.1
+++ lib/libc/gen/unvis.c	2001/03/22 18:41:49
@@ -38,6 +38,7 @@
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/types.h>
+#include <stdio.h>
 #include <vis.h>
 
 /*
@@ -53,19 +54,18 @@
 #define	S_HEX2		7	/* hex digit 2 */
 
 #define	S_HTTP		0x080	/* %HEXHEX escape */
+#define	S_QP		0x100	/* =HEXHEX escape */
 
-#define	isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
-#define	ishex(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '9' || ((u_char)(c)) >= 'a' && ((u_char)(c)) <= 'f')
+#define	isoctal(c)	((c) >= '0' && (c) <= '7')
+#define	ishex(c)	((c) >= '0' && (c) <= '9' || (c) >= 'a' && (c) <= 'f')
 
 /*
  * unvis - decode characters previously encoded by vis
  */
 int
 unvis(cp, c, astate, flag)
-	char *cp;
-	int c, *astate, flag;
+	int *cp, c, *astate, flag;
 {
-
 	if (flag & UNVIS_END) {
 		if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
 			*astate = S_GROUND;
@@ -74,15 +74,19 @@
 		return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
 	}
 
-	switch (*astate & ~S_HTTP) {
+	switch (*astate & ~(S_HTTP|S_QP)) {
 
 	case S_GROUND:
 		*cp = 0;
-		if (c == '\\') {
+		if (c == '\\' && !(flag & VIS_QPSTYLE)) {
 			*astate = S_START;
 			return (0);
+		}
+		if (c == '=' && (flag & VIS_QPSTYLE)) {
+			*astate = S_START | S_QP;
+			return (0);
 		}
-		if (flag & VIS_HTTPSTYLE && c == '%') {
+		if (c == '%' && (flag & VIS_HTTPSTYLE)) {
 			*astate = S_START | S_HTTP;
 			return (0);
 		}
@@ -90,9 +94,9 @@
 		return (UNVIS_VALID);
 
 	case S_START:
-		if (*astate & S_HTTP) {
+		if (*astate & (S_HTTP|S_QP)) {
 		    if (ishex(tolower(c))) {
-			*cp = isdigit(c) ? (c - '0') : (tolower(c) - 'a');
+			*cp = isdigit(c) ? (c - '0') : (tolower(c) - 'a' + 10);
 			*astate = S_HEX2;
 			return (0);
 		    }
@@ -218,7 +222,8 @@
 
 	case S_HEX2:	/* second mandatory hex digit */
 		if (ishex(tolower(c))) {
-			*cp = (isdigit(c) ? (*cp << 4) + (c - '0') : (*cp << 4) + (tolower(c) - 'a' + 10));
+			*cp = (*cp << 4) + (isdigit(c) ?
+			      (c - '0') : (tolower(c) - 'a' + 10));
 		}
 		*astate = S_GROUND;
 		return (UNVIS_VALID);
@@ -244,18 +249,19 @@
 	register char *dst;
 	register const char *src;
 {
-	register char c;
+	register int c;
+	int tc;
 	char *start = dst;
 	int state = 0;
 
 	while ( (c = *src++) ) {
 	again:
-		switch (unvis(dst, c, &state, 0)) {
+		switch (unvis(&tc, c, &state, 0)) {
 		case UNVIS_VALID:
-			dst++;
+			*dst++ = tc;
 			break;
 		case UNVIS_VALIDPUSH:
-			dst++;
+			*dst++ = tc;
 			goto again;
 		case 0:
 		case UNVIS_NOCHAR:
@@ -264,8 +270,8 @@
 			return (-1);
 		}
 	}
-	if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
-		dst++;
+	if (unvis(&tc, c, &state, UNVIS_END) == UNVIS_VALID)
+		*dst++ = tc;
 	*dst = '\0';
 	return (dst - start);
 }
@@ -274,19 +280,21 @@
 strunvisx(dst, src, flag)
 	register char *dst;
 	register const char *src;
+	int flag;
 {
-	register char c;
+	register int c;
+	int tc;
 	char *start = dst;
 	int state = 0;
     
 	while ( (c = *src++) ) {
 	again:
-		switch (unvis(dst, c, &state, flag)) {
+		switch (unvis(&tc, c, &state, flag)) {
 		case UNVIS_VALID:
-			dst++;
+			*dst++ = tc;
 			break;
 		case UNVIS_VALIDPUSH:
-			dst++;
+			*dst++ = tc;
 			goto again;
 		case 0:
 		case UNVIS_NOCHAR:
@@ -295,8 +303,8 @@
 			return (-1);
 		}
 	}
-	if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
-		dst++;
+	if (unvis(&tc, c, &state, UNVIS_END) == UNVIS_VALID)
+		*dst++ = tc;
 	*dst = '\0';
 	return (dst - start);
 }
Index: lib/libc/gen/vis.3
===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/vis.3,v
retrieving revision 1.8.2.4
diff -u -r1.8.2.4 vis.3
--- lib/libc/gen/vis.3	2001/03/06 16:45:55	1.8.2.4
+++ lib/libc/gen/vis.3	2001/03/22 02:24:03
@@ -67,7 +67,9 @@
 encoding a set of characters into a buffer, the size of the buffer should
 be four times the number of characters encoded, plus one for the trailing
 .Dv NUL .
-The flag parameter is used for altering the default range of
+The
+.Fa flag
+parameter is used for altering the default range of
 characters considered for encoding and for altering the visual
 representation.
 The additional character,
@@ -132,8 +134,7 @@
 except space, tab, and newline are encoded.
 (See
 .Xr isgraph 3 . )
-The following flags
-alter this:
+The following flags alter this:
 .Bl -tag -width VIS_WHITEX
 .It Dv VIS_SP
 Also encode space.
@@ -239,12 +240,19 @@
 is an octal digit, the latter representation is used to
 avoid ambiguity.
 .It Dv VIS_HTTPSTYLE
-Use URI encoding as described in RFC 1808.
+Use URI encoding as described in RFC 2396.
 The form is
 .Ql %dd
 where
+.Em d
+represents an hexadecimal digit.
+.It Dv VIS_QPSTYLE
+Use MIME quoted-printable encoding as described in RFC 2045.
+The form is
+.Ql =dd
+where
 .Em d
-represents a hexadecimal digit.
+represents an hexadecimal digit.
 .It Dv VIS_OCTAL
 Use a three digit octal sequence.  The form is
 .Ql \eddd
@@ -253,6 +261,13 @@
 represents an octal digit.
 .El
 .Pp
+If more than one style is specified, precedences are as follow :
+.Dv VIS_QPSTYLE ,
+.Dv VIS_HTTPSTYLE ,
+.Dv VIS_CSTYLE ,
+.Dv VIS_OCTAL ,
+.Dv (default) .
+.Pp
 There is one additional flag,
 .Dv VIS_NOSLASH ,
 which inhibits the
@@ -263,15 +278,33 @@
 meta characters as
 .Ql M-C ) .
 With this flag set, the encoding is
-ambiguous and non-invertible.
+ambiguous and non-invertible. The
+.Dv VIS_NOSLASH
+flag is implied by
+.Dv VIS_HTTPSTYLE
+or
+.Dv VIS_QPSTYLE
+styles.
 .Sh SEE ALSO
+.Xr vis 1 ,
 .Xr unvis 1 ,
 .Xr strunvis 3 ,
-.Xr unvis 3
+.Xr unvis 3 .
+.Rs
+.%T Multipurpose Internet Mail Extensions (MIME) Part One
+.%R Format of Internet Message Bodies.
+.%A N. Freed
+.%A N. Borenstein
+.%D November 1996
+.%O RFC2045
+.Re
 .Rs
+.%T Relative Uniform Resource Locators (URI)
+.%R Generic Syntax
+.%A T. Berners-Lee
 .%A R. Fielding
-.%T Relative Uniform Resource Locators
-.%O RFC1808
+.%D August 1998
+.%O RFC2396
 .Re
 .Sh HISTORY
 These functions first appeared in
Index: lib/libc/gen/vis.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/vis.c,v
retrieving revision 1.5.8.2
diff -u -r1.5.8.2 vis.c
--- lib/libc/gen/vis.c	2001/03/05 09:44:34	1.5.8.2
+++ lib/libc/gen/vis.c	2001/03/22 18:42:22
@@ -54,33 +54,84 @@
 	int c, nextc;
 	register int flag;
 {
-	c = (unsigned char)c;
+	static int lastc = EOF;
 
+	if (flag & VIS_QPSTYLE) {
+		/* Described in RFC 2045 */
+		if (c == '\n') {
+			if (isascii(lastc) && isblank(lastc)) {
+				*dst++ = '=';
+				*dst++ = c;
+			}
+			*dst++ = c;
+			goto done;
+		}
+		if (c == '=' || !(isascii(c) && (isgraph(c) || isblank(c)))) {
+			*dst++ = '=';
+			snprintf(dst, 4, "%02X", c);
+			dst += 2;
+			goto done;
+		}
+	}
+
 	if (flag & VIS_HTTPSTYLE) {
-		/* Described in RFC 1808 */
-		if (!(isalnum(c) /* alpha-numeric */
+		if (!(
+#define RFC 0
+#if RFC == 2396
+		    isalnum(c) /* alpha-numeric */
+		    /* reserved */
+		    || c == ';' || c == '/' || c == '?' || c == ':'
+		    || c == '@' || c == '&' || c == '=' || c == '+'
+		    || c == '$' || c == ','
+		    /* mark */
+		    || c == '-' || c == '_' || c == '.' || c == '!'
+		    || c == '~' || c == '*' || c == '\'' || c == '('
+		    || c == ')'
+		    /* delims /
+		    || c == '<' || c == '>' || c == '#' || c == '%'
+		    || c == '"'
+		    /* unwise */
+		    || c == '{' || c == '}' || c == '|' || c == '\\'
+		    || c == '^' || c == '[' || c == ']' || c == '`'
+#elif RFC == 1808 /* obsoleted by RFC2396 */
+		    !(isalnum(c) /* alpha-numeric */
 		    /* safe */
-		    || c == '$' || c == '-' || c == '_' || c == '.' || c == '+'
+		    || c == '$' || c == '-' || c == '_' || c == '.'
+		    || c == '+'
 		    /* extra */
 		    || c == '!' || c == '*' || c == '\'' || c == '('
-		    || c == ')' || c == ',')) {
+		    || c == ')' || c == ','
+		    /* national */
+		    || c == '{' || c == '}' || c == '|' || c == '\\'
+		    || c == '^' || c == '~' || c == '[' || c == ']'
+		    || c == '`'
+		    /* reserved */
+		    || c == ';' || c == '/' || c == '?' || c == ':'
+		    || c == '@' || c == '&' || c == '='
+		    /* punctuation */
+		    || c == '<' || c == '>' || c == '#' || c == '%'
+		    || c == '"'
+#else /* same as above, but faster. */
+		    isgraph(c) && isascii(c)
+#endif 
+		    )) {
 			*dst++ = '%';
-			snprintf(dst, 4, (c < 16 ? "0%X" : "%X"), c);
+			snprintf(dst, 4, "%02X", c);
 			dst += 2;
 			goto done;
 		}
 	}
 
 	if (isgraph(c) ||
-	   ((flag & VIS_SP) == 0 && c == ' ') ||
-	   ((flag & VIS_TAB) == 0 && c == '\t') ||
-	   ((flag & VIS_NL) == 0 && c == '\n') ||
-	   ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) {
+	    (c == ' '  && !(flag & VIS_SP)) ||
+	    (c == '\t' && !(flag & VIS_TAB)) ||
+	    (c == '\n' && !(flag & VIS_NL)) ||
+	    ((c == '\b' || c == '\007' || c == '\r')) && (flag & VIS_SAFE)) {
 		*dst++ = c;
-		if (c == '\\' && (flag & VIS_NOSLASH) == 0)
+		if (c == '\\' &&
+		    !(flag & (VIS_NOSLASH|VIS_QPSTYLE|VIS_HTTPSTYLE)))
 			*dst++ = '\\';
-		*dst = '\0';
-		return (dst);
+		goto done;
 	}
 
 	if (flag & VIS_CSTYLE) {
@@ -133,9 +184,9 @@
 	}
 	if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
 		*dst++ = '\\';
-		*dst++ = ((u_char)c >> 6 & 07) + '0';
-		*dst++ = ((u_char)c >> 3 & 07) + '0';
-		*dst++ = ((u_char)c & 07) + '0';
+		*dst++ = (c >> 6 & 07) + '0';
+		*dst++ = (c >> 3 & 07) + '0';
+		*dst++ = (c & 07) + '0';
 		goto done;
 	}
 	if ((flag & VIS_NOSLASH) == 0)
@@ -155,6 +206,7 @@
 		*dst++ = c;
 	}
 done:
+	lastc = c;
 	*dst = '\0';
 	return (dst);
 }
@@ -175,10 +227,10 @@
 	register const char *src;
 	int flag;
 {
-	register char c;
-	char *start;
+	register int c;
+	char *start = dst;
 
-	for (start = dst; (c = *src); )
+	while ( (c = *src) )
 		dst = vis(dst, c, flag, *++src);
 	*dst = '\0';
 	return (dst - start);
@@ -191,15 +243,15 @@
 	register size_t len;
 	int flag;
 {
-	int c;
-	char *start;
+	register int c;
+	char *start = dst;
 
-	for (start = dst; len > 1; len--) {
+	while (len-- > 1) {
 		c = *src;
 		dst = vis(dst, c, flag, *++src);
 	}
-	if (len)
-		dst = vis(dst, *src, flag, '\0');
+	if (len > 0)
+		dst = vis(dst, *src, flag, 0);
 	*dst = '\0';
 
 	return (dst - start);
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200103221928.f2MJS2I22918>