source: filter.c @ de22c3d

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since de22c3d was 12c35df, checked in by James M. Kretchmar <kretch@mit.edu>, 21 years ago
Fixed replies to loopback messages Fixed smartnarrow on classes/instances with spaces Don't allow duplicates in command history Added the 'loggingdirection' variable All loopback messages log to 'loopback' now Print an error message if trying an invalid color for a filter Fixed bug causing > not to go to end of editwin every time
  • Property mode set to 100644
File size: 10.6 KB
RevLine 
[7d4fbcd]1#include <string.h>
2#include "owl.h"
3
[1aee7d9]4static const char fileIdent[] = "$Id$";
5
[e187445]6int owl_filter_init_fromstring(owl_filter *f, char *name, char *string)
7{
[7d4fbcd]8  char **argv;
9  int argc, out;
10
11  argv=owl_parseline(string, &argc);
12  out=owl_filter_init(f, name, argc, argv);
13  /* owl_parsefree(argv, argc); */
14  return(out);
15}
16
[e187445]17int owl_filter_init(owl_filter *f, char *name, int argc, char **argv)
18{
[7d4fbcd]19  int i, error;
20  owl_filterelement *fe;
[65fc0900]21  char *regexstr;
[7d4fbcd]22   
23  f->name=owl_strdup(name);
24  f->polarity=0;
25  f->color=OWL_COLOR_DEFAULT;
[59cf91c]26  f->cachedmsgid=-1;
[7d4fbcd]27  owl_list_create(&(f->fes));
[65fc0900]28 
[7d4fbcd]29  /* first take arguments that have to come first */
30  /* set the color */
31  if (argc>=2 && !strcmp(argv[0], "-c")) {
[12c35df]32    if (owl_util_string_to_color(argv[1])==-1) {
33      owl_function_error("The color '%s' is not available, using default.", argv[1]);
34    } else {
35      f->color=owl_util_string_to_color(argv[1]);
36    }
[7d4fbcd]37    argc-=2;
38    argv+=2;
39  }
[65fc0900]40 
[7d4fbcd]41  /* then deal with the expression */
42  for (i=0; i<argc; i++) {
43    error=0;
44    fe=owl_malloc(sizeof(owl_filterelement));
[65fc0900]45   
[7d4fbcd]46    /* all the 0 argument possibilities */
47    if (!strcmp(argv[i], "(")) {
48      owl_filterelement_create_openbrace(fe);
49    } else if (!strcmp(argv[i], ")")) {
50      owl_filterelement_create_closebrace(fe);
51    } else if (!strcasecmp(argv[i], "and")) {
52      owl_filterelement_create_and(fe);
53    } else if (!strcasecmp(argv[i], "or")) {
54      owl_filterelement_create_or(fe);
55    } else if (!strcasecmp(argv[i], "not")) {
56      owl_filterelement_create_not(fe);
[89426ab]57    } else if (!strcasecmp(argv[i], "true")) {
58      owl_filterelement_create_true(fe);
59    } else if (!strcasecmp(argv[i], "false")) {
60      owl_filterelement_create_false(fe);
[65fc0900]61     
[7d4fbcd]62    } else if (i==argc-1) {
63      error=1;
64    } else {
65      if (!strcasecmp(argv[i], "class") ||
66          !strcasecmp(argv[i], "instance") ||
67          !strcasecmp(argv[i], "sender") ||
68          !strcasecmp(argv[i], "recipient") ||
[75be7c0]69          !strcasecmp(argv[i], "body") ||
[7d4fbcd]70          !strcasecmp(argv[i], "opcode") ||
71          !strcasecmp(argv[i], "realm") ||
[4b464a4]72          !strcasecmp(argv[i], "type") ||
[0c502e9]73          !strcasecmp(argv[i], "direction") ||
[49d467c]74          !strcasecmp(argv[i], "hostname") ||
[0c502e9]75          !strcasecmp(argv[i], "login")) {
[e3d9c77]76        regexstr=owl_text_substitute(argv[i+1], "%me%", owl_zephyr_get_sender());
[65fc0900]77        owl_filterelement_create_re(fe, argv[i], regexstr);
78        owl_free(regexstr);
[7d4fbcd]79        i++;
80      } else {
81        error=1;
82      }
83    }
84
85    if (!error) {
86      owl_list_append_element(&(f->fes), fe);
87    } else {
88      owl_free(fe);
89      owl_filter_free(f);
90      return(-1);
91    }
92
93  }
94  return(0);
95}
96
[e187445]97char *owl_filter_get_name(owl_filter *f)
98{
[7d4fbcd]99  return(f->name);
100}
101
[e187445]102void owl_filter_set_polarity_match(owl_filter *f)
103{
[7d4fbcd]104  f->polarity=0;
105}
106
[e187445]107void owl_filter_set_polarity_unmatch(owl_filter *f)
108{
[7d4fbcd]109  f->polarity=1;
110}
111
[e187445]112void owl_filter_set_color(owl_filter *f, int color)
113{
[7d4fbcd]114  f->color=color;
115}
116
[e187445]117int owl_filter_get_color(owl_filter *f)
118{
[7d4fbcd]119  return(f->color);
120}
121
[e187445]122void owl_filter_set_cachedmsgid(owl_filter *f, int cachedmsgid)
123{
[59cf91c]124  f->cachedmsgid=cachedmsgid;
125}
126
[e187445]127int owl_filter_get_cachedmsgid(owl_filter *f)
128{
[59cf91c]129  return(f->cachedmsgid);
130}
131
[e187445]132int owl_filter_message_match(owl_filter *f, owl_message *m)
133{
[7d4fbcd]134  int i, j, tmp;
135  owl_list work_fes, *fes;
136  owl_filterelement *fe;
137  char *field, *match;
138
[d09e5a1]139  /* create the working list of expression elements */
[7d4fbcd]140  fes=&(f->fes);
141  owl_list_create(&work_fes);
142  j=owl_list_get_size(fes);
143  for (i=0; i<j; i++) {
144    owl_list_append_element(&work_fes, owl_list_get_element(fes, i));
145  }
146
[d09e5a1]147  /* first go thru and evaluate all RE elements to true or false */
[7d4fbcd]148  match="";
149  for (i=0; i<j; i++) {
150    fe=owl_list_get_element(&work_fes, i);
151    if (!owl_filterelement_is_re(fe)) continue;
152    field=owl_filterelement_get_field(fe);
153    if (!strcasecmp(field, "class")) {
154      match=owl_message_get_class(m);
155    } else if (!strcasecmp(field, "instance")) {
156      match=owl_message_get_instance(m);
157    } else if (!strcasecmp(field, "sender")) {
158      match=owl_message_get_sender(m);
159    } else if (!strcasecmp(field, "recipient")) {
160      match=owl_message_get_recipient(m);
[75be7c0]161    } else if (!strcasecmp(field, "body")) {
162      match=owl_message_get_body(m);
[7d4fbcd]163    } else if (!strcasecmp(field, "opcode")) {
164      match=owl_message_get_opcode(m);
165    } else if (!strcasecmp(field, "realm")) {
166      match=owl_message_get_realm(m);
167    } else if (!strcasecmp(field, "type")) {
[37eab7f]168      match=owl_message_get_type(m);
[49d467c]169    } else if (!strcasecmp(field, "hostname")) {
170      match=owl_message_get_hostname(m);
[4b464a4]171    } else if (!strcasecmp(field, "direction")) {
172      if (owl_message_is_direction_out(m)) {
173        match="out";
174      } else if (owl_message_is_direction_in(m)) {
175        match="in";
176      } else if (owl_message_is_direction_none(m)) {
177        match="none";
178      } else {
179        match="";
180      }
[0c502e9]181    } else if (!strcasecmp(field, "login")) {
182      if (owl_message_is_login(m)) {
183        match="login";
184      } else if (owl_message_is_logout(m)) {
185        match="logout";
186      } else {
187        match="none";
188      }
[7d4fbcd]189    }
190   
191    tmp=owl_regex_compare(owl_filterelement_get_re(fe), match);
192    if (!tmp) {
193      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
194    } else {
195      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
196    }
197  }
198
[75be7c0]199  /* call the recrsive helper */
[7d4fbcd]200  i=_owl_filter_message_match_recurse(f, m, &work_fes, 0, owl_list_get_size(&(f->fes))-1);
201
[d09e5a1]202  /* now there will be only one TRUE / FALSE, find it among the NULL's */
[7d4fbcd]203  tmp=0;
204  for (i=0; i<j; i++) {
205    fe=owl_list_get_element(&work_fes, i);
206    if (owl_filterelement_is_null(fe)) continue;
207    if (owl_filterelement_is_true(fe)) {
208      tmp=1;
209      break;
210    }
211    if (owl_filterelement_is_false(fe)) {
212      tmp=0;
213      break;
214    }
215  } 
216
[d09e5a1]217  /* reverse the answer if negative polarity is in use */
218  if (f->polarity) tmp=!tmp;
219
[7d4fbcd]220  owl_list_free_simple(&work_fes);
221  return(tmp);
222}
223
[e187445]224int _owl_filter_message_match_recurse(owl_filter *f, owl_message *m, owl_list *fes, int start, int end)
225{
[7d4fbcd]226  int a=0, b=0, i, x, y, z, score, ret, type;
227  owl_filterelement *fe, *tmpfe=NULL;
228
[d09e5a1]229  /* Deal with parens first. */
[7d4fbcd]230  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
[d09e5a1]231    /* Find first open paren and matching close paren, store in x, y */
[7d4fbcd]232    score=x=y=0;
233    for (i=start; i<=end; i++) {
234      fe=owl_list_get_element(fes, i);
235      if (owl_filterelement_is_openbrace(fe)) {
236        if (score==0) x=i;
237        score++;
238      } else if (owl_filterelement_is_closebrace(fe)) {
239        score--;
240        if (score<0) {
241          /* unblanaced parens */
242          return(-1);
243        } else if (score==0) {
244          y=i; /* this is the matching close paren */
245          break;
246        }
247      }
248    }
249    if (score>0) {
250      /* unblanaced parens */
251      return(-1);
252    }
253
[d09e5a1]254    /* Simply the parens by removing them and evaluating what was in between */
[7d4fbcd]255    if (y>0) {
256      /* null out the parens */
257      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
258      owl_list_replace_element(fes, y, owl_global_get_filterelement_null(&g));
259
[d09e5a1]260      /* evaluate expression in between */
[7d4fbcd]261      ret=_owl_filter_message_match_recurse(f, m, fes, x+1, y-1);
262      if (ret<0) return(-1);
263
264      /* there may be more, so we continue */
265      continue;
266    } else {
267      /* otherwise we're done with this part */
268      break;
269    }
270  }
271  if (i==OWL_FILTER_MAX_DEPTH) {
[d09e5a1]272    /* hit the saftey limit, consider it invalid */
[7d4fbcd]273    return(-1);
274  }
275
[d09e5a1]276  /* Find AND / OR / NOT.
277   *   For binary expressions (AND/OR):
278   *     "type" is 1
279   *     "x" will index first val, "y" the operator and "z" the second val
280   *   For unary expressions (NOT):
281   *     "type" is 2
282   *     "x" will index the operator, "y" the value
283   *   "score" tallys how many expression elements have been found so far
284   */
[7d4fbcd]285  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
286    type=score=x=y=z=0;
287    for (i=start; i<=end; i++) {
288      fe=owl_list_get_element(fes, i);
289      if (owl_filterelement_is_null(fe)) continue;
290      if (score==0) {
291        if (owl_filterelement_is_value(fe)) {
292          x=i;
293          score=1;
294          type=1;
295        } else if (owl_filterelement_is_not(fe)) {
296          x=i;
297          score=1;
298          type=2;
299        }
300      } else if (score==1) {
301        if (type==1) {
302          if (owl_filterelement_is_and(fe) || owl_filterelement_is_or(fe)) {
303            score=2;
304            y=i;
305          } else {
[d09e5a1]306            /* it's not a valid binary expression */
[7d4fbcd]307            x=y=z=score=0;
308          }
309        } else if (type==2) {
310          if (owl_filterelement_is_value(fe)) {
[d09e5a1]311            /* valid unary expression, we're done */
[7d4fbcd]312            y=i;
313            break;
314          }
315        }
316      } else if (score==2) {
317        if (owl_filterelement_is_value(fe)) {
[d09e5a1]318          /* valid binary expression, we're done */
[7d4fbcd]319          z=i;
320          break;
321        } else {
322          x=y=z=score=0;
323        }
324      }
325    }
326
[d09e5a1]327    /* simplify AND / OR */
[7d4fbcd]328    if ((type==1) && (z>0)) {
329      fe=owl_list_get_element(fes, x);
330      if (owl_filterelement_is_true(fe)) {
331        a=1;
332      } else if (owl_filterelement_is_false(fe)) {
333        a=0;
334      }
335
336      fe=owl_list_get_element(fes, z);
337      if (owl_filterelement_is_true(fe)) {
338        b=1;
339      } else if (owl_filterelement_is_false(fe)) {
340        b=0;
341      }
342
343      fe=owl_list_get_element(fes, y);
344      if (owl_filterelement_is_and(fe)) {
345        if (a && b) {
346          tmpfe=owl_global_get_filterelement_true(&g);
347        } else {
348          tmpfe=owl_global_get_filterelement_false(&g);
349        }
350      } else if (owl_filterelement_is_or(fe)) {
351        if (a || b) {
352          tmpfe=owl_global_get_filterelement_true(&g);
353        } else {
354          tmpfe=owl_global_get_filterelement_false(&g);
355        }
356      }
357      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
358      owl_list_replace_element(fes, y, tmpfe);
359      owl_list_replace_element(fes, z, owl_global_get_filterelement_null(&g));
[d09e5a1]360    } else if ((type==2) && (y>0)) {
361      /* simplify NOT */
[7d4fbcd]362      fe=owl_list_get_element(fes, y);
363      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
364      if (owl_filterelement_is_false(fe)) {
365        owl_list_replace_element(fes, y, owl_global_get_filterelement_true(&g));
366      } else {
367        owl_list_replace_element(fes, y, owl_global_get_filterelement_false(&g));
368      }
369    } else {
370      break;
371    }
372  }
373  return(0);
374
375}
376
[e187445]377void owl_filter_print(owl_filter *f, char *out)
378{
[7d4fbcd]379  int i, j;
380  owl_filterelement *fe;
381  char *tmp;
382
383  strcpy(out, owl_filter_get_name(f));
384  strcat(out, ": ");
385
386  if (f->color!=OWL_COLOR_DEFAULT) {
387    strcat(out, "-c ");
388    strcat(out, owl_util_color_to_string(f->color));
389    strcat(out, " ");
390  }
391
392  j=owl_list_get_size(&(f->fes));
393  for (i=0; i<j; i++) {
394    fe=owl_list_get_element(&(f->fes), i);
395    tmp=owl_filterelement_to_string(fe);
396    strcat(out, tmp);
397    owl_free(tmp);
398  }
399  strcat(out, "\n");
400}
401
[e187445]402int owl_filter_equiv(owl_filter *a, owl_filter *b)
403{
[7d4fbcd]404  char buff[LINE], buff2[LINE];
405
406  owl_filter_print(a, buff);
407  owl_filter_print(b, buff2);
408
409  if (!strcmp(buff, buff2)) return(1);
410  return(0);
411}
412
[e187445]413void owl_filter_free(owl_filter *f)
414{
[7d4fbcd]415  void (*func)();
416
417  func=&owl_filterelement_free;
418 
419  if (f->name) owl_free(f->name);
420  owl_list_free_all(&(f->fes), func);
421}
Note: See TracBrowser for help on using the repository browser.