source: filterelement.c @ a1d98e4

release-1.6release-1.7release-1.8release-1.9
Last change on this file since a1d98e4 was a1d98e4, checked in by Nelson Elhage <nelhage@mit.edu>, 8 years ago
Support filtering on whether a message has been deleted.
  • Property mode set to 100644
File size: 9.3 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    owl_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 boolea 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, *q;
142  g_string_append(buf, fe->field);
143  g_string_append(buf, " ");
144
145  re = owl_regex_get_string(&(fe->re));
146  q = owl_getquoting(re);
147  g_string_append(buf, q);
148  g_string_append(buf, re);
149  g_string_append(buf, q);
150}
151
152static void owl_filterelement_print_filter(const owl_filterelement *fe, GString *buf)
153{
154  g_string_append(buf, "filter ");
155  g_string_append(buf, fe->field);
156}
157
158static void owl_filterelement_print_perl(const owl_filterelement *fe, GString *buf)
159{
160  g_string_append(buf, "perl ");
161  g_string_append(buf, fe->field);
162}
163
164static void owl_filterelement_print_group(const owl_filterelement *fe, GString *buf)
165{
166  g_string_append(buf, "( ");
167  owl_filterelement_print(fe->left, buf) ;
168  g_string_append(buf, " )");
169}
170
171static void owl_filterelement_print_or(const owl_filterelement *fe, GString *buf)
172{
173  owl_filterelement_print(fe->left, buf);
174  g_string_append(buf, " or ");
175  owl_filterelement_print(fe->right, buf);
176}
177
178static void owl_filterelement_print_and(const owl_filterelement *fe, GString *buf)
179{
180  owl_filterelement_print(fe->left, buf);
181  g_string_append(buf, " and ");
182  owl_filterelement_print(fe->right, buf);
183}
184
185static void owl_filterelement_print_not(const owl_filterelement *fe, GString *buf)
186{
187  g_string_append(buf, " not ");
188  owl_filterelement_print(fe->left, buf);
189}
190
191/* Constructors */
192
193void owl_filterelement_create(owl_filterelement *fe) {
194  fe->field = NULL;
195  fe->left = fe->right = NULL;
196  fe->match_message = NULL;
197  fe->print_elt = NULL;
198  owl_regex_init(&(fe->re));
199}
200
201
202void owl_filterelement_create_true(owl_filterelement *fe)
203{
204  owl_filterelement_create(fe);
205  fe->match_message = owl_filterelement_match_true;
206  fe->print_elt = owl_filterelement_print_true;
207}
208
209void owl_filterelement_create_false(owl_filterelement *fe)
210{
211  owl_filterelement_create(fe);
212  fe->match_message = owl_filterelement_match_false;
213  fe->print_elt = owl_filterelement_print_false;
214}
215
216int owl_filterelement_create_re(owl_filterelement *fe, const char *field, const char *re)
217{
218  owl_filterelement_create(fe);
219  fe->field=owl_strdup(field);
220  if(owl_regex_create(&(fe->re), re)) {
221    owl_free(fe->field);
222    fe->field = NULL;
223    return (-1);
224  }
225  fe->match_message = owl_filterelement_match_re;
226  fe->print_elt = owl_filterelement_print_re;
227  return 0;
228}
229
230void owl_filterelement_create_filter(owl_filterelement *fe, const char *name)
231{
232  owl_filterelement_create(fe);
233  fe->field=owl_strdup(name);
234  fe->match_message = owl_filterelement_match_filter;
235  fe->print_elt = owl_filterelement_print_filter;
236}
237
238void owl_filterelement_create_perl(owl_filterelement *fe, const char *name)
239{
240  owl_filterelement_create(fe);
241  fe->field=owl_strdup(name);
242  fe->match_message = owl_filterelement_match_perl;
243  fe->print_elt = owl_filterelement_print_perl;
244}
245
246void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
247{
248  owl_filterelement_create(fe);
249  fe->left = in;
250  fe->match_message = owl_filterelement_match_group;
251  fe->print_elt = owl_filterelement_print_group;
252}
253
254void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
255{
256  owl_filterelement_create(fe);
257  fe->left = in;
258  fe->match_message = owl_filterelement_match_not;
259  fe->print_elt = owl_filterelement_print_not;
260}
261
262void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
263{
264  owl_filterelement_create(fe);
265  fe->left = lhs;
266  fe->right = rhs;
267  fe->match_message = owl_filterelement_match_and;
268  fe->print_elt = owl_filterelement_print_and;
269}
270
271void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
272{
273  owl_filterelement_create(fe);
274  fe->left = lhs;
275  fe->right = rhs;
276  fe->match_message = owl_filterelement_match_or;
277  fe->print_elt = owl_filterelement_print_or;
278}
279
280int owl_filterelement_match(const owl_filterelement *fe, const owl_message *m)
281{
282  if(!fe) return 0;
283  if(!fe->match_message) return 0;
284  return fe->match_message(fe, m);
285}
286
287static int fe_visiting = 0;
288static int fe_visited  = 1;
289
290int owl_filterelement_is_toodeep(const owl_filter *f, const owl_filterelement *fe)
291{
292  int rv;
293  owl_dict filters;
294  owl_dict_create(&filters);
295
296  owl_dict_insert_element(&filters, f->name, &fe_visiting, owl_dict_noop_delete);
297
298  rv = _owl_filterelement_is_toodeep(fe, &filters);
299
300  owl_dict_cleanup(&filters, NULL);
301  return rv;
302}
303
304int _owl_filterelement_is_toodeep(const owl_filterelement *fe, owl_dict *seen)
305{
306  int rv = 0;
307  const owl_filter *f;
308
309  if(fe->match_message == owl_filterelement_match_filter) {
310    int *nval = owl_dict_find_element(seen, fe->field);
311    if(nval == &fe_visiting) {
312      return 1;
313    } else if (nval == NULL) {
314      f = owl_global_get_filter(&g, fe->field);
315      owl_dict_insert_element(seen, fe->field, &fe_visiting, owl_dict_noop_delete);
316      if(f) rv = _owl_filterelement_is_toodeep(f->root, seen);
317      owl_dict_insert_element(seen, fe->field, &fe_visited, owl_dict_noop_delete);
318    }
319  } else {
320    if(fe->left)
321      rv = rv || _owl_filterelement_is_toodeep(fe->left, seen);
322    if(fe->right)
323      rv = rv || _owl_filterelement_is_toodeep(fe->right, seen);
324  }
325  return rv;
326}
327
328void owl_filterelement_cleanup(owl_filterelement *fe)
329{
330  if (fe->field) owl_free(fe->field);
331  if (fe->left) {
332    owl_filterelement_cleanup(fe->left);
333    owl_free(fe->left);
334  }
335  if (fe->right) {
336    owl_filterelement_cleanup(fe->right);
337    owl_free(fe->right);
338  }
339  owl_regex_cleanup(&(fe->re));
340}
341
342void owl_filterelement_print(const owl_filterelement *fe, GString *buf)
343{
344  if(!fe || !fe->print_elt) return;
345  fe->print_elt(fe, buf);
346}
Note: See TracBrowser for help on using the repository browser.