source: filter.c @ 61d27fb

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