Commit 1040ed4b 1040ed4bdcd07fdfac57baebca3bf9cb931e2cf1 by uid65697

New sieve extension test.

1 parent 37dbcca2
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 GNU Mailutils 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
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 /* Implements "list" sieve extension test. See "Syntax:" below for the
19 description */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <mailutils/libsieve.h>
29
30
31
32 /* Auxiliary functions */
33 struct header_closure {
34 header_t header; /* Message header */
35 int index; /* Header index */
36 char *delim; /* List delimiter */
37 char *value; /* Retrieved header value */
38 char *save; /* Save pointer for strtok_r */
39 };
40
41 static void
42 cleanup (struct header_closure *hc)
43 {
44 free (hc->value);
45 hc->value = hc->save = NULL;
46 }
47
48 static int
49 retrieve_next_header (struct header_closure *hc, char *name, char **pval)
50 {
51 char buf[512];
52 size_t n;
53
54 cleanup (hc);
55 while (!header_get_field_name (hc->header, hc->index, buf, sizeof(buf), &n))
56 {
57 int i = hc->index++;
58 if (strcasecmp (buf, name) == 0)
59 {
60 if (header_aget_field_value (hc->header, i, &hc->value))
61 return 1;
62 *pval = strtok_r (hc->value, hc->delim, &hc->save);
63 if (*pval == NULL)
64 {
65 cleanup (hc);
66 return 1;
67 }
68 return 0;
69 }
70 }
71
72 return 1;
73 }
74
75 static int
76 list_retrieve_header (void *item, void *data, int idx, char **pval)
77 {
78 struct header_closure *hc = data;
79 char *p;
80
81 if (idx == 0)
82 hc->index = 1;
83
84 while (1)
85 {
86 if (!hc->value)
87 {
88 if (retrieve_next_header (hc, (char*) item, &p))
89 return 1;
90 }
91 else
92 {
93 p = strtok_r (NULL, hc->delim, &hc->save);
94 if (!p)
95 {
96 cleanup (hc);
97 continue;
98 }
99 }
100
101 *pval = strdup (p);
102 return 0;
103 }
104
105 return 1;
106 }
107
108 static int
109 waitdebug()
110 {
111 static volatile int _st=0;
112 while (!_st)
113 _st=_st;
114 }
115
116
117 /* The test proper */
118
119 /* Syntax: list [COMPARATOR] [MATCH-TYPE]
120 [ :delim <delimiters: string> ]
121 <headers: string-list> <key-list: string-list>
122
123 The "list" test evaluates to true if any of the headers
124 match any key. Each header is regarded as containing a
125 list of keywords. By default, comma is assumed as list
126 separator. This can be overridden by specifying ":delim"
127 tag, whose value is a string consisting of valid list
128 delimiter characters.
129
130 list :matches :delim " ," [ "X-Spam-Keywords", "X-Spamd-Keywords" ]
131 [ "HTML_*", "FORGED_*" ]
132
133
134 */
135
136 static int
137 list_test (sieve_machine_t mach, list_t args, list_t tags)
138 {
139 sieve_value_t *h, *v, *arg;
140 sieve_comparator_t comp = sieve_get_comparator (mach, tags);
141 struct header_closure clos;
142 int result;
143
144 memset (&clos, 0, sizeof clos);
145 if (sieve_tag_lookup (tags, "delim", &arg))
146 clos.delim = arg->v.string;
147 else
148 clos.delim = ",";
149
150 h = sieve_value_get (args, 0);
151 if (!h)
152 {
153 sieve_error (mach, _("list: can't get argument 1"));
154 sieve_abort (mach);
155 }
156 v = sieve_value_get (args, 1);
157 if (!v)
158 {
159 sieve_error (mach, _("list: can't get argument 2"));
160 sieve_abort (mach);
161 }
162
163 message_get_header (sieve_get_message (mach), &clos.header);
164 result = sieve_vlist_compare (h, v, comp, sieve_get_relcmp (mach, tags),
165 list_retrieve_header,
166 &clos, NULL) > 0;
167 cleanup (&clos);
168 return result;
169 }
170
171
172 /* Initialization */
173
174 /* Required arguments: */
175 static sieve_data_type list_req_args[] = {
176 SVT_STRING_LIST,
177 SVT_STRING_LIST,
178 SVT_VOID
179 };
180
181 static sieve_tag_def_t match_part_tags[] = {
182 { "is", SVT_VOID },
183 { "contains", SVT_VOID },
184 { "matches", SVT_VOID },
185 { "regex", SVT_VOID },
186 { "count", SVT_STRING },
187 { "value", SVT_STRING },
188 { "comparator", SVT_STRING },
189 { NULL }
190 };
191
192 static sieve_tag_def_t delim_part_tags[] = {
193 { "delim", SVT_STRING },
194 { NULL }
195 };
196
197 static sieve_tag_group_t list_tag_groups[] = {
198 { match_part_tags, sieve_match_part_checker },
199 { delim_part_tags, NULL },
200 { NULL }
201 };
202
203 /* Initialization function. */
204 int
205 SIEVE_EXPORT(list,init) (sieve_machine_t mach)
206 {
207 return sieve_register_test (mach, "list", list_test,
208 list_req_args, list_tag_groups, 1);
209 }
210
211 /* End of list.c */