xlat UTF-8 stuff for 1.1.x backport
Hi, using the attached patch my LDAP-requests returning UTF-8 and embedded commas work now using 1.1.7. This should fix bug #411, too. Enrik Index: src/lib/print.c =================================================================== RCS file: /source/radiusd/src/lib/print.c,v retrieving revision 1.26.2.1.2.2 diff -u -b -r1.26.2.1.2.2 print.c --- src/lib/print.c 15 Mar 2006 15:37:56 -0000 1.26.2.1.2.2 +++ src/lib/print.c 28 Aug 2007 14:26:07 -0000 @@ -33,28 +33,123 @@ #include "libradius.h" /* - * Convert a string to something printable. - * The output string has to be _at least_ 4x the size - * of the input string! + * Checks for utf-8, taken from: + * + * http://www.w3.org/International/questions/qa-forms-utf-8 + * + * Note that we don't care about the length of the input string, + * because '\0' is an invalid UTF-8 character. + */ +static int utf8_char(uint8_t *str) +{ + if (*str < 0x20) return 0; + + if (*str <= 0x7e) return 1; /* 1 */ + + if (*str <= 0xc1) return 0; + + if ((str[0] >= 0xc2) && /* 2 */ + (str[0] <= 0xdf) && + (str[1] >= 0x80) && + (str[1] <= 0xbf)) { + return 2; + } + + 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 ((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 UTF-8 Character + */ + return 0; +} + +/* + * Convert a string to something printable. The output string + * has to be larger than the input string by at least 5 bytes. + * If not, the output is silently truncated... */ 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 > 4)) { /* * 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) - break; - - sp = 0; + if ((inlen == 0) && (*str == 0)) break; switch (*str) { case '\\': @@ -69,25 +164,38 @@ case '\t': sp = 't'; break; + case '"': + sp = '"'; + break; default: - if (*str < 32 || (*str >= 128)){ - snprintf(out, outlen, "\\%03o", *str); - done += 4; - out += 4; - outlen -= 4; - } else { - *out++ = *str; - outlen--; - done++; - } + sp = 0; + break; } + if (sp) { *out++ = '\\'; *out++ = sp; outlen -= 2; - done += 2; + str++; + inlen--; + continue; } + + utf8 = utf8_char((uint8_t *)str); + if (!utf8) { + snprintf(out, outlen, "\\%03o", *str); + out += 4; + outlen -= 4; str++; + inlen--; + continue; + } + + do { + *out++ = *str++; + outlen--; + inlen--; + } while (--utf8 > 0); } *out = 0; } @@ -117,18 +225,23 @@ if (vp->attribute == PW_NAS_PORT) a = (char *)vp->strvalue; else { - if (delimitst && vp->flags.has_tag) { + if (delimitst == 1 && vp->flags.has_tag) { /* Tagged attribute: print delimter and ignore tag */ buf[0] = '"'; librad_safeprint((char *)(vp->strvalue), vp->length, buf + 1, sizeof(buf) - 2); strcat(buf, "\""); - } else if (delimitst) { + } else if (delimitst == 1) { /* Non-tagged attribute: print delimter */ buf[0] = '"'; librad_safeprint((char *)vp->strvalue, vp->length, buf + 1, sizeof(buf) - 2); strcat(buf, "\""); + + } else if (delimitst < 0) { /* xlat.c */ + strlcpy(out, vp->strvalue, outlen); + return strlen(out); + } else { /* Non-tagged attribute: no delimiter */ librad_safeprint((char *)vp->strvalue, Index: src/main/xlat.c =================================================================== RCS file: /source/radiusd/src/main/xlat.c,v retrieving revision 1.72.2.7.2.5 diff -u -b -r1.72.2.7.2.5 xlat.c --- src/main/xlat.c 14 Jul 2007 11:07:54 -0000 1.72.2.7.2.5 +++ src/main/xlat.c 28 Aug 2007 14:26:08 -0000 @@ -72,7 +72,7 @@ char buffer[MAX_STRING_LEN * 4]; if (pair != NULL) { - vp_prints_value(buffer, sizeof(buffer), pair, 0); + vp_prints_value(buffer, sizeof(buffer), pair, -1); return func(out, outlen, buffer); }
participants (1)
-
Enrik Berkhan