source: filterelement.c @ 1aa4cc4

release-1.6release-1.7release-1.8release-1.9
Last change on this file since 1aa4cc4 was a1d98e4, checked in by Nelson Elhage <nelhage@mit.edu>, 11 years ago
Support filtering on whether a message has been deleted.
  • Property mode set to 100644
File size: 9.3 KB
RevLine 
[7d4fbcd]1#include "owl.h"
2
[c08c70a]3static const char * owl_filterelement_get_field(const owl_message *m, const char * field)
[cb769bb]4{
[e19eb97]5  const char *match;
[cb769bb]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);
[a1d98e4]24  } else if (!strcasecmp(field, "deleted")) {
25    match=owl_message_is_delete(m) ? "true" : "false";
[cb769bb]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}
[7d4fbcd]51
[bd65108]52static int owl_filterelement_match_false(const owl_filterelement *fe, const owl_message *m)
[e187445]53{
[cb769bb]54  return 0;
[7d4fbcd]55}
56
[bd65108]57static int owl_filterelement_match_true(const owl_filterelement *fe, const owl_message *m)
[e187445]58{
[cb769bb]59  return 1;
[7d4fbcd]60}
61
[bd65108]62static int owl_filterelement_match_re(const owl_filterelement *fe, const owl_message *m)
[e187445]63{
[e19eb97]64  const char * val = owl_filterelement_get_field(m, fe->field);
[41c9a96]65  return !owl_regex_compare(&(fe->re), val, NULL, NULL);
[7d4fbcd]66}
67
[bd65108]68static int owl_filterelement_match_filter(const owl_filterelement *fe, const owl_message *m)
[e187445]69{
[4542047]70  const owl_filter *subfilter;
[cb769bb]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);
[7d4fbcd]79}
80
[bd65108]81static int owl_filterelement_match_perl(const owl_filterelement *fe, const owl_message *m)
[e187445]82{
[e19eb97]83  const char *subname;
[65b2173]84  char *perlrv;
[cb769bb]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;
[7d4fbcd]99}
100
[bd65108]101static int owl_filterelement_match_group(const owl_filterelement *fe, const owl_message *m)
[e187445]102{
[cb769bb]103  return owl_filterelement_match(fe->left, m);
[7d4fbcd]104}
105
[cb769bb]106/* XXX: Our boolea operators short-circuit here. The original owl did
107   not. Do we care?
108*/
109
[bd65108]110static int owl_filterelement_match_and(const owl_filterelement *fe, const owl_message *m)
[e187445]111{
[cb769bb]112  return owl_filterelement_match(fe->left, m) &&
113    owl_filterelement_match(fe->right, m);
[7d4fbcd]114}
115
[bd65108]116static int owl_filterelement_match_or(const owl_filterelement *fe, const owl_message *m)
[e187445]117{
[cb769bb]118  return owl_filterelement_match(fe->left, m) ||
119    owl_filterelement_match(fe->right, m);
[7d4fbcd]120}
121
[bd65108]122static int owl_filterelement_match_not(const owl_filterelement *fe, const owl_message *m)
[e187445]123{
[cb769bb]124  return !owl_filterelement_match(fe->left, m);
[7d4fbcd]125}
[5616acc]126
[af1920fd]127/* Print methods */
[cb769bb]128
[bd65108]129static void owl_filterelement_print_true(const owl_filterelement *fe, GString *buf)
[40458b9]130{
[0504f63]131  g_string_append(buf, "true");
[40458b9]132}
133
[bd65108]134static void owl_filterelement_print_false(const owl_filterelement *fe, GString *buf)
[32eed98]135{
[0504f63]136  g_string_append(buf, "false");
[32eed98]137}
138
[bd65108]139static void owl_filterelement_print_re(const owl_filterelement *fe, GString *buf)
[e187445]140{
[e19eb97]141  const char *re, *q;
[0504f63]142  g_string_append(buf, fe->field);
143  g_string_append(buf, " ");
[81655f8]144
145  re = owl_regex_get_string(&(fe->re));
146  q = owl_getquoting(re);
[0504f63]147  g_string_append(buf, q);
148  g_string_append(buf, re);
149  g_string_append(buf, q);
[cb769bb]150}
151
[bd65108]152static void owl_filterelement_print_filter(const owl_filterelement *fe, GString *buf)
[cb769bb]153{
[0504f63]154  g_string_append(buf, "filter ");
155  g_string_append(buf, fe->field);
[cb769bb]156}
157
[bd65108]158static void owl_filterelement_print_perl(const owl_filterelement *fe, GString *buf)
[cb769bb]159{
[0504f63]160  g_string_append(buf, "perl ");
161  g_string_append(buf, fe->field);
[7d4fbcd]162}
163
[bd65108]164static void owl_filterelement_print_group(const owl_filterelement *fe, GString *buf)
[e187445]165{
[0504f63]166  g_string_append(buf, "( ");
[cb769bb]167  owl_filterelement_print(fe->left, buf) ;
[0504f63]168  g_string_append(buf, " )");
[7d4fbcd]169}
170
[bd65108]171static void owl_filterelement_print_or(const owl_filterelement *fe, GString *buf)
[e187445]172{
[cb769bb]173  owl_filterelement_print(fe->left, buf);
[0504f63]174  g_string_append(buf, " or ");
[cb769bb]175  owl_filterelement_print(fe->right, buf);
[7d4fbcd]176}
177
[bd65108]178static void owl_filterelement_print_and(const owl_filterelement *fe, GString *buf)
[e187445]179{
[cb769bb]180  owl_filterelement_print(fe->left, buf);
[0504f63]181  g_string_append(buf, " and ");
[cb769bb]182  owl_filterelement_print(fe->right, buf);
[7d4fbcd]183}
184
[bd65108]185static void owl_filterelement_print_not(const owl_filterelement *fe, GString *buf)
[e187445]186{
[0504f63]187  g_string_append(buf, " not ");
[cb769bb]188  owl_filterelement_print(fe->left, buf);
189}
190
[af1920fd]191/* Constructors */
[cb769bb]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));
[7d4fbcd]199}
200
[cb769bb]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)
[e187445]210{
[cb769bb]211  owl_filterelement_create(fe);
212  fe->match_message = owl_filterelement_match_false;
213  fe->print_elt = owl_filterelement_print_false;
[7d4fbcd]214}
215
[e19eb97]216int owl_filterelement_create_re(owl_filterelement *fe, const char *field, const char *re)
[e187445]217{
[cb769bb]218  owl_filterelement_create(fe);
219  fe->field=owl_strdup(field);
[e6a4dd5]220  if(owl_regex_create(&(fe->re), re)) {
[27f6487]221    owl_free(fe->field);
[e6a4dd5]222    fe->field = NULL;
223    return (-1);
224  }
[cb769bb]225  fe->match_message = owl_filterelement_match_re;
226  fe->print_elt = owl_filterelement_print_re;
[e6a4dd5]227  return 0;
[7d4fbcd]228}
229
[e19eb97]230void owl_filterelement_create_filter(owl_filterelement *fe, const char *name)
[e187445]231{
[cb769bb]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;
[7d4fbcd]236}
237
[e19eb97]238void owl_filterelement_create_perl(owl_filterelement *fe, const char *name)
[e187445]239{
[cb769bb]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;
[7d4fbcd]244}
245
[cb769bb]246void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
[e187445]247{
[cb769bb]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;
[7d4fbcd]252}
253
[cb769bb]254void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
[32eed98]255{
[cb769bb]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;
[32eed98]260}
261
[cb769bb]262void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
[e187445]263{
[cb769bb]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;
[7d4fbcd]269}
270
[cb769bb]271void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
[40458b9]272{
[cb769bb]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;
[40458b9]278}
279
[bd65108]280int owl_filterelement_match(const owl_filterelement *fe, const owl_message *m)
[e187445]281{
[cb769bb]282  if(!fe) return 0;
283  if(!fe->match_message) return 0;
284  return fe->match_message(fe, m);
[40458b9]285}
286
[f446454]287static int fe_visiting = 0;
288static int fe_visited  = 1;
289
[4542047]290int owl_filterelement_is_toodeep(const owl_filter *f, const owl_filterelement *fe)
[40458b9]291{
[f446454]292  int rv;
[cb769bb]293  owl_dict filters;
294  owl_dict_create(&filters);
[f446454]295
[a1074de]296  owl_dict_insert_element(&filters, f->name, &fe_visiting, owl_dict_noop_delete);
[f446454]297
298  rv = _owl_filterelement_is_toodeep(fe, &filters);
299
[d537350]300  owl_dict_cleanup(&filters, NULL);
[f446454]301  return rv;
302}
303
[bd65108]304int _owl_filterelement_is_toodeep(const owl_filterelement *fe, owl_dict *seen)
[f446454]305{
306  int rv = 0;
[4542047]307  const owl_filter *f;
[f446454]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) {
[cb769bb]314      f = owl_global_get_filter(&g, fe->field);
[a1074de]315      owl_dict_insert_element(seen, fe->field, &fe_visiting, owl_dict_noop_delete);
[f446454]316      if(f) rv = _owl_filterelement_is_toodeep(f->root, seen);
[a1074de]317      owl_dict_insert_element(seen, fe->field, &fe_visited, owl_dict_noop_delete);
[cb769bb]318    }
[f446454]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);
[cb769bb]324  }
[f446454]325  return rv;
[7d4fbcd]326}
327
[75c7e8e]328void owl_filterelement_cleanup(owl_filterelement *fe)
[e187445]329{
[cb769bb]330  if (fe->field) owl_free(fe->field);
331  if (fe->left) {
[75c7e8e]332    owl_filterelement_cleanup(fe->left);
[cb769bb]333    owl_free(fe->left);
[7d4fbcd]334  }
[cb769bb]335  if (fe->right) {
[75c7e8e]336    owl_filterelement_cleanup(fe->right);
[cb769bb]337    owl_free(fe->right);
[7d4fbcd]338  }
[5cbc929]339  owl_regex_cleanup(&(fe->re));
[cb769bb]340}
[40458b9]341
[bd65108]342void owl_filterelement_print(const owl_filterelement *fe, GString *buf)
[cb769bb]343{
344  if(!fe || !fe->print_elt) return;
345  fe->print_elt(fe, buf);
[7d4fbcd]346}
Note: See TracBrowser for help on using the repository browser.