Commit c9e92991 c9e92991135ee0ce8cdcb02c6458d1cb40ae9cae by Sergey Poznyakoff

(sieve_register_comparator)

(_find_comparator,comp_false,sieve_match_part_checker):
Added support for relational tests.
1 parent 2b74ba3a
...@@ -39,7 +39,8 @@ sieve_register_comparator (sieve_machine_t mach, ...@@ -39,7 +39,8 @@ sieve_register_comparator (sieve_machine_t mach,
39 int required, 39 int required,
40 sieve_comparator_t is, sieve_comparator_t contains, 40 sieve_comparator_t is, sieve_comparator_t contains,
41 sieve_comparator_t matches, 41 sieve_comparator_t matches,
42 sieve_comparator_t regex) 42 sieve_comparator_t regex,
43 sieve_comparator_t eq)
43 { 44 {
44 sieve_comparator_record_t *rp; 45 sieve_comparator_record_t *rp;
45 46
...@@ -57,6 +58,7 @@ sieve_register_comparator (sieve_machine_t mach, ...@@ -57,6 +58,7 @@ sieve_register_comparator (sieve_machine_t mach,
57 rp->comp[MU_SIEVE_MATCH_CONTAINS] = contains; 58 rp->comp[MU_SIEVE_MATCH_CONTAINS] = contains;
58 rp->comp[MU_SIEVE_MATCH_MATCHES] = matches; 59 rp->comp[MU_SIEVE_MATCH_MATCHES] = matches;
59 rp->comp[MU_SIEVE_MATCH_REGEX] = regex; 60 rp->comp[MU_SIEVE_MATCH_REGEX] = regex;
61 rp->comp[MU_SIEVE_MATCH_EQ] = eq;
60 62
61 return list_append (mach->comp_list, rp); 63 return list_append (mach->comp_list, rp);
62 } 64 }
...@@ -111,7 +113,7 @@ _find_comparator (void *item, void *data) ...@@ -111,7 +113,7 @@ _find_comparator (void *item, void *data)
111 { 113 {
112 sieve_runtime_tag_t *tag = item; 114 sieve_runtime_tag_t *tag = item;
113 115
114 if (strcmp (tag->tag, "comparator") == 0) 116 if (strcmp (tag->tag, TAG_COMPFUN) == 0)
115 { 117 {
116 *(sieve_comparator_t*)data = tag->arg->v.ptr; 118 *(sieve_comparator_t*)data = tag->arg->v.ptr;
117 return 1; 119 return 1;
...@@ -194,13 +196,20 @@ _free_reglist (void *data) ...@@ -194,13 +196,20 @@ _free_reglist (void *data)
194 list_destroy (&list); 196 list_destroy (&list);
195 } 197 }
196 198
199 static int
200 comp_false (void *pattern, void *text)
201 {
202 return 0;
203 }
204
197 int 205 int
198 sieve_match_part_checker (const char *name, list_t tags, list_t args) 206 sieve_match_part_checker (const char *name, list_t tags, list_t args)
199 { 207 {
200 iterator_t itr; 208 iterator_t itr;
201 sieve_runtime_tag_t *match = NULL; 209 sieve_runtime_tag_t *match = NULL;
202 sieve_runtime_tag_t *comp = NULL; 210 sieve_runtime_tag_t *comp = NULL;
203 sieve_comparator_t compfun; 211 sieve_runtime_tag_t *tmp;
212 sieve_comparator_t compfun = NULL;
204 char *compname; 213 char *compname;
205 214
206 int matchtype; 215 int matchtype;
...@@ -218,10 +227,17 @@ sieve_match_part_checker (const char *name, list_t tags, list_t args) ...@@ -218,10 +227,17 @@ sieve_match_part_checker (const char *name, list_t tags, list_t args)
218 if (strcmp (t->tag, "is") == 0 227 if (strcmp (t->tag, "is") == 0
219 || strcmp (t->tag, "contains") == 0 228 || strcmp (t->tag, "contains") == 0
220 || strcmp (t->tag, "matches") == 0 229 || strcmp (t->tag, "matches") == 0
221 || strcmp (t->tag, "regex") == 0) 230 || strcmp (t->tag, "regex") == 0
231 || strcmp (t->tag, "count") == 0
232 || strcmp (t->tag, "value") == 0)
222 { 233 {
223 if (match) 234 if (match)
235 {
236 sieve_compile_error (sieve_filename, sieve_line_num,
237 _("match type specified twice in call to `%s'"),
238 name);
224 err = 1; 239 err = 1;
240 }
225 else 241 else
226 match = t; 242 match = t;
227 } 243 }
...@@ -232,12 +248,7 @@ sieve_match_part_checker (const char *name, list_t tags, list_t args) ...@@ -232,12 +248,7 @@ sieve_match_part_checker (const char *name, list_t tags, list_t args)
232 iterator_destroy (&itr); 248 iterator_destroy (&itr);
233 249
234 if (err) 250 if (err)
235 {
236 sieve_compile_error (sieve_filename, sieve_line_num,
237 _("match type specified twice in call to `%s'"),
238 name);
239 return 1; 251 return 1;
240 }
241 252
242 if (!match || strcmp (match->tag, "is") == 0) 253 if (!match || strcmp (match->tag, "is") == 0)
243 matchtype = MU_SIEVE_MATCH_IS; 254 matchtype = MU_SIEVE_MATCH_IS;
...@@ -247,31 +258,74 @@ sieve_match_part_checker (const char *name, list_t tags, list_t args) ...@@ -247,31 +258,74 @@ sieve_match_part_checker (const char *name, list_t tags, list_t args)
247 matchtype = MU_SIEVE_MATCH_MATCHES; 258 matchtype = MU_SIEVE_MATCH_MATCHES;
248 else if (strcmp (match->tag, "regex") == 0) 259 else if (strcmp (match->tag, "regex") == 0)
249 matchtype = MU_SIEVE_MATCH_REGEX; 260 matchtype = MU_SIEVE_MATCH_REGEX;
261 else
262 {
263 char *str = match->arg->v.string;
264 if (strcmp (match->tag, "count") == 0)
265 {
266 sieve_value_t *val;
267 char *str;
268 size_t count;
250 269
251 if (match) 270 if (comp && strcmp (comp->arg->v.string, "i;ascii-numeric"))
252 list_remove (tags, match);
253
254 compname = comp ? comp->arg->v.string : "i;ascii-casemap";
255 compfun = sieve_comparator_lookup (sieve_machine, compname, matchtype);
256 if (!compfun)
257 { 271 {
258 sieve_compile_error (sieve_filename, sieve_line_num, 272 sieve_compile_error (sieve_filename, sieve_line_num,
259 _("comparator `%s' is incompatible with match type `%s' in call to `%s'"), 273 _("comparator %s is incompatible with :count in call to `%s'"),
260 compname, match ? match->tag : _("is"), name); 274 comp->arg->v.string,
275 name);
261 return 1; 276 return 1;
262 } 277 }
263 278
264 if (comp) 279 compfun = comp_false;
280 val = sieve_value_get (args, 1);
281 if (!val)
282 return 1; /* shouldn't happen */
283 /* NOTE: Type of v is always SVT_STRING_LIST */
284 list_count (val->v.list, &count);
285 if (count > 1)
265 { 286 {
266 sieve_mfree (sieve_machine, comp->arg); 287 sieve_compile_error (sieve_filename, sieve_line_num,
288 _("second argument must be a list of one element"));
289 return 1;
290 }
291 list_get (val->v.list, 0, (void **) &str);
292 count = strtoul (str, &str, 10);
293 if (*str)
294 {
295 sieve_compile_error (sieve_filename, sieve_line_num,
296 _("second argument cannot be converted to number"));
297 return 1;
298 }
267 } 299 }
268 else 300 else
301 matchtype = MU_SIEVE_MATCH_EQ;
302
303 if (sieve_str_to_relcmp (str, NULL, NULL))
269 { 304 {
270 comp = sieve_malloc (sieve_machine, sizeof (*comp)); 305 sieve_compile_error (sieve_filename, sieve_line_num,
271 comp->tag = "comparator"; 306 _("invalid relational match `%s' in call to `%s'"),
272 list_append (tags, comp); 307 str, name);
308 return 1;
309 }
273 } 310 }
274 comp->arg = sieve_value_create (SVT_POINTER, compfun); 311
312 if (!compfun)
313 {
314 compname = comp ? comp->arg->v.string : "i;ascii-casemap";
315 compfun = sieve_comparator_lookup (sieve_machine, compname, matchtype);
316 if (!compfun)
317 {
318 sieve_compile_error (sieve_filename, sieve_line_num,
319 _("comparator `%s' is incompatible with match type `%s' in call to `%s'"),
320 compname, match ? match->tag : "is", name);
321 return 1;
322 }
323 }
324
325 tmp = sieve_malloc (sieve_machine, sizeof (*tmp));
326 tmp->tag = TAG_COMPFUN;
327 tmp->arg = sieve_value_create (SVT_POINTER, compfun);
328 list_append (tags, tmp);
275 329
276 if (matchtype == MU_SIEVE_MATCH_REGEX) 330 if (matchtype == MU_SIEVE_MATCH_REGEX)
277 { 331 {
...@@ -345,6 +399,12 @@ i_octet_regex (const char *pattern, const char *text) ...@@ -345,6 +399,12 @@ i_octet_regex (const char *pattern, const char *text)
345 return regexec ((regex_t *) pattern, text, 0, NULL, 0) == 0; 399 return regexec ((regex_t *) pattern, text, 0, NULL, 0) == 0;
346 } 400 }
347 401
402 static int
403 i_octet_eq (const char *pattern, const char *text)
404 {
405 return strcmp (text, pattern);
406 }
407
348 /* :comparator i;ascii-casemap */ 408 /* :comparator i;ascii-casemap */
349 static int 409 static int
350 i_ascii_casemap_is (const char *pattern, const char *text) 410 i_ascii_casemap_is (const char *pattern, const char *text)
...@@ -452,6 +512,12 @@ i_ascii_casemap_regex (const char *pattern, const char *text) ...@@ -452,6 +512,12 @@ i_ascii_casemap_regex (const char *pattern, const char *text)
452 return regexec ((regex_t *) pattern, text, 0, NULL, 0) == 0; 512 return regexec ((regex_t *) pattern, text, 0, NULL, 0) == 0;
453 } 513 }
454 514
515 static int
516 i_ascii_casemap_eq (const char *pattern, const char *text)
517 {
518 return strcasecmp (text, pattern);
519 }
520
455 /* :comparator i;ascii-numeric */ 521 /* :comparator i;ascii-numeric */
456 static int 522 static int
457 i_ascii_numeric_is (const char *pattern, const char *text) 523 i_ascii_numeric_is (const char *pattern, const char *text)
...@@ -469,6 +535,28 @@ i_ascii_numeric_is (const char *pattern, const char *text) ...@@ -469,6 +535,28 @@ i_ascii_numeric_is (const char *pattern, const char *text)
469 return 1; 535 return 1;
470 } 536 }
471 537
538 static int
539 i_ascii_numeric_eq (const char *pattern, const char *text)
540 {
541 if (isdigit ((int) *pattern))
542 {
543 if (isdigit ((int) *text))
544 {
545 size_t a = strtoul (pattern, NULL, 10);
546 size_t b = strtoul (text, NULL, 10);
547 if (b > a)
548 return 1;
549 else if (b < a)
550 return -1;
551 return 0;
552 }
553 else
554 return 1;
555 }
556 else
557 return 1;
558 }
559
472 void 560 void
473 sieve_register_standard_comparators (sieve_machine_t mach) 561 sieve_register_standard_comparators (sieve_machine_t mach)
474 { 562 {
...@@ -478,19 +566,22 @@ sieve_register_standard_comparators (sieve_machine_t mach) ...@@ -478,19 +566,22 @@ sieve_register_standard_comparators (sieve_machine_t mach)
478 i_octet_is, 566 i_octet_is,
479 i_octet_contains, 567 i_octet_contains,
480 i_octet_matches, 568 i_octet_matches,
481 i_octet_regex); 569 i_octet_regex,
570 i_octet_eq);
482 sieve_register_comparator (mach, 571 sieve_register_comparator (mach,
483 "i;ascii-casemap", 572 "i;ascii-casemap",
484 1, 573 1,
485 i_ascii_casemap_is, 574 i_ascii_casemap_is,
486 i_ascii_casemap_contains, 575 i_ascii_casemap_contains,
487 i_ascii_casemap_matches, 576 i_ascii_casemap_matches,
488 i_ascii_casemap_regex); 577 i_ascii_casemap_regex,
578 i_ascii_casemap_eq);
489 sieve_register_comparator (mach, 579 sieve_register_comparator (mach,
490 "i;ascii-numeric", 580 "i;ascii-numeric",
491 0, 581 0,
492 i_ascii_numeric_is, 582 i_ascii_numeric_is,
493 NULL, 583 NULL,
494 NULL, 584 NULL,
495 NULL); 585 NULL,
586 i_ascii_numeric_eq);
496 } 587 }
......