source: filter.c @ 59cf91c

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 59cf91c was 59cf91c, checked in by Erik Nygren <nygren@mit.edu>, 18 years ago
Attempts to stay near the current message when switching views. When switching from an empty view to one we've previously been in, the new current message position will attempt to be close to the current position from the last time we visited that view.
  • Property mode set to 100644
File size: 8.8 KB
Line 
1#include <string.h>
2#include "owl.h"
3
4static const char fileIdent[] = "$Id$";
5
6int owl_filter_init_fromstring(owl_filter *f, char *name, char *string) {
7  char **argv;
8  int argc, out;
9
10  argv=owl_parseline(string, &argc);
11  out=owl_filter_init(f, name, argc, argv);
12  /* owl_parsefree(argv, argc); */
13  return(out);
14}
15
16int owl_filter_init(owl_filter *f, char *name, int argc, char **argv) {
17  int i, error;
18  owl_filterelement *fe;
19   
20  f->name=owl_strdup(name);
21  f->polarity=0;
22  f->color=OWL_COLOR_DEFAULT;
23  f->cachedmsgid=-1;
24  owl_list_create(&(f->fes));
25
26  /* first take arguments that have to come first */
27  /* set the color */
28  if (argc>=2 && !strcmp(argv[0], "-c")) {
29    f->color=owl_util_string_to_color(argv[1]);
30    argc-=2;
31    argv+=2;
32  }
33
34  /* then deal with the expression */
35  for (i=0; i<argc; i++) {
36    error=0;
37    fe=owl_malloc(sizeof(owl_filterelement));
38
39    /* all the 0 argument possibilities */
40    if (!strcmp(argv[i], "(")) {
41      owl_filterelement_create_openbrace(fe);
42    } else if (!strcmp(argv[i], ")")) {
43      owl_filterelement_create_closebrace(fe);
44    } else if (!strcasecmp(argv[i], "and")) {
45      owl_filterelement_create_and(fe);
46    } else if (!strcasecmp(argv[i], "or")) {
47      owl_filterelement_create_or(fe);
48    } else if (!strcasecmp(argv[i], "not")) {
49      owl_filterelement_create_not(fe);
50
51    } else if (i==argc-1) {
52      error=1;
53    } else {
54      if (!strcasecmp(argv[i], "class") ||
55          !strcasecmp(argv[i], "instance") ||
56          !strcasecmp(argv[i], "sender") ||
57          !strcasecmp(argv[i], "recipient") ||
58          !strcasecmp(argv[i], "opcode") ||
59          !strcasecmp(argv[i], "realm") ||
60          !strcasecmp(argv[i], "type")) {
61        owl_filterelement_create_re(fe, argv[i], argv[i+1]);
62        i++;
63      } else {
64        error=1;
65      }
66    }
67
68    if (!error) {
69      owl_list_append_element(&(f->fes), fe);
70    } else {
71      owl_free(fe);
72      owl_filter_free(f);
73      return(-1);
74    }
75
76  }
77  return(0);
78}
79
80char *owl_filter_get_name(owl_filter *f) {
81  return(f->name);
82}
83
84void owl_filter_set_polarity_match(owl_filter *f) {
85  f->polarity=0;
86}
87
88void owl_filter_set_polarity_unmatch(owl_filter *f) {
89  f->polarity=1;
90}
91
92void owl_filter_set_color(owl_filter *f, int color) {
93  f->color=color;
94}
95
96int owl_filter_get_color(owl_filter *f) {
97  return(f->color);
98}
99
100void owl_filter_set_cachedmsgid(owl_filter *f, int cachedmsgid) {
101  f->cachedmsgid=cachedmsgid;
102}
103
104int owl_filter_get_cachedmsgid(owl_filter *f) {
105  return(f->cachedmsgid);
106}
107
108int owl_filter_message_match(owl_filter *f, owl_message *m) {
109  int i, j, tmp;
110  owl_list work_fes, *fes;
111  owl_filterelement *fe;
112  char *field, *match;
113
114  /* create the working list */
115  fes=&(f->fes);
116  owl_list_create(&work_fes);
117  j=owl_list_get_size(fes);
118  for (i=0; i<j; i++) {
119    owl_list_append_element(&work_fes, owl_list_get_element(fes, i));
120  }
121
122  /* first go thru and turn all RE elements into true or false */
123  match="";
124  for (i=0; i<j; i++) {
125    fe=owl_list_get_element(&work_fes, i);
126    if (!owl_filterelement_is_re(fe)) continue;
127    field=owl_filterelement_get_field(fe);
128    if (!strcasecmp(field, "class")) {
129      match=owl_message_get_class(m);
130    } else if (!strcasecmp(field, "instance")) {
131      match=owl_message_get_instance(m);
132    } else if (!strcasecmp(field, "sender")) {
133      match=owl_message_get_sender(m);
134    } else if (!strcasecmp(field, "recipient")) {
135      match=owl_message_get_recipient(m);
136    } else if (!strcasecmp(field, "opcode")) {
137      match=owl_message_get_opcode(m);
138    } else if (!strcasecmp(field, "realm")) {
139      match=owl_message_get_realm(m);
140    } else if (!strcasecmp(field, "type")) {
141      if (owl_message_is_zephyr(m)) {
142        match="zephyr";
143      } else if (owl_message_is_admin(m)) {
144        match="admin";
145      } else {
146        match="";
147      }
148    }
149   
150    tmp=owl_regex_compare(owl_filterelement_get_re(fe), match);
151    if (!tmp) {
152      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
153    } else {
154      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
155    }
156  }
157
158 
159  /* call the recursive helper */
160  i=_owl_filter_message_match_recurse(f, m, &work_fes, 0, owl_list_get_size(&(f->fes))-1);
161
162  tmp=0;
163  /* now we should have one value */
164  for (i=0; i<j; i++) {
165    fe=owl_list_get_element(&work_fes, i);
166    if (owl_filterelement_is_null(fe)) continue;
167    if (owl_filterelement_is_true(fe)) {
168      tmp=1;
169      break;
170    }
171    if (owl_filterelement_is_false(fe)) {
172      tmp=0;
173      break;
174    }
175  } 
176
177  if (f->polarity) {
178    tmp=!tmp;
179  }
180  owl_list_free_simple(&work_fes);
181  return(tmp);
182}
183
184int _owl_filter_message_match_recurse(owl_filter *f, owl_message *m, owl_list *fes, int start, int end) {
185  int a=0, b=0, i, x, y, z, score, ret, type;
186  owl_filterelement *fe, *tmpfe=NULL;
187
188  /* deal with parens first */
189  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
190    score=x=y=0;
191    for (i=start; i<=end; i++) {
192      fe=owl_list_get_element(fes, i);
193      if (owl_filterelement_is_openbrace(fe)) {
194        if (score==0) x=i;
195        score++;
196      } else if (owl_filterelement_is_closebrace(fe)) {
197        score--;
198        if (score<0) {
199          /* unblanaced parens */
200          return(-1);
201        } else if (score==0) {
202          y=i; /* this is the matching close paren */
203          break;
204        }
205      }
206    }
207    if (score>0) {
208      /* unblanaced parens */
209      return(-1);
210    }
211
212    if (y>0) {
213      /* null out the parens */
214      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
215      owl_list_replace_element(fes, y, owl_global_get_filterelement_null(&g));
216
217      /* simplify the part that was in between */
218      ret=_owl_filter_message_match_recurse(f, m, fes, x+1, y-1);
219      if (ret<0) return(-1);
220
221      /* there may be more, so we continue */
222      continue;
223    } else {
224      /* otherwise we're done with this part */
225      break;
226    }
227  }
228  if (i==OWL_FILTER_MAX_DEPTH) {
229    return(-1);
230  }
231
232  /* and / or / not */
233  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
234    type=score=x=y=z=0;
235    for (i=start; i<=end; i++) {
236      fe=owl_list_get_element(fes, i);
237      if (owl_filterelement_is_null(fe)) continue;
238      if (score==0) {
239        if (owl_filterelement_is_value(fe)) {
240          x=i;
241          score=1;
242          type=1;
243        } else if (owl_filterelement_is_not(fe)) {
244          x=i;
245          score=1;
246          type=2;
247        }
248      } else if (score==1) {
249        if (type==1) {
250          if (owl_filterelement_is_and(fe) || owl_filterelement_is_or(fe)) {
251            score=2;
252            y=i;
253          } else {
254            x=y=z=score=0;
255          }
256        } else if (type==2) {
257          if (owl_filterelement_is_value(fe)) {
258            /* it's a valid "NOT expr" */
259            y=i;
260            break;
261          }
262        }
263      } else if (score==2) {
264        if (owl_filterelement_is_value(fe)) {
265          /* yes, it's a good match */
266          z=i;
267          break;
268        } else {
269          x=y=z=score=0;
270        }
271      }
272    }
273
274    /* process and / or */
275    if ((type==1) && (z>0)) {
276      fe=owl_list_get_element(fes, x);
277      if (owl_filterelement_is_true(fe)) {
278        a=1;
279      } else if (owl_filterelement_is_false(fe)) {
280        a=0;
281      }
282
283      fe=owl_list_get_element(fes, z);
284      if (owl_filterelement_is_true(fe)) {
285        b=1;
286      } else if (owl_filterelement_is_false(fe)) {
287        b=0;
288      }
289
290      fe=owl_list_get_element(fes, y);
291      if (owl_filterelement_is_and(fe)) {
292        if (a && b) {
293          tmpfe=owl_global_get_filterelement_true(&g);
294        } else {
295          tmpfe=owl_global_get_filterelement_false(&g);
296        }
297      } else if (owl_filterelement_is_or(fe)) {
298        if (a || b) {
299          tmpfe=owl_global_get_filterelement_true(&g);
300        } else {
301          tmpfe=owl_global_get_filterelement_false(&g);
302        }
303      }
304      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
305      owl_list_replace_element(fes, y, tmpfe);
306      owl_list_replace_element(fes, z, owl_global_get_filterelement_null(&g));
307    } else if ((type==2) && (y>0)) { /* process NOT */
308      fe=owl_list_get_element(fes, y);
309      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
310      if (owl_filterelement_is_false(fe)) {
311        owl_list_replace_element(fes, y, owl_global_get_filterelement_true(&g));
312      } else {
313        owl_list_replace_element(fes, y, owl_global_get_filterelement_false(&g));
314      }
315    } else {
316      break;
317    }
318  }
319  return(0);
320
321}
322
323void owl_filter_print(owl_filter *f, char *out) {
324  int i, j;
325  owl_filterelement *fe;
326  char *tmp;
327
328  strcpy(out, owl_filter_get_name(f));
329  strcat(out, ": ");
330
331  if (f->color!=OWL_COLOR_DEFAULT) {
332    strcat(out, "-c ");
333    strcat(out, owl_util_color_to_string(f->color));
334    strcat(out, " ");
335  }
336
337  j=owl_list_get_size(&(f->fes));
338  for (i=0; i<j; i++) {
339    fe=owl_list_get_element(&(f->fes), i);
340    tmp=owl_filterelement_to_string(fe);
341    strcat(out, tmp);
342    owl_free(tmp);
343  }
344  strcat(out, "\n");
345}
346
347int owl_filter_equiv(owl_filter *a, owl_filter *b) {
348  char buff[LINE], buff2[LINE];
349
350  owl_filter_print(a, buff);
351  owl_filter_print(b, buff2);
352
353  if (!strcmp(buff, buff2)) return(1);
354  return(0);
355}
356
357void owl_filter_free(owl_filter *f) {
358  void (*func)();
359
360  func=&owl_filterelement_free;
361 
362  if (f->name) owl_free(f->name);
363  owl_list_free_all(&(f->fes), func);
364}
Note: See TracBrowser for help on using the repository browser.