source: filterelement.c @ 41c9a96

release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 41c9a96 was 41c9a96, checked in by Anders Kaseorg <andersk@mit.edu>, 12 years ago
Reimplement search in terms of owl_regex. The current implementation of stristr has problems and there isn’t a good replacement available. This was its only caller, so we can get rid of it now. Also, this will make it possible to search with arbitrary regexes if someone feels like coming up with a syntax. 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, NULL, NULL);
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.