/* Copyright (c) 2002,2003,2004,2009 James M. Kretchmar
*
* This file is part of Owl.
*
* Owl is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Owl is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Owl. If not, see .
*
* ---------------------------------------------------------------
*
* As of Owl version 2.1.12 there are patches contributed by
* developers of the the branched BarnOwl project, Copyright (c)
* 2006-2008 The BarnOwl Developers. All rights reserved.
*/
#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);
}
/* return 1 if the message matches the given filter, otherwise
* return 0.
*/
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);
}