source: filterelement.c @ d43edd2

release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since d43edd2 was d43edd2, checked in by Anders Kaseorg <andersk@mit.edu>, 9 years ago
Death to RCS keywords. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Property mode set to 100644
File size: 8.9 KB
Line 
1#include "owl.h"
2
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}
49
50static int owl_filterelement_match_false(owl_filterelement *fe, owl_message *m)
51{
52  return 0;
53}
54
55static int owl_filterelement_match_true(owl_filterelement *fe, owl_message *m)
56{
57  return 1;
58}
59
60static int owl_filterelement_match_re(owl_filterelement *fe, owl_message *m)
61{
62  char * val = owl_filterelement_get_field(m, fe->field);
63  return !owl_regex_compare(&(fe->re), val);
64}
65
66static int owl_filterelement_match_filter(owl_filterelement *fe, owl_message *m)
67{
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);
77}
78
79static int owl_filterelement_match_perl(owl_filterelement *fe, owl_message *m)
80{
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;
96}
97
98static int owl_filterelement_match_group(owl_filterelement *fe, owl_message *m)
99{
100  return owl_filterelement_match(fe->left, m);
101}
102
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)
108{
109  return owl_filterelement_match(fe->left, m) &&
110    owl_filterelement_match(fe->right, m);
111}
112
113static int owl_filterelement_match_or(owl_filterelement *fe, owl_message *m)
114{
115  return owl_filterelement_match(fe->left, m) ||
116    owl_filterelement_match(fe->right, m);
117}
118
119static int owl_filterelement_match_not(owl_filterelement *fe, owl_message *m)
120{
121  return !owl_filterelement_match(fe->left, m);
122}
123
124/* Print methods */
125
126static void owl_filterelement_print_true(owl_filterelement *fe, GString *buf)
127{
128  g_string_append(buf, "true");
129}
130
131static void owl_filterelement_print_false(owl_filterelement *fe, GString *buf)
132{
133  g_string_append(buf, "false");
134}
135
136static void owl_filterelement_print_re(owl_filterelement *fe, GString *buf)
137{
138  char *re, *q;
139  g_string_append(buf, fe->field);
140  g_string_append(buf, " ");
141
142  re = owl_regex_get_string(&(fe->re));
143  q = owl_getquoting(re);
144  g_string_append(buf, q);
145  g_string_append(buf, re);
146  g_string_append(buf, q);
147}
148
149static void owl_filterelement_print_filter(owl_filterelement *fe, GString *buf)
150{
151  g_string_append(buf, "filter ");
152  g_string_append(buf, fe->field);
153}
154
155static void owl_filterelement_print_perl(owl_filterelement *fe, GString *buf)
156{
157  g_string_append(buf, "perl ");
158  g_string_append(buf, fe->field);
159}
160
161static void owl_filterelement_print_group(owl_filterelement *fe, GString *buf)
162{
163  g_string_append(buf, "( ");
164  owl_filterelement_print(fe->left, buf) ;
165  g_string_append(buf, " )");
166}
167
168static void owl_filterelement_print_or(owl_filterelement *fe, GString *buf)
169{
170  owl_filterelement_print(fe->left, buf);
171  g_string_append(buf, " or ");
172  owl_filterelement_print(fe->right, buf);
173}
174
175static void owl_filterelement_print_and(owl_filterelement *fe, GString *buf)
176{
177  owl_filterelement_print(fe->left, buf);
178  g_string_append(buf, " and ");
179  owl_filterelement_print(fe->right, buf);
180}
181
182static void owl_filterelement_print_not(owl_filterelement *fe, GString *buf)
183{
184  g_string_append(buf, " not ");
185  owl_filterelement_print(fe->left, buf);
186}
187
188/* Constructors */
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));
196}
197
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)
207{
208  owl_filterelement_create(fe);
209  fe->match_message = owl_filterelement_match_false;
210  fe->print_elt = owl_filterelement_print_false;
211}
212
213int owl_filterelement_create_re(owl_filterelement *fe, char *field, char *re)
214{
215  owl_filterelement_create(fe);
216  fe->field=owl_strdup(field);
217  if(owl_regex_create(&(fe->re), re)) {
218    free(fe->field);
219    fe->field = NULL;
220    return (-1);
221  }
222  fe->match_message = owl_filterelement_match_re;
223  fe->print_elt = owl_filterelement_print_re;
224  return 0;
225}
226
227void owl_filterelement_create_filter(owl_filterelement *fe, char *name)
228{
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;
233}
234
235void owl_filterelement_create_perl(owl_filterelement *fe, char *name)
236{
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;
241}
242
243void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
244{
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;
249}
250
251void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
252{
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;
257}
258
259void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
260{
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;
266}
267
268void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
269{
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;
275}
276
277int owl_filterelement_match(owl_filterelement *fe, owl_message *m)
278{
279  if(!fe) return 0;
280  if(!fe->match_message) return 0;
281  return fe->match_message(fe, m);
282}
283
284static int fe_visiting = 0;
285static int fe_visited  = 1;
286
287int owl_filterelement_is_toodeep(owl_filter *f, owl_filterelement *fe)
288{
289  int rv;
290  owl_dict filters;
291  owl_dict_create(&filters);
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) {
311      f = owl_global_get_filter(&g, fe->field);
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);
315    }
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);
321  }
322  return rv;
323}
324
325void owl_filterelement_free(owl_filterelement *fe)
326{
327  if (fe->field) owl_free(fe->field);
328  if (fe->left) {
329    owl_filterelement_free(fe->left);
330    owl_free(fe->left);
331  }
332  if (fe->right) {
333    owl_filterelement_free(fe->right);
334    owl_free(fe->right);
335  }
336  owl_regex_free(&(fe->re));
337}
338
339void owl_filterelement_print(owl_filterelement *fe, GString *buf)
340{
341  if(!fe || !fe->print_elt) return;
342  fe->print_elt(fe, buf);
343}
Note: See TracBrowser for help on using the repository browser.