Index: src/lib/print.c
===================================================================
RCS file: /source/radiusd/src/lib/print.c,v
retrieving revision 1.49
diff -u -r1.49 print.c
--- src/lib/print.c	29 May 2007 14:33:26 -0000	1.49
+++ src/lib/print.c	27 Aug 2007 20:45:03 -0000
@@ -28,30 +28,122 @@
 #include	<ctype.h>
 
 /*
+ *	Checks for utf-8,
+ *	taken from:
+ *
+ *  http://www.w3.org/International/questions/qa-forms-utf-8
+ */
+static int utf8_char(uint8_t *str, size_t len)
+{
+	if (len < 1 || *str < 0x20) goto invalid;
+
+	if (*str <= 0x7e) return 1; /* 1 */
+
+	if (len < 2 || *str <= 0xc1) goto invalid;
+	if ((str[0] >= 0xc2) &&	/* 2 */
+	    (str[0] <= 0xdf) &&
+	    (str[1] >= 0x80) &&
+	    (str[1] <= 0xbf)) {
+		return 2;
+	}
+
+	if (len < 3) goto invalid; /* incomplete UTF-8 character */
+	if ((str[0] == 0xe0) &&	/* 3 */
+	    (str[1] >= 0xa0) &&
+	    (str[1] <= 0xbf) &&
+	    (str[2] >= 0x80) &&
+	    (str[2] <= 0xbf)) {
+		return 3;
+	}
+
+	if ((str[0] >= 0xe1) &&	/* 4a */
+	    (str[0] <= 0xec) &&
+	    (str[1] >= 0x80) &&
+	    (str[1] <= 0xbf) &&
+	    (str[2] >= 0x80) &&
+	    (str[2] <= 0xbf)) {
+		return 3;
+	}
+
+	if ((str[0] >= 0xee) &&	/* 4b */
+	    (str[0] <= 0xef) &&
+	    (str[1] >= 0x80) &&
+	    (str[1] <= 0xbf) &&
+	    (str[2] >= 0x80) &&
+	    (str[2] <= 0xbf)) {
+		return 3;
+	}
+
+	if ((str[0] == 0xed) &&	/* 5 */
+	    (str[1] >= 0x80) &&
+	    (str[1] <= 0x9f) &&
+	    (str[2] >= 0x80) &&
+	    (str[2] <= 0xbf)) {
+		return 3;
+	}
+
+	if (len < 4) goto invalid; /* incomplete UTF-8 character */
+	if ((str[0] == 0xf0) &&	/* 6 */
+	    (str[1] >= 0x90) &&
+	    (str[1] <= 0xbf) &&
+	    (str[2] >= 0x80) &&
+	    (str[2] <= 0xbf) &&
+	    (str[3] >= 0x80) &&
+	    (str[3] <= 0xbf)) {
+		return 4;
+	}
+
+	if ((str[0] >= 0xf1) &&	/* 6 */
+	    (str[1] <= 0xf3) &&
+	    (str[1] >= 0x80) &&
+	    (str[1] <= 0xbf) &&
+	    (str[2] >= 0x80) &&
+	    (str[2] <= 0xbf) &&
+	    (str[3] >= 0x80) &&
+	    (str[3] <= 0xbf)) {
+		return 4;
+	}
+
+
+	if ((str[0] == 0xf4) &&	/* 7 */
+	    (str[1] >= 0x80) &&
+	    (str[1] <= 0x8f) &&
+	    (str[2] >= 0x80) &&
+	    (str[2] <= 0xbf) &&
+	    (str[3] >= 0x80) &&
+	    (str[3] <= 0xbf)) {
+		return 4;
+	}
+
+invalid:
+	/*
+	 *	Invalid UTF-8 Character
+	 */
+	return 0;
+}
+
+/*
  *	Convert a string to something printable.
  *	The output string has to be _at least_ 4x the size
  *	of the input string!
  */
 void librad_safeprint(char *in, int inlen, char *out, int outlen)
 {
-	unsigned char	*str = (unsigned char *)in;
-	int		done = 0;
 	int		sp = 0;
+	int		utf8 = 0;
 
 	if (inlen < 0) inlen = strlen(in);
 
-	while (inlen-- > 0 && (done + 3) < outlen) {
+	while (inlen > 0 && outlen > 1) {
 		/*
 		 *	Hack: never print trailing zero.
 		 *	Some clients send strings with an off-by-one
 		 *	length (confused with strings in C).
 		 */
-		if (inlen == 0 && *str == 0)
+		if (inlen == 0 && *in == 0)
 			break;
 
-		sp = 0;
-
-		switch (*str) {
+		switch (*in) {
 			case '\\':
 				sp = '\\';
 				break;
@@ -68,24 +160,31 @@
 				sp = '"';
 				break;
 			default:
-			  if (*str < 32 || (*str >= 128)){
-					snprintf(out, outlen, "\\%03o", *str);
-					done += 4;
-					out  += 4;
-					outlen -= 4;
+				if ((utf8 = utf8_char((uint8_t *)in, inlen)) == 0) {
+				    if (outlen > 4) {
+					size_t printed = snprintf(out, outlen, "\\%03o", (unsigned)*in & 0xFF);
+					inlen--;
+					in++;
+					outlen -= printed;
+					out += printed;
+				     }
 				} else {
-					*out++ = *str;
-					outlen--;
-					done++;
+				    if (outlen > utf8) { /* do not output incomplete characters */
+				        inlen -= utf8;
+					outlen -= utf8;
+				        while(utf8--)
+					    *out++ = *in++;
+				    }
 				}
 		}
-		if (sp) {
+		if (sp && outlen > 2) {
+			inlen--;
+			in++;
 			*out++ = '\\';
 			*out++ = sp;
 			outlen -= 2;
-			done += 2;
+			sp = 0;
 		}
-		str++;
 	}
 	*out = 0;
 }
@@ -121,11 +220,6 @@
 				librad_safeprint((char *)vp->vp_strvalue,
 						 vp->length, buf + 1, sizeof(buf) - 2);
 				strcat(buf, "\"");
-
-			} else if (delimitst < 0) {
-				strlcpy(out, vp->vp_strvalue, outlen);
-				return strlen(out);
-
 			} else {
 				/* Non-tagged attribute: no delimiter */
 				librad_safeprint((char *)vp->vp_strvalue,
