Statistics
| Branch: | Tag: | Revision:

root / lib / filters / textcontent-filter.c @ 2d9cf61c

History | View | Annotate | Download (5.63 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 <glib.h>
8
#include <stdio.h>
9
#include <string.h>
10

    
11
#include "filter.h"
12
#include "textcontent-filter.h"
13

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

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

    
32

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

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

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

    
65
        file = xfilter_message_data_get_file(data);
66
        if (!file)
67
                return NULL;
68

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

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

    
85
        text = g_string_new("");
86

    
87
        partinfo = mimeinfo;
88
        while (partinfo) {
89
                const char *name;
90

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

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

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

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

    
150
        fclose(fp);
151
        procmime_mimeinfo_free_all(mimeinfo);
152

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

    
167
        g_string_free(text, TRUE);
168
        procmsg_msginfo_free(msginfo);
169
        return newdata;
170
}
171

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

    
178
        g_return_val_if_fail(result != NULL, XF_ERROR);
179

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

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

    
209
        xfilter_result_set_status(result, XF_REWRITTEN);
210
        return XF_REWRITTEN;
211
}
212

    
213
XFilter *xfilter_textcontent_new(void)
214
{
215
        XFilter *filter;
216

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

    
221
        return filter;
222
}