source: filterelement.c @ 0d53dfb

Last change on this file since 0d53dfb was 7dcef03, checked in by Anders Kaseorg <andersk@mit.edu>, 8 years ago
Use the Glib slice allocator for fixed-size objects The slice allocator, available since GLib 2.10, is more space-efficient than [g_]malloc. Since BarnOwl is obviously at the leading edge of space-efficient technology, this seems like a natural fit. Use it for every fixed-size object except owl_viewwin_search_data (which would need an extra destroy_cbdata function to g_slice_free it). Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • 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    }
[ddbbcffa]96    g_free(perlrv);
[cb769bb]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
[7756dde]106/* XXX: Our boolean operators short-circuit here. The original owl did
[cb769bb]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{
[d222c44]141  const char *re;
[0504f63]142  g_string_append(buf, fe->field);
143  g_string_append(buf, " ");
[81655f8]144
145  re = owl_regex_get_string(&(fe->re));
[d222c44]146  owl_string_append_quoted_arg(buf, re);
[cb769bb]147}
148
[bd65108]149static void owl_filterelement_print_filter(const owl_filterelement *fe, GString *buf)
[cb769bb]150{
[0504f63]151  g_string_append(buf, "filter ");
[d222c44]152  owl_string_append_quoted_arg(buf, fe->field);
[cb769bb]153}
154
[bd65108]155static void owl_filterelement_print_perl(const owl_filterelement *fe, GString *buf)
[cb769bb]156{
[0504f63]157  g_string_append(buf, "perl ");
[d222c44]158  owl_string_append_quoted_arg(buf, fe->field);
[7d4fbcd]159}
160
[bd65108]161static void owl_filterelement_print_group(const owl_filterelement *fe, GString *buf)
[e187445]162{
[0504f63]163  g_string_append(buf, "( ");
[cb769bb]164  owl_filterelement_print(fe->left, buf) ;
[0504f63]165  g_string_append(buf, " )");
[7d4fbcd]166}
167
[bd65108]168static void owl_filterelement_print_or(const owl_filterelement *fe, GString *buf)
[e187445]169{
[cb769bb]170  owl_filterelement_print(fe->left, buf);
[0504f63]171  g_string_append(buf, " or ");
[cb769bb]172  owl_filterelement_print(fe->right, buf);
[7d4fbcd]173}
174
[bd65108]175static void owl_filterelement_print_and(const owl_filterelement *fe, GString *buf)
[e187445]176{
[cb769bb]177  owl_filterelement_print(fe->left, buf);
[0504f63]178  g_string_append(buf, " and ");
[cb769bb]179  owl_filterelement_print(fe->right, buf);
[7d4fbcd]180}
181
[bd65108]182static void owl_filterelement_print_not(const owl_filterelement *fe, GString *buf)
[e187445]183{
[0504f63]184  g_string_append(buf, " not ");
[cb769bb]185  owl_filterelement_print(fe->left, buf);
186}
187
[af1920fd]188/* Constructors */
[cb769bb]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));
[7d4fbcd]196}
197
[cb769bb]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)
[e187445]207{
[cb769bb]208  owl_filterelement_create(fe);
209  fe->match_message = owl_filterelement_match_false;
210  fe->print_elt = owl_filterelement_print_false;
[7d4fbcd]211}
212
[e19eb97]213int owl_filterelement_create_re(owl_filterelement *fe, const char *field, const char *re)
[e187445]214{
[cb769bb]215  owl_filterelement_create(fe);
[d4927a7]216  fe->field=g_strdup(field);
[e6a4dd5]217  if(owl_regex_create(&(fe->re), re)) {
[ddbbcffa]218    g_free(fe->field);
[e6a4dd5]219    fe->field = NULL;
220    return (-1);
221  }
[cb769bb]222  fe->match_message = owl_filterelement_match_re;
223  fe->print_elt = owl_filterelement_print_re;
[e6a4dd5]224  return 0;
[7d4fbcd]225}
226
[e19eb97]227void owl_filterelement_create_filter(owl_filterelement *fe, const char *name)
[e187445]228{
[cb769bb]229  owl_filterelement_create(fe);
[d4927a7]230  fe->field=g_strdup(name);
[cb769bb]231  fe->match_message = owl_filterelement_match_filter;
232  fe->print_elt = owl_filterelement_print_filter;
[7d4fbcd]233}
234
[e19eb97]235void owl_filterelement_create_perl(owl_filterelement *fe, const char *name)
[e187445]236{
[cb769bb]237  owl_filterelement_create(fe);
[d4927a7]238  fe->field=g_strdup(name);
[cb769bb]239  fe->match_message = owl_filterelement_match_perl;
240  fe->print_elt = owl_filterelement_print_perl;
[7d4fbcd]241}
242
[cb769bb]243void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
[e187445]244{
[cb769bb]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;
[7d4fbcd]249}
250
[cb769bb]251void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
[32eed98]252{
[cb769bb]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;
[32eed98]257}
258
[cb769bb]259void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
[e187445]260{
[cb769bb]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;
[7d4fbcd]266}
267
[cb769bb]268void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
[40458b9]269{
[cb769bb]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;
[40458b9]275}
276
[bd65108]277int owl_filterelement_match(const owl_filterelement *fe, const owl_message *m)
[e187445]278{
[cb769bb]279  if(!fe) return 0;
280  if(!fe->match_message) return 0;
281  return fe->match_message(fe, m);
[40458b9]282}
283
[f446454]284static int fe_visiting = 0;
285static int fe_visited  = 1;
286
[4542047]287int owl_filterelement_is_toodeep(const owl_filter *f, const owl_filterelement *fe)
[40458b9]288{
[f446454]289  int rv;
[cb769bb]290  owl_dict filters;
291  owl_dict_create(&filters);
[f446454]292
[a1074de]293  owl_dict_insert_element(&filters, f->name, &fe_visiting, owl_dict_noop_delete);
[f446454]294
295  rv = _owl_filterelement_is_toodeep(fe, &filters);
296
[d537350]297  owl_dict_cleanup(&filters, NULL);
[f446454]298  return rv;
299}
300
[bd65108]301int _owl_filterelement_is_toodeep(const owl_filterelement *fe, owl_dict *seen)
[f446454]302{
303  int rv = 0;
[4542047]304  const owl_filter *f;
[f446454]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) {
[cb769bb]311      f = owl_global_get_filter(&g, fe->field);
[a1074de]312      owl_dict_insert_element(seen, fe->field, &fe_visiting, owl_dict_noop_delete);
[f446454]313      if(f) rv = _owl_filterelement_is_toodeep(f->root, seen);
[a1074de]314      owl_dict_insert_element(seen, fe->field, &fe_visited, owl_dict_noop_delete);
[cb769bb]315    }
[f446454]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);
[cb769bb]321  }
[f446454]322  return rv;
[7d4fbcd]323}
324
[75c7e8e]325void owl_filterelement_cleanup(owl_filterelement *fe)
[e187445]326{
[ddbbcffa]327  if (fe->field) g_free(fe->field);
[cb769bb]328  if (fe->left) {
[75c7e8e]329    owl_filterelement_cleanup(fe->left);
[7dcef03]330    g_slice_free(owl_filterelement, fe->left);
[7d4fbcd]331  }
[cb769bb]332  if (fe->right) {
[75c7e8e]333    owl_filterelement_cleanup(fe->right);
[7dcef03]334    g_slice_free(owl_filterelement, fe->right);
[7d4fbcd]335  }
[5cbc929]336  owl_regex_cleanup(&(fe->re));
[cb769bb]337}
[40458b9]338
[bd65108]339void owl_filterelement_print(const owl_filterelement *fe, GString *buf)
[cb769bb]340{
341  if(!fe || !fe->print_elt) return;
342  fe->print_elt(fe, buf);
[7d4fbcd]343}
Note: See TracBrowser for help on using the repository browser.