summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mailutils/filter.h3
-rw-r--r--libmailutils/Makefile.am1
-rw-r--r--libmailutils/filter.c1
-rw-r--r--libmailutils/fromflt.c283
-rw-r--r--libmailutils/tests/Makefile.am1
-rw-r--r--libmailutils/tests/base64d.at4
-rw-r--r--libmailutils/tests/base64e.at4
-rw-r--r--libmailutils/tests/fltst.c2
-rw-r--r--libmailutils/tests/fromflt.at96
-rw-r--r--libmailutils/tests/testsuite.at1
-rw-r--r--libproto/mbox/mbox.c17
11 files changed, 403 insertions, 10 deletions
diff --git a/include/mailutils/filter.h b/include/mailutils/filter.h
index 120318d57..d9c53ca7f 100644
--- a/include/mailutils/filter.h
+++ b/include/mailutils/filter.h
@@ -103,7 +103,8 @@ extern mu_filter_record_t mu_bit8_filter;
103extern mu_filter_record_t mu_bit7_filter; 103extern mu_filter_record_t mu_bit7_filter;
104extern mu_filter_record_t mu_rfc_2047_Q_filter; 104extern mu_filter_record_t mu_rfc_2047_Q_filter;
105extern mu_filter_record_t mu_rfc_2047_B_filter; 105extern mu_filter_record_t mu_rfc_2047_B_filter;
106 106extern mu_filter_record_t mu_from_filter;
107
107enum mu_iconv_fallback_mode 108enum mu_iconv_fallback_mode
108 { 109 {
109 mu_fallback_none, 110 mu_fallback_none,
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 3f083e01d..07a0a4e54 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -83,6 +83,7 @@ libmailutils_la_SOURCES = \
83 fltstream.c\ 83 fltstream.c\
84 folder.c\ 84 folder.c\
85 freeitem.c\ 85 freeitem.c\
86 fromflt.c\
86 gdebug.c\ 87 gdebug.c\
87 getpass.c\ 88 getpass.c\
88 gocs.c\ 89 gocs.c\
diff --git a/libmailutils/filter.c b/libmailutils/filter.c
index 8fdc25f90..0008ba0f1 100644
--- a/libmailutils/filter.c
+++ b/libmailutils/filter.c
@@ -78,6 +78,7 @@ mu_filter_get_list (mu_list_t *plist)
78 mu_list_append (filter_list, mu_dot_filter); 78 mu_list_append (filter_list, mu_dot_filter);
79 mu_list_append (filter_list, mu_rfc_2047_Q_filter); 79 mu_list_append (filter_list, mu_rfc_2047_Q_filter);
80 mu_list_append (filter_list, mu_rfc_2047_B_filter); 80 mu_list_append (filter_list, mu_rfc_2047_B_filter);
81 mu_list_append (filter_list, mu_from_filter);
81 /* FIXME: add the default encodings? */ 82 /* FIXME: add the default encodings? */
82 } 83 }
83 *plist = filter_list; 84 *plist = filter_list;
diff --git a/libmailutils/fromflt.c b/libmailutils/fromflt.c
new file mode 100644
index 000000000..d96d46d85
--- /dev/null
+++ b/libmailutils/fromflt.c
@@ -0,0 +1,283 @@
1/* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003, 2007, 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library; if not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301 USA */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <mailutils/errno.h>
26#include <mailutils/filter.h>
27#include <mailutils/stream.h>
28
29enum from_decode_state
30 {
31 from_decode_init,
32 from_decode_nl,
33 from_decode_char
34 };
35
36#define GT_FROM_MARK_STR ">From "
37#define GT_FROM_MARK_LEN (sizeof (GT_FROM_MARK_STR) - 1)
38
39/* Move min(isize,osize) bytes from iptr to optr, replacing each '>From '
40 at the beginning of line with 'From '. */
41static enum mu_filter_result
42_from_decoder (void *xd,
43 enum mu_filter_command cmd,
44 struct mu_filter_io *iobuf)
45{
46 int *pstate = xd;
47 const unsigned char *iptr;
48 size_t isize;
49 char *optr;
50 size_t osize;
51 enum from_decode_state state;
52 size_t i, j;
53
54 switch (cmd)
55 {
56 case mu_filter_init:
57 *pstate = from_decode_init;
58 return mu_filter_ok;
59
60 case mu_filter_done:
61 return mu_filter_ok;
62
63 default:
64 state = *pstate;
65 break;
66 }
67
68 iptr = (const unsigned char *) iobuf->input;
69 isize = iobuf->isize;
70 optr = iobuf->output;
71 osize = iobuf->osize;
72
73 for (i = j = 0; i < isize && j < osize; i++)
74 {
75 unsigned char c = *iptr++;
76
77 if (c == '\n')
78 state = from_decode_nl;
79 else if (state == from_decode_init || state == from_decode_nl)
80 {
81 size_t len = isize - i;
82
83 if (len < GT_FROM_MARK_LEN)
84 {
85 if (memcmp (iptr - 1, GT_FROM_MARK_STR, len) == 0)
86 {
87 if (i == 0)
88 {
89 iobuf->isize = GT_FROM_MARK_LEN - len;
90 return mu_filter_moreinput;
91 }
92 break;
93 }
94 else
95 state = from_decode_char;
96 }
97 else if (memcmp (iptr - 1, GT_FROM_MARK_STR, GT_FROM_MARK_LEN) == 0)
98 {
99 /* Skip > */
100 state = from_decode_char;
101 continue;
102 }
103 }
104 optr[j++] = c;
105 }
106
107 *pstate = state;
108 iobuf->isize = i;
109 iobuf->osize = j;
110 return mu_filter_ok;
111}
112
113#define FROM_MARK_STR "From "
114#define FROM_MARK_LEN (sizeof (FROM_MARK_STR) - 1)
115
116enum from_encode_state
117 {
118 from_encode_init,
119 from_encode_nl,
120 from_encode_char,
121 from_encode_gt,
122 from_encode_f,
123 from_encode_r,
124 from_encode_o,
125 from_encode_m,
126 from_encode_sp
127 };
128
129static int length_to_state_tab[] = {
130 from_encode_gt,
131 from_encode_f,
132 from_encode_r,
133 from_encode_o,
134 from_encode_m,
135 from_encode_sp
136};
137
138static int state_to_length_tab[] = {
139 0, 0, 0,
140 GT_FROM_MARK_LEN,
141 GT_FROM_MARK_LEN-1,
142 GT_FROM_MARK_LEN-2,
143 GT_FROM_MARK_LEN-3,
144 GT_FROM_MARK_LEN-4,
145 GT_FROM_MARK_LEN-5
146};
147
148/* Move min(isize,osize) bytes from iptr to optr, replacing each 'From '
149 at the beginning of line with '>From '. */
150
151static enum mu_filter_result
152_from_encoder (void *xd,
153 enum mu_filter_command cmd,
154 struct mu_filter_io *iobuf)
155{
156 int *pstate = xd;
157 const unsigned char *iptr;
158 size_t isize;
159 char *optr;
160 size_t osize;
161 enum from_encode_state state;
162 size_t i, j;
163
164 switch (cmd)
165 {
166 case mu_filter_init:
167 *pstate = from_encode_init;
168 return mu_filter_ok;
169
170 case mu_filter_done:
171 return mu_filter_ok;
172
173 default:
174 state = *pstate;
175 switch (state)
176 {
177 case from_encode_init:
178 case from_encode_nl:
179 case from_encode_char:
180 break;
181
182 default:
183 osize = state_to_length_tab[state];
184 if (iobuf->osize < osize)
185 {
186 iobuf->osize = osize;
187 return mu_filter_moreoutput;
188 }
189 memcpy (iobuf->output, GT_FROM_MARK_STR + GT_FROM_MARK_LEN - osize,
190 osize);
191 iobuf->osize = osize;
192 iobuf->isize = osize;
193 *pstate = from_encode_init;
194 return mu_filter_ok;
195 }
196 break;
197 }
198
199 iptr = (const unsigned char *) iobuf->input;
200 isize = iobuf->isize;
201 optr = iobuf->output;
202 osize = iobuf->osize;
203
204 for (i = j = 0; i < isize && j < osize; i++)
205 {
206 unsigned char c = *iptr++;
207
208 if (c == '\n')
209 state = from_encode_nl;
210 else if (state == from_encode_init || state == from_encode_nl)
211 {
212 size_t len = isize - i;
213
214 if (len < FROM_MARK_LEN)
215 {
216 if (memcmp (iptr - 1, FROM_MARK_STR, len) == 0)
217 {
218 if (i == 0)
219 {
220 iobuf->isize = FROM_MARK_LEN;
221 return mu_filter_moreinput;
222 }
223 break;
224 }
225 else
226 state = from_encode_char;
227 }
228 else if (memcmp (iptr - 1, FROM_MARK_STR, FROM_MARK_LEN) == 0)
229 {
230 size_t rest = osize - j;
231
232 if (rest > GT_FROM_MARK_LEN)
233 rest = GT_FROM_MARK_LEN;
234 else if (rest < 2)
235 {
236 if (i == 0)
237 {
238 iobuf->osize = GT_FROM_MARK_LEN;
239 return mu_filter_moreoutput;
240 }
241 break;
242 }
243
244 memcpy (optr + j, GT_FROM_MARK_STR, rest);
245 i += rest - 2;
246 iptr += rest - 2;
247 j += rest;
248 if (rest < GT_FROM_MARK_LEN)
249 state = length_to_state_tab[rest];
250 else
251 state = from_encode_char;
252 continue;
253 }
254 else
255 state = from_encode_char;
256 }
257 optr[j++] = c;
258 }
259 *pstate = state;
260 iobuf->isize = i;
261 iobuf->osize = j;
262 return mu_filter_ok;
263}
264
265static int
266_from_alloc_state (void **pret, int mode, void *data MU_ARG_UNUSED)
267{
268 *pret = malloc (sizeof (int));
269 if (!*pret)
270 return ENOMEM;
271 return 0;
272}
273
274static struct _mu_filter_record _from_filter = {
275 "FROM",
276 0,
277 _from_alloc_state,
278 _from_encoder,
279 _from_decoder
280};
281
282mu_filter_record_t mu_from_filter = &_from_filter;
283
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 7324e88e4..a8215fb5f 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -64,6 +64,7 @@ TESTSUITE_AT = \
64 base64e.at\ 64 base64e.at\
65 decode2047.at\ 65 decode2047.at\
66 encode2047.at\ 66 encode2047.at\
67 fromflt.at\
67 list.at\ 68 list.at\
68 mailcap.at\ 69 mailcap.at\
69 testsuite.at\ 70 testsuite.at\
diff --git a/libmailutils/tests/base64d.at b/libmailutils/tests/base64d.at
index b26c41591..df1efd31d 100644
--- a/libmailutils/tests/base64d.at
+++ b/libmailutils/tests/base64d.at
@@ -16,7 +16,7 @@
16# This file is part of Mailfromd testsuite. 16# This file is part of Mailfromd testsuite.
17 17
18AT_SETUP([base64 decoding (read)]) 18AT_SETUP([base64 decoding (read)])
19AT_KEYWORDS([base64 base64d base64dr decode]) 19AT_KEYWORDS([base64 base64d base64dr decode filter])
20 20
21AT_CHECK([ 21AT_CHECK([
22cp $abs_top_srcdir/libmailutils/tests/Encode expout 22cp $abs_top_srcdir/libmailutils/tests/Encode expout
@@ -28,7 +28,7 @@ AT_CLEANUP
28 28
29 29
30AT_SETUP([base64 decoding (write)]) 30AT_SETUP([base64 decoding (write)])
31AT_KEYWORDS([base64 base64d base64dw decode]) 31AT_KEYWORDS([base64 base64d base64dw decode filter])
32 32
33AT_CHECK([ 33AT_CHECK([
34cp $abs_top_srcdir/libmailutils/tests/Encode expout 34cp $abs_top_srcdir/libmailutils/tests/Encode expout
diff --git a/libmailutils/tests/base64e.at b/libmailutils/tests/base64e.at
index c753471a1..b94522e41 100644
--- a/libmailutils/tests/base64e.at
+++ b/libmailutils/tests/base64e.at
@@ -16,7 +16,7 @@
16# This file is part of Mailfromd testsuite. 16# This file is part of Mailfromd testsuite.
17 17
18AT_SETUP([base64 encoding (read)]) 18AT_SETUP([base64 encoding (read)])
19AT_KEYWORDS([base64 base64e base64er encode]) 19AT_KEYWORDS([base64 base64e base64er encode filter])
20 20
21AT_CHECK([ 21AT_CHECK([
22cp $abs_top_srcdir/libmailutils/tests/Decode expout 22cp $abs_top_srcdir/libmailutils/tests/Decode expout
@@ -28,7 +28,7 @@ AT_CLEANUP
28 28
29 29
30AT_SETUP([base64 encoding (write)]) 30AT_SETUP([base64 encoding (write)])
31AT_KEYWORDS([base64 base64e base64ew encode]) 31AT_KEYWORDS([base64 base64e base64ew encode filter])
32 32
33AT_CHECK([ 33AT_CHECK([
34cp $abs_top_srcdir/libmailutils/tests/Decode expout 34cp $abs_top_srcdir/libmailutils/tests/Decode expout
diff --git a/libmailutils/tests/fltst.c b/libmailutils/tests/fltst.c
index 8597dd5a0..d62a02b2e 100644
--- a/libmailutils/tests/fltst.c
+++ b/libmailutils/tests/fltst.c
@@ -114,7 +114,7 @@ main (int argc, char * argv [])
114 114
115 if (argc == 1) 115 if (argc == 1)
116 usage (NULL); 116 usage (NULL);
117 if (argc < 3) 117 if (argc < 4)
118 usage ("not enough arguments"); 118 usage ("not enough arguments");
119 119
120 fltname = argv[1]; 120 fltname = argv[1];
diff --git a/libmailutils/tests/fromflt.at b/libmailutils/tests/fromflt.at
new file mode 100644
index 000000000..a5b331375
--- /dev/null
+++ b/libmailutils/tests/fromflt.at
@@ -0,0 +1,96 @@
1# This file is part of GNU Mailutils. -*- Autotest -*-
2# Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3#
4# GNU Mailutils is free software; you can redistribute it and/or
5# modify it under the terms of the GNU General Public License as
6# published by the Free Software Foundation; either version 3, or (at
7# your option) any later version.
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12# General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
16# This file is part of Mailfromd testsuite.
17
18# -------------------------------------------
19# Data for 'From' filter tests.
20# -------------------------------------------
21
22m4_define([from_plain_text],[From this time on
23from that source
24 From stdin
25and
26From them
27])
28
29m4_define([from_encoded_text],[>From this time on
30from that source
31 From stdin
32and
33>From them
34])
35
36# -------------------------------------------
37# Test 'From' encoding
38# -------------------------------------------
39
40# Test read mode
41
42AT_SETUP([from filter encoding (read)])
43AT_KEYWORDS([from frome fromer encode])
44
45AT_CHECK([
46AT_DATA([input],from_plain_text)
47fltst from encode read < input
48],
49[0],
50[from_encoded_text])
51
52AT_CLEANUP
53
54# The same, in write mode
55
56AT_SETUP([from filter encoding (write)])
57AT_KEYWORDS([from frome fromew encode])
58
59AT_CHECK([
60AT_DATA([input],from_plain_text)
61fltst from encode write < input
62],
63[0],
64[from_encoded_text])
65
66AT_CLEANUP
67
68# -------------------------------------------
69# Test '>From' decoding
70# -------------------------------------------
71
72AT_SETUP([from filter decoding (read)])
73AT_KEYWORDS([from fromd fromdr decode])
74
75AT_CHECK([
76AT_DATA([input],from_encoded_text)
77fltst from decode read < input
78],
79[0],
80[from_plain_text])
81
82AT_CLEANUP
83
84# The same, in write mode
85
86AT_SETUP([from filter decoding (write)])
87AT_KEYWORDS([from fromd fromdw decode])
88
89AT_CHECK([
90AT_DATA([input],from_encoded_text)
91fltst from decode write < input
92],
93[0],
94[from_plain_text])
95
96AT_CLEANUP
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index 1de64b66b..fbdc7c99b 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -63,4 +63,5 @@ m4_include([base64e.at])
63m4_include([base64d.at]) 63m4_include([base64d.at])
64m4_include([decode2047.at]) 64m4_include([decode2047.at])
65m4_include([encode2047.at]) 65m4_include([encode2047.at])
66m4_include([fromflt.at])
66 67
diff --git a/libproto/mbox/mbox.c b/libproto/mbox/mbox.c
index 62507657e..cc412ff37 100644
--- a/libproto/mbox/mbox.c
+++ b/libproto/mbox/mbox.c
@@ -28,6 +28,7 @@
28#include <mbox0.h> 28#include <mbox0.h>
29#include <mailutils/cstr.h> 29#include <mailutils/cstr.h>
30#include <mailutils/io.h> 30#include <mailutils/io.h>
31#include <mailutils/filter.h>
31 32
32#define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED) 33#define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED)
33#define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2) 34#define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2)
@@ -1033,7 +1034,7 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg,
1033 mbox_data_t mud, int flags) 1034 mbox_data_t mud, int flags)
1034{ 1035{
1035 int status; 1036 int status;
1036 mu_stream_t istr; 1037 mu_stream_t istr, flt;
1037 1038
1038 status = msg_envelope_to_stream (ostr, msg); 1039 status = msg_envelope_to_stream (ostr, msg);
1039 if (status) 1040 if (status)
@@ -1084,10 +1085,18 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg,
1084 if (status) 1085 if (status)
1085 return status; 1086 return status;
1086 } 1087 }
1087 status = mu_stream_copy (ostr, istr, 0, NULL); 1088
1088 mu_stream_destroy (&istr); 1089 status = mu_filter_create (&flt, istr, "FROM",
1090 MU_FILTER_ENCODE, MU_STREAM_READ);
1091 mu_stream_unref (istr);
1089 if (status == 0) 1092 if (status == 0)
1090 status = mu_stream_write (ostr, "\n", 1, NULL); 1093 {
1094 status = mu_stream_copy (ostr, flt, 0, NULL);
1095 mu_stream_destroy (&flt);
1096 if (status == 0)
1097 status = mu_stream_write (ostr, "\n", 1, NULL);
1098 }
1099
1091 return status; 1100 return status;
1092} 1101}
1093 1102

Return to:

Send suggestions and report system problems to the System administrator.