source: filterelement.c @ 21dc927

release-1.10release-1.8release-1.9
Last change on this file since 21dc927 was 7756dde, checked in by Jason Gross <jgross@mit.edu>, 13 years ago
Fix a typo in variable.c and a typo in filterelement.c
  • Property mode set to 100644
File size: 9.2 KB
Line 
1#include "owl.h"
2
3static const char * owl_filterelement_get_field(const owl_message *m, const char * field)
4{
5  const 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, "deleted")) {
25    match=owl_message_is_delete(m) ? "true" : "false";
26  } else if (!strcasecmp(field, "direction")) {
27    if (owl_message_is_direction_out(m)) {
28      match="out";
29    } else if (owl_message_is_direction_in(m)) {
30      match="in";
31    } else if (owl_message_is_direction_none(m)) {
32      match="none";
33    } else {
34      match="";
35    }
36  } else if (!strcasecmp(field, "login")) {
37    if (owl_message_is_login(m)) {
38      match="login";
39    } else if (owl_message_is_logout(m)) {
40      match="logout";
41    } else {
42      match="none";
43    }
44  } else {
45    match = owl_message_get_attribute_value(m,field);
46    if(match == NULL) match = "";
47  }
48
49  return match;
50}
51
52static int owl_filterelement_match_false(const owl_filterelement *fe, const owl_message *m)
53{
54  return 0;
55}
56
57static int owl_filterelement_match_true(const owl_filterelement *fe, const owl_message *m)
58{
59  return 1;
60}
61
62static int owl_filterelement_match_re(const owl_filterelement *fe, const owl_message *m)
63{
64  const char * val = owl_filterelement_get_field(m, fe->field);
65  return !owl_regex_compare(&(fe->re), val, NULL, NULL);
66}
67
68static int owl_filterelement_match_filter(const owl_filterelement *fe, const owl_message *m)
69{
70  const owl_filter *subfilter;
71  subfilter=owl_global_get_filter(&g, fe->field);
72  if (!subfilter) {
73    /* the filter does not exist, maybe because it was deleted.
74     * Default to not matching
75     */
76    return 0;
77  } 
78  return owl_filter_message_match(subfilter, m);
79}
80
81static int owl_filterelement_match_perl(const owl_filterelement *fe, const owl_message *m)
82{
83  const char *subname;
84  char *perlrv;
85  int   tf=0;
86
87  subname = fe->field;
88  if (!owl_perlconfig_is_function(subname)) {
89    return 0;
90  }
91  perlrv = owl_perlconfig_call_with_message(subname, m);
92  if (perlrv) {
93    if (0 == strcmp(perlrv, "1")) {
94      tf=1;
95    }
96    g_free(perlrv);
97  }
98  return tf;
99}
100
101static int owl_filterelement_match_group(const owl_filterelement *fe, const owl_message *m)
102{
103  return owl_filterelement_match(fe->left, m);
104}
105
106/* XXX: Our boolean operators short-circuit here. The original owl did
107   not. Do we care?
108*/
109
110static int owl_filterelement_match_and(const owl_filterelement *fe, const owl_message *m)
111{
112  return owl_filterelement_match(fe->left, m) &&
113    owl_filterelement_match(fe->right, m);
114}
115
116static int owl_filterelement_match_or(const owl_filterelement *fe, const owl_message *m)
117{
118  return owl_filterelement_match(fe->left, m) ||
119    owl_filterelement_match(fe->right, m);
120}
121
122static int owl_filterelement_match_not(const owl_filterelement *fe, const owl_message *m)
123{
124  return !owl_filterelement_match(fe->left, m);
125}
126
127/* Print methods */
128
129static void owl_filterelement_print_true(const owl_filterelement *fe, GString *buf)
130{
131  g_string_append(buf, "true");
132}
133
134static void owl_filterelement_print_false(const owl_filterelement *fe, GString *buf)
135{
136  g_string_append(buf, "false");
137}
138
139static void owl_filterelement_print_re(const owl_filterelement *fe, GString *buf)
140{
141  const char *re;
142  g_string_append(buf, fe->field);
143  g_string_append(buf, " ");
144
145  re = owl_regex_get_string(&(fe->re));
146  owl_string_append_quoted_arg(buf, re);
147}
148
149static void owl_filterelement_print_filter(const owl_filterelement *fe, GString *buf)
150{
151  g_string_append(buf, "filter ");
152  owl_string_append_quoted_arg(buf, fe->field);
153}
154
155static void owl_filterelement_print_perl(const owl_filterelement *fe, GString *buf)
156{
157  g_string_append(buf, "perl ");
158  owl_string_append_quoted_arg(buf, fe->field);
159}
160
161static void owl_filterelement_print_group(const 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(const 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(const 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(const 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, const char *field, const char *re)
214{
215  owl_filterelement_create(fe);
216  fe->field=g_strdup(field);
217  if(owl_regex_create(&(fe->re), re)) {
218    g_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, const char *name)
228{
229  owl_filterelement_create(fe);
230  fe->field=g_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, const char *name)
236{
237  owl_filterelement_create(fe);
238  fe->field=g_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(const owl_filterelement *fe, const 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(const owl_filter *f, const 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_delete);
294
295  rv = _owl_filterelement_is_toodeep(fe, &filters);
296
297  owl_dict_cleanup(&filters, NULL);
298  return rv;
299}
300
301int _owl_filterelement_is_toodeep(const owl_filterelement *fe, owl_dict *seen)
302{
303  int rv = 0;
304  const 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_delete);
313      if(f) rv = _owl_filterelement_is_toodeep(f->root, seen);
314      owl_dict_insert_element(seen, fe->field, &fe_visited, owl_dict_noop_delete);
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_cleanup(owl_filterelement *fe)
326{
327  if (fe->field) g_free(fe->field);
328  if (fe->left) {
329    owl_filterelement_cleanup(fe->left);
330    g_free(fe->left);
331  }
332  if (fe->right) {
333    owl_filterelement_cleanup(fe->right);
334    g_free(fe->right);
335  }
336  owl_regex_cleanup(&(fe->re));
337}
338
339void owl_filterelement_print(const 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.