Statistics
| Branch: | Tag: | Revision:

root / lib / filters / textcontent-filter.c @ aebfd4cc

History | View | Annotate | Download (4.26 KB)

1
/* SylFilter - a message filter
2
 *
3
 * Copyright (C) 2011 Hiroyuki Yamamoto
4
 * Copyright (C) 2011 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
#include "libsylph/procheader.h"
15
#include "libsylph/procmsg.h"
16
#include "libsylph/procmime.h"
17
#include "libsylph/utils.h"
18

    
19
#define IS_BASE64_CHR(c)                        \
20
        ((c >= '0' && c <= '9') ||                \
21
         (c >= 'A' && c <= 'Z') ||                \
22
         (c >= 'a' && c <= 'z') ||                \
23
         c == '+' || c == '/' || c == '=')
24

    
25

    
26
static void xfilter_read_body_text(GString *text, FILE *fp)
27
{
28
        char buf[8192];
29
        int i;
30

    
31
        while (fgets(buf, sizeof(buf), fp) != NULL) {
32
                for (i = 0; buf[i] != '\0'; i++) {
33
                        if (!IS_BASE64_CHR(buf[i]))
34
                                break;
35
                }
36
                if (i <= 60)
37
                        g_string_append(text, buf);
38
#if 0
39
                else
40
                        g_print("skip line: %s", buf);
41
#endif
42
        }
43
}
44

    
45
static XMessageData *xfilter_rfc822_to_text(const XMessageData *data)
46
{
47
        const char *file;
48
        MsgInfo *msginfo;
49
        MsgFlags flags = {0};
50
        MimeInfo *mimeinfo, *partinfo;
51
        XMessageData *newdata;
52
        FILE *fp, *outfp;
53
        GString *text;
54

    
55
        file = xfilter_message_data_get_file(data);
56
        if (!file)
57
                return NULL;
58

    
59
        msginfo = procheader_parse_file(file, flags, TRUE);
60
        if (!msginfo)
61
                return NULL;
62
        msginfo->file_path = g_strdup(file);
63

    
64
        mimeinfo = procmime_scan_message(msginfo);
65
        if (!mimeinfo) {
66
                procmsg_msginfo_free(msginfo);
67
                return NULL;
68
        }
69
        if ((fp = procmsg_open_message(msginfo)) == NULL) {
70
                procmime_mimeinfo_free_all(mimeinfo);
71
                procmsg_msginfo_free(msginfo);
72
                return NULL;
73
        }
74

    
75
        text = g_string_new("");
76

    
77
        partinfo = mimeinfo;
78
        while (partinfo) {
79
                const char *name;
80

    
81
                name = partinfo->filename ? partinfo->filename :
82
                        partinfo->name ? partinfo->name : NULL;
83
                if (name) {
84
                        if (text->len > 0)
85
                                g_string_append_c(text, '\n');
86
                        g_string_append(text, name);
87
                        g_string_append_c(text, '\n');
88
                }
89

    
90
                if (partinfo->mime_type == MIME_TEXT ||
91
                    partinfo->mime_type == MIME_TEXT_HTML) {
92
                        if (text->len > 0)
93
                                g_string_append_c(text, '\n');
94
                        outfp = procmime_get_text_content(partinfo, fp, NULL);
95
                        xfilter_read_body_text(text, outfp);
96
                        fclose(outfp);
97
                }
98
                partinfo = procmime_mimeinfo_next(partinfo);
99
        }
100

    
101
        fclose(fp);
102
        procmime_mimeinfo_free_all(mimeinfo);
103

    
104
        newdata = xfilter_message_data_new(text->str, "text/plain");
105
        if (msginfo->from)
106
                xfilter_message_data_set_attribute(newdata, XM_FROM, msginfo->from, FALSE);
107
        if (msginfo->to)
108
                xfilter_message_data_set_attribute(newdata, XM_TO, msginfo->to, FALSE);
109
        if (msginfo->cc)
110
                xfilter_message_data_set_attribute(newdata, XM_CC, msginfo->cc, FALSE);
111
        if (msginfo->subject)
112
                xfilter_message_data_set_attribute(newdata, XM_SUBJECT, msginfo->subject, FALSE);
113

    
114
        g_string_free(text, TRUE);
115
        procmsg_msginfo_free(msginfo);
116
        return newdata;
117
}
118

    
119
static XFilterStatus xfilter_content_func(XFilter *filter, const XMessageData *data, XFilterResult *result)
120
{
121
        const char *mime_type;
122
        const char *content;
123
        XMessageData *newdata;
124

    
125
        g_return_val_if_fail(result != NULL, XF_ERROR);
126

    
127
        mime_type = xfilter_message_data_get_mime_type(data);
128
        if (!mime_type) {
129
                xfilter_result_set_status(result, XF_UNSUPPORTED_TYPE);
130
                return XF_UNSUPPORTED_TYPE;
131
        }
132

    
133
        if (!g_strncasecmp(mime_type, "text/", 5)) {
134
                content = xfilter_message_data_get_content(data);
135
                newdata = xfilter_message_data_new(content, "text/plain");
136
                xfilter_result_set_message_data(result, newdata);
137
        } else if (!g_strcasecmp(mime_type, "message/rfc822")) {
138
                newdata = xfilter_rfc822_to_text(data);
139
                if (!newdata) {
140
                        xfilter_result_set_status(result, XF_ERROR);
141
                        return XF_ERROR;
142
                }
143
                xfilter_result_set_message_data(result, newdata);
144
#if 0
145
                xfilter_debug_print("from:%s\n", xfilter_message_data_get_attribute(newdata, XM_FROM));
146
                xfilter_debug_print("to:%s\n", xfilter_message_data_get_attribute(newdata, XM_TO));
147
                xfilter_debug_print("cc:%s\n", xfilter_message_data_get_attribute(newdata, XM_CC));
148
                xfilter_debug_print("subject:%s\n", xfilter_message_data_get_attribute(newdata, XM_SUBJECT));
149
#endif
150
        } else {
151
                xfilter_result_set_status(result, XF_UNSUPPORTED_TYPE);
152
                return XF_UNSUPPORTED_TYPE;
153
        }
154

    
155
        xfilter_result_set_status(result, XF_REWRITTEN);
156
        return XF_REWRITTEN;
157
}
158

    
159
XFilter *xfilter_textcontent_new(void)
160
{
161
        XFilter *filter;
162

    
163
        filter = xfilter_new(XF_CONTENT, "text-content");
164
        xfilter_set_content_filter_func(X_CONTENT_FILTER(filter),
165
                                        xfilter_content_func);
166

    
167
        return filter;
168
}