source: filterelement.c @ ab225e0

release-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since ab225e0 was d43edd2, checked in by Anders Kaseorg <andersk@mit.edu>, 15 years ago
Death to RCS keywords. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Property mode set to 100644
File size: 8.9 KB
RevLine 
[7d4fbcd]1#include "owl.h"
2
[cb769bb]3static char * owl_filterelement_get_field(owl_message *m, char * field)
4{
5  char *match;
6  if (!strcasecmp(field, "class")) {
7    match=owl_message_get_class(m);
8  } else if (!strcasecmp(field, "instance")) {
9    match=owl_message_get_instance(m);
10  } else if (!strcasecmp(field, "sender")) {
11    match=owl_message_get_sender(m);
12  } else if (!strcasecmp(field, "recipient")) {
13    match=owl_message_get_recipient(m);
14  } else if (!strcasecmp(field, "body")) {
15    match=owl_message_get_body(m);
16  } else if (!strcasecmp(field, "opcode")) {
17    match=owl_message_get_opcode(m);
18  } else if (!strcasecmp(field, "realm")) {
19    match=owl_message_get_realm(m);
20  } else if (!strcasecmp(field, "type")) {
21    match=owl_message_get_type(m);
22  } else if (!strcasecmp(field, "hostname")) {
23    match=owl_message_get_hostname(m);
24  } else if (!strcasecmp(field, "direction")) {
25    if (owl_message_is_direction_out(m)) {
26      match="out";
27    } else if (owl_message_is_direction_in(m)) {
28      match="in";
29    } else if (owl_message_is_direction_none(m)) {
30      match="none";
31    } else {
32      match="";
33    }
34  } else if (!strcasecmp(field, "login")) {
35    if (owl_message_is_login(m)) {
36      match="login";
37    } else if (owl_message_is_logout(m)) {
38      match="logout";
39    } else {
40      match="none";
41    }
42  } else {
43    match = owl_message_get_attribute_value(m,field);
44    if(match == NULL) match = "";
45  }
46
47  return match;
48}
[7d4fbcd]49
[cb769bb]50static int owl_filterelement_match_false(owl_filterelement *fe, owl_message *m)
[e187445]51{
[cb769bb]52  return 0;
[7d4fbcd]53}
54
[cb769bb]55static int owl_filterelement_match_true(owl_filterelement *fe, owl_message *m)
[e187445]56{
[cb769bb]57  return 1;
[7d4fbcd]58}
59
[cb769bb]60static int owl_filterelement_match_re(owl_filterelement *fe, owl_message *m)
[e187445]61{
[cb769bb]62  char * val = owl_filterelement_get_field(m, fe->field);
63  return !owl_regex_compare(&(fe->re), val);
[7d4fbcd]64}
65
[cb769bb]66static int owl_filterelement_match_filter(owl_filterelement *fe, owl_message *m)
[e187445]67{
[cb769bb]68  owl_filter *subfilter;
69  subfilter=owl_global_get_filter(&g, fe->field);
70  if (!subfilter) {
71    /* the filter does not exist, maybe because it was deleted.
72     * Default to not matching
73     */
74    return 0;
75  } 
76  return owl_filter_message_match(subfilter, m);
[7d4fbcd]77}
78
[cb769bb]79static int owl_filterelement_match_perl(owl_filterelement *fe, owl_message *m)
[e187445]80{
[cb769bb]81  char *subname, *perlrv;
82  int   tf=0;
83
84  subname = fe->field;
85  if (!owl_perlconfig_is_function(subname)) {
86    return 0;
87  }
88  perlrv = owl_perlconfig_call_with_message(subname, m);
89  if (perlrv) {
90    if (0 == strcmp(perlrv, "1")) {
91      tf=1;
92    }
93    owl_free(perlrv);
94  }
95  return tf;
[7d4fbcd]96}
97
[cb769bb]98static int owl_filterelement_match_group(owl_filterelement *fe, owl_message *m)
[e187445]99{
[cb769bb]100  return owl_filterelement_match(fe->left, m);
[7d4fbcd]101}
102
[cb769bb]103/* XXX: Our boolea operators short-circuit here. The original owl did
104   not. Do we care?
105*/
106
107static int owl_filterelement_match_and(owl_filterelement *fe, owl_message *m)
[e187445]108{
[cb769bb]109  return owl_filterelement_match(fe->left, m) &&
110    owl_filterelement_match(fe->right, m);
[7d4fbcd]111}
112
[cb769bb]113static int owl_filterelement_match_or(owl_filterelement *fe, owl_message *m)
[e187445]114{
[cb769bb]115  return owl_filterelement_match(fe->left, m) ||
116    owl_filterelement_match(fe->right, m);
[7d4fbcd]117}
118
[cb769bb]119static int owl_filterelement_match_not(owl_filterelement *fe, owl_message *m)
[e187445]120{
[cb769bb]121  return !owl_filterelement_match(fe->left, m);
[7d4fbcd]122}
[5616acc]123
[af1920fd]124/* Print methods */
[cb769bb]125
[0504f63]126static void owl_filterelement_print_true(owl_filterelement *fe, GString *buf)
[40458b9]127{
[0504f63]128  g_string_append(buf, "true");
[40458b9]129}
130
[0504f63]131static void owl_filterelement_print_false(owl_filterelement *fe, GString *buf)
[32eed98]132{
[0504f63]133  g_string_append(buf, "false");
[32eed98]134}
135
[0504f63]136static void owl_filterelement_print_re(owl_filterelement *fe, GString *buf)
[e187445]137{
[81655f8]138  char *re, *q;
[0504f63]139  g_string_append(buf, fe->field);
140  g_string_append(buf, " ");
[81655f8]141
142  re = owl_regex_get_string(&(fe->re));
143  q = owl_getquoting(re);
[0504f63]144  g_string_append(buf, q);
145  g_string_append(buf, re);
146  g_string_append(buf, q);
[cb769bb]147}
148
[0504f63]149static void owl_filterelement_print_filter(owl_filterelement *fe, GString *buf)
[cb769bb]150{
[0504f63]151  g_string_append(buf, "filter ");
152  g_string_append(buf, fe->field);
[cb769bb]153}
154
[0504f63]155static void owl_filterelement_print_perl(owl_filterelement *fe, GString *buf)
[cb769bb]156{
[0504f63]157  g_string_append(buf, "perl ");
158  g_string_append(buf, fe->field);
[7d4fbcd]159}
160
[0504f63]161static void owl_filterelement_print_group(owl_filterelement *fe, GString *buf)
[e187445]162{
[0504f63]163  g_string_append(buf, "( ");
[cb769bb]164  owl_filterelement_print(fe->left, buf) ;
[0504f63]165  g_string_append(buf, " )");
[7d4fbcd]166}
167
[0504f63]168static void owl_filterelement_print_or(owl_filterelement *fe, GString *buf)
[e187445]169{
[cb769bb]170  owl_filterelement_print(fe->left, buf);
[0504f63]171  g_string_append(buf, " or ");
[cb769bb]172  owl_filterelement_print(fe->right, buf);
[7d4fbcd]173}
174
[0504f63]175static void owl_filterelement_print_and(owl_filterelement *fe, GString *buf)
[e187445]176{
[cb769bb]177  owl_filterelement_print(fe->left, buf);
[0504f63]178  g_string_append(buf, " and ");
[cb769bb]179  owl_filterelement_print(fe->right, buf);
[7d4fbcd]180}
181
[0504f63]182static void owl_filterelement_print_not(owl_filterelement *fe, GString *buf)
[e187445]183{
[0504f63]184  g_string_append(buf, " not ");
[cb769bb]185  owl_filterelement_print(fe->left, buf);
186}
187
[af1920fd]188/* Constructors */
[cb769bb]189
190void owl_filterelement_create(owl_filterelement *fe) {
191  fe->field = NULL;
192  fe->left = fe->right = NULL;
193  fe->match_message = NULL;
194  fe->print_elt = NULL;
195  owl_regex_init(&(fe->re));
[7d4fbcd]196}
197
[cb769bb]198
199void owl_filterelement_create_true(owl_filterelement *fe)
200{
201  owl_filterelement_create(fe);
202  fe->match_message = owl_filterelement_match_true;
203  fe->print_elt = owl_filterelement_print_true;
204}
205
206void owl_filterelement_create_false(owl_filterelement *fe)
[e187445]207{
[cb769bb]208  owl_filterelement_create(fe);
209  fe->match_message = owl_filterelement_match_false;
210  fe->print_elt = owl_filterelement_print_false;
[7d4fbcd]211}
212
[e6a4dd5]213int owl_filterelement_create_re(owl_filterelement *fe, char *field, char *re)
[e187445]214{
[cb769bb]215  owl_filterelement_create(fe);
216  fe->field=owl_strdup(field);
[e6a4dd5]217  if(owl_regex_create(&(fe->re), re)) {
218    free(fe->field);
219    fe->field = NULL;
220    return (-1);
221  }
[cb769bb]222  fe->match_message = owl_filterelement_match_re;
223  fe->print_elt = owl_filterelement_print_re;
[e6a4dd5]224  return 0;
[7d4fbcd]225}
226
[cb769bb]227void owl_filterelement_create_filter(owl_filterelement *fe, char *name)
[e187445]228{
[cb769bb]229  owl_filterelement_create(fe);
230  fe->field=owl_strdup(name);
231  fe->match_message = owl_filterelement_match_filter;
232  fe->print_elt = owl_filterelement_print_filter;
[7d4fbcd]233}
234
[cb769bb]235void owl_filterelement_create_perl(owl_filterelement *fe, char *name)
[e187445]236{
[cb769bb]237  owl_filterelement_create(fe);
238  fe->field=owl_strdup(name);
239  fe->match_message = owl_filterelement_match_perl;
240  fe->print_elt = owl_filterelement_print_perl;
[7d4fbcd]241}
242
[cb769bb]243void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
[e187445]244{
[cb769bb]245  owl_filterelement_create(fe);
246  fe->left = in;
247  fe->match_message = owl_filterelement_match_group;
248  fe->print_elt = owl_filterelement_print_group;
[7d4fbcd]249}
250
[cb769bb]251void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
[32eed98]252{
[cb769bb]253  owl_filterelement_create(fe);
254  fe->left = in;
255  fe->match_message = owl_filterelement_match_not;
256  fe->print_elt = owl_filterelement_print_not;
[32eed98]257}
258
[cb769bb]259void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
[e187445]260{
[cb769bb]261  owl_filterelement_create(fe);
262  fe->left = lhs;
263  fe->right = rhs;
264  fe->match_message = owl_filterelement_match_and;
265  fe->print_elt = owl_filterelement_print_and;
[7d4fbcd]266}
267
[cb769bb]268void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
[40458b9]269{
[cb769bb]270  owl_filterelement_create(fe);
271  fe->left = lhs;
272  fe->right = rhs;
273  fe->match_message = owl_filterelement_match_or;
274  fe->print_elt = owl_filterelement_print_or;
[40458b9]275}
276
[cb769bb]277int owl_filterelement_match(owl_filterelement *fe, owl_message *m)
[e187445]278{
[cb769bb]279  if(!fe) return 0;
280  if(!fe->match_message) return 0;
281  return fe->match_message(fe, m);
[40458b9]282}
283
[f446454]284static int fe_visiting = 0;
285static int fe_visited  = 1;
286
[cb769bb]287int owl_filterelement_is_toodeep(owl_filter *f, owl_filterelement *fe)
[40458b9]288{
[f446454]289  int rv;
[cb769bb]290  owl_dict filters;
291  owl_dict_create(&filters);
[f446454]292
293  owl_dict_insert_element(&filters, f->name, &fe_visiting, owl_dict_noop_free);
294
295  rv = _owl_filterelement_is_toodeep(fe, &filters);
296
297  owl_dict_free_simple(&filters);
298  return rv;
299}
300
301int _owl_filterelement_is_toodeep(owl_filterelement *fe, owl_dict *seen)
302{
303  int rv = 0;
304  owl_filter *f;
305
306  if(fe->match_message == owl_filterelement_match_filter) {
307    int *nval = owl_dict_find_element(seen, fe->field);
308    if(nval == &fe_visiting) {
309      return 1;
310    } else if (nval == NULL) {
[cb769bb]311      f = owl_global_get_filter(&g, fe->field);
[f446454]312      owl_dict_insert_element(seen, fe->field, &fe_visiting, owl_dict_noop_free);
313      if(f) rv = _owl_filterelement_is_toodeep(f->root, seen);
314      owl_dict_insert_element(seen, fe->field, &fe_visited, owl_dict_noop_free);
[cb769bb]315    }
[f446454]316  } else {
317    if(fe->left)
318      rv = rv || _owl_filterelement_is_toodeep(fe->left, seen);
319    if(fe->right)
320      rv = rv || _owl_filterelement_is_toodeep(fe->right, seen);
[cb769bb]321  }
[f446454]322  return rv;
[7d4fbcd]323}
324
[cb769bb]325void owl_filterelement_free(owl_filterelement *fe)
[e187445]326{
[cb769bb]327  if (fe->field) owl_free(fe->field);
328  if (fe->left) {
329    owl_filterelement_free(fe->left);
330    owl_free(fe->left);
[7d4fbcd]331  }
[cb769bb]332  if (fe->right) {
333    owl_filterelement_free(fe->right);
334    owl_free(fe->right);
[7d4fbcd]335  }
[cb769bb]336  owl_regex_free(&(fe->re));
337}
[40458b9]338
[0504f63]339void owl_filterelement_print(owl_filterelement *fe, GString *buf)
[cb769bb]340{
341  if(!fe || !fe->print_elt) return;
342  fe->print_elt(fe, buf);
[7d4fbcd]343}
Note: See TracBrowser for help on using the repository browser.