aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-mime-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-mime-utils.c')
-rw-r--r--camel/camel-mime-utils.c122
1 files changed, 64 insertions, 58 deletions
diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c
index ba704b19dc..594c1de05e 100644
--- a/camel/camel-mime-utils.c
+++ b/camel/camel-mime-utils.c
@@ -1004,32 +1004,63 @@ g_string_append_len(GString *st, const char *s, int l)
according to the rfc's. Anyway, since the conversion to utf-8
is trivial, just do it here without iconv */
static GString *
-append_latin1(GString *out, const char *in, int len)
+append_latin1 (GString *out, const char *in, int len)
{
unsigned int c;
-
+
while (len) {
c = (unsigned int)*in++;
len--;
if (c & 0x80) {
- out = g_string_append_c(out, 0xc0 | ((c>>6) & 0x3)); /* 110000xx */
- out = g_string_append_c(out, 0x80 | (c&0x3f)); /* 10xxxxxx */
+ out = g_string_append_c (out, 0xc0 | ((c >> 6) & 0x3)); /* 110000xx */
+ out = g_string_append_c (out, 0x80 | (c & 0x3f)); /* 10xxxxxx */
} else {
- out = g_string_append_c(out, c);
+ out = g_string_append_c (out, c);
}
}
return out;
}
+static void
+append_8bit (GString *out, const char *inbuf, int inlen, const char *default_charset)
+{
+ char *outbase, *outbuf;
+ int outlen;
+ iconv_t ic;
+
+ ic = iconv_open ("UTF-8", default_charset);
+ if (ic != (iconv_t) -1) {
+ int ret;
+
+ outlen = inlen * 6 + 16;
+ outbuf = outbase = g_malloc (outlen);
+
+ ret = iconv (ic, &inbuf, &inlen, &outbuf, &outlen);
+ if (ret >= 0) {
+ iconv (ic, NULL, 0, &outbuf, &outlen);
+ *outbuf = '\0';
+ }
+
+ iconv_close (ic);
+
+ /* FIXME: is outlen == strlen (outbuf) ?? */
+ g_string_append_len (out, outbase, strlen (outbase));
+ } else {
+ /* bah, completely broken...just append as raw text */
+ g_string_append_len (out, inbuf, inlen);
+ }
+}
+
/* decodes a simple text, rfc822 */
static char *
-header_decode_text (const char *in, int inlen)
+header_decode_text (const char *in, int inlen, const char *default_charset)
{
GString *out;
char *inptr, *inend, *start, *word_start;
char *decoded;
gboolean wasdword = FALSE;
gboolean wasspace = FALSE;
+ gboolean islatin1 = FALSE;
out = g_string_new ("");
start = inptr = (char *) in;
@@ -1056,8 +1087,12 @@ header_decode_text (const char *in, int inlen)
g_string_append (out, dword);
g_free (dword);
wasdword = TRUE;
+ } else if (islatin1 || !default_charset) {
+ /* append_latin1 is safe for 7bit ascii too */
+ append_latin1 (out, start, inptr - start - 1);
+ wasdword = FALSE;
} else {
- out = append_latin1 (out, start, inptr - start - 1);
+ append_8bit (out, start, inptr - start - 1, default_charset);
wasdword = FALSE;
}
@@ -1068,6 +1103,11 @@ header_decode_text (const char *in, int inlen)
wasspace = FALSE;
if (!word_start)
word_start = inptr - 1;
+
+ if (c & 0x80 || c <= 127)
+ islatin1 = TRUE;
+ else
+ islatin1 = FALSE;
}
}
@@ -1087,8 +1127,11 @@ header_decode_text (const char *in, int inlen)
g_string_append (out, dword);
g_free (dword);
+ } else if (islatin1 || !default_charset) {
+ /* append_latin1 is safe for 7bit ascii too */
+ append_latin1 (out, start, inptr - start);
} else {
- out = append_latin1 (out, start, inptr - start);
+ append_8bit (out, start, inptr - start, default_charset);
}
}
@@ -1098,49 +1141,12 @@ header_decode_text (const char *in, int inlen)
return decoded;
}
-#if 0 /* This is broken */
-
-/* so in what way is it broken? */
-
-/* decodes a simple text, rfc822 */
-static char *
-header_decode_text(const char *in, int inlen)
-{
- GString *out;
- const char *inptr = in;
- const char *inend = in+inlen;
- char *encstart, *encend;
- char *decword;
-
- out = g_string_new("");
- while ( (encstart = strstr(inptr, "=?"))
- && (encend = strstr(encstart+2, "?=")) ) {
-
- decword = rfc2047_decode_word(encstart, encend-encstart+2);
- if (decword) {
- out = g_string_append_len(out, inptr, encstart-inptr);
- out = g_string_append_len(out, decword, strlen(decword));
- g_free (decword);
- } else {
- out = append_latin1(out, inptr, encend-inptr+2);
- }
- inptr = encend+2;
- }
- out = append_latin1(out, inptr, inend-inptr);
-
- encstart = out->str;
- g_string_free(out, FALSE);
-
- return encstart;
-}
-#endif
-
char *
-header_decode_string(const char *in)
+header_decode_string (const char *in, const char *default_charset)
{
if (in == NULL)
return NULL;
- return header_decode_text(in, strlen(in));
+ return header_decode_text (in, strlen (in), default_charset);
}
/* how long a sequence of pre-encoded words should be less than, to attempt to
@@ -2248,13 +2254,13 @@ header_decode_mailbox(const char **in)
header_decode_lwsp(&inptr);
if (!(*inptr == '.' || *inptr == '@' || *inptr==',' || *inptr=='\0')) {
/* ',' and '\0' required incase it is a simple address, no @ domain part (buggy writer) */
- name = g_string_new("");
+ name = g_string_new ("");
while (pre) {
char *text, *last;
/* perform internationalised decoding, and append */
- text = header_decode_string(pre);
- name = g_string_append(name, text);
+ text = header_decode_string (pre, NULL);
+ g_string_append (name, text);
last = pre;
g_free(text);
@@ -2362,19 +2368,19 @@ header_decode_mailbox(const char **in)
if (comend > comstart) {
d(printf(" looking at subset '%.*s'\n", comend-comstart, comstart));
- tmp = g_strndup(comstart, comend-comstart);
- text = header_decode_string(tmp);
- name = g_string_new(text);
- g_free(tmp);
- g_free(text);
+ tmp = g_strndup (comstart, comend-comstart);
+ text = header_decode_string (tmp, NULL);
+ name = g_string_new (text);
+ g_free (tmp);
+ g_free (text);
}
}
}
-
+
*in = inptr;
-
+
if (addr->len > 0) {
- address = header_address_new_name(name?name->str:"", addr->str);
+ address = header_address_new_name(name ? name->str : "", addr->str);
}
g_string_free(addr, TRUE);