Statistics
| Branch: | Tag: | Revision:

root / lib / filters / textcontent-filter.c @ 90da63dd

History | View | Annotate | Download (5.65 KB)

1
/* SylFilter - a message filter
2
 *
3
 * Copyright (C) 2011-2012 Hiroyuki Yamamoto
4
 * Copyright (C) 2011-2012 Sylpheed Development Team
5
 */
6

    
7
#include "config.h"
8

    
9
#include <glib.h>
10
#include <stdio.h>
11
#include <string.h>
12

    
13
#include "filter.h"
14
#include "textcontent-filter.h"
15

    
16
#ifdef BUILTIN_LIBSYLPH
17
#  include "libsylph/procheader.h"
18
#  include "libsylph/procmsg.h"
19
#  include "libsylph/procmime.h"
20
#  include "libsylph/utils.h"
21
#else
22
#  include <sylph/procheader.h>
23
#  include <sylph/procmsg.h>
24
#  include <sylph/procmime.h>
25
#  include <sylph/utils.h>
26
#endif
27

    
28
#define IS_BASE64_CHR(c)                        \
29
        ((c >= '0' && c <= '9') ||                \
30
         (c >= 'A' && c <= 'Z') ||                \
31
         (c >= 'a' && c <= 'z') ||                \
32
         c == '+' || c == '/' || c == '=')
33

    
34

    
35
static void xfilter_read_body_text(GString *text, FILE *fp)
36
{
37
        char buf[8192];
38
        int i;
39

    
40
        while (fgets(buf, sizeof(buf), fp) != NULL) {
41
                for (i = 0; buf[i] != '\0'; i++) {
42
                        if (!IS_BASE64_CHR(buf[i]))
43
                                break;
44
                }
45
                if (i <= 60)
46
                        g_string_append(text, buf);
47
#if 0
48
                else
49
                        g_print("skip line: %s", buf);
50
#endif
51
        }
52
}
53

    
54
static XMessageData *xfilter_rfc822_to_text(const XMessageData *data)
55
{
56
        const char *file;
57
        MsgInfo *msginfo;
58
        MsgFlags flags = {0};
59
        MimeInfo *mimeinfo, *partinfo;
60
        XMessageData *newdata;
61
        FILE *fp, *outfp;
62
        GString *text;
63
        GPtrArray *array;
64
        int i;
65
        char *received = NULL;
66

    
67
        file = xfilter_message_data_get_file(data);
68
        if (!file)
69
                return NULL;
70

    
71
        msginfo = procheader_parse_file(file, flags, TRUE);
72
        if (!msginfo)
73
                return NULL;
74
        msginfo->file_path = g_strdup(file);
75

    
76
        mimeinfo = procmime_scan_message(msginfo);
77
        if (!mimeinfo) {
78
                procmsg_msginfo_free(msginfo);
79
                return NULL;
80
        }
81
        if ((fp = procmsg_open_message(msginfo)) == NULL) {
82
                procmime_mimeinfo_free_all(mimeinfo);
83
                procmsg_msginfo_free(msginfo);
84
                return NULL;
85
        }
86

    
87
        text = g_string_new("");
88

    
89
        partinfo = mimeinfo;
90
        while (partinfo) {
91
                const char *name;
92

    
93
                name = partinfo->filename ? partinfo->filename :
94
                        partinfo->name ? partinfo->name : NULL;
95
                if (name) {
96
                        if (text->len > 0)
97
                                g_string_append_c(text, '\n');
98
                        g_string_append(text, name);
99
                        g_string_append_c(text, '\n');
100
                }
101

    
102
                if (partinfo->mime_type == MIME_TEXT ||
103
                    partinfo->mime_type == MIME_TEXT_HTML) {
104
                        if (text->len > 0)
105
                                g_string_append_c(text, '\n');
106
                        outfp = procmime_get_text_content(partinfo, fp, NULL);
107
                        xfilter_read_body_text(text, outfp);
108
                        fclose(outfp);
109
                }
110
                partinfo = procmime_mimeinfo_next(partinfo);
111
        }
112

    
113
        /* get last Received: header */
114
        rewind(fp);
115
        array = procheader_get_header_array(fp, NULL);
116
        for (i = array->len - 1; i >= 0; i--) {
117
                Header *h;
118
                char *p, *ep;
119

    
120
                h = g_ptr_array_index(array, i);
121
                if (!g_ascii_strcasecmp(h->name, "Received")) {
122
                        p = h->body;
123
                        while (g_ascii_isspace(*p))
124
                                p++;
125
                        if (!strncmp(p, "from ", 5))
126
                                p += 5;
127
                        if (!strncmp(p, "by ", 3))
128
                                p += 3;
129
                        ep = strpbrk(p, ";\r\n");
130
                        if (ep)
131
                                received = g_strndup(p, ep - p);
132
                        else
133
                                received = g_strdup(p);
134
                        if ((p = strstr(received, " by ")) != NULL)
135
                                memcpy(p + 1, "  ", 2);
136
                        if ((p = strstr(received, " with ")) != NULL)
137
                                memcpy(p + 1, "    ", 4);
138
                        if ((p = strstr(received, " for ")) != NULL)
139
                                memcpy(p + 1, "   ", 3);
140
                        if ((p = strstr(received, " id ")) != NULL) {
141
                                memcpy(p + 1, "  ", 2);
142
                                p += 4;
143
                                while (*p != '\0' && !g_ascii_isspace(*p)) {
144
                                        *p++ = ' ';
145
                                }
146
                        }
147
                        break;
148
                }
149
        }
150
        procheader_header_array_destroy(array);
151

    
152
        fclose(fp);
153
        procmime_mimeinfo_free_all(mimeinfo);
154

    
155
        newdata = xfilter_message_data_new(text->str, "text/plain");
156
        if (msginfo->from)
157
                xfilter_message_data_set_attribute(newdata, XM_FROM, msginfo->from, FALSE);
158
        if (msginfo->to)
159
                xfilter_message_data_set_attribute(newdata, XM_TO, msginfo->to, FALSE);
160
        if (msginfo->cc)
161
                xfilter_message_data_set_attribute(newdata, XM_CC, msginfo->cc, FALSE);
162
        if (msginfo->subject)
163
                xfilter_message_data_set_attribute(newdata, XM_SUBJECT, msginfo->subject, FALSE);
164
        if (received) {
165
                xfilter_message_data_set_attribute(newdata, XM_RECEIVED, received, FALSE);
166
                g_free(received);
167
        }
168

    
169
        g_string_free(text, TRUE);
170
        procmsg_msginfo_free(msginfo);
171
        return newdata;
172
}
173

    
174
static XFilterStatus xfilter_content_func(XFilter *filter, const XMessageData *data, XFilterResult *result)
175
{
176
        const char *mime_type;
177
        const char *content;
178
        XMessageData *newdata;
179

    
180
        g_return_val_if_fail(result != NULL, XF_ERROR);
181

    
182
        mime_type = xfilter_message_data_get_mime_type(data);
183
        if (!mime_type) {
184
                xfilter_result_set_status(result, XF_UNSUPPORTED_TYPE);
185
                return XF_UNSUPPORTED_TYPE;
186
        }
187

    
188
        if (!g_strncasecmp(mime_type, "text/", 5)) {
189
                content = xfilter_message_data_get_content(data);
190
                newdata = xfilter_message_data_new(content, "text/plain");
191
                xfilter_result_set_message_data(result, newdata);
192
        } else if (!g_strcasecmp(mime_type, "message/rfc822")) {
193
                newdata = xfilter_rfc822_to_text(data);
194
                if (!newdata) {
195
                        xfilter_result_set_status(result, XF_ERROR);
196
                        return XF_ERROR;
197
                }
198
                xfilter_result_set_message_data(result, newdata);
199
#if 0
200
                xfilter_debug_print("from:%s\n", xfilter_message_data_get_attribute(newdata, XM_FROM));
201
                xfilter_debug_print("to:%s\n", xfilter_message_data_get_attribute(newdata, XM_TO));
202
                xfilter_debug_print("cc:%s\n", xfilter_message_data_get_attribute(newdata, XM_CC));
203
                xfilter_debug_print("subject:%s\n", xfilter_message_data_get_attribute(newdata, XM_SUBJECT));
204
                xfilter_debug_print("received:%s\n", xfilter_message_data_get_attribute(newdata, XM_RECEIVED));
205
#endif
206
        } else {
207
                xfilter_result_set_status(result, XF_UNSUPPORTED_TYPE);
208
                return XF_UNSUPPORTED_TYPE;
209
        }
210

    
211
        xfilter_result_set_status(result, XF_REWRITTEN);
212
        return XF_REWRITTEN;
213
}
214

    
215
XFilter *xfilter_textcontent_new(void)
216
{
217
        XFilter *filter;
218

    
219
        filter = xfilter_new(XF_CONTENT, "text-content");
220
        xfilter_set_content_filter_func(X_CONTENT_FILTER(filter),
221
                                        xfilter_content_func);
222

    
223
        return filter;
224
}