source: filter.c @ 4b464a4

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