0.9.6claws5
[claws.git] / src / unmime.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2003 Hiroyuki Yamamoto
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program 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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 void unmime_header(gchar *out, const gchar *str)
38 {
39         const gchar *p = str;
40         gchar *outp = out;
41         const gchar *sp;
42         const gchar *eword_begin_p, *encoding_begin_p, *text_begin_p,
43                     *eword_end_p;
44         gchar charset[32];
45         gchar encoding;
46         gchar *conv_str;
47         gint len;
48
49         while (*p != '\0') {
50                 gchar *decoded_text = NULL;
51
52                 eword_begin_p = strstr(p, ENCODED_WORD_BEGIN);
53                 if (!eword_begin_p) {
54                         strcpy(outp, p);
55                         return;
56                 }
57                 encoding_begin_p = strchr(eword_begin_p + 2, '?');
58                 if (!encoding_begin_p) {
59                         strcpy(outp, p);
60                         return;
61                 }
62                 text_begin_p = strchr(encoding_begin_p + 1, '?');
63                 if (!text_begin_p) {
64                         strcpy(outp, p);
65                         return;
66                 }
67                 eword_end_p = strstr(text_begin_p + 1, ENCODED_WORD_END);
68                 if (!eword_end_p) {
69                         strcpy(outp, p);
70                         return;
71                 }
72
73                 if (p == str) {
74                         memcpy(outp, p, eword_begin_p - p);
75                         outp += eword_begin_p - p;
76                         p = eword_begin_p;
77                 } else {
78                         /* ignore spaces between encoded words */
79                         for (sp = p; sp < eword_begin_p; sp++) {
80                                 if (!isspace(*sp)) {
81                                         memcpy(outp, p, eword_begin_p - p);
82                                         outp += eword_begin_p - p;
83                                         p = eword_begin_p;
84                                         break;
85                                 }
86                         }
87                 }
88
89                 len = MIN(sizeof(charset) - 1,
90                           encoding_begin_p - (eword_begin_p + 2));
91                 memcpy(charset, eword_begin_p + 2, len);
92                 charset[len] = '\0';
93                 encoding = toupper(*(encoding_begin_p + 1));
94
95                 if (encoding == 'B') {
96                         decoded_text = g_malloc
97                                 (eword_end_p - (text_begin_p + 1) + 1);
98                         len = base64_decode(decoded_text, text_begin_p + 1,
99                                             eword_end_p - (text_begin_p + 1));
100                         decoded_text[len] = '\0';
101                 } else if (encoding == 'Q') {
102                         decoded_text = g_malloc
103                                 (eword_end_p - (text_begin_p + 1) + 1);
104                         len = qp_decode_q_encoding
105                                 (decoded_text, text_begin_p + 1,
106                                  eword_end_p - (text_begin_p + 1));
107                 } else {
108                         memcpy(outp, p, eword_end_p + 2 - p);
109                         outp += eword_end_p + 2 - p;
110                         p = eword_end_p + 2;
111                         continue;
112                 }
113
114                 /* convert to locale encoding */
115                 conv_str = conv_codeset_strdup(decoded_text, charset, NULL);
116                 if (conv_str) {
117                         len = strlen(conv_str);
118                         memcpy(outp, conv_str, len);
119                         g_free(conv_str);
120                 } else {
121                         len = strlen(decoded_text);
122                         conv_localetodisp(outp, len + 1, decoded_text);
123                 }
124                 outp += len;
125
126                 g_free(decoded_text);
127
128                 p = eword_end_p + 2;
129         }
130
131         *outp = '\0';
132 }