source: filter.c @ 0c502e9

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 0c502e9 was 0c502e9, checked in by James M. Kretchmar <kretch@mit.edu>, 17 years ago
Added filter field 'login' which can take the values 'login' 'logout' or 'none' Added the perl variable $owl::login, just as above Updated the 'login' and 'trash' filters appropriately Fix for checking for DES Bug fix in using makemsg when no curses window present
  • Property mode set to 100644
File size: 10.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    } else if (!strcasecmp(argv[i], "true")) {
52      owl_filterelement_create_true(fe);
53    } else if (!strcasecmp(argv[i], "false")) {
54      owl_filterelement_create_false(fe);
55     
56    } else if (i==argc-1) {
57      error=1;
58    } else {
59      if (!strcasecmp(argv[i], "class") ||
60          !strcasecmp(argv[i], "instance") ||
61          !strcasecmp(argv[i], "sender") ||
62          !strcasecmp(argv[i], "recipient") ||
63          !strcasecmp(argv[i], "body") ||
64          !strcasecmp(argv[i], "opcode") ||
65          !strcasecmp(argv[i], "realm") ||
66          !strcasecmp(argv[i], "type") ||
67          !strcasecmp(argv[i], "direction") ||
68          !strcasecmp(argv[i], "login")) {
69        regexstr=owl_util_substitute(argv[i+1], "%me%", ZGetSender());
70        owl_filterelement_create_re(fe, argv[i], regexstr);
71        owl_free(regexstr);
72        i++;
73      } else {
74        error=1;
75      }
76    }
77
78    if (!error) {
79      owl_list_append_element(&(f->fes), fe);
80    } else {
81      owl_free(fe);
82      owl_filter_free(f);
83      return(-1);
84    }
85
86  }
87  return(0);
88}
89
90char *owl_filter_get_name(owl_filter *f) {
91  return(f->name);
92}
93
94void owl_filter_set_polarity_match(owl_filter *f) {
95  f->polarity=0;
96}
97
98void owl_filter_set_polarity_unmatch(owl_filter *f) {
99  f->polarity=1;
100}
101
102void owl_filter_set_color(owl_filter *f, int color) {
103  f->color=color;
104}
105
106int owl_filter_get_color(owl_filter *f) {
107  return(f->color);
108}
109
110void owl_filter_set_cachedmsgid(owl_filter *f, int cachedmsgid) {
111  f->cachedmsgid=cachedmsgid;
112}
113
114int owl_filter_get_cachedmsgid(owl_filter *f) {
115  return(f->cachedmsgid);
116}
117
118int owl_filter_message_match(owl_filter *f, owl_message *m) {
119  int i, j, tmp;
120  owl_list work_fes, *fes;
121  owl_filterelement *fe;
122  char *field, *match;
123
124  /* create the working list of expression elements */
125  fes=&(f->fes);
126  owl_list_create(&work_fes);
127  j=owl_list_get_size(fes);
128  for (i=0; i<j; i++) {
129    owl_list_append_element(&work_fes, owl_list_get_element(fes, i));
130  }
131
132  /* first go thru and evaluate all RE elements to true or false */
133  match="";
134  for (i=0; i<j; i++) {
135    fe=owl_list_get_element(&work_fes, i);
136    if (!owl_filterelement_is_re(fe)) continue;
137    field=owl_filterelement_get_field(fe);
138    if (!strcasecmp(field, "class")) {
139      match=owl_message_get_class(m);
140    } else if (!strcasecmp(field, "instance")) {
141      match=owl_message_get_instance(m);
142    } else if (!strcasecmp(field, "sender")) {
143      match=owl_message_get_sender(m);
144    } else if (!strcasecmp(field, "recipient")) {
145      match=owl_message_get_recipient(m);
146    } else if (!strcasecmp(field, "body")) {
147      match=owl_message_get_body(m);
148    } else if (!strcasecmp(field, "opcode")) {
149      match=owl_message_get_opcode(m);
150    } else if (!strcasecmp(field, "realm")) {
151      match=owl_message_get_realm(m);
152    } else if (!strcasecmp(field, "type")) {
153      match=owl_message_type_to_string(m);
154    } else if (!strcasecmp(field, "direction")) {
155      if (owl_message_is_direction_out(m)) {
156        match="out";
157      } else if (owl_message_is_direction_in(m)) {
158        match="in";
159      } else if (owl_message_is_direction_none(m)) {
160        match="none";
161      } else {
162        match="";
163      }
164    } else if (!strcasecmp(field, "login")) {
165      if (owl_message_is_login(m)) {
166        match="login";
167      } else if (owl_message_is_logout(m)) {
168        match="logout";
169      } else {
170        match="none";
171      }
172    }
173   
174    tmp=owl_regex_compare(owl_filterelement_get_re(fe), match);
175    if (!tmp) {
176      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
177    } else {
178      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
179    }
180  }
181
182  /* call the recrsive helper */
183  i=_owl_filter_message_match_recurse(f, m, &work_fes, 0, owl_list_get_size(&(f->fes))-1);
184
185  /* now there will be only one TRUE / FALSE, find it among the NULL's */
186  tmp=0;
187  for (i=0; i<j; i++) {
188    fe=owl_list_get_element(&work_fes, i);
189    if (owl_filterelement_is_null(fe)) continue;
190    if (owl_filterelement_is_true(fe)) {
191      tmp=1;
192      break;
193    }
194    if (owl_filterelement_is_false(fe)) {
195      tmp=0;
196      break;
197    }
198  } 
199
200  /* reverse the answer if negative polarity is in use */
201  if (f->polarity) tmp=!tmp;
202
203  owl_list_free_simple(&work_fes);
204  return(tmp);
205}
206
207int _owl_filter_message_match_recurse(owl_filter *f, owl_message *m, owl_list *fes, int start, int end) {
208  int a=0, b=0, i, x, y, z, score, ret, type;
209  owl_filterelement *fe, *tmpfe=NULL;
210
211  /* Deal with parens first. */
212  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
213    /* Find first open paren and matching close paren, store in x, y */
214    score=x=y=0;
215    for (i=start; i<=end; i++) {
216      fe=owl_list_get_element(fes, i);
217      if (owl_filterelement_is_openbrace(fe)) {
218        if (score==0) x=i;
219        score++;
220      } else if (owl_filterelement_is_closebrace(fe)) {
221        score--;
222        if (score<0) {
223          /* unblanaced parens */
224          return(-1);
225        } else if (score==0) {
226          y=i; /* this is the matching close paren */
227          break;
228        }
229      }
230    }
231    if (score>0) {
232      /* unblanaced parens */
233      return(-1);
234    }
235
236    /* Simply the parens by removing them and evaluating what was in between */
237    if (y>0) {
238      /* null out the parens */
239      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
240      owl_list_replace_element(fes, y, owl_global_get_filterelement_null(&g));
241
242      /* evaluate expression in between */
243      ret=_owl_filter_message_match_recurse(f, m, fes, x+1, y-1);
244      if (ret<0) return(-1);
245
246      /* there may be more, so we continue */
247      continue;
248    } else {
249      /* otherwise we're done with this part */
250      break;
251    }
252  }
253  if (i==OWL_FILTER_MAX_DEPTH) {
254    /* hit the saftey limit, consider it invalid */
255    return(-1);
256  }
257
258  /* Find AND / OR / NOT.
259   *   For binary expressions (AND/OR):
260   *     "type" is 1
261   *     "x" will index first val, "y" the operator and "z" the second val
262   *   For unary expressions (NOT):
263   *     "type" is 2
264   *     "x" will index the operator, "y" the value
265   *   "score" tallys how many expression elements have been found so far
266   */
267  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
268    type=score=x=y=z=0;
269    for (i=start; i<=end; i++) {
270      fe=owl_list_get_element(fes, i);
271      if (owl_filterelement_is_null(fe)) continue;
272      if (score==0) {
273        if (owl_filterelement_is_value(fe)) {
274          x=i;
275          score=1;
276          type=1;
277        } else if (owl_filterelement_is_not(fe)) {
278          x=i;
279          score=1;
280          type=2;
281        }
282      } else if (score==1) {
283        if (type==1) {
284          if (owl_filterelement_is_and(fe) || owl_filterelement_is_or(fe)) {
285            score=2;
286            y=i;
287          } else {
288            /* it's not a valid binary expression */
289            x=y=z=score=0;
290          }
291        } else if (type==2) {
292          if (owl_filterelement_is_value(fe)) {
293            /* valid unary expression, we're done */
294            y=i;
295            break;
296          }
297        }
298      } else if (score==2) {
299        if (owl_filterelement_is_value(fe)) {
300          /* valid binary expression, we're done */
301          z=i;
302          break;
303        } else {
304          x=y=z=score=0;
305        }
306      }
307    }
308
309    /* simplify AND / OR */
310    if ((type==1) && (z>0)) {
311      fe=owl_list_get_element(fes, x);
312      if (owl_filterelement_is_true(fe)) {
313        a=1;
314      } else if (owl_filterelement_is_false(fe)) {
315        a=0;
316      }
317
318      fe=owl_list_get_element(fes, z);
319      if (owl_filterelement_is_true(fe)) {
320        b=1;
321      } else if (owl_filterelement_is_false(fe)) {
322        b=0;
323      }
324
325      fe=owl_list_get_element(fes, y);
326      if (owl_filterelement_is_and(fe)) {
327        if (a && b) {
328          tmpfe=owl_global_get_filterelement_true(&g);
329        } else {
330          tmpfe=owl_global_get_filterelement_false(&g);
331        }
332      } else if (owl_filterelement_is_or(fe)) {
333        if (a || b) {
334          tmpfe=owl_global_get_filterelement_true(&g);
335        } else {
336          tmpfe=owl_global_get_filterelement_false(&g);
337        }
338      }
339      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
340      owl_list_replace_element(fes, y, tmpfe);
341      owl_list_replace_element(fes, z, owl_global_get_filterelement_null(&g));
342    } else if ((type==2) && (y>0)) {
343      /* simplify NOT */
344      fe=owl_list_get_element(fes, y);
345      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
346      if (owl_filterelement_is_false(fe)) {
347        owl_list_replace_element(fes, y, owl_global_get_filterelement_true(&g));
348      } else {
349        owl_list_replace_element(fes, y, owl_global_get_filterelement_false(&g));
350      }
351    } else {
352      break;
353    }
354  }
355  return(0);
356
357}
358
359void owl_filter_print(owl_filter *f, char *out) {
360  int i, j;
361  owl_filterelement *fe;
362  char *tmp;
363
364  strcpy(out, owl_filter_get_name(f));
365  strcat(out, ": ");
366
367  if (f->color!=OWL_COLOR_DEFAULT) {
368    strcat(out, "-c ");
369    strcat(out, owl_util_color_to_string(f->color));
370    strcat(out, " ");
371  }
372
373  j=owl_list_get_size(&(f->fes));
374  for (i=0; i<j; i++) {
375    fe=owl_list_get_element(&(f->fes), i);
376    tmp=owl_filterelement_to_string(fe);
377    strcat(out, tmp);
378    owl_free(tmp);
379  }
380  strcat(out, "\n");
381}
382
383int owl_filter_equiv(owl_filter *a, owl_filter *b) {
384  char buff[LINE], buff2[LINE];
385
386  owl_filter_print(a, buff);
387  owl_filter_print(b, buff2);
388
389  if (!strcmp(buff, buff2)) return(1);
390  return(0);
391}
392
393void owl_filter_free(owl_filter *f) {
394  void (*func)();
395
396  func=&owl_filterelement_free;
397 
398  if (f->name) owl_free(f->name);
399  owl_list_free_all(&(f->fes), func);
400}
Note: See TracBrowser for help on using the repository browser.