source: filterelement.c @ e6a4dd5

debianrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since e6a4dd5 was e6a4dd5, checked in by Nelson Elhage <nelhage@mit.edu>, 9 years ago
Propagate regex compile failures out of filter creation. Make calls to owl_filter_init_fromstring fail if the filter includes an illegal regex (e.g. an initial *), by having owl_filterelement_create_re return an error code which propagates up. This fixes an issue where a command like 'unpunt class *' would segfault because it succeeds in creating the invalid filter, but then fails to print it successfully. fixes: #70
  • Property mode set to 100644
File size: 8.9 KB
Line 
1#include "owl.h"
2
3static const char fileIdent[] = "$Id$";
4
5static char * owl_filterelement_get_field(owl_message *m, char * field)
6{
7  char *match;
8  if (!strcasecmp(field, "class")) {
9    match=owl_message_get_class(m);
10  } else if (!strcasecmp(field, "instance")) {
11    match=owl_message_get_instance(m);
12  } else if (!strcasecmp(field, "sender")) {
13    match=owl_message_get_sender(m);
14  } else if (!strcasecmp(field, "recipient")) {
15    match=owl_message_get_recipient(m);
16  } else if (!strcasecmp(field, "body")) {
17    match=owl_message_get_body(m);
18  } else if (!strcasecmp(field, "opcode")) {
19    match=owl_message_get_opcode(m);
20  } else if (!strcasecmp(field, "realm")) {
21    match=owl_message_get_realm(m);
22  } else if (!strcasecmp(field, "type")) {
23    match=owl_message_get_type(m);
24  } else if (!strcasecmp(field, "hostname")) {
25    match=owl_message_get_hostname(m);
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(owl_filterelement *fe, owl_message *m)
53{
54  return 0;
55}
56
57static int owl_filterelement_match_true(owl_filterelement *fe, owl_message *m)
58{
59  return 1;
60}
61
62static int owl_filterelement_match_re(owl_filterelement *fe, owl_message *m)
63{
64  char * val = owl_filterelement_get_field(m, fe->field);
65  return !owl_regex_compare(&(fe->re), val);
66}
67
68static int owl_filterelement_match_filter(owl_filterelement *fe, owl_message *m)
69{
70  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(owl_filterelement *fe, owl_message *m)
82{
83  char *subname, *perlrv;
84  int   tf=0;
85
86  subname = fe->field;
87  if (!owl_perlconfig_is_function(subname)) {
88    return 0;
89  }
90  perlrv = owl_perlconfig_call_with_message(subname, m);
91  if (perlrv) {
92    if (0 == strcmp(perlrv, "1")) {
93      tf=1;
94    }
95    owl_free(perlrv);
96  }
97  return tf;
98}
99
100static int owl_filterelement_match_group(owl_filterelement *fe, owl_message *m)
101{
102  return owl_filterelement_match(fe->left, m);
103}
104
105/* XXX: Our boolea operators short-circuit here. The original owl did
106   not. Do we care?
107*/
108
109static int owl_filterelement_match_and(owl_filterelement *fe, owl_message *m)
110{
111  return owl_filterelement_match(fe->left, m) &&
112    owl_filterelement_match(fe->right, m);
113}
114
115static int owl_filterelement_match_or(owl_filterelement *fe, owl_message *m)
116{
117  return owl_filterelement_match(fe->left, m) ||
118    owl_filterelement_match(fe->right, m);
119}
120
121static int owl_filterelement_match_not(owl_filterelement *fe, owl_message *m)
122{
123  return !owl_filterelement_match(fe->left, m);
124}
125
126/* Print methods */
127
128static void owl_filterelement_print_true(owl_filterelement *fe, GString *buf)
129{
130  g_string_append(buf, "true");
131}
132
133static void owl_filterelement_print_false(owl_filterelement *fe, GString *buf)
134{
135  g_string_append(buf, "false");
136}
137
138static void owl_filterelement_print_re(owl_filterelement *fe, GString *buf)
139{
140  char *re, *q;
141  g_string_append(buf, fe->field);
142  g_string_append(buf, " ");
143
144  re = owl_regex_get_string(&(fe->re));
145  q = owl_getquoting(re);
146  g_string_append(buf, q);
147  g_string_append(buf, re);
148  g_string_append(buf, q);
149}
150
151static void owl_filterelement_print_filter(owl_filterelement *fe, GString *buf)
152{
153  g_string_append(buf, "filter ");
154  g_string_append(buf, fe->field);
155}
156
157static void owl_filterelement_print_perl(owl_filterelement *fe, GString *buf)
158{
159  g_string_append(buf, "perl ");
160  g_string_append(buf, fe->field);
161}
162
163static void owl_filterelement_print_group(owl_filterelement *fe, GString *buf)
164{
165  g_string_append(buf, "( ");
166  owl_filterelement_print(fe->left, buf) ;
167  g_string_append(buf, " )");
168}
169
170static void owl_filterelement_print_or(owl_filterelement *fe, GString *buf)
171{
172  owl_filterelement_print(fe->left, buf);
173  g_string_append(buf, " or ");
174  owl_filterelement_print(fe->right, buf);
175}
176
177static void owl_filterelement_print_and(owl_filterelement *fe, GString *buf)
178{
179  owl_filterelement_print(fe->left, buf);
180  g_string_append(buf, " and ");
181  owl_filterelement_print(fe->right, buf);
182}
183
184static void owl_filterelement_print_not(owl_filterelement *fe, GString *buf)
185{
186  g_string_append(buf, " not ");
187  owl_filterelement_print(fe->left, buf);
188}
189
190/* Constructors */
191
192void owl_filterelement_create(owl_filterelement *fe) {
193  fe->field = NULL;
194  fe->left = fe->right = NULL;
195  fe->match_message = NULL;
196  fe->print_elt = NULL;
197  owl_regex_init(&(fe->re));
198}
199
200
201void owl_filterelement_create_true(owl_filterelement *fe)
202{
203  owl_filterelement_create(fe);
204  fe->match_message = owl_filterelement_match_true;
205  fe->print_elt = owl_filterelement_print_true;
206}
207
208void owl_filterelement_create_false(owl_filterelement *fe)
209{
210  owl_filterelement_create(fe);
211  fe->match_message = owl_filterelement_match_false;
212  fe->print_elt = owl_filterelement_print_false;
213}
214
215int owl_filterelement_create_re(owl_filterelement *fe, char *field, char *re)
216{
217  owl_filterelement_create(fe);
218  fe->field=owl_strdup(field);
219  if(owl_regex_create(&(fe->re), re)) {
220    free(fe->field);
221    fe->field = NULL;
222    return (-1);
223  }
224  fe->match_message = owl_filterelement_match_re;
225  fe->print_elt = owl_filterelement_print_re;
226  return 0;
227}
228
229void owl_filterelement_create_filter(owl_filterelement *fe, char *name)
230{
231  owl_filterelement_create(fe);
232  fe->field=owl_strdup(name);
233  fe->match_message = owl_filterelement_match_filter;
234  fe->print_elt = owl_filterelement_print_filter;
235}
236
237void owl_filterelement_create_perl(owl_filterelement *fe, char *name)
238{
239  owl_filterelement_create(fe);
240  fe->field=owl_strdup(name);
241  fe->match_message = owl_filterelement_match_perl;
242  fe->print_elt = owl_filterelement_print_perl;
243}
244
245void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
246{
247  owl_filterelement_create(fe);
248  fe->left = in;
249  fe->match_message = owl_filterelement_match_group;
250  fe->print_elt = owl_filterelement_print_group;
251}
252
253void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
254{
255  owl_filterelement_create(fe);
256  fe->left = in;
257  fe->match_message = owl_filterelement_match_not;
258  fe->print_elt = owl_filterelement_print_not;
259}
260
261void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
262{
263  owl_filterelement_create(fe);
264  fe->left = lhs;
265  fe->right = rhs;
266  fe->match_message = owl_filterelement_match_and;
267  fe->print_elt = owl_filterelement_print_and;
268}
269
270void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
271{
272  owl_filterelement_create(fe);
273  fe->left = lhs;
274  fe->right = rhs;
275  fe->match_message = owl_filterelement_match_or;
276  fe->print_elt = owl_filterelement_print_or;
277}
278
279int owl_filterelement_match(owl_filterelement *fe, owl_message *m)
280{
281  if(!fe) return 0;
282  if(!fe->match_message) return 0;
283  return fe->match_message(fe, m);
284}
285
286static int fe_visiting = 0;
287static int fe_visited  = 1;
288
289int owl_filterelement_is_toodeep(owl_filter *f, owl_filterelement *fe)
290{
291  int rv;
292  owl_dict filters;
293  owl_dict_create(&filters);
294
295  owl_dict_insert_element(&filters, f->name, &fe_visiting, owl_dict_noop_free);
296
297  rv = _owl_filterelement_is_toodeep(fe, &filters);
298
299  owl_dict_free_simple(&filters);
300  return rv;
301}
302
303int _owl_filterelement_is_toodeep(owl_filterelement *fe, owl_dict *seen)
304{
305  int rv = 0;
306  owl_filter *f;
307
308  if(fe->match_message == owl_filterelement_match_filter) {
309    int *nval = owl_dict_find_element(seen, fe->field);
310    if(nval == &fe_visiting) {
311      return 1;
312    } else if (nval == NULL) {
313      f = owl_global_get_filter(&g, fe->field);
314      owl_dict_insert_element(seen, fe->field, &fe_visiting, owl_dict_noop_free);
315      if(f) rv = _owl_filterelement_is_toodeep(f->root, seen);
316      owl_dict_insert_element(seen, fe->field, &fe_visited, owl_dict_noop_free);
317    }
318  } else {
319    if(fe->left)
320      rv = rv || _owl_filterelement_is_toodeep(fe->left, seen);
321    if(fe->right)
322      rv = rv || _owl_filterelement_is_toodeep(fe->right, seen);
323  }
324  return rv;
325}
326
327void owl_filterelement_free(owl_filterelement *fe)
328{
329  if (fe->field) owl_free(fe->field);
330  if (fe->left) {
331    owl_filterelement_free(fe->left);
332    owl_free(fe->left);
333  }
334  if (fe->right) {
335    owl_filterelement_free(fe->right);
336    owl_free(fe->right);
337  }
338  owl_regex_free(&(fe->re));
339}
340
341void owl_filterelement_print(owl_filterelement *fe, GString *buf)
342{
343  if(!fe || !fe->print_elt) return;
344  fe->print_elt(fe, buf);
345}
Note: See TracBrowser for help on using the repository browser.