Alan DeKok wrote:
Bleah. There's no need to use a function with local non-thread-aware storage. It's easy to know what a valid UTF-8 character is. We should just check ourselves, and escape anything that isn't valid.
You're right. So this could be a start: static int valid_utf8(const unsigned char *p, size_t len) { if (len >= 1 && p[0] < 0x7f) { return 1; } else if (len >= 2 && p[0] >= 0xC0 && p[0] < 0xE0 && (p[1]&0x80) == 0x80) { return 2; } else if (len >= 3 && p[0] >= 0xE0 && p[0] < 0xF0 && (p[1]&0x80) == 0x80 && (p[2]&0x80) == 0x80) { return 3; } else if (len >= 4 && p[0] >= 0xF0 && p[0] < 0xF8 && (p[1]&0x80) == 0x80 && (p[2]&0x80) == 0x80 && (p[3]&0x80) == 0x80) { return 4; } else if (len >= 5 && p[0] >= 0xF8 && p[0] < 0xFC && (p[1]&0x80) == 0x80 && (p[2]&0x80) == 0x80 && (p[3]&0x80) == 0x80 && (p[4]&0x80) == 0x80) { return 5; } else if (len >= 6 && p[0] >= 0xFC && p[0] < 0xFE && (p[1]&0x80) == 0x80 && (p[2]&0x80) == 0x80 && (p[3]&0x80) == 0x80 && (p[4]&0x80) == 0x80 && (p[5]&0x80) == 0x80) { return 6; } return 0; } /* * Check if string contains valid UTF-8, escape violating bytes. * The output string has to be _at least_ 4x the size * of the input string! */ void librad_utf8_sanitize(const char *in, size_t inlen, char *out, size_t outlen) { while (inlen && outlen) { size_t next = valid_utf8(in, inlen); if (next) { if (outlen > next) { inlen -= next; outlen -= next; while(next--) *out++ = *in++; } else { goto no_more; } } else { if (outlen > 4) { /* room for \ooo\0 */ sprintf(out, "\\%03o", (unsigned char)(*in++)&0xff); out += 4; inlen--; outlen -= 4; } else { goto no_more; } } } no_more: *out = 0; } Enrik