source: filter.c @ 2b6622a6

release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 2b6622a6 was 23fddad, checked in by Karl Ramm <kcr@1ts.org>, 12 years ago
refactor & rename filter creation & storage management filter_init_fromstring -> filter_new_fromstring filter_init -> filter_new filter_free -> filter_delete Every time owl_filter_init and owl_filter_init_fromstring were called, there was a call to malloc right above them; Conversely, after every owl_filter_free there needed to be a call to owl_free (and sometimes there wasn't).
  • Property mode set to 100644
File size: 5.9 KB
Line 
1#include <string.h>
2#include "owl.h"
3
4owl_filter *owl_filter_new_fromstring(const char *name, const char *string)
5{
6  owl_filter *f;
7  char **argv;
8  int argc;
9
10  argv = owl_parseline(string, &argc);
11  f = owl_filter_new(name, argc, strs(argv));
12  owl_parsefree(argv, argc);
13
14  return f;
15}
16
17owl_filter *owl_filter_new(const char *name, int argc, const char *const *argv)
18{
19  owl_filter *f;
20
21  f = owl_malloc(sizeof(owl_filter));
22
23  f->name=owl_strdup(name);
24  f->fgcolor=OWL_COLOR_DEFAULT;
25  f->bgcolor=OWL_COLOR_DEFAULT;
26  f->cachedmsgid=-1;
27
28  /* first take arguments that have to come first */
29  /* set the color */
30  while ( argc>=2 && ( !strcmp(argv[0], "-c") ||
31                       !strcmp(argv[0], "-b") ) ) {
32    if (owl_util_string_to_color(argv[1])==OWL_COLOR_INVALID) {
33      owl_function_error("The color '%s' is not available, using default.", argv[1]);
34    } else {
35      switch (argv[0][1]) {
36      case 'c':
37        f->fgcolor=owl_util_string_to_color(argv[1]);
38        break;
39      case 'b':
40        f->bgcolor=owl_util_string_to_color(argv[1]);
41        break;
42      }
43    }
44    argc-=2;
45    argv+=2;
46  }
47
48  if (!(f->root = owl_filter_parse_expression(argc, argv, NULL))) {
49    owl_filter_delete(f);
50    return NULL;
51  }
52
53  /* Now check for recursion. */
54  if (owl_filter_is_toodeep(f)) {
55    owl_function_error("Filter loop!");
56    owl_filter_delete(f);
57    return NULL;
58  }
59
60  return f;
61}
62
63
64/* A primitive expression is one without any toplevel ``and'' or ``or''s*/
65
66static owl_filterelement * owl_filter_parse_primitive_expression(int argc, const char *const *argv, int *next)
67{
68  owl_filterelement *fe, *op;
69  int i = 0, skip;
70
71  if(!argc) return NULL;
72
73  fe = owl_malloc(sizeof(owl_filterelement));
74  owl_filterelement_create(fe);
75
76  if(!strcasecmp(argv[i], "(")) {
77    i++;
78    op = owl_filter_parse_expression(argc-i, argv+i, &skip);
79    if(!op) goto err;
80    i += skip;
81    if(i >= argc) goto err;
82    if(strcasecmp(argv[i++], ")")) goto err;
83    owl_filterelement_create_group(fe, op);
84  } else if(!strcasecmp(argv[i], "not")) {
85    i++;
86    op = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
87    if(!op) goto err;
88    i += skip;
89    owl_filterelement_create_not(fe, op);
90  } else if(!strcasecmp(argv[i], "true")) {
91    i++;
92    owl_filterelement_create_true(fe);
93  } else if(!strcasecmp(argv[i], "false")) {
94    i++;
95    owl_filterelement_create_false(fe);
96  } else {
97    if(argc == 1) goto err;
98    if(!strcasecmp(*argv, "filter")) {
99      owl_filterelement_create_filter(fe, *(argv+1));
100    } else if(!strcasecmp(*argv, "perl")) {
101      owl_filterelement_create_perl(fe, *(argv+1));
102    } else {
103      if(owl_filterelement_create_re(fe, *argv, *(argv+1))) {
104        goto err;
105      }
106    }
107    i += 2;
108  }
109
110  if(next) {
111    *next = i;
112  } else if(i != argc) {
113    goto err;
114  }
115  return fe;
116err:
117  owl_filterelement_free(fe);
118  owl_free(fe);
119  return NULL;
120}
121
122owl_filterelement * owl_filter_parse_expression(int argc, const char *const *argv, int *next)
123{
124  int i = 0, skip;
125  owl_filterelement * op1 = NULL, * op2 = NULL, *tmp;
126
127  op1 = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
128  i += skip;
129  if(!op1) goto err;
130
131  while(i < argc) {
132    if(strcasecmp(argv[i], "and") &&
133       strcasecmp(argv[i], "or")) break;
134    op2 = owl_filter_parse_primitive_expression(argc-i-1, argv+i+1, &skip);
135    if(!op2) goto err;
136    tmp = owl_malloc(sizeof(owl_filterelement));
137    if(!strcasecmp(argv[i], "and")) {
138      owl_filterelement_create_and(tmp, op1, op2);
139    } else {
140      owl_filterelement_create_or(tmp, op1, op2);
141    }
142    op1 = tmp;
143    op2 = NULL;
144    i += skip+1;
145  }
146
147  if(next) {
148    *next = i;
149  } else if(i != argc) {
150    goto err;
151  }
152  return op1;
153err:
154  if(op1) {
155    owl_filterelement_free(op1);
156    owl_free(op1);
157  }
158  return NULL;
159}
160
161const char *owl_filter_get_name(const owl_filter *f)
162{
163  return(f->name);
164}
165
166void owl_filter_set_fgcolor(owl_filter *f, int color)
167{
168  f->fgcolor=color;
169}
170
171int owl_filter_get_fgcolor(const owl_filter *f)
172{
173  return(f->fgcolor);
174}
175
176void owl_filter_set_bgcolor(owl_filter *f, int color)
177{
178  f->bgcolor=color;
179}
180
181int owl_filter_get_bgcolor(const owl_filter *f)
182{
183  return(f->bgcolor);
184}
185
186void owl_filter_set_cachedmsgid(owl_filter *f, int cachedmsgid)
187{
188  f->cachedmsgid=cachedmsgid;
189}
190
191int owl_filter_get_cachedmsgid(const owl_filter *f)
192{
193  return(f->cachedmsgid);
194}
195
196/* return 1 if the message matches the given filter, otherwise
197 * return 0.
198 */
199int owl_filter_message_match(const owl_filter *f, const owl_message *m)
200{
201  int ret;
202  if(!f->root) return 0;
203  ret = owl_filterelement_match(f->root, m);
204  return ret;
205}
206
207
208char* owl_filter_print(const owl_filter *f)
209{
210  GString *out = g_string_new("");
211
212  if (f->fgcolor!=OWL_COLOR_DEFAULT) {
213    g_string_append(out, "-c ");
214    if (f->fgcolor < 8) {
215      g_string_append(out, owl_util_color_to_string(f->fgcolor));
216    }
217    else {
218      g_string_append_printf(out, "%i",f->fgcolor);
219    }
220    g_string_append(out, " ");
221  }
222  if (f->bgcolor!=OWL_COLOR_DEFAULT) {
223    g_string_append(out, "-b ");
224    if (f->bgcolor < 8) {
225      g_string_append(out, owl_util_color_to_string(f->bgcolor));
226    }
227    else {
228      g_string_append_printf(out, "%i",f->fgcolor);
229    }
230    g_string_append(out, " ");
231  }
232  if(f->root) {
233    owl_filterelement_print(f->root, out);
234    g_string_append(out, "\n");
235  }
236
237  return g_string_free(out, 0);
238}
239
240/* Return 1 if the filters 'a' and 'b' are equivalent, 0 otherwise */
241int owl_filter_equiv(const owl_filter *a, const owl_filter *b)
242{
243  char *buffa, *buffb;
244  int ret;
245
246  buffa = owl_filter_print(a);
247  buffb = owl_filter_print(b);
248
249  ret = !strcmp(buffa, buffb);
250  ret = ret && !strcmp(owl_filter_get_name(a),
251                       owl_filter_get_name(b));
252
253  owl_free(buffa);
254  owl_free(buffb);
255
256  return ret;
257}
258
259
260int owl_filter_is_toodeep(const owl_filter *f)
261{
262  return owl_filterelement_is_toodeep(f, f->root);
263}
264
265void owl_filter_delete(owl_filter *f)
266{
267  if (f == NULL)
268    return;
269  if (f->root) {
270    owl_filterelement_free(f->root);
271    owl_free(f->root);
272  }
273  if (f->name)
274    owl_free(f->name);
275  owl_free(f);
276}
Note: See TracBrowser for help on using the repository browser.