Commit 8f8d9036 8f8d9036cc943e4884b21ad050a1d443e102e47e by Sergey Poznyakoff

Implement filter chains. Revamp filter output length support.

* include/mailutils/filter.h (mu_filter_chain_create_pred)
(mu_filter_chain_create): New prototypes.
(_mu_filter_record)<max_line_length>: Remove.
* libmailutils/filter/fltchain.c: New file.
* libmailutils/filter/Makefile.am (libfilter_la_SOURCES): Add fltchain.c.
* libmailutils/filter/base64.c: Implement line length limit for encoder.
(base64_state): New enum.
(base64_line): New struct.
(_base64_encoder): xd brings a pointer to struct base64_line. Use it
to limit the output line length.
(alloc_state): New function.
(_base64_filter): Register alloc_state.
(_base64_filter, _B_filter): Remove max_line_length initialization.

* libmailutils/filter/binflt.c: Remove max_line_length initialization.
* libmailutils/filter/crlfflt.c: Likewise.
* libmailutils/filter/dot.c: Likewise.
* libmailutils/filter/fromflt.c: Likewise.
* libmailutils/filter/header.c: Likewise.
* libmailutils/filter/inline-comment.c: Likewise.
* libmailutils/filter/linecon.c: Likewise.
* libmailutils/filter/qpflt.c: Likewise.

* libmailutils/filter/linelenflt.c: Redo line filter as a regular filter.
(mu_linelen_filter): New global.

* libmailutils/filter/filter.c (mu_filter_get_list): Register mu_linelen_filter.
(filter_create_rd, filter_create_wr): Remove.
(mu_filter_create_args): Use mu_filter_stream_create directly.

* examples/base64.c: Re-implement the -l option via filter chains.

* libmailutils/tests/fltst.c: Remove the linelen option.
* libmailutils/tests/base64d.at: Remove the linelen option from fltst
invocations.
* mu/filter.c: Remove the --line-length option.  Not needed now, its
effect is achieved by "FLT + [~]linelen" chain.
1 parent aa1caef5
...@@ -93,23 +93,6 @@ c_copy (mu_stream_t out, mu_stream_t in) ...@@ -93,23 +93,6 @@ c_copy (mu_stream_t out, mu_stream_t in)
93 } 93 }
94 } 94 }
95 95
96 /* Set the maximum line length for the filter NAME to LENGTH.
97 FIXME: This is a kludge. Perhaps API should provide a function
98 for that. */
99 static void
100 reset_line_length (const char *name, size_t length)
101 {
102 mu_list_t list;
103 int status;
104 mu_filter_record_t frec;
105
106 mu_filter_get_list (&list);
107 status = mu_list_locate (list, (void*)name, (void**)&frec);
108 if (status == 0)
109 frec->max_line_length = length;
110 /* don't bail out, leave that to mu_filter_create */
111 }
112
113 int 96 int
114 main (int argc, char * argv []) 97 main (int argc, char * argv [])
115 { 98 {
...@@ -120,8 +103,9 @@ main (int argc, char * argv []) ...@@ -120,8 +103,9 @@ main (int argc, char * argv [])
120 char *input = NULL, *output = NULL; 103 char *input = NULL, *output = NULL;
121 char *encoding = "base64"; 104 char *encoding = "base64";
122 mu_off_t shift = 0; 105 mu_off_t shift = 0;
123 size_t line_length; 106 char *line_length_option = NULL;
124 int line_length_option = 0; 107 char *fargv[5];
108 size_t fargc = 0;
125 109
126 while ((c = getopt (argc, argv, "deE:hi:l:o:ps:vw")) != EOF) 110 while ((c = getopt (argc, argv, "deE:hi:l:o:ps:vw")) != EOF)
127 switch (c) 111 switch (c)
...@@ -147,8 +131,7 @@ main (int argc, char * argv []) ...@@ -147,8 +131,7 @@ main (int argc, char * argv [])
147 break; 131 break;
148 132
149 case 'l': 133 case 'l':
150 line_length = strtoul (optarg, NULL, 10); 134 line_length_option = optarg;
151 line_length_option = 1;
152 break; 135 break;
153 136
154 case 'p': 137 case 'p':
...@@ -186,22 +169,33 @@ main (int argc, char * argv []) ...@@ -186,22 +169,33 @@ main (int argc, char * argv [])
186 else 169 else
187 MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0)); 170 MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
188 171
189 if (line_length_option) 172 fargv[fargc++] = encoding;
190 reset_line_length (encoding, line_length); 173 if (line_length_option && strcmp (line_length_option, "0"))
174 {
175 if (mu_c_strcasecmp (encoding, "base64") == 0)
176 fargv[0] = "B"; /* B encoding has no length limit */
177 fargv[fargc++] = "+";
178 fargv[fargc++] = (mode == MU_FILTER_DECODE) ? "~linelen" : "linelen";
179 fargv[fargc++] = line_length_option;
180 }
181 fargv[fargc] = NULL;
191 182
192 if (flags == MU_STREAM_READ) 183 if (flags == MU_STREAM_READ)
193 { 184 {
194 MU_ASSERT (mu_filter_create (&flt, in, encoding, mode, 185 MU_ASSERT (mu_filter_chain_create (&flt, in, mode,
195 MU_STREAM_READ|MU_STREAM_SEEK| 186 MU_STREAM_READ|MU_STREAM_SEEK,
196 MU_STREAM_AUTOCLOSE)); 187 fargc, fargv));
188 mu_stream_unref (in);
197 if (shift) 189 if (shift)
198 MU_ASSERT (mu_stream_seek (flt, shift, MU_SEEK_SET, NULL)); 190 MU_ASSERT (mu_stream_seek (flt, shift, MU_SEEK_SET, NULL));
199 c_copy (out, flt); 191 c_copy (out, flt);
200 } 192 }
201 else 193 else
202 { 194 {
203 MU_ASSERT (mu_filter_create (&flt, out, encoding, mode, 195 MU_ASSERT (mu_filter_chain_create (&flt, out, mode,
204 MU_STREAM_WRITE|MU_STREAM_AUTOCLOSE)); 196 MU_STREAM_WRITE,
197 fargc, fargv));
198 mu_stream_unref (out);
205 if (shift) 199 if (shift)
206 MU_ASSERT (mu_stream_seek (in, shift, MU_SEEK_SET, NULL)); 200 MU_ASSERT (mu_stream_seek (in, shift, MU_SEEK_SET, NULL));
207 c_copy (flt, in); 201 c_copy (flt, in);
......
...@@ -81,11 +81,19 @@ int mu_filter_stream_create (mu_stream_t *pflt, ...@@ -81,11 +81,19 @@ int mu_filter_stream_create (mu_stream_t *pflt,
81 void *xdata, 81 void *xdata,
82 int flags); 82 int flags);
83 83
84 int mu_filter_chain_create_pred (mu_stream_t *pret, mu_stream_t transport,
85 int defmode, int flags,
86 size_t argc, char **argv,
87 int (*pred) (void *, mu_stream_t,
88 const char *),
89 void *closure);
90 int mu_filter_chain_create (mu_stream_t *pret, mu_stream_t transport,
91 int defmode, int flags,
92 size_t argc, char **argv);
84 93
85 struct _mu_filter_record 94 struct _mu_filter_record
86 { 95 {
87 const char *name; 96 const char *name;
88 size_t max_line_length;
89 mu_filter_new_data_t newdata; 97 mu_filter_new_data_t newdata;
90 mu_filter_xcode_t encoder; 98 mu_filter_xcode_t encoder;
91 mu_filter_xcode_t decoder; 99 mu_filter_xcode_t decoder;
...@@ -111,6 +119,7 @@ extern mu_filter_record_t mu_from_filter; ...@@ -111,6 +119,7 @@ extern mu_filter_record_t mu_from_filter;
111 extern mu_filter_record_t mu_inline_comment_filter; 119 extern mu_filter_record_t mu_inline_comment_filter;
112 extern mu_filter_record_t mu_header_filter; 120 extern mu_filter_record_t mu_header_filter;
113 extern mu_filter_record_t mu_linecon_filter; 121 extern mu_filter_record_t mu_linecon_filter;
122 extern mu_filter_record_t mu_linelen_filter;
114 123
115 enum mu_iconv_fallback_mode 124 enum mu_iconv_fallback_mode
116 { 125 {
......
...@@ -26,6 +26,7 @@ libfilter_la_SOURCES =\ ...@@ -26,6 +26,7 @@ libfilter_la_SOURCES =\
26 dot.c\ 26 dot.c\
27 filter.c\ 27 filter.c\
28 filter_iconv.c\ 28 filter_iconv.c\
29 fltchain.c\
29 fromflt.c\ 30 fromflt.c\
30 header.c\ 31 header.c\
31 inline-comment.c\ 32 inline-comment.c\
......
...@@ -175,25 +175,54 @@ _base64_decoder (void *xd MU_ARG_UNUSED, ...@@ -175,25 +175,54 @@ _base64_decoder (void *xd MU_ARG_UNUSED,
175 return mu_filter_ok; 175 return mu_filter_ok;
176 } 176 }
177 177
178 enum base64_state
179 {
180 base64_init,
181 base64_newline,
182 base64_rollback
183 };
184
185 struct base64_line
186 {
187 enum base64_state state;
188 size_t max_len;
189 size_t cur_len;
190 char save[3];
191 int idx;
192 };
193
178 static enum mu_filter_result 194 static enum mu_filter_result
179 _base64_encoder (void *xd MU_ARG_UNUSED, 195 _base64_encoder (void *xd,
180 enum mu_filter_command cmd, 196 enum mu_filter_command cmd,
181 struct mu_filter_io *iobuf) 197 struct mu_filter_io *iobuf)
182 { 198 {
199 struct base64_line bline, *lp = xd;
183 size_t consumed = 0; 200 size_t consumed = 0;
184 int pad = 0; 201 int pad = 0;
185 const unsigned char *ptr = (const unsigned char*) iobuf->input; 202 const unsigned char *ptr;
186 size_t nbytes = 0; 203 size_t nbytes = 0;
187 size_t isize; 204 size_t isize;
188 char *optr; 205 char *optr;
189 size_t osize; 206 size_t osize;
190 enum mu_filter_result res; 207 enum mu_filter_result res;
191 208
209 if (!lp)
210 {
211 lp = &bline;
212 lp->max_len = 0;
213 lp->state = base64_init;
214 }
192 switch (cmd) 215 switch (cmd)
193 { 216 {
194 case mu_filter_init: 217 case mu_filter_init:
218 lp->state = base64_init;
219 lp->cur_len = 0;
220 lp->idx = 3;
221 return mu_filter_ok;
222
195 case mu_filter_done: 223 case mu_filter_done:
196 return mu_filter_ok; 224 return mu_filter_ok;
225
197 default: 226 default:
198 break; 227 break;
199 } 228 }
...@@ -214,15 +243,48 @@ _base64_encoder (void *xd MU_ARG_UNUSED, ...@@ -214,15 +243,48 @@ _base64_encoder (void *xd MU_ARG_UNUSED,
214 return mu_filter_moreoutput; 243 return mu_filter_moreoutput;
215 } 244 }
216 245
246 ptr = (const unsigned char*) iobuf->input;
217 isize = iobuf->isize; 247 isize = iobuf->isize;
218 optr = iobuf->output; 248 optr = iobuf->output;
219 osize = iobuf->osize; 249 osize = iobuf->osize;
220 250
221 while ((consumed + 3 <= isize && nbytes + 4 <= osize) || pad) 251 while (nbytes < osize)
222 { 252 {
223 unsigned char c1 = 0, c2 = 0, x = '=', y = '='; 253 unsigned char c1 = 0, c2 = 0, x = '=', y = '=';
254
255 if (lp->max_len && lp->cur_len == lp->max_len)
256 {
257 if (lp->state == base64_init)
258 lp->idx = 3;
259 lp->state = base64_newline;
260 }
261 switch (lp->state)
262 {
263 case base64_init:
264 break;
265 case base64_newline:
266 *optr++ = '\n';
267 nbytes++;
268 lp->cur_len = 0;
269 lp->state = base64_rollback;
270 /* Fall through */
271 case base64_rollback:
272 if (lp->idx < 3)
273 {
274 *optr++ = lp->save[lp->idx++];
275 nbytes++;
276 lp->cur_len++;
277 continue;
278 }
279 lp->state = base64_init;
280 }
281
282 if (!(consumed + 3 <= isize || pad))
283 break;
224 284
225 *optr++ = b64tab[ptr[0] >> 2]; 285 *optr++ = b64tab[ptr[0] >> 2];
286 nbytes++;
287 lp->cur_len++;
226 consumed++; 288 consumed++;
227 switch (isize - consumed) 289 switch (isize - consumed)
228 { 290 {
...@@ -235,20 +297,22 @@ _base64_encoder (void *xd MU_ARG_UNUSED, ...@@ -235,20 +297,22 @@ _base64_encoder (void *xd MU_ARG_UNUSED,
235 x = b64tab[((ptr[1] << 2) + c2) & 0x3f]; 297 x = b64tab[((ptr[1] << 2) + c2) & 0x3f];
236 c1 = (ptr[1] >> 4); 298 c1 = (ptr[1] >> 4);
237 case 0: 299 case 0:
238 *optr++ = b64tab[((ptr[0] << 4) + c1) & 0x3f]; 300 lp->save[0] = b64tab[((ptr[0] << 4) + c1) & 0x3f];
239 *optr++ = x; 301 lp->save[1] = x;
240 *optr++ = y; 302 lp->save[2] = y;
303 lp->idx = 0;
304 lp->state = base64_rollback;
241 } 305 }
242 306
243 ptr += 3; 307 ptr += 3;
244 nbytes += 4;
245 pad = 0; 308 pad = 0;
246 } 309 }
247 310
248 /* Consumed may grow bigger than isize if cmd is mu_filter_lastbuf */ 311 /* Consumed may grow bigger than isize if cmd is mu_filter_lastbuf */
249 if (consumed > iobuf->isize) 312 if (consumed > iobuf->isize)
250 consumed = iobuf->isize; 313 consumed = iobuf->isize;
251 if (cmd == mu_filter_lastbuf && consumed < iobuf->isize) 314 if (cmd == mu_filter_lastbuf &&
315 (consumed < iobuf->isize || lp->state == base64_rollback))
252 res = mu_filter_again; 316 res = mu_filter_again;
253 else 317 else
254 res = mu_filter_ok; 318 res = mu_filter_ok;
...@@ -257,10 +321,25 @@ _base64_encoder (void *xd MU_ARG_UNUSED, ...@@ -257,10 +321,25 @@ _base64_encoder (void *xd MU_ARG_UNUSED,
257 return res; 321 return res;
258 } 322 }
259 323
324 static int
325 alloc_state (void **pret, int mode, int argc, const char **argv)
326 {
327 if (mode == MU_FILTER_ENCODE)
328 {
329 struct base64_line *lp = malloc (sizeof (*lp));
330 if (!lp)
331 return ENOMEM;
332 lp->max_len = 76;
333 *pret = lp;
334 }
335 else
336 *pret = NULL;
337 return 0;
338 }
339
260 static struct _mu_filter_record _base64_filter = { 340 static struct _mu_filter_record _base64_filter = {
261 "base64", 341 "base64",
262 76, 342 alloc_state,
263 NULL,
264 _base64_encoder, 343 _base64_encoder,
265 _base64_decoder 344 _base64_decoder
266 }; 345 };
...@@ -269,7 +348,6 @@ mu_filter_record_t mu_base64_filter = &_base64_filter; ...@@ -269,7 +348,6 @@ mu_filter_record_t mu_base64_filter = &_base64_filter;
269 348
270 static struct _mu_filter_record _B_filter = { 349 static struct _mu_filter_record _B_filter = {
271 "B", 350 "B",
272 0,
273 NULL, 351 NULL,
274 _base64_encoder, 352 _base64_encoder,
275 _base64_decoder 353 _base64_decoder
......
...@@ -83,7 +83,6 @@ _bit7_coder (void *xd MU_ARG_UNUSED, ...@@ -83,7 +83,6 @@ _bit7_coder (void *xd MU_ARG_UNUSED,
83 83
84 static struct _mu_filter_record _binary_filter = { 84 static struct _mu_filter_record _binary_filter = {
85 "binary", 85 "binary",
86 0,
87 NULL, 86 NULL,
88 _copy_codec, 87 _copy_codec,
89 _copy_codec 88 _copy_codec
...@@ -94,7 +93,6 @@ mu_filter_record_t mu_binary_filter = &_binary_filter; ...@@ -94,7 +93,6 @@ mu_filter_record_t mu_binary_filter = &_binary_filter;
94 93
95 static struct _mu_filter_record _bit8_filter = { 94 static struct _mu_filter_record _bit8_filter = {
96 "8bit", 95 "8bit",
97 0,
98 NULL, 96 NULL,
99 _copy_codec, 97 _copy_codec,
100 _copy_codec 98 _copy_codec
...@@ -104,7 +102,6 @@ mu_filter_record_t mu_bit8_filter = &_bit8_filter; ...@@ -104,7 +102,6 @@ mu_filter_record_t mu_bit8_filter = &_bit8_filter;
104 102
105 static struct _mu_filter_record _bit7_filter = { 103 static struct _mu_filter_record _bit7_filter = {
106 "7bit", 104 "7bit",
107 0,
108 NULL, 105 NULL,
109 _bit7_coder, 106 _bit7_coder,
110 _copy_codec 107 _copy_codec
......
...@@ -327,7 +327,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, ...@@ -327,7 +327,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED,
327 327
328 static struct _mu_filter_record _crlfdot_filter = { 328 static struct _mu_filter_record _crlfdot_filter = {
329 "CRLFDOT", 329 "CRLFDOT",
330 0,
331 alloc_state, 330 alloc_state,
332 _crlfdot_encoder, 331 _crlfdot_encoder,
333 _crlfdot_decoder 332 _crlfdot_decoder
......
...@@ -160,7 +160,6 @@ alloc_state (void **pret, int mode, ...@@ -160,7 +160,6 @@ alloc_state (void **pret, int mode,
160 160
161 static struct _mu_filter_record _crlf_filter = { 161 static struct _mu_filter_record _crlf_filter = {
162 "CRLF", 162 "CRLF",
163 0,
164 alloc_state, 163 alloc_state,
165 _crlf_encoder, 164 _crlf_encoder,
166 _crlf_decoder 165 _crlf_decoder
...@@ -172,7 +171,6 @@ mu_filter_record_t mu_crlf_filter = &_crlf_filter; ...@@ -172,7 +171,6 @@ mu_filter_record_t mu_crlf_filter = &_crlf_filter;
172 /* For compatibility with previous versions */ 171 /* For compatibility with previous versions */
173 static struct _mu_filter_record _rfc822_filter = { 172 static struct _mu_filter_record _rfc822_filter = {
174 "RFC822", 173 "RFC822",
175 0,
176 alloc_state, 174 alloc_state,
177 _crlf_encoder, 175 _crlf_encoder,
178 _crlf_decoder 176 _crlf_decoder
......
...@@ -259,7 +259,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, ...@@ -259,7 +259,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED,
259 259
260 static struct _mu_filter_record _dot_filter = { 260 static struct _mu_filter_record _dot_filter = {
261 "DOT", 261 "DOT",
262 0,
263 alloc_state, 262 alloc_state,
264 _dot_encoder, 263 _dot_encoder,
265 _dot_decoder 264 _dot_decoder
......
...@@ -81,6 +81,7 @@ mu_filter_get_list (mu_list_t *plist) ...@@ -81,6 +81,7 @@ mu_filter_get_list (mu_list_t *plist)
81 mu_list_append (filter_list, mu_inline_comment_filter); 81 mu_list_append (filter_list, mu_inline_comment_filter);
82 mu_list_append (filter_list, mu_header_filter); 82 mu_list_append (filter_list, mu_header_filter);
83 mu_list_append (filter_list, mu_linecon_filter); 83 mu_list_append (filter_list, mu_linecon_filter);
84 mu_list_append (filter_list, mu_linelen_filter);
84 /* FIXME: add the default encodings? */ 85 /* FIXME: add the default encodings? */
85 } 86 }
86 *plist = filter_list; 87 *plist = filter_list;
...@@ -88,77 +89,6 @@ mu_filter_get_list (mu_list_t *plist) ...@@ -88,77 +89,6 @@ mu_filter_get_list (mu_list_t *plist)
88 return 0; 89 return 0;
89 } 90 }
90 91
91 static int
92 filter_create_rd (mu_stream_t *pstream, mu_stream_t stream,
93 size_t max_line_length,
94 int mode,
95 mu_filter_xcode_t xcode, void *xdata,
96 int flags)
97 {
98 int status;
99 mu_stream_t fltstream;
100
101 flags &= ~MU_STREAM_AUTOCLOSE;
102
103 status = mu_filter_stream_create (&fltstream, stream,
104 mode, xcode, xdata,
105 flags);
106 if (status == 0)
107 {
108 if (max_line_length)
109 {
110 status = mu_linelen_filter_create (pstream, fltstream,
111 max_line_length,
112 flags);
113 mu_stream_unref (fltstream);
114 if (status)
115 return status;
116 }
117 else
118 *pstream = fltstream;
119
120 if (flags & MU_STREAM_AUTOCLOSE)
121 mu_stream_unref (stream);
122 }
123 return status;
124 }
125
126 static int
127 filter_create_wr (mu_stream_t *pstream, mu_stream_t stream,
128 size_t max_line_length,
129 int mode,
130 mu_filter_xcode_t xcode, void *xdata,
131 int flags)
132 {
133 int status;
134 mu_stream_t fltstream, instream = NULL, tmpstr;
135
136 flags &= ~MU_STREAM_AUTOCLOSE;
137
138 if (max_line_length)
139 {
140 status = mu_linelen_filter_create (&instream, stream,
141 max_line_length,
142 flags);
143 if (status)
144 return status;
145 tmpstr = instream;
146 }
147 else
148 tmpstr = stream;
149
150 status = mu_filter_stream_create (&fltstream, tmpstr,
151 mode, xcode, xdata,
152 flags);
153 mu_stream_unref (instream);
154 if (status)
155 return status;
156 *pstream = fltstream;
157 if (flags & MU_STREAM_AUTOCLOSE)
158 mu_stream_unref (stream);
159 return status;
160 }
161
162 int 92 int
163 mu_filter_create_args (mu_stream_t *pstream, mu_stream_t stream, 93 mu_filter_create_args (mu_stream_t *pstream, mu_stream_t stream,
164 const char *name, int argc, const char **argv, 94 const char *name, int argc, const char **argv,
...@@ -189,15 +119,12 @@ mu_filter_create_args (mu_stream_t *pstream, mu_stream_t stream, ...@@ -189,15 +119,12 @@ mu_filter_create_args (mu_stream_t *pstream, mu_stream_t stream,
189 return status; 119 return status;
190 } 120 }
191 121
192 status = ((flags & MU_STREAM_WRITE) ? filter_create_wr : filter_create_rd) 122 status = mu_filter_stream_create (pstream, stream,
193 (pstream, stream, 123 mode, xcode, xdata,
194 mode == MU_FILTER_ENCODE ? frec->max_line_length : 0, 124 flags);
195 mode,
196 xcode,
197 xdata,
198 flags);
199 if (status) 125 if (status)
200 free (xdata); 126 free (xdata);
127
201 return status; 128 return status;
202 } 129 }
203 130
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2009, 2010 Free
3 Software Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General
16 Public License along with this library. If not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <errno.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include <mailutils/filter.h>
28 #include <mailutils/stream.h>
29 #include <mailutils/errno.h>
30
31 static int
32 negate_filter_mode (int mode)
33 {
34 if (mode == MU_FILTER_DECODE)
35 return MU_FILTER_ENCODE;
36 else if (mode == MU_FILTER_ENCODE)
37 return MU_FILTER_DECODE;
38 abort ();
39 }
40
41 static int
42 _add_next_link (mu_stream_t *pret, mu_stream_t transport,
43 int defmode, int flags,
44 size_t argc, char **argv,
45 int (*pred) (void *, mu_stream_t, const char *),
46 void *closure)
47 {
48 int mode;
49 int qmark = 0;
50 char *fltname;
51 int status = 0;
52
53 fltname = argv[0];
54 if (fltname[0] == '?')
55 {
56 if (pred)
57 qmark = 1;
58 fltname++;
59 }
60
61 if (fltname[0] == '~')
62 {
63 mode = negate_filter_mode (defmode);
64 fltname++;
65 }
66 else
67 mode = defmode;
68
69 if (qmark == 0 || pred (closure, transport, fltname))
70 {
71 status = mu_filter_create_args (pret, transport, fltname,
72 argc, (const char **)argv,
73 mode, flags);
74 mu_stream_unref (transport);
75 }
76 return status;
77 }
78
79 int
80 _filter_chain_create (mu_stream_t *pret, mu_stream_t transport,
81 int defmode,
82 int flags,
83 size_t argc, char **argv,
84 int (*pred) (void *, mu_stream_t, const char *),
85 void *closure)
86 {
87 while (argc)
88 {
89 size_t i;
90 int status;
91 mu_stream_t stream;
92
93 for (i = 1; i < argc; i++)
94 if (strcmp (argv[i], "+") == 0)
95 break;
96
97 status = _add_next_link (&stream, transport,
98 defmode, flags,
99 i, argv,
100 pred, closure);
101 if (status)
102 return status;
103 transport = stream;
104
105 argc -= i;
106 argv += i;
107 if (argc)
108 {
109 argc--;
110 argv++;
111 }
112 }
113 *pret = transport;
114 return 0;
115 }
116
117 int
118 _filter_chain_create_rev (mu_stream_t *pret, mu_stream_t transport,
119 int defmode,
120 int flags,
121 size_t argc, char **argv,
122 int (*pred) (void *, mu_stream_t, const char *),
123 void *closure)
124 {
125 size_t pos;
126
127 for (pos = argc; pos > 0;)
128 {
129 size_t i;
130 int status;
131 mu_stream_t stream;
132
133 for (i = pos; i > 0; i--)
134 {
135 if (strcmp (argv[i - 1], "+") == 0)
136 break;
137 }
138
139 status = _add_next_link (&stream, transport,
140 defmode, flags,
141 pos - i, argv + i,
142 pred, closure);
143 if (status)
144 return status;
145 transport = stream;
146 if (i > 0)
147 i--;
148 pos = i;
149 }
150 *pret = transport;
151 return 0;
152 }
153
154 int
155 mu_filter_chain_create_pred (mu_stream_t *pret, mu_stream_t transport,
156 int defmode,
157 int flags,
158 size_t argc, char **argv,
159 int (*pred) (void *, mu_stream_t, const char *),
160 void *closure)
161 {
162 int rc;
163
164 mu_stream_ref (transport);
165 if (flags & MU_STREAM_WRITE)
166 rc = _filter_chain_create_rev (pret, transport,
167 defmode, flags,
168 argc, argv,
169 pred, closure);
170 else
171 rc = _filter_chain_create (pret, transport,
172 defmode, flags,
173 argc, argv, pred, closure);
174 if (rc)
175 mu_stream_unref (transport);
176 return rc;
177 }
178
179 int
180 mu_filter_chain_create (mu_stream_t *pret, mu_stream_t transport,
181 int defmode, int flags,
182 size_t argc, char **argv)
183 {
184 return mu_filter_chain_create_pred (pret, transport, defmode, flags,
185 argc, argv, NULL, NULL);
186 }
187
...@@ -273,7 +273,6 @@ _from_alloc_state (void **pret, int mode, ...@@ -273,7 +273,6 @@ _from_alloc_state (void **pret, int mode,
273 273
274 static struct _mu_filter_record _from_filter = { 274 static struct _mu_filter_record _from_filter = {
275 "FROM", 275 "FROM",
276 0,
277 _from_alloc_state, 276 _from_alloc_state,
278 _from_encoder, 277 _from_encoder,
279 _from_decoder 278 _from_decoder
......
...@@ -112,7 +112,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, ...@@ -112,7 +112,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED,
112 112
113 static struct _mu_filter_record _header_filter = { 113 static struct _mu_filter_record _header_filter = {
114 "HEADER", 114 "HEADER",
115 0,
116 alloc_state, 115 alloc_state,
117 NULL, 116 NULL,
118 _hflt_decoder 117 _hflt_decoder
......
...@@ -487,7 +487,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, int argc, const char **argv) ...@@ -487,7 +487,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, int argc, const char **argv)
487 487
488 static struct _mu_filter_record _inline_comment_filter = { 488 static struct _mu_filter_record _inline_comment_filter = {
489 "INLINE-COMMENT", 489 "INLINE-COMMENT",
490 0,
491 alloc_state, 490 alloc_state,
492 _ilcmt_encoder, 491 _ilcmt_encoder,
493 _ilcmt_decoder 492 _ilcmt_decoder
......
...@@ -213,7 +213,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, int argc, const char **argv) ...@@ -213,7 +213,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, int argc, const char **argv)
213 213
214 static struct _mu_filter_record _linecon_filter = { 214 static struct _mu_filter_record _linecon_filter = {
215 "LINECON", 215 "LINECON",
216 0,
217 alloc_state, 216 alloc_state,
218 NULL, 217 NULL,
219 _linecon_decoder, 218 _linecon_decoder,
......
...@@ -107,4 +107,35 @@ mu_linelen_filter_create (mu_stream_t *pstream, mu_stream_t stream, ...@@ -107,4 +107,35 @@ mu_linelen_filter_create (mu_stream_t *pstream, mu_stream_t stream,
107 return mu_filter_stream_create (pstream, stream, 107 return mu_filter_stream_create (pstream, stream,
108 MU_FILTER_ENCODE, _ll_encoder, flt, flags); 108 MU_FILTER_ENCODE, _ll_encoder, flt, flags);
109 } 109 }
110
111 static int
112 alloc_state (void **pret, int mode MU_ARG_UNUSED, int argc, const char **argv)
113 {
114 struct _mu_linelen_filter *flt = malloc (sizeof (flt[0]));
110 115
116 if (!flt)
117 return ENOMEM;
118 flt->cur_len = 0;
119 flt->max_len = 76;
120 if (argc > 1)
121 {
122 char *p;
123 flt->max_len = strtoul (argv[1], &p, 10);
124 if (*p)
125 {
126 free (flt);
127 return MU_ERR_PARSE;
128 }
129 }
130 *pret = flt;
131 return 0;
132 }
133
134 static struct _mu_filter_record _linelen_filter = {
135 "LINELEN",
136 alloc_state,
137 _ll_encoder,
138 NULL,
139 };
140
141 mu_filter_record_t mu_linelen_filter = &_linelen_filter;
......
...@@ -243,7 +243,6 @@ _qp_encoder (void *xd MU_ARG_UNUSED, ...@@ -243,7 +243,6 @@ _qp_encoder (void *xd MU_ARG_UNUSED,
243 243
244 static struct _mu_filter_record _qp_filter = { 244 static struct _mu_filter_record _qp_filter = {
245 "quoted-printable", 245 "quoted-printable",
246 0,
247 NULL, 246 NULL,
248 _qp_encoder, 247 _qp_encoder,
249 _qp_decoder 248 _qp_decoder
...@@ -253,7 +252,6 @@ mu_filter_record_t mu_qp_filter = &_qp_filter; ...@@ -253,7 +252,6 @@ mu_filter_record_t mu_qp_filter = &_qp_filter;
253 252
254 static struct _mu_filter_record _Q_filter = { 253 static struct _mu_filter_record _Q_filter = {
255 "Q", 254 "Q",
256 0,
257 NULL, 255 NULL,
258 _qp_encoder, 256 _qp_encoder,
259 _qp_decoder 257 _qp_decoder
......
...@@ -19,7 +19,7 @@ AT_KEYWORDS([base64 base64d base64dr decode filter]) ...@@ -19,7 +19,7 @@ AT_KEYWORDS([base64 base64d base64dr decode filter])
19 19
20 AT_CHECK([ 20 AT_CHECK([
21 cp $abs_top_srcdir/libmailutils/tests/Encode expout 21 cp $abs_top_srcdir/libmailutils/tests/Encode expout
22 fltst base64 decode read linelen=0 < $abs_top_srcdir/libmailutils/tests/Decode], 22 fltst base64 decode read < $abs_top_srcdir/libmailutils/tests/Decode],
23 [0], 23 [0],
24 [expout]) 24 [expout])
25 25
...@@ -31,7 +31,7 @@ AT_KEYWORDS([base64 base64d base64dw decode filter]) ...@@ -31,7 +31,7 @@ AT_KEYWORDS([base64 base64d base64dw decode filter])
31 31
32 AT_CHECK([ 32 AT_CHECK([
33 cp $abs_top_srcdir/libmailutils/tests/Encode expout 33 cp $abs_top_srcdir/libmailutils/tests/Encode expout
34 fltst base64 decode write linelen=0 < $abs_top_srcdir/libmailutils/tests/Decode], 34 fltst base64 decode write < $abs_top_srcdir/libmailutils/tests/Decode],
35 [0], 35 [0],
36 [expout]) 36 [expout])
37 37
......
...@@ -68,23 +68,6 @@ c_copy (mu_stream_t out, mu_stream_t in) ...@@ -68,23 +68,6 @@ c_copy (mu_stream_t out, mu_stream_t in)
68 68
69 } 69 }
70 70
71 /* Set the maximum line length for the filter NAME to LENGTH.
72 FIXME: This is a kludge. Perhaps API should provide a function
73 for that. */
74 static void
75 reset_line_length (const char *name, size_t length)
76 {
77 mu_list_t list;
78 int status;
79 mu_filter_record_t frec;
80
81 mu_filter_get_list (&list);
82 status = mu_list_locate (list, (void*)name, (void**)&frec);
83 if (status == 0)
84 frec->max_line_length = length;
85 /* don't bail out, leave that to mu_filter_create */
86 }
87
88 void 71 void
89 usage (const char *diag) 72 usage (const char *diag)
90 { 73 {
...@@ -99,7 +82,7 @@ usage (const char *diag) ...@@ -99,7 +82,7 @@ usage (const char *diag)
99 fp = stdout; 82 fp = stdout;
100 83
101 fprintf (fp, "%s", 84 fprintf (fp, "%s",
102 "usage: fltst FILTER {encode|decode} {read|write} [shift=N] [linelen=N] [verbose] [printable] [nl] [-- args]\n"); 85 "usage: fltst FILTER {encode|decode} {read|write} [shift=N] [verbose] [printable] [nl] [-- args]\n");
103 exit (diag ? 1 : 0); 86 exit (diag ? 1 : 0);
104 } 87 }
105 88
...@@ -112,8 +95,6 @@ main (int argc, char * argv []) ...@@ -112,8 +95,6 @@ main (int argc, char * argv [])
112 int flags = MU_STREAM_READ; 95 int flags = MU_STREAM_READ;
113 char *fltname; 96 char *fltname;
114 mu_off_t shift = 0; 97 mu_off_t shift = 0;
115 size_t line_length;
116 int line_length_option = 0;
117 int newline_option = 0; 98 int newline_option = 0;
118 99
119 if (argc == 1) 100 if (argc == 1)
...@@ -141,11 +122,6 @@ main (int argc, char * argv []) ...@@ -141,11 +122,6 @@ main (int argc, char * argv [])
141 { 122 {
142 if (strncmp (argv[i], "shift=", 6) == 0) 123 if (strncmp (argv[i], "shift=", 6) == 0)
143 shift = strtoul (argv[i] + 6, NULL, 0); 124 shift = strtoul (argv[i] + 6, NULL, 0);
144 else if (strncmp (argv[i], "linelen=", 8) == 0)
145 {
146 line_length = strtoul (argv[i] + 8, NULL, 10);
147 line_length_option = 1;
148 }
149 else if (strcmp (argv[i], "verbose") == 0) 125 else if (strcmp (argv[i], "verbose") == 0)
150 verbose++; 126 verbose++;
151 else if (strcmp (argv[i], "printable") == 0) 127 else if (strcmp (argv[i], "printable") == 0)
...@@ -167,9 +143,6 @@ main (int argc, char * argv []) ...@@ -167,9 +143,6 @@ main (int argc, char * argv [])
167 MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0)); 143 MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
168 MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0)); 144 MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
169 145
170 if (line_length_option)
171 reset_line_length (fltname, line_length);
172
173 if (flags == MU_STREAM_READ) 146 if (flags == MU_STREAM_READ)
174 { 147 {
175 MU_ASSERT (mu_filter_create_args (&flt, in, fltname, 148 MU_ASSERT (mu_filter_create_args (&flt, in, fltname,
......
...@@ -30,7 +30,6 @@ static char filter_args_doc[] = N_("[~]NAME [ARGS] [+ [~]NAME [ARGS]...]"); ...@@ -30,7 +30,6 @@ static char filter_args_doc[] = N_("[~]NAME [ARGS] [+ [~]NAME [ARGS]...]");
30 static struct argp_option filter_options[] = { 30 static struct argp_option filter_options[] = {
31 { "encode", 'e', NULL, 0, N_("encode the input (default)") }, 31 { "encode", 'e', NULL, 0, N_("encode the input (default)") },
32 { "decode", 'd', NULL, 0, N_("decode the input") }, 32 { "decode", 'd', NULL, 0, N_("decode the input") },
33 { "line-length", 'l', N_("NUMBER"), 0, N_("limit output line length") },
34 { "newline", 'n', NULL, 0, N_("print additional newline") }, 33 { "newline", 'n', NULL, 0, N_("print additional newline") },
35 { "list", 'L', NULL, 0, N_("list supported filters") }, 34 { "list", 'L', NULL, 0, N_("list supported filters") },
36 { NULL } 35 { NULL }
...@@ -38,15 +37,11 @@ static struct argp_option filter_options[] = { ...@@ -38,15 +37,11 @@ static struct argp_option filter_options[] = {
38 37
39 static int filter_mode = MU_FILTER_ENCODE; 38 static int filter_mode = MU_FILTER_ENCODE;
40 static int newline_option = 0; 39 static int newline_option = 0;
41 static size_t line_length;
42 static int line_length_option = 0;
43 static int list_option; 40 static int list_option;
44 41
45 static error_t 42 static error_t
46 filter_parse_opt (int key, char *arg, struct argp_state *state) 43 filter_parse_opt (int key, char *arg, struct argp_state *state)
47 { 44 {
48 char *p;
49
50 switch (key) 45 switch (key)
51 { 46 {
52 case 'e': 47 case 'e':
...@@ -61,13 +56,6 @@ filter_parse_opt (int key, char *arg, struct argp_state *state) ...@@ -61,13 +56,6 @@ filter_parse_opt (int key, char *arg, struct argp_state *state)
61 newline_option = 1; 56 newline_option = 1;
62 break; 57 break;
63 58
64 case 'l':
65 line_length = strtoul (arg, &p, 10);
66 if (*p)
67 argp_error (state, N_("not a number"));
68 line_length_option = 1;
69 break;
70
71 case 'L': 59 case 'L':
72 list_option = 1; 60 list_option = 1;
73 break; 61 break;
...@@ -88,22 +76,6 @@ static struct argp filter_argp = { ...@@ -88,22 +76,6 @@ static struct argp filter_argp = {
88 NULL 76 NULL
89 }; 77 };
90 78
91 /* FIXME: This is definitely a kludge. The API should provide a function
92 for that. */
93 static void
94 reset_line_length (const char *name, size_t length)
95 {
96 mu_list_t list;
97 int status;
98 mu_filter_record_t frec;
99
100 mu_filter_get_list (&list);
101 status = mu_list_locate (list, (void*)name, (void**)&frec);
102 if (status == 0)
103 frec->max_line_length = length;
104 /* don't bail out, leave that to mu_filter_create */
105 }
106
107 static int 79 static int
108 filter_printer (void *item, void *data) 80 filter_printer (void *item, void *data)
109 { 81 {
...@@ -184,9 +156,6 @@ mutool_filter (int argc, char **argv) ...@@ -184,9 +156,6 @@ mutool_filter (int argc, char **argv)
184 if (strcmp (argv[i], "+") == 0) 156 if (strcmp (argv[i], "+") == 0)
185 break; 157 break;
186 158
187 if (line_length_option)
188 reset_line_length (fltname, line_length);
189
190 rc = mu_filter_create_args (&flt, prev_stream, fltname, 159 rc = mu_filter_create_args (&flt, prev_stream, fltname,
191 i, (const char **)argv, 160 i, (const char **)argv,
192 mode, MU_STREAM_READ); 161 mode, MU_STREAM_READ);
......