Statistics
| Branch: | Tag: | Revision:

root / libsylph / unmime.c @ aebfd4cc

History | View | Annotate | Download (2.74 KB)

1
/*
2
 * LibSylph -- E-Mail client library
3
 * Copyright (C) 1999-2011 Hiroyuki Yamamoto
4
 */
5

    
6
#ifdef HAVE_CONFIG_H
7
#  include "config.h"
8
#endif
9

    
10
#include <glib.h>
11
#include <string.h>
12
#include <ctype.h>
13

    
14
#include "codeconv.h"
15
#include "base64.h"
16
#include "quoted-printable.h"
17

    
18
#define ENCODED_WORD_BEGIN        "=?"
19
#define ENCODED_WORD_END        "?="
20

    
21
/* Decodes headers based on RFC2045 and RFC2047. */
22

    
23
gchar *unmime_header(const gchar *encoded_str)
24
{
25
        const gchar *p = encoded_str;
26
        const gchar *eword_begin_p, *encoding_begin_p, *text_begin_p,
27
                    *eword_end_p;
28
        gchar charset[32];
29
        gchar encoding;
30
        gchar *conv_str;
31
        GString *outbuf;
32
        gchar *out_str;
33
        gsize out_len;
34

    
35
        outbuf = g_string_sized_new(strlen(encoded_str) * 2);
36

    
37
        while (*p != '\0') {
38
                gchar *decoded_text = NULL;
39
                gint len;
40

    
41
                eword_begin_p = strstr(p, ENCODED_WORD_BEGIN);
42
                if (!eword_begin_p) {
43
                        g_string_append(outbuf, p);
44
                        break;
45
                }
46
                encoding_begin_p = strchr(eword_begin_p + 2, '?');
47
                if (!encoding_begin_p) {
48
                        g_string_append(outbuf, p);
49
                        break;
50
                }
51
                text_begin_p = strchr(encoding_begin_p + 1, '?');
52
                if (!text_begin_p) {
53
                        g_string_append(outbuf, p);
54
                        break;
55
                }
56
                eword_end_p = strstr(text_begin_p + 1, ENCODED_WORD_END);
57
                if (!eword_end_p) {
58
                        g_string_append(outbuf, p);
59
                        break;
60
                }
61

    
62
                if (p == encoded_str) {
63
                        g_string_append_len(outbuf, p, eword_begin_p - p);
64
                        p = eword_begin_p;
65
                } else {
66
                        /* ignore spaces between encoded words */
67
                        const gchar *sp;
68

    
69
                        for (sp = p; sp < eword_begin_p; sp++) {
70
                                if (!g_ascii_isspace(*sp)) {
71
                                        g_string_append_len
72
                                                (outbuf, p, eword_begin_p - p);
73
                                        p = eword_begin_p;
74
                                        break;
75
                                }
76
                        }
77
                }
78

    
79
                len = MIN(sizeof(charset) - 1,
80
                          encoding_begin_p - (eword_begin_p + 2));
81
                memcpy(charset, eword_begin_p + 2, len);
82
                charset[len] = '\0';
83
                encoding = g_ascii_toupper(*(encoding_begin_p + 1));
84

    
85
                if (encoding == 'B') {
86
                        decoded_text = g_malloc
87
                                (eword_end_p - (text_begin_p + 1) + 1);
88
                        len = base64_decode((guchar *)decoded_text,
89
                                            text_begin_p + 1,
90
                                            eword_end_p - (text_begin_p + 1));
91
                        decoded_text[len] = '\0';
92
                } else if (encoding == 'Q') {
93
                        decoded_text = g_malloc
94
                                (eword_end_p - (text_begin_p + 1) + 1);
95
                        len = qp_decode_q_encoding
96
                                ((guchar *)decoded_text, text_begin_p + 1,
97
                                 eword_end_p - (text_begin_p + 1));
98
                } else {
99
                        g_string_append_len(outbuf, p, eword_end_p + 2 - p);
100
                        p = eword_end_p + 2;
101
                        continue;
102
                }
103

    
104
                /* convert to UTF-8 */
105
                conv_str = conv_codeset_strdup(decoded_text, charset, NULL);
106
                if (!conv_str)
107
                        conv_str = conv_utf8todisp(decoded_text, NULL);
108
                g_string_append(outbuf, conv_str);
109
                g_free(conv_str);
110

    
111
                g_free(decoded_text);
112

    
113
                p = eword_end_p + 2;
114
        }
115

    
116
        out_str = outbuf->str;
117
        out_len = outbuf->len;
118
        g_string_free(outbuf, FALSE);
119

    
120
        return g_realloc(out_str, out_len + 1);
121
}