source: filter.c @ 7d4fbcd

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