From a3da112d94058194e33d69d800293178605abc13 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 4 Feb 2015 11:53:47 +0000 Subject: [PATCH] Split out get_utf8char() from buf_append_utf16le() We'll want this for working around Yubikey/Android PIN weirdness. Signed-off-by: David Woodhouse --- http.c | 89 ++++++++++++++++++++++-------------------- openconnect-internal.h | 1 + 2 files changed, 48 insertions(+), 42 deletions(-) diff --git a/http.c b/http.c index a55bebcb..8a459d9b 100644 --- a/http.c +++ b/http.c @@ -171,56 +171,61 @@ void buf_append_from_utf16le(struct oc_text_buf *buf, const void *_utf16) buf_append_bytes(buf, utf8, 1); } -int buf_append_utf16le(struct oc_text_buf *buf, const char *utf8) +int get_utf8char(const char **p) { - int len = 0; + const char *utf8 = *p; unsigned char c; - unsigned long utfchar; - int min; - int nr_extra; + int utfchar, nr_extra, min; + + c = *(utf8++); + if (c < 128) { + utfchar = c; + nr_extra = 0; + min = 0; + } else if ((c & 0xe0) == 0xc0) { + utfchar = c & 0x1f; + nr_extra = 1; + min = 0x80; + } else if ((c & 0xf0) == 0xe0) { + utfchar = c & 0x0f; + nr_extra = 2; + min = 0x800; + } else if ((c & 0xf8) == 0xf0) { + utfchar = c & 0x07; + nr_extra = 3; + min = 0x10000; + } else { + return -EILSEQ; + } - /* Ick. Now I'm implementing my own UTF8 handling too. Perhaps it's - time to bite the bullet and start requiring something like glib? */ - while (*utf8) { + while (nr_extra--) { c = *(utf8++); - if (c < 128) { - utfchar = c; - nr_extra = 0; - min = 0; - } else if ((c & 0xe0) == 0xc0) { - utfchar = c & 0x1f; - nr_extra = 1; - min = 0x80; - } else if ((c & 0xf0) == 0xe0) { - utfchar = c & 0x0f; - nr_extra = 2; - min = 0x800; - } else if ((c & 0xf8) == 0xf0) { - utfchar = c & 0x07; - nr_extra = 3; - min = 0x10000; - } else { - if (buf) - buf->error = -EILSEQ; + if ((c & 0xc0) != 0x80) return -EILSEQ; - } - while (nr_extra--) { - c = *(utf8++); - if ((c & 0xc0) != 0x80) { - if (buf) - buf->error = -EILSEQ; - return -EILSEQ; - } - utfchar <<= 6; - utfchar |= (c & 0x3f); - } - if (utfchar > 0x10ffff || utfchar < min) { + utfchar <<= 6; + utfchar |= (c & 0x3f); + } + if (utfchar > 0x10ffff || utfchar < min) + return -EILSEQ; + + *p = utf8; + return utfchar; +} + +int buf_append_utf16le(struct oc_text_buf *buf, const char *utf8) +{ + int utfchar, len = 0; + + /* Ick. Now I'm implementing my own UTF8 handling too. Perhaps it's + time to bite the bullet and start requiring something like glib? */ + while (*utf8) { + utfchar = get_utf8char(&utf8); + if (utfchar < 0) { if (buf) - buf->error = -EILSEQ; - return -EILSEQ; + buf->error = utfchar; + return utfchar; } - if (!buf) continue; diff --git a/openconnect-internal.h b/openconnect-internal.h index a71211f6..b65c01da 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -920,6 +920,7 @@ void __attribute__ ((format (printf, 2, 3))) void buf_append_bytes(struct oc_text_buf *buf, const void *bytes, int len); void buf_append_base64(struct oc_text_buf *buf, const void *bytes, int len); int buf_append_utf16le(struct oc_text_buf *buf, const char *utf8); +int get_utf8char(const char **utf8); void buf_append_from_utf16le(struct oc_text_buf *buf, const void *utf16); void *openconnect_base64_decode(int *len, const char *in); void buf_truncate(struct oc_text_buf *buf);