source: filter.c @ 75be7c0

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 75be7c0 was 75be7c0, checked in by James M. Kretchmar <kretch@mit.edu>, 18 years ago
Added "body" as a valid field to match on in a filter.
  • Property mode set to 100644
File size: 8.9 KB
Line 
1#include <string.h>
2#include "owl.h"
3
4static const char fileIdent[] = "$Id$";
5
6int owl_filter_init_fromstring(owl_filter *f, char *name, char *string) {
7  char **argv;
8  int argc, out;
9
10  argv=owl_parseline(string, &argc);
11  out=owl_filter_init(f, name, argc, argv);
12  /* owl_parsefree(argv, argc); */
13  return(out);
14}
15
16int owl_filter_init(owl_filter *f, char *name, int argc, char **argv) {
17  int i, error;
18  owl_filterelement *fe;
19   
20  f->name=owl_strdup(name);
21  f->polarity=0;
22  f->color=OWL_COLOR_DEFAULT;
23  f->cachedmsgid=-1;
24  owl_list_create(&(f->fes));
25
26  /* first take arguments that have to come first */
27  /* set the color */
28  if (argc>=2 && !strcmp(argv[0], "-c")) {
29    f->color=owl_util_string_to_color(argv[1]);
30    argc-=2;
31    argv+=2;
32  }
33
34  /* then deal with the expression */
35  for (i=0; i<argc; i++) {
36    error=0;
37    fe=owl_malloc(sizeof(owl_filterelement));
38
39    /* all the 0 argument possibilities */
40    if (!strcmp(argv[i], "(")) {
41      owl_filterelement_create_openbrace(fe);
42    } else if (!strcmp(argv[i], ")")) {
43      owl_filterelement_create_closebrace(fe);
44    } else if (!strcasecmp(argv[i], "and")) {
45      owl_filterelement_create_and(fe);
46    } else if (!strcasecmp(argv[i], "or")) {
47      owl_filterelement_create_or(fe);
48    } else if (!strcasecmp(argv[i], "not")) {
49      owl_filterelement_create_not(fe);
50
51    } else if (i==argc-1) {
52      error=1;
53    } else {
54      if (!strcasecmp(argv[i], "class") ||
55          !strcasecmp(argv[i], "instance") ||
56          !strcasecmp(argv[i], "sender") ||
57          !strcasecmp(argv[i], "recipient") ||
58          !strcasecmp(argv[i], "body") ||
59          !strcasecmp(argv[i], "opcode") ||
60          !strcasecmp(argv[i], "realm") ||
61          !strcasecmp(argv[i], "type")) {
62        owl_filterelement_create_re(fe, argv[i], argv[i+1]);
63        i++;
64      } else {
65        error=1;
66      }
67    }
68
69    if (!error) {
70      owl_list_append_element(&(f->fes), fe);
71    } else {
72      owl_free(fe);
73      owl_filter_free(f);
74      return(-1);
75    }
76
77  }
78  return(0);
79}
80
81char *owl_filter_get_name(owl_filter *f) {
82  return(f->name);
83}
84
85void owl_filter_set_polarity_match(owl_filter *f) {
86  f->polarity=0;
87}
88
89void owl_filter_set_polarity_unmatch(owl_filter *f) {
90  f->polarity=1;
91}
92
93void owl_filter_set_color(owl_filter *f, int color) {
94  f->color=color;
95}
96
97int owl_filter_get_color(owl_filter *f) {
98  return(f->color);
99}
100
101void owl_filter_set_cachedmsgid(owl_filter *f, int cachedmsgid) {
102  f->cachedmsgid=cachedmsgid;
103}
104
105int owl_filter_get_cachedmsgid(owl_filter *f) {
106  return(f->cachedmsgid);
107}
108
109int owl_filter_message_match(owl_filter *f, owl_message *m) {
110  int i, j, tmp;
111  owl_list work_fes, *fes;
112  owl_filterelement *fe;
113  char *field, *match;
114
115  /* create the working list */
116  fes=&(f->fes);
117  owl_list_create(&work_fes);
118  j=owl_list_get_size(fes);
119  for (i=0; i<j; i++) {
120    owl_list_append_element(&work_fes, owl_list_get_element(fes, i));
121  }
122
123  /* first go thru and turn all RE elements into true or false */
124  match="";
125  for (i=0; i<j; i++) {
126    fe=owl_list_get_element(&work_fes, i);
127    if (!owl_filterelement_is_re(fe)) continue;
128    field=owl_filterelement_get_field(fe);
129    if (!strcasecmp(field, "class")) {
130      match=owl_message_get_class(m);
131    } else if (!strcasecmp(field, "instance")) {
132      match=owl_message_get_instance(m);
133    } else if (!strcasecmp(field, "sender")) {
134      match=owl_message_get_sender(m);
135    } else if (!strcasecmp(field, "recipient")) {
136      match=owl_message_get_recipient(m);
137    } else if (!strcasecmp(field, "body")) {
138      match=owl_message_get_body(m);
139    } else if (!strcasecmp(field, "opcode")) {
140      match=owl_message_get_opcode(m);
141    } else if (!strcasecmp(field, "realm")) {
142      match=owl_message_get_realm(m);
143    } else if (!strcasecmp(field, "type")) {
144      if (owl_message_is_zephyr(m)) {
145        match="zephyr";
146      } else if (owl_message_is_admin(m)) {
147        match="admin";
148      } else {
149        match="";
150      }
151    }
152   
153    tmp=owl_regex_compare(owl_filterelement_get_re(fe), match);
154    if (!tmp) {
155      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
156    } else {
157      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
158    }
159  }
160
161 
162  /* call the recrsive helper */
163  i=_owl_filter_message_match_recurse(f, m, &work_fes, 0, owl_list_get_size(&(f->fes))-1);
164
165  tmp=0;
166  /* now we should have one value */
167  for (i=0; i<j; i++) {
168    fe=owl_list_get_element(&work_fes, i);
169    if (owl_filterelement_is_null(fe)) continue;
170    if (owl_filterelement_is_true(fe)) {
171      tmp=1;
172      break;
173    }
174    if (owl_filterelement_is_false(fe)) {
175      tmp=0;
176      break;
177    }
178  } 
179
180  if (f->polarity) {
181    tmp=!tmp;
182  }
183  owl_list_free_simple(&work_fes);
184  return(tmp);
185}
186
187int _owl_filter_message_match_recurse(owl_filter *f, owl_message *m, owl_list *fes, int start, int end) {
188  int a=0, b=0, i, x, y, z, score, ret, type;
189  owl_filterelement *fe, *tmpfe=NULL;
190
191  /* deal with parens first */
192  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
193    score=x=y=0;
194    for (i=start; i<=end; i++) {
195      fe=owl_list_get_element(fes, i);
196      if (owl_filterelement_is_openbrace(fe)) {
197        if (score==0) x=i;
198        score++;
199      } else if (owl_filterelement_is_closebrace(fe)) {
200        score--;
201        if (score<0) {
202          /* unblanaced parens */
203          return(-1);
204        } else if (score==0) {
205          y=i; /* this is the matching close paren */
206          break;
207        }
208      }
209    }
210    if (score>0) {
211      /* unblanaced parens */
212      return(-1);
213    }
214
215    if (y>0) {
216      /* null out the parens */
217      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
218      owl_list_replace_element(fes, y, owl_global_get_filterelement_null(&g));
219
220      /* simplify the part that was in between */
221      ret=_owl_filter_message_match_recurse(f, m, fes, x+1, y-1);
222      if (ret<0) return(-1);
223
224      /* there may be more, so we continue */
225      continue;
226    } else {
227      /* otherwise we're done with this part */
228      break;
229    }
230  }
231  if (i==OWL_FILTER_MAX_DEPTH) {
232    return(-1);
233  }
234
235  /* and / or / not */
236  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
237    type=score=x=y=z=0;
238    for (i=start; i<=end; i++) {
239      fe=owl_list_get_element(fes, i);
240      if (owl_filterelement_is_null(fe)) continue;
241      if (score==0) {
242        if (owl_filterelement_is_value(fe)) {
243          x=i;
244          score=1;
245          type=1;
246        } else if (owl_filterelement_is_not(fe)) {
247          x=i;
248          score=1;
249          type=2;
250        }
251      } else if (score==1) {
252        if (type==1) {
253          if (owl_filterelement_is_and(fe) || owl_filterelement_is_or(fe)) {
254            score=2;
255            y=i;
256          } else {
257            x=y=z=score=0;
258          }
259        } else if (type==2) {
260          if (owl_filterelement_is_value(fe)) {
261            /* it's a valid "NOT expr" */
262            y=i;
263            break;
264          }
265        }
266      } else if (score==2) {
267        if (owl_filterelement_is_value(fe)) {
268          /* yes, it's a good match */
269          z=i;
270          break;
271        } else {
272          x=y=z=score=0;
273        }
274      }
275    }
276
277    /* process and / or */
278    if ((type==1) && (z>0)) {
279      fe=owl_list_get_element(fes, x);
280      if (owl_filterelement_is_true(fe)) {
281        a=1;
282      } else if (owl_filterelement_is_false(fe)) {
283        a=0;
284      }
285
286      fe=owl_list_get_element(fes, z);
287      if (owl_filterelement_is_true(fe)) {
288        b=1;
289      } else if (owl_filterelement_is_false(fe)) {
290        b=0;
291      }
292
293      fe=owl_list_get_element(fes, y);
294      if (owl_filterelement_is_and(fe)) {
295        if (a && b) {
296          tmpfe=owl_global_get_filterelement_true(&g);
297        } else {
298          tmpfe=owl_global_get_filterelement_false(&g);
299        }
300      } else if (owl_filterelement_is_or(fe)) {
301        if (a || b) {
302          tmpfe=owl_global_get_filterelement_true(&g);
303        } else {
304          tmpfe=owl_global_get_filterelement_false(&g);
305        }
306      }
307      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
308      owl_list_replace_element(fes, y, tmpfe);
309      owl_list_replace_element(fes, z, owl_global_get_filterelement_null(&g));
310    } else if ((type==2) && (y>0)) { /* process NOT */
311      fe=owl_list_get_element(fes, y);
312      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
313      if (owl_filterelement_is_false(fe)) {
314        owl_list_replace_element(fes, y, owl_global_get_filterelement_true(&g));
315      } else {
316        owl_list_replace_element(fes, y, owl_global_get_filterelement_false(&g));
317      }
318    } else {
319      break;
320    }
321  }
322  return(0);
323
324}
325
326void owl_filter_print(owl_filter *f, char *out) {
327  int i, j;
328  owl_filterelement *fe;
329  char *tmp;
330
331  strcpy(out, owl_filter_get_name(f));
332  strcat(out, ": ");
333
334  if (f->color!=OWL_COLOR_DEFAULT) {
335    strcat(out, "-c ");
336    strcat(out, owl_util_color_to_string(f->color));
337    strcat(out, " ");
338  }
339
340  j=owl_list_get_size(&(f->fes));
341  for (i=0; i<j; i++) {
342    fe=owl_list_get_element(&(f->fes), i);
343    tmp=owl_filterelement_to_string(fe);
344    strcat(out, tmp);
345    owl_free(tmp);
346  }
347  strcat(out, "\n");
348}
349
350int owl_filter_equiv(owl_filter *a, owl_filter *b) {
351  char buff[LINE], buff2[LINE];
352
353  owl_filter_print(a, buff);
354  owl_filter_print(b, buff2);
355
356  if (!strcmp(buff, buff2)) return(1);
357  return(0);
358}
359
360void owl_filter_free(owl_filter *f) {
361  void (*func)();
362
363  func=&owl_filterelement_free;
364 
365  if (f->name) owl_free(f->name);
366  owl_list_free_all(&(f->fes), func);
367}
Note: See TracBrowser for help on using the repository browser.