(sieve_register_comparator)
(_find_comparator,comp_false,sieve_match_part_checker): Added support for relational tests.
Showing
1 changed file
with
117 additions
and
26 deletions
... | @@ -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 | } | ... | ... |
-
Please register or sign in to post a comment