source: filter.c @ e8074ed

release-1.10release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since e8074ed was 3cc4bfc, checked in by David Benjamin <davidben@mit.edu>, 15 years ago
Add owl_filter_to_sv for exporting filters Currently just returns the name. Signed-off-by: David Benjamin <davidben@mit.edu>
  • Property mode set to 100644
File size: 6.0 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
166SV *owl_filter_to_sv(const owl_filter *f)
167{
168  return owl_new_sv(owl_filter_get_name(f));
169}
170
171void owl_filter_set_fgcolor(owl_filter *f, int color)
172{
173  f->fgcolor=color;
174}
175
176int owl_filter_get_fgcolor(const owl_filter *f)
177{
178  return(f->fgcolor);
179}
180
181void owl_filter_set_bgcolor(owl_filter *f, int color)
182{
183  f->bgcolor=color;
184}
185
186int owl_filter_get_bgcolor(const owl_filter *f)
187{
188  return(f->bgcolor);
189}
190
191void owl_filter_set_cachedmsgid(owl_filter *f, int cachedmsgid)
192{
193  f->cachedmsgid=cachedmsgid;
194}
195
196int owl_filter_get_cachedmsgid(const owl_filter *f)
197{
198  return(f->cachedmsgid);
199}
200
201/* return 1 if the message matches the given filter, otherwise
202 * return 0.
203 */
204int owl_filter_message_match(const owl_filter *f, const owl_message *m)
205{
206  int ret;
207  if(!f->root) return 0;
208  ret = owl_filterelement_match(f->root, m);
209  return ret;
210}
211
212
213char* owl_filter_print(const owl_filter *f)
214{
215  GString *out = g_string_new("");
216
217  if (f->fgcolor!=OWL_COLOR_DEFAULT) {
218    g_string_append(out, "-c ");
219    if (f->fgcolor < 8) {
220      g_string_append(out, owl_util_color_to_string(f->fgcolor));
221    }
222    else {
223      g_string_append_printf(out, "%i",f->fgcolor);
224    }
225    g_string_append(out, " ");
226  }
227  if (f->bgcolor!=OWL_COLOR_DEFAULT) {
228    g_string_append(out, "-b ");
229    if (f->bgcolor < 8) {
230      g_string_append(out, owl_util_color_to_string(f->bgcolor));
231    }
232    else {
233      g_string_append_printf(out, "%i",f->fgcolor);
234    }
235    g_string_append(out, " ");
236  }
237  if(f->root) {
238    owl_filterelement_print(f->root, out);
239    g_string_append(out, "\n");
240  }
241
242  return g_string_free(out, 0);
243}
244
245/* Return 1 if the filters 'a' and 'b' are equivalent, 0 otherwise */
246int owl_filter_equiv(const owl_filter *a, const owl_filter *b)
247{
248  char *buffa, *buffb;
249  int ret;
250
251  buffa = owl_filter_print(a);
252  buffb = owl_filter_print(b);
253
254  ret = !strcmp(buffa, buffb);
255  ret = ret && !strcmp(owl_filter_get_name(a),
256                       owl_filter_get_name(b));
257
258  owl_free(buffa);
259  owl_free(buffb);
260
261  return ret;
262}
263
264
265int owl_filter_is_toodeep(const owl_filter *f)
266{
267  return owl_filterelement_is_toodeep(f, f->root);
268}
269
270void owl_filter_delete(owl_filter *f)
271{
272  if (f == NULL)
273    return;
274  if (f->root) {
275    owl_filterelement_free(f->root);
276    owl_free(f->root);
277  }
278  if (f->name)
279    owl_free(f->name);
280  owl_free(f);
281}
Note: See TracBrowser for help on using the repository browser.