#include #include "owl.h" static const char fileIdent[] = "$Id$"; #define OWL_FILTER_MAXRECURSE 20 int owl_filter_init_fromstring(owl_filter *f, char *name, char *string) { char **argv; int argc, out; argv=owl_parseline(string, &argc); out=owl_filter_init(f, name, argc, argv); /* owl_parsefree(argv, argc); */ return(out); } int owl_filter_init(owl_filter *f, char *name, int argc, char **argv) { int i, j, error; owl_filterelement *fe; char *regexstr; owl_list list; f->name=owl_strdup(name); f->polarity=0; f->color=OWL_COLOR_DEFAULT; f->cachedmsgid=-1; owl_list_create(&(f->fes)); /* first take arguments that have to come first */ /* set the color */ if (argc>=2 && !strcmp(argv[0], "-c")) { if (owl_util_string_to_color(argv[1])==-1) { owl_function_error("The color '%s' is not available, using default.", argv[1]); } else { f->color=owl_util_string_to_color(argv[1]); } argc-=2; argv+=2; } /* then deal with the expression */ for (i=0; ifes), fe); } else { owl_free(fe); owl_filter_free(f); return(-1); } } /* Are we trying to use the filter we're creating? Bad. */ owl_list_create(&list); _owl_filter_get_subfilter_names(f, &list); j=owl_list_get_size(&list); for (i=0; iname); } void owl_filter_set_polarity_match(owl_filter *f) { f->polarity=0; } void owl_filter_set_polarity_unmatch(owl_filter *f) { f->polarity=1; } void owl_filter_set_color(owl_filter *f, int color) { f->color=color; } int owl_filter_get_color(owl_filter *f) { return(f->color); } void owl_filter_set_cachedmsgid(owl_filter *f, int cachedmsgid) { f->cachedmsgid=cachedmsgid; } int owl_filter_get_cachedmsgid(owl_filter *f) { return(f->cachedmsgid); } int owl_filter_message_match(owl_filter *f, owl_message *m) { int i, j, tmp; owl_list work_fes, *fes; owl_filterelement *fe; char *field, *match; /* create the working list of expression elements */ fes=&(f->fes); owl_list_create(&work_fes); j=owl_list_get_size(fes); for (i=0; ifes))-1); /* now there will be only one TRUE / FALSE, find it among the NULL's */ tmp=0; for (i=0; ipolarity) tmp=!tmp; owl_list_free_simple(&work_fes); return(tmp); } int _owl_filter_message_match_recurse(owl_filter *f, owl_message *m, owl_list *fes, int start, int end) { int a=0, b=0, i, x, y, z, score, ret, type; owl_filterelement *fe, *tmpfe=NULL; /* Deal with parens first. */ for (i=0; i0) { /* unblanaced parens */ return(-1); } /* Simply the parens by removing them and evaluating what was in between */ if (y>0) { /* null out the parens */ owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g)); owl_list_replace_element(fes, y, owl_global_get_filterelement_null(&g)); /* evaluate expression in between */ ret=_owl_filter_message_match_recurse(f, m, fes, x+1, y-1); if (ret<0) return(-1); /* there may be more, so we continue */ continue; } else { /* otherwise we're done with this part */ break; } } if (i==OWL_FILTER_MAX_DEPTH) { /* hit the saftey limit, consider it invalid */ return(-1); } /* Find AND / OR / NOT. * For binary expressions (AND/OR): * "type" is 1 * "x" will index first val, "y" the operator and "z" the second val * For unary expressions (NOT): * "type" is 2 * "x" will index the operator, "y" the value * "score" tallys how many expression elements have been found so far */ for (i=0; i0)) { fe=owl_list_get_element(fes, x); if (owl_filterelement_is_true(fe)) { a=1; } else if (owl_filterelement_is_false(fe)) { a=0; } fe=owl_list_get_element(fes, z); if (owl_filterelement_is_true(fe)) { b=1; } else if (owl_filterelement_is_false(fe)) { b=0; } fe=owl_list_get_element(fes, y); if (owl_filterelement_is_and(fe)) { if (a && b) { tmpfe=owl_global_get_filterelement_true(&g); } else { tmpfe=owl_global_get_filterelement_false(&g); } } else if (owl_filterelement_is_or(fe)) { if (a || b) { tmpfe=owl_global_get_filterelement_true(&g); } else { tmpfe=owl_global_get_filterelement_false(&g); } } owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g)); owl_list_replace_element(fes, y, tmpfe); owl_list_replace_element(fes, z, owl_global_get_filterelement_null(&g)); } else if ((type==2) && (y>0)) { /* simplify NOT */ fe=owl_list_get_element(fes, y); owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g)); if (owl_filterelement_is_false(fe)) { owl_list_replace_element(fes, y, owl_global_get_filterelement_true(&g)); } else { owl_list_replace_element(fes, y, owl_global_get_filterelement_false(&g)); } } else { break; } } return(0); } void owl_filter_print(owl_filter *f, char *out) { int i, j; owl_filterelement *fe; char *tmp; strcpy(out, owl_filter_get_name(f)); strcat(out, ": "); if (f->color!=OWL_COLOR_DEFAULT) { strcat(out, "-c "); strcat(out, owl_util_color_to_string(f->color)); strcat(out, " "); } j=owl_list_get_size(&(f->fes)); for (i=0; ifes), i); tmp=owl_filterelement_to_string(fe); strcat(out, tmp); owl_free(tmp); } strcat(out, "\n"); } /* Return 1 if the filters 'a' and 'b' are equivalent, 0 otherwise */ int owl_filter_equiv(owl_filter *a, owl_filter *b) { char buff[LINE], buff2[LINE]; owl_filter_print(a, buff); owl_filter_print(b, buff2); if (!strcmp(buff, buff2)) return(1); return(0); } /* Private * 'list' should already be allocated and initialized * This function places into list the string names of all filters * used in the filter expression for 'f'. * Caller must do a full free on 'list', including elements. */ void _owl_filter_get_subfilter_names(owl_filter *f, owl_list *list) { int i, j; owl_filterelement *fe; j=owl_list_get_size(&(f->fes)); for (i=0; ifes), i); if (owl_filterelement_is_filter(fe)) { owl_list_append_element(list, owl_strdup(owl_filterelement_get_filtername(fe))); } } } int owl_filter_is_toodeep(owl_filter *f) { owl_list seen, tocheck, tmp; int i, j, x, y; owl_filter *subfilter; owl_list_create(&seen); owl_list_create(&tocheck); owl_list_create(&tmp); /* seed 'tocheck' with the first set of filters */ _owl_filter_get_subfilter_names(f, &tmp); j=owl_list_get_size(&tmp); for (i=0; iname) owl_free(f->name); owl_list_free_all(&(f->fes), func); }