source: filterelement.c @ fb2f9ab

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