source: filter.c @ 65fc0900

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