sieve: improve moderator extension.
* libmu_sieve/extensions/moderator.c: Implement the :program tag. Use _sget_ functions to reduce memory requirements. * sieve/tests/moderator.mbox: New file. * sieve/tests/moderator.at: New file. * sieve/tests/Makefile.am (EXTRA_DIST): Add moderator.mbox. (TESTSUITE_AT): Add moderator.at * sieve/tests/testsuite.at (MUT_SIEVE_EXT_NAME): New define. (MUT_SIEVE_EXT_TEST): New macro. Include moderator.at.
Showing
6 changed files
with
228 additions
and
12 deletions
... | @@ -31,6 +31,7 @@ | ... | @@ -31,6 +31,7 @@ |
31 | 31 | ||
32 | moderator [:keep] | 32 | moderator [:keep] |
33 | [:address <address: string>] | 33 | [:address <address: string>] |
34 | [:program <sieve-program: string>] | ||
34 | [:source <sieve-file: string>] | 35 | [:source <sieve-file: string>] |
35 | 36 | ||
36 | The moderator action spawns an inferior Sieve machine and filters the | 37 | The moderator action spawns an inferior Sieve machine and filters the |
... | @@ -40,9 +41,15 @@ | ... | @@ -40,9 +41,15 @@ |
40 | reply can be modified using :address tag. After discarding the message, | 41 | reply can be modified using :address tag. After discarding the message, |
41 | moderator marks it as deleted, unless it is given :keep tag. | 42 | moderator marks it as deleted, unless it is given :keep tag. |
42 | 43 | ||
43 | If :source tag is given, its argument sieve-file specifies the Sieve | 44 | If :source tag is given, its argument sieve-file specifies a Sieve |
44 | source file to be used on the message. Otherwise, moderator will create | 45 | source file to be used on the message. If :program tag is given, its |
45 | a copy of the existing Sieve machine. | 46 | argument supplies a Sieve program to be used on this message. Only |
47 | one of :program or :source may be specified. Supplying them both, or | ||
48 | supplying several instances of the same keyword, is an error. The | ||
49 | behavior of the action in this case is undefined. | ||
50 | |||
51 | If neither :program nor :source is supplied, moderator will create | ||
52 | a copy of the existing Sieve machine and use it on the message. | ||
46 | 53 | ||
47 | The action checks the message structure: it will bail out if the message | 54 | The action checks the message structure: it will bail out if the message |
48 | does not have exactly 3 MIME parts, or if parts 2 and 3 are not of | 55 | does not have exactly 3 MIME parts, or if parts 2 and 3 are not of |
... | @@ -93,6 +100,24 @@ moderator_filter_message (mu_sieve_machine_t mach, mu_list_t tags, | ... | @@ -93,6 +100,24 @@ moderator_filter_message (mu_sieve_machine_t mach, mu_list_t tags, |
93 | if (rc) | 100 | if (rc) |
94 | mu_sieve_error (mach, _("cannot compile source `%s'"), arg->v.string); | 101 | mu_sieve_error (mach, _("cannot compile source `%s'"), arg->v.string); |
95 | } | 102 | } |
103 | else if (mu_sieve_tag_lookup (tags, "program", &arg)) | ||
104 | { | ||
105 | struct mu_locus locus; | ||
106 | |||
107 | rc = mu_sieve_machine_inherit (mach, &newmach); | ||
108 | if (rc) | ||
109 | { | ||
110 | mu_sieve_error (mach, _("cannot initialize sieve machine: %s"), | ||
111 | mu_strerror (rc)); | ||
112 | return 1; | ||
113 | } | ||
114 | mu_sieve_get_locus (mach, &locus); | ||
115 | rc = mu_sieve_compile_buffer (newmach, | ||
116 | arg->v.string, strlen (arg->v.string), | ||
117 | locus.mu_file, locus.mu_line); | ||
118 | if (rc) | ||
119 | mu_sieve_error (mach, _("cannot compile subprogram")); | ||
120 | } | ||
96 | else | 121 | else |
97 | rc = mu_sieve_machine_dup (mach, &newmach); | 122 | rc = mu_sieve_machine_dup (mach, &newmach); |
98 | 123 | ||
... | @@ -119,15 +144,15 @@ copy_header (mu_sieve_machine_t mach, | ... | @@ -119,15 +144,15 @@ copy_header (mu_sieve_machine_t mach, |
119 | mu_header_t to_hdr, char *to, mu_header_t from_hdr, char *from) | 144 | mu_header_t to_hdr, char *to, mu_header_t from_hdr, char *from) |
120 | { | 145 | { |
121 | int rc; | 146 | int rc; |
122 | char *value = NULL; | 147 | const char *value = NULL; |
123 | if ((rc = mu_header_aget_value (from_hdr, from, &value))) | 148 | |
149 | if ((rc = mu_header_sget_value (from_hdr, from, &value))) | ||
124 | { | 150 | { |
125 | mu_sieve_error (mach, _("cannot get `%s:' header: %s"), | 151 | mu_sieve_error (mach, _("cannot get `%s:' header: %s"), |
126 | from, mu_strerror (rc)); | 152 | from, mu_strerror (rc)); |
127 | return rc; | 153 | return rc; |
128 | } | 154 | } |
129 | rc = mu_header_set_value (to_hdr, to, value, 0); | 155 | rc = mu_header_set_value (to_hdr, to, value, 0); |
130 | free (value); | ||
131 | return rc; | 156 | return rc; |
132 | } | 157 | } |
133 | 158 | ||
... | @@ -194,7 +219,7 @@ moderator_message_get_part (mu_sieve_machine_t mach, | ... | @@ -194,7 +219,7 @@ moderator_message_get_part (mu_sieve_machine_t mach, |
194 | int rc; | 219 | int rc; |
195 | mu_message_t tmp; | 220 | mu_message_t tmp; |
196 | mu_header_t hdr = NULL; | 221 | mu_header_t hdr = NULL; |
197 | char *value; | 222 | const char *value; |
198 | 223 | ||
199 | if ((rc = mu_message_get_part (msg, index, &tmp))) | 224 | if ((rc = mu_message_get_part (msg, index, &tmp))) |
200 | { | 225 | { |
... | @@ -204,13 +229,12 @@ moderator_message_get_part (mu_sieve_machine_t mach, | ... | @@ -204,13 +229,12 @@ moderator_message_get_part (mu_sieve_machine_t mach, |
204 | } | 229 | } |
205 | 230 | ||
206 | mu_message_get_header (tmp, &hdr); | 231 | mu_message_get_header (tmp, &hdr); |
207 | if (mu_header_aget_value (hdr, MU_HEADER_CONTENT_TYPE, &value) == 0 | 232 | if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TYPE, &value) == 0 |
208 | && memcmp (value, "message/rfc822", 14) == 0) | 233 | && memcmp (value, "message/rfc822", 14) == 0) |
209 | { | 234 | { |
210 | mu_stream_t str; | 235 | mu_stream_t str; |
211 | mu_body_t body; | 236 | mu_body_t body; |
212 | 237 | ||
213 | free (value); | ||
214 | mu_message_get_body (tmp, &body); | 238 | mu_message_get_body (tmp, &body); |
215 | mu_body_get_streamref (body, &str); | 239 | mu_body_get_streamref (body, &str); |
216 | 240 | ||
... | @@ -229,7 +253,6 @@ moderator_message_get_part (mu_sieve_machine_t mach, | ... | @@ -229,7 +253,6 @@ moderator_message_get_part (mu_sieve_machine_t mach, |
229 | mu_sieve_error (mach, | 253 | mu_sieve_error (mach, |
230 | _("expected message type message/rfc822, but found %s"), | 254 | _("expected message type message/rfc822, but found %s"), |
231 | value); | 255 | value); |
232 | free (value); | ||
233 | return 1; | 256 | return 1; |
234 | } | 257 | } |
235 | else | 258 | else |
... | @@ -333,6 +356,7 @@ static mu_sieve_tag_def_t moderator_tags[] = { | ... | @@ -333,6 +356,7 @@ static mu_sieve_tag_def_t moderator_tags[] = { |
333 | { "keep", SVT_VOID }, | 356 | { "keep", SVT_VOID }, |
334 | { "address", SVT_STRING }, | 357 | { "address", SVT_STRING }, |
335 | { "source", SVT_STRING }, | 358 | { "source", SVT_STRING }, |
359 | { "program", SVT_STRING }, | ||
336 | { NULL } | 360 | { NULL } |
337 | }; | 361 | }; |
338 | 362 | ... | ... |
... | @@ -95,7 +95,7 @@ spamd_send_message (mu_stream_t stream, mu_message_t msg) | ... | @@ -95,7 +95,7 @@ spamd_send_message (mu_stream_t stream, mu_message_t msg) |
95 | rc = mu_message_get_streamref (msg, &mstr); | 95 | rc = mu_message_get_streamref (msg, &mstr); |
96 | if (rc) | 96 | if (rc) |
97 | return rc; | 97 | return rc; |
98 | rc = mu_filter_create (&flt, mstr, "rfc822", MU_FILTER_ENCODE, | 98 | rc = mu_filter_create (&flt, mstr, "CRLF", MU_FILTER_ENCODE, |
99 | MU_STREAM_READ|MU_STREAM_SEEK); | 99 | MU_STREAM_READ|MU_STREAM_SEEK); |
100 | if (rc) | 100 | if (rc) |
101 | { | 101 | { | ... | ... |
... | @@ -14,7 +14,7 @@ | ... | @@ -14,7 +14,7 @@ |
14 | # You should have received a copy of the GNU General Public License | 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/>. | 15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | ||
17 | EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 | 17 | EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 moderator.mbox |
18 | DISTCLEANFILES = atconfig $(check_SCRIPTS) | 18 | DISTCLEANFILES = atconfig $(check_SCRIPTS) |
19 | MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) | 19 | MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) |
20 | #SUBDIRS = etc | 20 | #SUBDIRS = etc |
... | @@ -53,6 +53,7 @@ TESTSUITE_AT = \ | ... | @@ -53,6 +53,7 @@ TESTSUITE_AT = \ |
53 | i-casemap.at\ | 53 | i-casemap.at\ |
54 | i-numeric.at\ | 54 | i-numeric.at\ |
55 | i-octet.at\ | 55 | i-octet.at\ |
56 | moderator.at\ | ||
56 | mul-addr.at\ | 57 | mul-addr.at\ |
57 | not.at\ | 58 | not.at\ |
58 | redirect.at\ | 59 | redirect.at\ | ... | ... |
sieve/tests/moderator.at
0 → 100644
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 | # GNU Mailutils 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 | |||
17 | m4_pushdef([MUT_SIEVE_EXT_NAME],[moderator]) | ||
18 | |||
19 | MUT_SIEVE_EXT_TEST([program discard],[mod00], | ||
20 | [require "moderator"; | ||
21 | |||
22 | moderator :program "discard;"; | ||
23 | ], | ||
24 | [cp ${abs_top_srcdir}/sieve/tests/moderator.mbox mailbox | ||
25 | chmod +w mailbox | ||
26 | |||
27 | MTA_DIAG=`pwd`/mta.diag | ||
28 | export MTA_DIAG | ||
29 | sieve MUT_SIEVE_CMDLINE dnl | ||
30 | --clearpath -L "${abs_top_builddir}/libmu_sieve/extensions" -f ./mailbox prog || exit 1 | ||
31 | sed 's/ENVELOPE FROM:.*/ENVELOPE FROM/' ./mta.diag | ||
32 | ], | ||
33 | [ENVELOPE FROM | ||
34 | ENVELOPE TO: <bug-foobar-request@example.org> | ||
35 | 0: Subject: confirm 7e02c99a82a21a2349291a4f142ee2347bb5fd0b | ||
36 | 1: To: bug-foobar-request@example.org | ||
37 | 2: | ||
38 | END OF MESSAGE | ||
39 | ], | ||
40 | [DISCARD on msg uid 0: marking as deleted | ||
41 | MODERATOR on msg uid 1: discarding message | ||
42 | ]) | ||
43 | |||
44 | MUT_SIEVE_EXT_TEST([program address discard],[mod01], | ||
45 | [require "moderator"; | ||
46 | |||
47 | moderator :program "discard;" :address "<sergiusz@example.org>"; | ||
48 | ], | ||
49 | [cp ${abs_top_srcdir}/sieve/tests/moderator.mbox mailbox | ||
50 | chmod +w mailbox | ||
51 | |||
52 | MTA_DIAG=`pwd`/mta.diag | ||
53 | export MTA_DIAG | ||
54 | sieve MUT_SIEVE_CMDLINE dnl | ||
55 | --clearpath -L "${abs_top_builddir}/libmu_sieve/extensions" -f ./mailbox prog || exit 1 | ||
56 | cat ./mta.diag | ||
57 | ], | ||
58 | [ENVELOPE FROM: sergiusz@example.org | ||
59 | ENVELOPE TO: <bug-foobar-request@example.org> | ||
60 | 0: From: <sergiusz@example.org> | ||
61 | 1: Subject: confirm 7e02c99a82a21a2349291a4f142ee2347bb5fd0b | ||
62 | 2: To: bug-foobar-request@example.org | ||
63 | 3: | ||
64 | END OF MESSAGE | ||
65 | ], | ||
66 | [DISCARD on msg uid 0: marking as deleted | ||
67 | MODERATOR on msg uid 1: discarding message | ||
68 | ]) | ||
69 | |||
70 | MUT_SIEVE_EXT_TEST([program keep],[mod02], | ||
71 | [require "moderator"; | ||
72 | |||
73 | moderator :program "keep;"; | ||
74 | ], | ||
75 | [cp ${abs_top_srcdir}/sieve/tests/moderator.mbox mailbox | ||
76 | chmod +w mailbox | ||
77 | |||
78 | MTA_DIAG=`pwd`/mta.diag | ||
79 | export MTA_DIAG | ||
80 | sieve MUT_SIEVE_CMDLINE dnl | ||
81 | --clearpath -L "${abs_top_builddir}/libmu_sieve/extensions" -f ./mailbox prog || exit $? | ||
82 | test -f ./mta.diag && echo ./mta.diag | ||
83 | exit 0 | ||
84 | ], | ||
85 | [], | ||
86 | [KEEP on msg uid 0 | ||
87 | MODERATOR on msg uid 1: keeping message | ||
88 | ]) | ||
89 | |||
90 | m4_popdef([MUT_SIEVE_EXT_NAME]) |
sieve/tests/moderator.mbox
0 → 100644
1 | From mailman-bounces@example.org Sat Jul 2 01:36:47 2005 | ||
2 | Subject: Bug-foobar post from somebody@example.com requires approval | ||
3 | From: bug-foobar-owner@example.org | ||
4 | To: bug-foobar-owner@example.org | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: multipart/mixed; boundary="===============1223730756==" | ||
7 | Message-ID: <mailman.16340.1120257323.2856.bug-foobar@example.org> | ||
8 | Date: Fri, 01 Jul 2005 18:35:23 -0400 | ||
9 | Precedence: bulk | ||
10 | X-BeenThere: bug-foobar@example.org | ||
11 | X-Mailman-Version: 2.1.5 | ||
12 | List-Id: Bug reports for GNU foobar <bug-foobar.example.org> | ||
13 | X-List-Administrivia: yes | ||
14 | Sender: mailman-bounces@example.org | ||
15 | Errors-To: mailman-bounces@example.org | ||
16 | X-IMAPbase: 1292609256 2 | ||
17 | Status: | ||
18 | X-UID: 1 | ||
19 | |||
20 | --===============1223730756== | ||
21 | Content-Type: text/plain; charset="us-ascii" | ||
22 | MIME-Version: 1.0 | ||
23 | Content-Transfer-Encoding: 7bit | ||
24 | |||
25 | As list administrator, your authorization is requested for the | ||
26 | following mailing list posting: | ||
27 | |||
28 | List: Bug-foobar@example.org | ||
29 | From: somebody@example.com | ||
30 | Subject: Problems building foobar | ||
31 | Reason: Post by non-member to a members-only list | ||
32 | |||
33 | At your convenience, visit: | ||
34 | |||
35 | http://lists.example.org/mailman/admindb/bug-foobar | ||
36 | |||
37 | to approve or deny the request. | ||
38 | |||
39 | --===============1223730756== | ||
40 | Content-Type: message/rfc822 | ||
41 | MIME-Version: 1.0 | ||
42 | |||
43 | Envelope-to: bug-foobar@example.org | ||
44 | Subject: Problems building foobar | ||
45 | Date: Fri, 1 Jul 2005 15:26:59 -0700 | ||
46 | Message-ID: <7A2E278D550047489A84AC706B36D595250E75@example.com> | ||
47 | Thread-Topic: Problems building foobar | ||
48 | Thread-Index: AcV+i/85qSfLCmCAToipt+481y99vw== | ||
49 | From: somebody@example.com | ||
50 | To: <bug-foobar@example.org> | ||
51 | |||
52 | Hi, | ||
53 | |||
54 | I'm trying to build foobar under Linux and am getting the following | ||
55 | error. Please help. | ||
56 | |||
57 | blah blah blah | ||
58 | |||
59 | --===============1223730756== | ||
60 | Content-Type: message/rfc822 | ||
61 | MIME-Version: 1.0 | ||
62 | |||
63 | Content-Type: text/plain; charset="us-ascii" | ||
64 | MIME-Version: 1.0 | ||
65 | Content-Transfer-Encoding: 7bit | ||
66 | Subject: confirm 7e02c99a82a21a2349291a4f142ee2347bb5fd0b | ||
67 | Sender: bug-foobar-request@example.org | ||
68 | From: bug-foobar-request@example.org | ||
69 | |||
70 | If you reply to this message, keeping the Subject: header intact, | ||
71 | Mailman will discard the held message. Do this if the message is | ||
72 | spam. If you reply to this message and include an Approved: header | ||
73 | with the list password in it, the message will be approved for posting | ||
74 | to the list. The Approved: header can also appear in the first line | ||
75 | of the body of the reply. | ||
76 | --===============1223730756==-- | ||
77 | |||
78 |
... | @@ -78,6 +78,27 @@ m4_define([MUT_PREREQ_CAPA],[ | ... | @@ -78,6 +78,27 @@ m4_define([MUT_PREREQ_CAPA],[ |
78 | sieve --show-config-options | grep '^$1' > /dev/null 2>&1 || AT_SKIP_TEST | 78 | sieve --show-config-options | grep '^$1' > /dev/null 2>&1 || AT_SKIP_TEST |
79 | ]) | 79 | ]) |
80 | 80 | ||
81 | dnl ------------------------------------------------------------ | ||
82 | m4_define([MUT_SIEVE_EXT_NAME]) | ||
83 | |||
84 | dnl ------------------------------------------------------------ | ||
85 | dnl MUT_SIEVE_EXT_TEST([NAME],[KW = `'], [PROG], [TEST], | ||
86 | dnl [STDOUT = `'],[STDERR = `']) | ||
87 | m4_define([MUT_SIEVE_EXT_TEST],[ | ||
88 | AT_SETUP(MUT_SIEVE_EXT_NAME[: $1]) | ||
89 | AT_KEYWORDS([MUT_SIEVE_EXT_NAME $2]) | ||
90 | |||
91 | AT_CHECK([ | ||
92 | MUT_PREREQ_CAPA([HAVE_LIBLTDL]) | ||
93 | |||
94 | AT_DATA([prog],[$3]) | ||
95 | $4 | ||
96 | ], | ||
97 | [0], | ||
98 | [$5],[$6]) | ||
99 | AT_CLEANUP]) | ||
100 | |||
101 | |||
81 | AT_INIT | 102 | AT_INIT |
82 | 103 | ||
83 | AT_TESTED([sieve]) | 104 | AT_TESTED([sieve]) |
... | @@ -103,5 +124,7 @@ m4_include([size.at]) | ... | @@ -103,5 +124,7 @@ m4_include([size.at]) |
103 | m4_include([redirect.at]) | 124 | m4_include([redirect.at]) |
104 | m4_include([reject.at]) | 125 | m4_include([reject.at]) |
105 | m4_include([ext.at]) | 126 | m4_include([ext.at]) |
127 | m4_include([moderator.at]) | ||
128 | |||
106 | 129 | ||
107 | 130 | ... | ... |
-
Please register or sign in to post a comment