summaryrefslogtreecommitdiff
path: root/libmailutils
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-10-07 13:23:45 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-10-07 13:23:45 +0300
commitdd8d091ba3cae58fd437c664478de8bcbdf25ac6 (patch)
tree8ffdc4ca5a4a05808d247a69ca87635a9f92a71a /libmailutils
parentf24df125b4a5f7e29eee39e89127871a38856281 (diff)
downloadmailutils-dd8d091ba3cae58fd437c664478de8bcbdf25ac6.tar.gz
mailutils-dd8d091ba3cae58fd437c664478de8bcbdf25ac6.tar.bz2
Implement a filter for quoting ^From. Use it for appending to UNIX mailboxes.
* libmailutils/fromflt.c: New file. * libmailutils/Makefile.am (libmailutils_la_SOURCES): Add fromflt.c * libmailutils/tests/testsuite.at: Include fromflt.at. * include/mailutils/filter.h (mu_from_filter): New filter type. * libmailutils/filter.c (mu_filter_get_list): Register mu_from_filter. * libmailutils/fromflt.at: New file. * libmailutils/tests/Makefile.am (TESTSUITE_AT): Add fromflt.at. * libmailutils/tests/base64d.at: Mention `filter' in the keywords. * libmailutils/tests/base64e.at: Likewise. * libmailutils/tests/fltst.c (main): Fix argc check. * libproto/mbox/mbox.c (append_message_to_stream): Use "FROM" filter.
Diffstat (limited to 'libmailutils')
-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
9 files changed, 388 insertions, 5 deletions
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;