Statistics
| Revision:

root / libsylph / unmime.c @ 3050

History | View | Annotate | Download (3.5 kB)

1 528 hiro
/*
2 578 hiro
 * LibSylph -- E-Mail client library
3 528 hiro
 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
4 528 hiro
 *
5 578 hiro
 * This library is free software; you can redistribute it and/or
6 578 hiro
 * modify it under the terms of the GNU Lesser General Public
7 578 hiro
 * License as published by the Free Software Foundation; either
8 578 hiro
 * version 2.1 of the License, or (at your option) any later version.
9 528 hiro
 *
10 578 hiro
 * This library is distributed in the hope that it will be useful,
11 528 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 578 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 578 hiro
 * Lesser General Public License for more details.
14 528 hiro
 *
15 578 hiro
 * You should have received a copy of the GNU Lesser General Public
16 578 hiro
 * License along with this library; if not, write to the Free Software
17 578 hiro
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 528 hiro
 */
19 528 hiro
20 528 hiro
#ifdef HAVE_CONFIG_H
21 528 hiro
#  include "config.h"
22 528 hiro
#endif
23 528 hiro
24 528 hiro
#include <glib.h>
25 528 hiro
#include <string.h>
26 528 hiro
#include <ctype.h>
27 528 hiro
28 528 hiro
#include "codeconv.h"
29 528 hiro
#include "base64.h"
30 528 hiro
#include "quoted-printable.h"
31 528 hiro
32 528 hiro
#define ENCODED_WORD_BEGIN        "=?"
33 528 hiro
#define ENCODED_WORD_END        "?="
34 528 hiro
35 528 hiro
/* Decodes headers based on RFC2045 and RFC2047. */
36 528 hiro
37 528 hiro
gchar *unmime_header(const gchar *encoded_str)
38 528 hiro
{
39 528 hiro
        const gchar *p = encoded_str;
40 528 hiro
        const gchar *eword_begin_p, *encoding_begin_p, *text_begin_p,
41 528 hiro
                    *eword_end_p;
42 528 hiro
        gchar charset[32];
43 528 hiro
        gchar encoding;
44 528 hiro
        gchar *conv_str;
45 528 hiro
        GString *outbuf;
46 528 hiro
        gchar *out_str;
47 528 hiro
        gsize out_len;
48 528 hiro
49 528 hiro
        outbuf = g_string_sized_new(strlen(encoded_str) * 2);
50 528 hiro
51 528 hiro
        while (*p != '\0') {
52 528 hiro
                gchar *decoded_text = NULL;
53 528 hiro
                gint len;
54 528 hiro
55 528 hiro
                eword_begin_p = strstr(p, ENCODED_WORD_BEGIN);
56 528 hiro
                if (!eword_begin_p) {
57 528 hiro
                        g_string_append(outbuf, p);
58 528 hiro
                        break;
59 528 hiro
                }
60 528 hiro
                encoding_begin_p = strchr(eword_begin_p + 2, '?');
61 528 hiro
                if (!encoding_begin_p) {
62 528 hiro
                        g_string_append(outbuf, p);
63 528 hiro
                        break;
64 528 hiro
                }
65 528 hiro
                text_begin_p = strchr(encoding_begin_p + 1, '?');
66 528 hiro
                if (!text_begin_p) {
67 528 hiro
                        g_string_append(outbuf, p);
68 528 hiro
                        break;
69 528 hiro
                }
70 528 hiro
                eword_end_p = strstr(text_begin_p + 1, ENCODED_WORD_END);
71 528 hiro
                if (!eword_end_p) {
72 528 hiro
                        g_string_append(outbuf, p);
73 528 hiro
                        break;
74 528 hiro
                }
75 528 hiro
76 528 hiro
                if (p == encoded_str) {
77 528 hiro
                        g_string_append_len(outbuf, p, eword_begin_p - p);
78 528 hiro
                        p = eword_begin_p;
79 528 hiro
                } else {
80 528 hiro
                        /* ignore spaces between encoded words */
81 528 hiro
                        const gchar *sp;
82 528 hiro
83 528 hiro
                        for (sp = p; sp < eword_begin_p; sp++) {
84 528 hiro
                                if (!g_ascii_isspace(*sp)) {
85 528 hiro
                                        g_string_append_len
86 528 hiro
                                                (outbuf, p, eword_begin_p - p);
87 528 hiro
                                        p = eword_begin_p;
88 528 hiro
                                        break;
89 528 hiro
                                }
90 528 hiro
                        }
91 528 hiro
                }
92 528 hiro
93 528 hiro
                len = MIN(sizeof(charset) - 1,
94 528 hiro
                          encoding_begin_p - (eword_begin_p + 2));
95 528 hiro
                memcpy(charset, eword_begin_p + 2, len);
96 528 hiro
                charset[len] = '\0';
97 528 hiro
                encoding = g_ascii_toupper(*(encoding_begin_p + 1));
98 528 hiro
99 528 hiro
                if (encoding == 'B') {
100 528 hiro
                        decoded_text = g_malloc
101 528 hiro
                                (eword_end_p - (text_begin_p + 1) + 1);
102 544 hiro
                        len = base64_decode((guchar *)decoded_text,
103 544 hiro
                                            text_begin_p + 1,
104 528 hiro
                                            eword_end_p - (text_begin_p + 1));
105 528 hiro
                        decoded_text[len] = '\0';
106 528 hiro
                } else if (encoding == 'Q') {
107 528 hiro
                        decoded_text = g_malloc
108 528 hiro
                                (eword_end_p - (text_begin_p + 1) + 1);
109 528 hiro
                        len = qp_decode_q_encoding
110 544 hiro
                                ((guchar *)decoded_text, text_begin_p + 1,
111 528 hiro
                                 eword_end_p - (text_begin_p + 1));
112 528 hiro
                } else {
113 528 hiro
                        g_string_append_len(outbuf, p, eword_end_p + 2 - p);
114 528 hiro
                        p = eword_end_p + 2;
115 528 hiro
                        continue;
116 528 hiro
                }
117 528 hiro
118 528 hiro
                /* convert to UTF-8 */
119 528 hiro
                conv_str = conv_codeset_strdup(decoded_text, charset, NULL);
120 528 hiro
                if (!conv_str)
121 528 hiro
                        conv_str = conv_utf8todisp(decoded_text, NULL);
122 528 hiro
                g_string_append(outbuf, conv_str);
123 528 hiro
                g_free(conv_str);
124 528 hiro
125 528 hiro
                g_free(decoded_text);
126 528 hiro
127 528 hiro
                p = eword_end_p + 2;
128 528 hiro
        }
129 528 hiro
130 528 hiro
        out_str = outbuf->str;
131 528 hiro
        out_len = outbuf->len;
132 528 hiro
        g_string_free(outbuf, FALSE);
133 528 hiro
134 528 hiro
        return g_realloc(out_str, out_len + 1);
135 528 hiro
}