source: filterelement.c @ 5cbc929

release-1.6release-1.7release-1.8release-1.9
Last change on this file since 5cbc929 was 5cbc929, checked in by Anders Kaseorg <andersk@mit.edu>, 9 years ago
Rename owl_regex_free to owl_regex_cleanup. Signed-off-by: Anders Kaseorg <andersk@mit.edu> Reviewed-by: Nelson Elhage <nelhage@mit.edu>
  • 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, "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(const owl_filterelement *fe, const owl_message *m)
51{
52  return 0;
53}
54
55static int owl_filterelement_match_true(const owl_filterelement *fe, const owl_message *m)
56{
57  return 1;
58}
59
60static int owl_filterelement_match_re(const owl_filterelement *fe, const owl_message *m)
61{
62  const char * val = owl_filterelement_get_field(m, fe->field);
63  return !owl_regex_compare(&(fe->re), val, NULL, NULL);
64}
65
66static int owl_filterelement_match_filter(const owl_filterelement *fe, const owl_message *m)
67{
68  const 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(const owl_filterelement *fe, const owl_message *m)
80{
81  const char *subname;
82  char *perlrv;
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;
97}
98
99static int owl_filterelement_match_group(const owl_filterelement *fe, const owl_message *m)
100{
101  return owl_filterelement_match(fe->left, m);
102}
103
104/* XXX: Our boolea operators short-circuit here. The original owl did
105   not. Do we care?
106*/
107
108static int owl_filterelement_match_and(const owl_filterelement *fe, const owl_message *m)
109{
110  return owl_filterelement_match(fe->left, m) &&
111    owl_filterelement_match(fe->right, m);
112}
113
114static int owl_filterelement_match_or(const owl_filterelement *fe, const owl_message *m)
115{
116  return owl_filterelement_match(fe->left, m) ||
117    owl_filterelement_match(fe->right, m);
118}
119
120static int owl_filterelement_match_not(const owl_filterelement *fe, const owl_message *m)
121{
122  return !owl_filterelement_match(fe->left, m);
123}
124
125/* Print methods */
126
127static void owl_filterelement_print_true(const owl_filterelement *fe, GString *buf)
128{
129  g_string_append(buf, "true");
130}
131
132static void owl_filterelement_print_false(const owl_filterelement *fe, GString *buf)
133{
134  g_string_append(buf, "false");
135}
136
137static void owl_filterelement_print_re(const owl_filterelement *fe, GString *buf)
138{
139  const char *re, *q;
140  g_string_append(buf, fe->field);
141  g_string_append(buf, " ");
142
143  re = owl_regex_get_string(&(fe->re));
144  q = owl_getquoting(re);
145  g_string_append(buf, q);
146  g_string_append(buf, re);
147  g_string_append(buf, q);
148}
149
150static void owl_filterelement_print_filter(const owl_filterelement *fe, GString *buf)
151{
152  g_string_append(buf, "filter ");
153  g_string_append(buf, fe->field);
154}
155
156static void owl_filterelement_print_perl(const owl_filterelement *fe, GString *buf)
157{
158  g_string_append(buf, "perl ");
159  g_string_append(buf, fe->field);
160}
161
162static void owl_filterelement_print_group(const owl_filterelement *fe, GString *buf)
163{
164  g_string_append(buf, "( ");
165  owl_filterelement_print(fe->left, buf) ;
166  g_string_append(buf, " )");
167}
168
169static void owl_filterelement_print_or(const owl_filterelement *fe, GString *buf)
170{
171  owl_filterelement_print(fe->left, buf);
172  g_string_append(buf, " or ");
173  owl_filterelement_print(fe->right, buf);
174}
175
176static void owl_filterelement_print_and(const owl_filterelement *fe, GString *buf)
177{
178  owl_filterelement_print(fe->left, buf);
179  g_string_append(buf, " and ");
180  owl_filterelement_print(fe->right, buf);
181}
182
183static void owl_filterelement_print_not(const owl_filterelement *fe, GString *buf)
184{
185  g_string_append(buf, " not ");
186  owl_filterelement_print(fe->left, buf);
187}
188
189/* Constructors */
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));
197}
198
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)
208{
209  owl_filterelement_create(fe);
210  fe->match_message = owl_filterelement_match_false;
211  fe->print_elt = owl_filterelement_print_false;
212}
213
214int owl_filterelement_create_re(owl_filterelement *fe, const char *field, const char *re)
215{
216  owl_filterelement_create(fe);
217  fe->field=owl_strdup(field);
218  if(owl_regex_create(&(fe->re), re)) {
219    owl_free(fe->field);
220    fe->field = NULL;
221    return (-1);
222  }
223  fe->match_message = owl_filterelement_match_re;
224  fe->print_elt = owl_filterelement_print_re;
225  return 0;
226}
227
228void owl_filterelement_create_filter(owl_filterelement *fe, const char *name)
229{
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;
234}
235
236void owl_filterelement_create_perl(owl_filterelement *fe, const char *name)
237{
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;
242}
243
244void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
245{
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;
250}
251
252void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
253{
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;
258}
259
260void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
261{
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;
267}
268
269void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
270{
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;
276}
277
278int owl_filterelement_match(const owl_filterelement *fe, const owl_message *m)
279{
280  if(!fe) return 0;
281  if(!fe->match_message) return 0;
282  return fe->match_message(fe, m);
283}
284
285static int fe_visiting = 0;
286static int fe_visited  = 1;
287
288int owl_filterelement_is_toodeep(const owl_filter *f, const owl_filterelement *fe)
289{
290  int rv;
291  owl_dict filters;
292  owl_dict_create(&filters);
293
294  owl_dict_insert_element(&filters, f->name, &fe_visiting, owl_dict_noop_delete);
295
296  rv = _owl_filterelement_is_toodeep(fe, &filters);
297
298  owl_dict_cleanup(&filters, NULL);
299  return rv;
300}
301
302int _owl_filterelement_is_toodeep(const owl_filterelement *fe, owl_dict *seen)
303{
304  int rv = 0;
305  const owl_filter *f;
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) {
312      f = owl_global_get_filter(&g, fe->field);
313      owl_dict_insert_element(seen, fe->field, &fe_visiting, owl_dict_noop_delete);
314      if(f) rv = _owl_filterelement_is_toodeep(f->root, seen);
315      owl_dict_insert_element(seen, fe->field, &fe_visited, owl_dict_noop_delete);
316    }
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);
322  }
323  return rv;
324}
325
326void owl_filterelement_free(owl_filterelement *fe)
327{
328  if (fe->field) owl_free(fe->field);
329  if (fe->left) {
330    owl_filterelement_free(fe->left);
331    owl_free(fe->left);
332  }
333  if (fe->right) {
334    owl_filterelement_free(fe->right);
335    owl_free(fe->right);
336  }
337  owl_regex_cleanup(&(fe->re));
338}
339
340void owl_filterelement_print(const owl_filterelement *fe, GString *buf)
341{
342  if(!fe || !fe->print_elt) return;
343  fe->print_elt(fe, buf);
344}
Note: See TracBrowser for help on using the repository browser.