source: filter.c @ 2e9b9ad

release-1.10
Last change on this file since 2e9b9ad was c068c03, checked in by Jason Gross <jgross@mit.edu>, 12 years ago
Fix some undefined behavior in filter.c, caught by clang scan-build
  • Property mode set to 100644
File size: 5.8 KB
RevLine 
[7d4fbcd]1#include "owl.h"
2
[23fddad]3owl_filter *owl_filter_new_fromstring(const char *name, const char *string)
[e187445]4{
[23fddad]5  owl_filter *f;
[7d4fbcd]6  char **argv;
[23fddad]7  int argc;
[7d4fbcd]8
[23fddad]9  argv = owl_parseline(string, &argc);
10  f = owl_filter_new(name, argc, strs(argv));
[e56303f]11  g_strfreev(argv);
[23fddad]12
13  return f;
[7d4fbcd]14}
15
[23fddad]16owl_filter *owl_filter_new(const char *name, int argc, const char *const *argv)
[e187445]17{
[23fddad]18  owl_filter *f;
19
[96828e4]20  f = g_new(owl_filter, 1);
[23fddad]21
[d4927a7]22  f->name=g_strdup(name);
[8fa9562]23  f->fgcolor=OWL_COLOR_DEFAULT;
24  f->bgcolor=OWL_COLOR_DEFAULT;
[cb769bb]25
[7d4fbcd]26  /* first take arguments that have to come first */
27  /* set the color */
[8fa9562]28  while ( argc>=2 && ( !strcmp(argv[0], "-c") ||
29                       !strcmp(argv[0], "-b") ) ) {
[601733d]30    if (owl_util_string_to_color(argv[1])==OWL_COLOR_INVALID) {
[12c35df]31      owl_function_error("The color '%s' is not available, using default.", argv[1]);
32    } else {
[8fa9562]33      switch (argv[0][1]) {
34      case 'c':
35        f->fgcolor=owl_util_string_to_color(argv[1]);
36        break;
37      case 'b':
38        f->bgcolor=owl_util_string_to_color(argv[1]);
39        break;
40      }
[12c35df]41    }
[7d4fbcd]42    argc-=2;
43    argv+=2;
44  }
45
[23fddad]46  if (!(f->root = owl_filter_parse_expression(argc, argv, NULL))) {
47    owl_filter_delete(f);
48    return NULL;
49  }
[7d4fbcd]50
[cb769bb]51  /* Now check for recursion. */
[40458b9]52  if (owl_filter_is_toodeep(f)) {
[9711a6e]53    owl_function_error("Filter loop!");
[23fddad]54    owl_filter_delete(f);
55    return NULL;
[7d4fbcd]56  }
[cb769bb]57
[23fddad]58  return f;
[7d4fbcd]59}
60
[cb769bb]61
62/* A primitive expression is one without any toplevel ``and'' or ``or''s*/
63
[e19eb97]64static owl_filterelement * owl_filter_parse_primitive_expression(int argc, const char *const *argv, int *next)
[cb769bb]65{
[ad15610]66  owl_filterelement *fe, *op;
67  int i = 0, skip;
[cb769bb]68
[ad15610]69  if(!argc) return NULL;
[cb769bb]70
[96828e4]71  fe = g_new(owl_filterelement, 1);
[cb769bb]72  owl_filterelement_create(fe);
73
74  if(!strcasecmp(argv[i], "(")) {
75    i++;
76    op = owl_filter_parse_expression(argc-i, argv+i, &skip);
77    if(!op) goto err;
78    i += skip;
[d791cdb]79    if(i >= argc) goto err;
[cb769bb]80    if(strcasecmp(argv[i++], ")")) goto err;
81    owl_filterelement_create_group(fe, op);
82  } else if(!strcasecmp(argv[i], "not")) {
83    i++;
84    op = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
85    if(!op) goto err;
86    i += skip;
87    owl_filterelement_create_not(fe, op);
88  } else if(!strcasecmp(argv[i], "true")) {
89    i++;
90    owl_filterelement_create_true(fe);
91  } else if(!strcasecmp(argv[i], "false")) {
92    i++;
93    owl_filterelement_create_false(fe);
94  } else {
95    if(argc == 1) goto err;
96    if(!strcasecmp(*argv, "filter")) {
97      owl_filterelement_create_filter(fe, *(argv+1));
98    } else if(!strcasecmp(*argv, "perl")) {
99      owl_filterelement_create_perl(fe, *(argv+1));
100    } else {
[e6a4dd5]101      if(owl_filterelement_create_re(fe, *argv, *(argv+1))) {
102        goto err;
103      }
[cb769bb]104    }
105    i += 2;
106  }
107
108  if(next) {
109    *next = i;
110  } else if(i != argc) {
111    goto err;
112  }
113  return fe;
114err:
[75c7e8e]115  owl_filterelement_cleanup(fe);
[ddbbcffa]116  g_free(fe);
[cb769bb]117  return NULL;
118}
119
[e19eb97]120owl_filterelement * owl_filter_parse_expression(int argc, const char *const *argv, int *next)
[cb769bb]121{
122  int i = 0, skip;
[ad15610]123  owl_filterelement * op1 = NULL, * op2 = NULL, *tmp;
[cb769bb]124
125  op1 = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
126  if(!op1) goto err;
[c068c03]127  i += skip;
[cb769bb]128
129  while(i < argc) {
130    if(strcasecmp(argv[i], "and") &&
131       strcasecmp(argv[i], "or")) break;
132    op2 = owl_filter_parse_primitive_expression(argc-i-1, argv+i+1, &skip);
133    if(!op2) goto err;
[96828e4]134    tmp = g_new(owl_filterelement, 1);
[cb769bb]135    if(!strcasecmp(argv[i], "and")) {
136      owl_filterelement_create_and(tmp, op1, op2);
137    } else {
138      owl_filterelement_create_or(tmp, op1, op2);
139    }
140    op1 = tmp;
141    op2 = NULL;
142    i += skip+1;
143  }
144
145  if(next) {
146    *next = i;
147  } else if(i != argc) {
148    goto err;
149  }
150  return op1;
151err:
152  if(op1) {
[75c7e8e]153    owl_filterelement_cleanup(op1);
[ddbbcffa]154    g_free(op1);
[cb769bb]155  }
156  return NULL;
157}
158
[4542047]159const char *owl_filter_get_name(const owl_filter *f)
[e187445]160{
[7d4fbcd]161  return(f->name);
162}
163
[3cc4bfc]164SV *owl_filter_to_sv(const owl_filter *f)
165{
166  return owl_new_sv(owl_filter_get_name(f));
167}
168
[8fa9562]169void owl_filter_set_fgcolor(owl_filter *f, int color)
[e187445]170{
[8fa9562]171  f->fgcolor=color;
[7d4fbcd]172}
173
[4542047]174int owl_filter_get_fgcolor(const owl_filter *f)
[e187445]175{
[8fa9562]176  return(f->fgcolor);
177}
178
179void owl_filter_set_bgcolor(owl_filter *f, int color)
180{
181  f->bgcolor=color;
182}
183
[4542047]184int owl_filter_get_bgcolor(const owl_filter *f)
[8fa9562]185{
186  return(f->bgcolor);
[7d4fbcd]187}
188
[15b34fd]189/* return 1 if the message matches the given filter, otherwise
190 * return 0.
191 */
[4542047]192int owl_filter_message_match(const owl_filter *f, const owl_message *m)
[e187445]193{
[ad15610]194  int ret;
[cb769bb]195  if(!f->root) return 0;
[ad15610]196  ret = owl_filterelement_match(f->root, m);
[cb769bb]197  return ret;
[7d4fbcd]198}
199
200
[2560529]201CALLER_OWN char *owl_filter_print(const owl_filter *f)
[e187445]202{
[cdc6ff1]203  GString *out = g_string_new("");
[446aa2b]204
[8fa9562]205  if (f->fgcolor!=OWL_COLOR_DEFAULT) {
[0504f63]206    g_string_append(out, "-c ");
[c2c5c77]207    if (f->fgcolor < 8) {
[0504f63]208      g_string_append(out, owl_util_color_to_string(f->fgcolor));
[c2c5c77]209    }
210    else {
[0504f63]211      g_string_append_printf(out, "%i",f->fgcolor);
[c2c5c77]212    }
[0504f63]213    g_string_append(out, " ");
[8fa9562]214  }
215  if (f->bgcolor!=OWL_COLOR_DEFAULT) {
[0504f63]216    g_string_append(out, "-b ");
[c2c5c77]217    if (f->bgcolor < 8) {
[0504f63]218      g_string_append(out, owl_util_color_to_string(f->bgcolor));
[c2c5c77]219    }
220    else {
[30781f6]221      g_string_append_printf(out, "%i",f->bgcolor);
[c2c5c77]222    }
[0504f63]223    g_string_append(out, " ");
224  }
225  if(f->root) {
226    owl_filterelement_print(f->root, out);
227    g_string_append(out, "\n");
[446aa2b]228  }
[0504f63]229
230  return g_string_free(out, 0);
[7d4fbcd]231}
232
[40458b9]233/* Return 1 if the filters 'a' and 'b' are equivalent, 0 otherwise */
[4542047]234int owl_filter_equiv(const owl_filter *a, const owl_filter *b)
[e187445]235{
[0504f63]236  char *buffa, *buffb;
237  int ret;
[7d4fbcd]238
[0504f63]239  buffa = owl_filter_print(a);
240  buffb = owl_filter_print(b);
[7d4fbcd]241
[0504f63]242  ret = !strcmp(buffa, buffb);
[cdc6ff1]243  ret = ret && !strcmp(owl_filter_get_name(a),
244                       owl_filter_get_name(b));
[0504f63]245
[ddbbcffa]246  g_free(buffa);
247  g_free(buffb);
[0504f63]248
249  return ret;
[7d4fbcd]250}
251
[cb769bb]252
[4542047]253int owl_filter_is_toodeep(const owl_filter *f)
[40458b9]254{
[cb769bb]255  return owl_filterelement_is_toodeep(f, f->root);
[40458b9]256}
257
[23fddad]258void owl_filter_delete(owl_filter *f)
[40458b9]259{
[23fddad]260  if (f == NULL)
261    return;
262  if (f->root) {
[75c7e8e]263    owl_filterelement_cleanup(f->root);
[ddbbcffa]264    g_free(f->root);
[40458b9]265  }
[23fddad]266  if (f->name)
[ddbbcffa]267    g_free(f->name);
268  g_free(f);
[cb769bb]269}
Note: See TracBrowser for help on using the repository browser.