static int _regex_compile (void *item, void *data) { struct regex_data *rd = data; int rc; regex_t *preg = mu_sieve_malloc (mu_sieve_machine, sizeof (*preg)); rc = regcomp (preg, (char*)item, rd->flags); if (rc) { size_t size = regerror (rc, preg, NULL, 0); char *errbuf = malloc (size + 1); if (errbuf) { regerror (rc, preg, errbuf, size); mu_sv_compile_error (&mu_sieve_locus, _("regex error: %s"), errbuf); free (errbuf); } else mu_sv_compile_error (&mu_sieve_locus, _("regex error")); return rc; } mu_list_append (rd->list, preg); return 0; }
void mu_sieve_require (mu_list_t slist) { int status; mu_iterator_t itr; status = mu_list_get_iterator (slist, &itr); if (status) { mu_sv_compile_error (&mu_sieve_locus, _("cannot create iterator: %s"), mu_strerror (status)); return; } for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) { char *name; int (*reqfn) (mu_sieve_machine_t mach, const char *name) = NULL; const char *text = NULL; mu_iterator_current (itr, (void **)&name); if (strncmp (name, "comparator-", 11) == 0) { name += 11; reqfn = mu_sieve_require_comparator; text = _("required comparator"); } else if (strncmp (name, "test-", 5) == 0) /* GNU extension */ { name += 5; reqfn = mu_sieve_require_test; text = _("required test"); } else if (strcmp (name, "relational") == 0) /* RFC 3431 */ { reqfn = mu_sieve_require_relational; text = ""; } else { reqfn = mu_sieve_require_action; text = _("required action"); } if (reqfn (mu_sieve_machine, name)) { mu_sv_compile_error (&mu_sieve_locus, _("source for the %s %s is not available"), text, name); } } mu_iterator_destroy (&itr); }
/* FIXME: The checker interface should be redone. Until then this function is commented out. Problems: 1. Checkers are called per group, there's no way to call them per tag. 2. See FIXMEs in the code. */ static int index_checker (const char *name, mu_list_t tags, mu_list_t args) { mu_iterator_t itr; mu_sieve_runtime_tag_t *match = NULL; int err; if (!tags || mu_list_get_iterator (tags, &itr)) return 0; err = 0; for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr); mu_iterator_next (itr)) { mu_sieve_runtime_tag_t *t; mu_iterator_current (itr, (void **)&t); if (strcmp (t->tag, "index") == 0) { if (match) { /* FIXME: 1. This function must be public. 2. locus should be included in t */ mu_sv_compile_error (&mu_sieve_locus, _("index specified twice in call to `%s'"), name); err = 1; break; } } } mu_iterator_destroy (&itr); if (err) return 1; if (match) { if (match->arg->v.number < 1) { // See FIXME above mu_sv_compile_error (&mu_sieve_locus, _("invalid index value: %s"), match->arg->v.string); return 1; } } return 0; }
int mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) { mu_iterator_t itr; mu_sieve_runtime_tag_t *match = NULL; mu_sieve_runtime_tag_t *comp = NULL; mu_sieve_runtime_tag_t *tmp; mu_sieve_comparator_t compfun = NULL; char *compname = "false"; int matchtype; int err = 0; if (!tags || mu_list_get_iterator (tags, &itr)) return 0; for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr); mu_iterator_next (itr)) { mu_sieve_runtime_tag_t *t; mu_iterator_current (itr, (void **)&t); if (strcmp (t->tag, "is") == 0 || strcmp (t->tag, "contains") == 0 || strcmp (t->tag, "matches") == 0 || strcmp (t->tag, "regex") == 0 || strcmp (t->tag, "count") == 0 || strcmp (t->tag, "value") == 0) { if (match) { mu_sv_compile_error (&mu_sieve_locus, _("match type specified twice in call to `%s'"), name); err = 1; } else match = t; } else if (strcmp (t->tag, "comparator") == 0) comp = t; } mu_iterator_destroy (&itr); if (err) return 1; if (!match || strcmp (match->tag, "is") == 0) matchtype = MU_SIEVE_MATCH_IS; else if (strcmp (match->tag, "contains") == 0) matchtype = MU_SIEVE_MATCH_CONTAINS; else if (strcmp (match->tag, "matches") == 0) matchtype = MU_SIEVE_MATCH_MATCHES; else if (strcmp (match->tag, "regex") == 0) matchtype = MU_SIEVE_MATCH_REGEX; else { char *str = match->arg->v.string; if (strcmp (match->tag, "count") == 0) { mu_sieve_value_t *val; char *str; size_t count; if (comp && strcmp (comp->arg->v.string, "i;ascii-numeric")) { mu_sv_compile_error (&mu_sieve_locus, /* TRANSLATORS: Do not translate ':count'. It is the name of a Sieve tag */ _("comparator %s is incompatible with " ":count in call to `%s'"), comp->arg->v.string, name); return 1; } matchtype = MU_SIEVE_MATCH_LAST; /* to not leave it undefined */ compfun = comp_false; val = mu_sieve_value_get (args, 1); if (!val) return 1; /* shouldn't happen */ /* NOTE: Type of v is always SVT_STRING_LIST */ mu_list_count (val->v.list, &count); if (count > 1) { mu_sv_compile_error (&mu_sieve_locus, _("second argument must be a list of one element")); return 1; } mu_list_get (val->v.list, 0, (void **) &str); count = strtoul (str, &str, 10); if (*str) { mu_sv_compile_error (&mu_sieve_locus, _("second argument cannot be converted to number")); return 1; } } else matchtype = MU_SIEVE_MATCH_EQ; if (mu_sieve_str_to_relcmp (str, NULL, NULL)) { mu_sv_compile_error (&mu_sieve_locus, _("invalid relational match `%s' in call to `%s'"), str, name); return 1; } } if (!compfun) { compname = comp ? comp->arg->v.string : "i;ascii-casemap"; compfun = mu_sieve_comparator_lookup (mu_sieve_machine, compname, matchtype); if (!compfun) { mu_sv_compile_error (&mu_sieve_locus, _("comparator `%s' is incompatible with match type `%s' in call to `%s'"), compname, match ? match->tag : "is", name); return 1; } } tmp = mu_sieve_malloc (mu_sieve_machine, sizeof (*tmp)); tmp->tag = TAG_COMPFUN; tmp->arg = mu_sieve_value_create (SVT_POINTER, compfun); mu_list_append (tags, tmp); if (matchtype == MU_SIEVE_MATCH_REGEX) { /* To speed up things, compile all patterns at once. Notice that it is supposed that patterns are in arg 2 */ mu_sieve_value_t *val, *newval; struct regex_data rd; int rc; if (mu_list_get (args, 1, (void**)&val)) return 0; rd.flags = REG_EXTENDED; if (strcmp (compname, "i;ascii-casemap") == 0) rd.flags |= REG_ICASE; mu_list_create (&rd.list); rc = mu_sieve_vlist_do (val, _regex_compile, &rd); mu_sieve_machine_add_destructor (mu_sieve_machine, _free_reglist, rd.list); if (rc) return rc; newval = mu_sieve_value_create (SVT_STRING_LIST, rd.list); mu_list_replace (args, val, newval); } #ifndef FNM_CASEFOLD else if (matchtype == MU_SIEVE_MATCH_MATCHES && strcmp (compname, "i;ascii-casemap") == 0) { int rc; mu_sieve_value_t *val; if (mu_list_get (args, 1, (void**)&val)) return 0; rc = mu_sieve_vlist_do (val, _pattern_upcase, NULL); if (rc) return rc; } #endif return 0; }