Commit 8bf6d372 8bf6d37210f6dc0136007dd9a973a7426cce55fb by Sergey Poznyakoff

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.
1 parent 6824980f
...@@ -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\
......
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])
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
......