Statistics
| Branch: | Tag: | Revision:

root / libsylph / unmime.c @ 8d7dcace

History | View | Annotate | Download (3.46 KB)

1
/*
2
 * LibSylph -- E-Mail client library
3
 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19

    
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23

    
24
#include <glib.h>
25
#include <string.h>
26
#include <ctype.h>
27

    
28
#include "codeconv.h"
29
#include "base64.h"
30
#include "quoted-printable.h"
31

    
32
#define ENCODED_WORD_BEGIN        "=?"
33
#define ENCODED_WORD_END        "?="
34

    
35
/* Decodes headers based on RFC2045 and RFC2047. */
36

    
37
gchar *unmime_header(const gchar *encoded_str)
38
{
39
        const gchar *p = encoded_str;
40
        const gchar *eword_begin_p, *encoding_begin_p, *text_begin_p,
41
                    *eword_end_p;
42
        gchar charset[32];
43
        gchar encoding;
44
        gchar *conv_str;
45
        GString *outbuf;
46
        gchar *out_str;
47
        gsize out_len;
48

    
49
        outbuf = g_string_sized_new(strlen(encoded_str) * 2);
50

    
51
        while (*p != '\0') {
52
                gchar *decoded_text = NULL;
53
                gint len;
54

    
55
                eword_begin_p = strstr(p, ENCODED_WORD_BEGIN);
56
                if (!eword_begin_p) {
57
                        g_string_append(outbuf, p);
58
                        break;
59
                }
60
                encoding_begin_p = strchr(eword_begin_p + 2, '?');
61
                if (!encoding_begin_p) {
62
                        g_string_append(outbuf, p);
63
                        break;
64
                }
65
                text_begin_p = strchr(encoding_begin_p + 1, '?');
66
                if (!text_begin_p) {
67
                        g_string_append(outbuf, p);
68
                        break;
69
                }
70
                eword_end_p = strstr(text_begin_p + 1, ENCODED_WORD_END);
71
                if (!eword_end_p) {
72
                        g_string_append(outbuf, p);
73
                        break;
74
                }
75

    
76
                if (p == encoded_str) {
77
                        g_string_append_len(outbuf, p, eword_begin_p - p);
78
                        p = eword_begin_p;
79
                } else {
80
                        /* ignore spaces between encoded words */
81
                        const gchar *sp;
82

    
83
                        for (sp = p; sp < eword_begin_p; sp++) {
84
                                if (!g_ascii_isspace(*sp)) {
85
                                        g_string_append_len
86
                                                (outbuf, p, eword_begin_p - p);
87
                                        p = eword_begin_p;
88
                                        break;
89
                                }
90
                        }
91
                }
92

    
93
                len = MIN(sizeof(charset) - 1,
94
                          encoding_begin_p - (eword_begin_p + 2));
95
                memcpy(charset, eword_begin_p + 2, len);
96
                charset[len] = '\0';
97
                encoding = g_ascii_toupper(*(encoding_begin_p + 1));
98

    
99
                if (encoding == 'B') {
100
                        decoded_text = g_malloc
101
                                (eword_end_p - (text_begin_p + 1) + 1);
102
                        len = base64_decode((guchar *)decoded_text,
103
                                            text_begin_p + 1,
104
                                            eword_end_p - (text_begin_p + 1));
105
                        decoded_text[len] = '\0';
106
                } else if (encoding == 'Q') {
107
                        decoded_text = g_malloc
108
                                (eword_end_p - (text_begin_p + 1) + 1);
109
                        len = qp_decode_q_encoding
110
                                ((guchar *)decoded_text, text_begin_p + 1,
111
                                 eword_end_p - (text_begin_p + 1));
112
                } else {
113
                        g_string_append_len(outbuf, p, eword_end_p + 2 - p);
114
                        p = eword_end_p + 2;
115
                        continue;
116
                }
117

    
118
                /* convert to UTF-8 */
119
                conv_str = conv_codeset_strdup(decoded_text, charset, NULL);
120
                if (!conv_str)
121
                        conv_str = conv_utf8todisp(decoded_text, NULL);
122
                g_string_append(outbuf, conv_str);
123
                g_free(conv_str);
124

    
125
                g_free(decoded_text);
126

    
127
                p = eword_end_p + 2;
128
        }
129

    
130
        out_str = outbuf->str;
131
        out_len = outbuf->len;
132
        g_string_free(outbuf, FALSE);
133

    
134
        return g_realloc(out_str, out_len + 1);
135
}