[339] in BarnOwl Developers

home help back first fref pref prev next nref lref last post

[D-O-H] r484 - in trunk: . owl owl/perl/modules

daemon@ATHENA.MIT.EDU (nelhage@MIT.EDU)
Thu Oct 29 18:05:05 2009

Resent-From: nelhage@mit.edu
Resent-To: barnowl-dev-mtg@charon.mit.edu
To: dirty-owl-hackers@mit.edu
From: nelhage@MIT.EDU
Reply-to: dirty-owl-hackers@MIT.EDU
Date: Tue, 26 Dec 2006 01:05:26 -0500 (EST)

Author: nelhage
Date: 2006-12-26 01:05:26 -0500 (Tue, 26 Dec 2006)
New Revision: 484

Modified:
   trunk/
   trunk/owl/filter.c
   trunk/owl/filterelement.c
   trunk/owl/global.c
   trunk/owl/owl.c
   trunk/owl/owl.h
   trunk/owl/perl/modules/jabber.pl
   trunk/owl/regex.c
   trunk/owl/tester.c
Log:
 r15874@phanatique:  nelhage | 2006-12-24 18:25:33 -0500
 Don't quit if we can't contact the hostmaster. 
 r15884@phanatique:  nelhage | 2006-12-24 18:56:03 -0500
 Respect the displayoutgoing variable
 r15885@phanatique:  nelhage | 2006-12-24 20:10:44 -0500
 You can now write filters based off arbitrary message attributes
 r15887@phanatique:  nelhage | 2006-12-24 22:59:39 -0500
  r15886@phanatique (orig r476):  nelhage | 2006-12-24 22:59:10 -0500
   r24493@heretique:  nelhage | 2006-12-24 22:59:02 -0500
   Moving zephyr initialization later, so that zephyr works again
  
 
 r15891@phanatique:  nelhage | 2006-12-25 14:40:08 -0500
 * perl messages hashes use `private', not `isprivate'
 * get rid of a perl warning if login fails
 r15900@phanatique:  nelhage | 2006-12-25 21:04:15 -0500
 Merging in filter regression tests from my local branch.
 r15926@phanatique:  nelhage | 2006-12-26 00:57:07 -0500
  r15901@phanatique:  nelhage | 2006-12-25 21:08:47 -0500
  Base framework for the filter rewrite system. Only understands regexes and true/false so far.
 
 r15927@phanatique:  nelhage | 2006-12-26 00:57:08 -0500
  r15902@phanatique:  nelhage | 2006-12-25 23:03:33 -0500
  support for negation and parentheses
 
 r15928@phanatique:  nelhage | 2006-12-26 00:57:08 -0500
  r15924@phanatique:  nelhage | 2006-12-26 00:16:30 -0500
  Now passing all tests except for recursion detection
 
 r15929@phanatique:  nelhage | 2006-12-26 00:57:08 -0500
  r15925@phanatique:  nelhage | 2006-12-26 00:52:09 -0500
  Checking for filter recursion loops
 



Property changes on: trunk
___________________________________________________________________
Name: svk:merge
   - bb873fd7-8e23-0410-944a-99ec44c633eb:/local/d-o-h/trunk:15872
   + bb873fd7-8e23-0410-944a-99ec44c633eb:/branches/owl/filter-rewrite:15925
bb873fd7-8e23-0410-944a-99ec44c633eb:/local/d-o-h/trunk:15935

Modified: trunk/owl/filter.c
===================================================================
--- trunk/owl/filter.c	2006-12-26 06:00:43 UTC (rev 483)
+++ trunk/owl/filter.c	2006-12-26 06:05:26 UTC (rev 484)
@@ -18,17 +18,11 @@
 
 int owl_filter_init(owl_filter *f, char *name, int argc, char **argv)
 {
-  int i, j, error;
-  owl_filterelement *fe;
-  char *regexstr;
-  owl_list list;
-   
   f->name=owl_strdup(name);
   f->polarity=0;
   f->color=OWL_COLOR_DEFAULT;
   f->cachedmsgid=-1;
-  owl_list_create(&(f->fes));
-  
+
   /* first take arguments that have to come first */
   /* set the color */
   if (argc>=2 && !strcmp(argv[0], "-c")) {
@@ -40,78 +34,115 @@
     argc-=2;
     argv+=2;
   }
-  
-  /* then deal with the expression */
-  for (i=0; i<argc; i++) {
-    error=0;
-    fe=owl_malloc(sizeof(owl_filterelement));
-    
-    /* all the 0 argument possibilities */
-    if (!strcmp(argv[i], "(")) {
-      owl_filterelement_create_openbrace(fe);
-    } else if (!strcmp(argv[i], ")")) {
-      owl_filterelement_create_closebrace(fe);
-    } else if (!strcasecmp(argv[i], "and")) {
-      owl_filterelement_create_and(fe);
-    } else if (!strcasecmp(argv[i], "or")) {
-      owl_filterelement_create_or(fe);
-    } else if (!strcasecmp(argv[i], "not")) {
-      owl_filterelement_create_not(fe);
-    } else if (!strcasecmp(argv[i], "true")) {
-      owl_filterelement_create_true(fe);
-    } else if (!strcasecmp(argv[i], "false")) {
-      owl_filterelement_create_false(fe);
-      
-    } else if (i==argc-1) { /* we need more than one arg at this point */
-      error=1;
-    } else {
-      if (!strcasecmp(argv[i], "filter")) {
-	owl_filterelement_create_filter(fe, argv[i+1]);
-	i++;
-      } else if (!strcasecmp(argv[i], "perl")) {
-	owl_filterelement_create_perl(fe, argv[i+1]);
-	i++;
-      } else {
-	regexstr=owl_text_substitute(argv[i+1], "%me%", owl_zephyr_get_sender());
-	owl_filterelement_create_re(fe, argv[i], regexstr);
-	owl_free(regexstr);
-	i++;
-      } 
-    }
 
-    if (!error) {
-      owl_list_append_element(&(f->fes), fe);
-    } else {
-      owl_free(fe);
-      owl_filter_free(f);
-      return(-1);
-    }
-  }
-  
-  /* Are we trying to use the filter we're creating?  Bad. */
-  owl_list_create(&list);
-  _owl_filter_get_subfilter_names(f, &list);
-  j=owl_list_get_size(&list);
-  for (i=0; i<j; i++) {
-    if (!strcasecmp(name, owl_list_get_element(&list, i))) {
-      owl_function_error("Filter loop.");
-      owl_filter_free(f);
-      owl_list_free_all(&list, owl_free);
-      return(-1);
-    }
-  }
-  owl_list_free_all(&list, owl_free);
+  if(!(f->root = owl_filter_parse_expression(argc, argv, NULL)))
+    return(-1);
 
-  /* Now check for more subtle recursion. */
+  /* Now check for recursion. */
   if (owl_filter_is_toodeep(f)) {
     owl_function_error("Filter loop or exceeds recursion depth");
     owl_filter_free(f);
     return(-1);
   }
-  
+
   return(0);
 }
 
+
+/* A primitive expression is one without any toplevel ``and'' or ``or''s*/
+
+static owl_filterelement * owl_filter_parse_primitive_expression(int argc, char **argv, int *next)
+{
+  if(!argc) return NULL;
+
+  owl_filterelement * fe = owl_malloc(sizeof(owl_filterelement));
+  owl_filterelement *op;
+
+  owl_filterelement_create(fe);
+  int i = 0, skip;
+
+  if(!strcasecmp(argv[i], "(")) {
+    i++;
+    op = owl_filter_parse_expression(argc-i, argv+i, &skip);
+    if(!op) goto err;
+    i += skip;
+    if(strcasecmp(argv[i++], ")")) goto err;
+    owl_filterelement_create_group(fe, op);
+  } else if(!strcasecmp(argv[i], "not")) {
+    i++;
+    op = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
+    if(!op) goto err;
+    i += skip;
+    owl_filterelement_create_not(fe, op);
+  } else if(!strcasecmp(argv[i], "true")) {
+    i++;
+    owl_filterelement_create_true(fe);
+  } else if(!strcasecmp(argv[i], "false")) {
+    i++;
+    owl_filterelement_create_false(fe);
+  } else {
+    if(argc == 1) goto err;
+    if(!strcasecmp(*argv, "filter")) {
+      owl_filterelement_create_filter(fe, *(argv+1));
+    } else if(!strcasecmp(*argv, "perl")) {
+      owl_filterelement_create_perl(fe, *(argv+1));
+    } else {
+      owl_filterelement_create_re(fe, *argv, *(argv+1));
+    }
+    i += 2;
+  }
+
+  if(next) {
+    *next = i;
+  } else if(i != argc) {
+    goto err;
+  }
+  return fe;
+err:
+  owl_filterelement_free(fe);
+  owl_free(fe);
+  return NULL;
+}
+
+owl_filterelement * owl_filter_parse_expression(int argc, char **argv, int *next)
+{
+  int i = 0, skip;
+  owl_filterelement * op1 = NULL, * op2 = NULL;
+
+  op1 = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
+  i += skip;
+  if(!op1) goto err;
+
+  while(i < argc) {
+    if(strcasecmp(argv[i], "and") &&
+       strcasecmp(argv[i], "or")) break;
+    op2 = owl_filter_parse_primitive_expression(argc-i-1, argv+i+1, &skip);
+    if(!op2) goto err;
+    owl_filterelement * tmp = owl_malloc(sizeof(owl_filterelement));
+    if(!strcasecmp(argv[i], "and")) {
+      owl_filterelement_create_and(tmp, op1, op2);
+    } else {
+      owl_filterelement_create_or(tmp, op1, op2);
+    }
+    op1 = tmp;
+    op2 = NULL;
+    i += skip+1;
+  }
+
+  if(next) {
+    *next = i;
+  } else if(i != argc) {
+    goto err;
+  }
+  return op1;
+err:
+  if(op1) {
+    owl_filterelement_free(op1);
+    owl_free(op1);
+  }
+  return NULL;
+}
+
 char *owl_filter_get_name(owl_filter *f)
 {
   return(f->name);
@@ -152,318 +183,18 @@
  */
 int owl_filter_message_match(owl_filter *f, owl_message *m)
 {
-  int i, j, tmp;
-  owl_list work_fes, *fes;
-  owl_filterelement *fe;
-  char *field, *match;
-
-  /* create the working list of expression elements */
-  fes=&(f->fes);
-  owl_list_create(&work_fes);
-  j=owl_list_get_size(fes);
-  for (i=0; i<j; i++) {
-    owl_list_append_element(&work_fes, owl_list_get_element(fes, i));
-  }
-
-  /* first go thru and evaluate all RE elements to true or false */
-  match="";
-  for (i=0; i<j; i++) {
-    fe=owl_list_get_element(&work_fes, i);
-    if (!owl_filterelement_is_re(fe)) continue;
-    field=owl_filterelement_get_field(fe);
-    if (!strcasecmp(field, "class")) {
-      match=owl_message_get_class(m);
-    } else if (!strcasecmp(field, "instance")) {
-      match=owl_message_get_instance(m);
-    } else if (!strcasecmp(field, "sender")) {
-      match=owl_message_get_sender(m);
-    } else if (!strcasecmp(field, "recipient")) {
-      match=owl_message_get_recipient(m);
-    } else if (!strcasecmp(field, "body")) {
-      match=owl_message_get_body(m);
-    } else if (!strcasecmp(field, "opcode")) {
-      match=owl_message_get_opcode(m);
-    } else if (!strcasecmp(field, "realm")) {
-      match=owl_message_get_realm(m);
-    } else if (!strcasecmp(field, "type")) {
-      match=owl_message_get_type(m);
-    } else if (!strcasecmp(field, "hostname")) {
-      match=owl_message_get_hostname(m);
-    } else if (!strcasecmp(field, "direction")) {
-      if (owl_message_is_direction_out(m)) {
-	match="out";
-      } else if (owl_message_is_direction_in(m)) {
-	match="in";
-      } else if (owl_message_is_direction_none(m)) {
-	match="none";
-      } else {
-	match="";
-      }
-    } else if (!strcasecmp(field, "login")) {
-      if (owl_message_is_login(m)) {
-	match="login";
-      } else if (owl_message_is_logout(m)) {
-	match="logout";
-      } else {
-	match="none";
-      }
-    } else {
-      match = owl_message_get_attribute_value(m,field);
-      if(match == NULL) match = "";
-    }
-
-    tmp=owl_regex_compare(owl_filterelement_get_re(fe), match);
-    if (!tmp) {
-      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
-    } else {
-      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
-    }
-  }
-
-  /* now subfilters and perl functions */
-  for (i=0; i<j; i++) {
-    owl_filter *subfilter;
-			   
-    fe=owl_list_get_element(&work_fes, i);
-
-    if (owl_filterelement_is_filter(fe)) {
-
-      subfilter=owl_global_get_filter(&g, owl_filterelement_get_filtername(fe));
-      if (!subfilter) {
-	/* the filter does not exist, maybe because it was deleted.
-	 * Default to not matching
-	 */
-	owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
-      } else if (owl_filter_message_match(subfilter, m)) {
-	owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
-      } else {
-	owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
-      }
-
-    } else if (owl_filterelement_is_perl(fe)) {
-      char *subname, *perlrv;
-      int   tf=0;
-
-      subname = owl_filterelement_get_filtername(fe);
-      if (!owl_perlconfig_is_function(subname)) {
-	owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
-	continue;
-      }
-      perlrv = owl_perlconfig_call_with_message(subname, m);
-      if (perlrv) {
-	if (0 == strcmp(perlrv, "1")) {
-	  tf=1;
-	}
-	owl_free(perlrv);
-      } 
-      if (tf) {
-	owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
-      } else {
-	owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
-      }
-    }
-  }
-
-  /* call the recrsive helper */
-  i=_owl_filter_message_match_recurse(f, m, &work_fes, 0, owl_list_get_size(&(f->fes))-1);
-
-  /* now there will be only one TRUE / FALSE, find it among the NULL's */
-  tmp=0;
-  for (i=0; i<j; i++) {
-    fe=owl_list_get_element(&work_fes, i);
-    if (owl_filterelement_is_null(fe)) continue;
-    if (owl_filterelement_is_true(fe)) {
-      tmp=1;
-      break;
-    }
-    if (owl_filterelement_is_false(fe)) {
-      tmp=0;
-      break;
-    }
-  }  
-
-  /* reverse the answer if negative polarity is in use */
-  if (f->polarity) tmp=!tmp;
-
-  owl_list_free_simple(&work_fes);
-  return(tmp);
+  if(!f->root) return 0;
+  int ret = owl_filterelement_match(f->root, m);
+  if(f->polarity) ret = !ret;
+  return ret;
 }
 
-int _owl_filter_message_match_recurse(owl_filter *f, owl_message *m, owl_list *fes, int start, int end)
-{
-  int a=0, b=0, i, x, y, z, score, ret, type;
-  owl_filterelement *fe, *tmpfe=NULL;
 
-  /* Deal with parens first. */
-  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
-    /* Find first open paren and matching close paren, store in x, y */
-    score=x=y=0;
-    for (i=start; i<=end; i++) {
-      fe=owl_list_get_element(fes, i);
-      if (owl_filterelement_is_openbrace(fe)) {
-	if (score==0) x=i;
-	score++;
-      } else if (owl_filterelement_is_closebrace(fe)) {
-	score--;
-	if (score<0) {
-	  /* unblanaced parens */
-	  return(-1);
-	} else if (score==0) {
-	  y=i; /* this is the matching close paren */
-	  break;
-	}
-      }
-    }
-    if (score>0) {
-      /* unblanaced parens */
-      return(-1);
-    }
-
-    /* Simply the parens by removing them and evaluating what was in between */
-    if (y>0) {
-      /* null out the parens */
-      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
-      owl_list_replace_element(fes, y, owl_global_get_filterelement_null(&g));
-
-      /* evaluate expression in between */
-      ret=_owl_filter_message_match_recurse(f, m, fes, x+1, y-1);
-      if (ret<0) return(-1);
-
-      /* there may be more, so we continue */
-      continue;
-    } else {
-      /* otherwise we're done with this part */
-      break;
-    }
-  }
-  if (i==OWL_FILTER_MAX_DEPTH) {
-    /* hit the saftey limit, consider it invalid */
-    return(-1);
-  }
-
-  /* Find AND / OR / NOT.
-   *   For binary expressions (AND/OR):
-   *     "type" is 1
-   *     "x" will index first val, "y" the operator and "z" the second val
-   *   For unary expressions (NOT):
-   *     "type" is 2
-   *     "x" will index the operator, "y" the value
-   *   "score" tallys how many expression elements have been found so far
-   */
-  for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
-    type=score=x=y=z=0;
-    for (i=start; i<=end; i++) {
-      fe=owl_list_get_element(fes, i);
-      if (owl_filterelement_is_null(fe)) continue;
-      if (score==0) {
-	if (owl_filterelement_is_value(fe)) {
-	  x=i;
-	  score=1;
-	  type=1;
-	} else if (owl_filterelement_is_not(fe)) {
-	  x=i;
-	  score=1;
-	  type=2;
-	}
-      } else if (score==1) {
-	if (type==1) {
-	  if (owl_filterelement_is_and(fe) || owl_filterelement_is_or(fe)) {
-	    score=2;
-	    y=i;
-	  } else {
-	    /* it's not a valid binary expression */
-	    x=y=z=score=0;
-	  }
-	} else if (type==2) {
-	  if (owl_filterelement_is_value(fe)) {
-	    /* valid unary expression, we're done */
-	    y=i;
-	    break;
-	  }
-	}
-      } else if (score==2) {
-	if (owl_filterelement_is_value(fe)) {
-	  /* valid binary expression, we're done */
-	  z=i;
-	  break;
-	} else {
-	  x=y=z=score=0;
-	}
-      }
-    }
-
-    /* simplify AND / OR */
-    if ((type==1) && (z>0)) {
-      fe=owl_list_get_element(fes, x);
-      if (owl_filterelement_is_true(fe)) {
-	a=1;
-      } else if (owl_filterelement_is_false(fe)) {
-	a=0;
-      }
-
-      fe=owl_list_get_element(fes, z);
-      if (owl_filterelement_is_true(fe)) {
-	b=1;
-      } else if (owl_filterelement_is_false(fe)) {
-	b=0;
-      }
-
-      fe=owl_list_get_element(fes, y);
-      if (owl_filterelement_is_and(fe)) {
-	if (a && b) {
-	  tmpfe=owl_global_get_filterelement_true(&g);
-	} else {
-	  tmpfe=owl_global_get_filterelement_false(&g);
-	}
-      } else if (owl_filterelement_is_or(fe)) {
-	if (a || b) {
-	  tmpfe=owl_global_get_filterelement_true(&g);
-	} else {
-	  tmpfe=owl_global_get_filterelement_false(&g);
-	}
-      }
-      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
-      owl_list_replace_element(fes, y, tmpfe);
-      owl_list_replace_element(fes, z, owl_global_get_filterelement_null(&g));
-    } else if ((type==2) && (y>0)) {
-      /* simplify NOT */
-      fe=owl_list_get_element(fes, y);
-      owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
-      if (owl_filterelement_is_false(fe)) {
-	owl_list_replace_element(fes, y, owl_global_get_filterelement_true(&g));
-      } else {
-	owl_list_replace_element(fes, y, owl_global_get_filterelement_false(&g));
-      }
-    } else {
-      break;
-    }
-  }
-  return(0);
-
-}
-
 void owl_filter_print(owl_filter *f, char *out)
 {
-  int i, j;
-  owl_filterelement *fe;
-  char *tmp;
-
-  strcpy(out, owl_filter_get_name(f));
-  strcat(out, ": ");
-
-  if (f->color!=OWL_COLOR_DEFAULT) {
-    strcat(out, "-c ");
-    strcat(out, owl_util_color_to_string(f->color));
-    strcat(out, " ");
-  }
-
-  j=owl_list_get_size(&(f->fes));
-  for (i=0; i<j; i++) {
-    fe=owl_list_get_element(&(f->fes), i);
-    tmp=owl_filterelement_to_string(fe);
-    strcat(out, tmp);
-    owl_free(tmp);
-  }
+  strcpy(out, "");
+  if(!f->root) return;
+  owl_filterelement_print(f->root, out);
   strcat(out, "\n");
 }
 
@@ -479,108 +210,110 @@
   return(0);
 }
 
-/* Private
- * 'list' should already be allocated and initialized
- * This function places into list the string names of all filters
- * used in the filter expression for 'f'.
- * Caller must do a full free on 'list', including elements.
- */
-void _owl_filter_get_subfilter_names(owl_filter *f, owl_list *list)
+
+int owl_filter_is_toodeep(owl_filter *f)
 {
-  int i, j;
-  owl_filterelement *fe;
+  return owl_filterelement_is_toodeep(f, f->root);
+}
 
-  j=owl_list_get_size(&(f->fes));
-  for (i=0; i<j; i++) {
-    fe=owl_list_get_element(&(f->fes), i);
-    if (owl_filterelement_is_filter(fe)) {
-      owl_list_append_element(list, owl_strdup(owl_filterelement_get_filtername(fe)));
-    }
+void owl_filter_free(owl_filter *f)
+{
+  if(f->root) {
+    owl_filterelement_free(f->root);
+    owl_free(f->root);
   }
+  if (f->name) owl_free(f->name);
 }
 
-int owl_filter_is_toodeep(owl_filter *f)
-{
-  owl_list seen, tocheck, tmp;
-  int i, j, x, y;
-  owl_filter *subfilter;
+/**************************************************************************/
+/************************* REGRESSION TESTS *******************************/
+/**************************************************************************/
 
-  owl_list_create(&seen);
-  owl_list_create(&tocheck);
-  owl_list_create(&tmp);
+#ifdef OWL_INCLUDE_REG_TESTS
 
-  /* seed 'tocheck' with the first set of filters */
-  _owl_filter_get_subfilter_names(f, &tmp);
-  j=owl_list_get_size(&tmp);
-  for (i=0; i<j; i++) {
-    owl_util_list_add_unique_string(&tocheck, owl_list_get_element(&tmp, i));
+int owl_filter_test_string(char * filt, owl_message *m, int shouldmatch) /* noproto */ {
+  owl_filter f;
+  int ok;
+  int failed = 0;
+  if(owl_filter_init_fromstring(&f, "test-filter", filt)) {
+    printf("\tFAIL: parse %s\n", filt);
+    failed = 1;
+    goto out;
   }
-  owl_list_free_all(&tmp, owl_free);
-  owl_list_create(&tmp);
+  ok = owl_filter_message_match(&f, m);
+  if((shouldmatch && !ok) || (!shouldmatch && ok)) {
+    printf("\tFAIL: match %s (got %d, expected %d)\n", filt, ok, shouldmatch);
+    failed = 1;
+  }
+ out:
+  owl_filter_free(&f);
+  if(!failed) {
+    printf("\tok  : %s %s\n", shouldmatch ? "matches" : "doesn't match", filt);
+  }
+  return failed;
+}
 
-  /* add this list to the 'seen' list */
-  owl_list_append_element(&seen, owl_strdup(owl_filter_get_name(f)));
 
-  for (i=0; i<OWL_FILTER_MAXRECURSE; i++) {
-    /* if anything in 'tocheck' is in 'seen' we have a loop */
-    if (owl_util_common_strings_in_lists(&tocheck, &seen)) {
-      owl_list_free_all(&tmp, owl_free);
-      owl_list_free_all(&tocheck, owl_free);
-      owl_list_free_all(&seen, owl_free);
-      return(1);
-    }
+#include "test.h"
 
-    /* if there's nothing to check, we're done */
-    y=owl_list_get_size(&tocheck);
-    if (y==0) {
-      owl_list_free_all(&tmp, owl_free);
-      owl_list_free_all(&tocheck, owl_free);
-      owl_list_free_all(&seen, owl_free);
-      return(0);
-    }
 
-    /* add everything in 'tocheck' to the 'seen' list */
-    /* y=owl_list_get_size(&tocheck); */
-    for (x=0; x<y; x++) {
-      owl_list_append_element(&seen, owl_strdup(owl_list_get_element(&tocheck, x)));
-    }
+int owl_filter_regtest(void) {
+  owl_list_create(&(g.filterlist));
+  int numfailed=0;
+  owl_message m;
+  owl_message_init(&m);
+  owl_message_set_type_zephyr(&m);
+  owl_message_set_direction_in(&m);
+  owl_message_set_class(&m, "owl");
+  owl_message_set_instance(&m, "tester");
+  owl_message_set_sender(&m, "owl-user");
+  owl_message_set_recipient(&m, "joe");
+  owl_message_set_attribute(&m, "foo", "bar");
 
-    /* make a new list into 'tmp' with the children of 'tocheck' */
-    /* y=owl_list_get_size(&tocheck); */
-    for (x=0; x<y; x++) {
-      subfilter=owl_global_get_filter(&g, owl_list_get_element(&tocheck, x));
-      if (!subfilter) return(0);
-      _owl_filter_get_subfilter_names(subfilter, &tmp);
-    }
+#define TEST_FILTER(f, e) numfailed += owl_filter_test_string(f, &m, e)
 
-    /* clean out 'tocheck' */
-    owl_list_free_all(&tocheck, owl_free);
-    owl_list_create(&tocheck);
 
-    /* put 'tmp' into 'tocheck' */
-    y=owl_list_get_size(&tmp);
-    for (x=0; x<y; x++) {
-      owl_util_list_add_unique_string(&tocheck, owl_list_get_element(&tmp, x));
-    }
+  TEST_FILTER("true", 1);
+  TEST_FILTER("false", 0);
+  TEST_FILTER("( true )", 1);
+  TEST_FILTER("not false", 1);
+  TEST_FILTER("( true ) or ( false )", 1);
+  TEST_FILTER("true and false", 0);
+  TEST_FILTER("( true or true ) or ( ( false ) )", 1);
 
-    /* clean out 'tmp' */
-    owl_list_free_all(&tmp, owl_free);
-    owl_list_create(&tmp);
-  }
+  TEST_FILTER("class owl", 1);
+  TEST_FILTER("class ^owl$", 1);
+  TEST_FILTER("instance test", 1);
+  TEST_FILTER("instance ^test$", 0);
+  TEST_FILTER("instance ^tester$", 1);
 
-  owl_list_free_all(&tmp, owl_free);
-  owl_list_free_all(&tocheck, owl_free);
-  owl_list_free_all(&seen, owl_free);
+  TEST_FILTER("foo bar", 1);
+  TEST_FILTER("class owl and instance tester", 1);
+  TEST_FILTER("type ^zephyr$ and direction ^in$ and ( class ^owl$ or instance ^owl$ )", 1);
 
-  return(1);
-}
+  // Order of operations and precedence
+  TEST_FILTER("not true or false", 0);
+  TEST_FILTER("true or true and false", 0);
+  TEST_FILTER("true and true and false or true", 1);
+  TEST_FILTER("false and false or true", 1);
+  TEST_FILTER("true and false or false", 0);
 
-void owl_filter_free(owl_filter *f)
-{
-  void (*func)();
+  owl_filter f1, f2, f3, f4;
 
-  func=&owl_filterelement_free;
-  
-  if (f->name) owl_free(f->name);
-  owl_list_free_all(&(f->fes), func);
+  owl_filter_init_fromstring(&f1, "f1", "class owl");
+  owl_global_add_filter(&g, &f1);
+  TEST_FILTER("filter f1", 1);
+
+  // Test recursion prevention
+  FAIL_UNLESS("self reference", owl_filter_init_fromstring(&f2, "test", "filter test"));
+
+  // mutual recursion
+  owl_filter_init_fromstring(&f3, "f3", "filter f4");
+  owl_global_add_filter(&g, &f3);
+  FAIL_UNLESS("mutual recursion",   owl_filter_init_fromstring(&f4, "f4", "filter f3"));
+
+  return 0;
 }
+
+
+#endif /* OWL_INCLUDE_REG_TESTS */

Modified: trunk/owl/filterelement.c
===================================================================
--- trunk/owl/filterelement.c	2006-12-26 06:00:43 UTC (rev 483)
+++ trunk/owl/filterelement.c	2006-12-26 06:05:26 UTC (rev 484)
@@ -2,214 +2,320 @@
 
 static const char fileIdent[] = "$Id$";
 
-#define OWL_FILTERELEMENT_NULL        0
-#define OWL_FILTERELEMENT_TRUE        1
-#define OWL_FILTERELEMENT_FALSE       2
-#define OWL_FILTERELEMENT_OPENBRACE   3
-#define OWL_FILTERELEMENT_CLOSEBRACE  4
-#define OWL_FILTERELEMENT_AND         5
-#define OWL_FILTERELEMENT_OR          6
-#define OWL_FILTERELEMENT_NOT         7
-#define OWL_FILTERELEMENT_RE          8
-#define OWL_FILTERELEMENT_FILTER      9
-#define OWL_FILTERELEMENT_PERL       10
+static char * owl_filterelement_get_field(owl_message *m, char * field)
+{
+  char *match;
+  if (!strcasecmp(field, "class")) {
+    match=owl_message_get_class(m);
+  } else if (!strcasecmp(field, "instance")) {
+    match=owl_message_get_instance(m);
+  } else if (!strcasecmp(field, "sender")) {
+    match=owl_message_get_sender(m);
+  } else if (!strcasecmp(field, "recipient")) {
+    match=owl_message_get_recipient(m);
+  } else if (!strcasecmp(field, "body")) {
+    match=owl_message_get_body(m);
+  } else if (!strcasecmp(field, "opcode")) {
+    match=owl_message_get_opcode(m);
+  } else if (!strcasecmp(field, "realm")) {
+    match=owl_message_get_realm(m);
+  } else if (!strcasecmp(field, "type")) {
+    match=owl_message_get_type(m);
+  } else if (!strcasecmp(field, "hostname")) {
+    match=owl_message_get_hostname(m);
+  } else if (!strcasecmp(field, "direction")) {
+    if (owl_message_is_direction_out(m)) {
+      match="out";
+    } else if (owl_message_is_direction_in(m)) {
+      match="in";
+    } else if (owl_message_is_direction_none(m)) {
+      match="none";
+    } else {
+      match="";
+    }
+  } else if (!strcasecmp(field, "login")) {
+    if (owl_message_is_login(m)) {
+      match="login";
+    } else if (owl_message_is_logout(m)) {
+      match="logout";
+    } else {
+      match="none";
+    }
+  } else {
+    match = owl_message_get_attribute_value(m,field);
+    if(match == NULL) match = "";
+  }
 
-void owl_filterelement_create_null(owl_filterelement *fe)
+  return match;
+}
+
+static int owl_filterelement_match_false(owl_filterelement *fe, owl_message *m)
 {
-  fe->type=OWL_FILTERELEMENT_NULL;
-  fe->field=NULL;
-  fe->filtername=NULL;
+  return 0;
 }
 
-void owl_filterelement_create_openbrace(owl_filterelement *fe)
+static int owl_filterelement_match_true(owl_filterelement *fe, owl_message *m)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_OPENBRACE;
+  return 1;
 }
 
-void owl_filterelement_create_closebrace(owl_filterelement *fe)
+static int owl_filterelement_match_re(owl_filterelement *fe, owl_message *m)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_CLOSEBRACE;
+  char * val = owl_filterelement_get_field(m, fe->field);
+  return !owl_regex_compare(&(fe->re), val);
 }
 
-void owl_filterelement_create_and(owl_filterelement *fe)
+static int owl_filterelement_match_filter(owl_filterelement *fe, owl_message *m)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_AND;
+  owl_filter *subfilter;
+  subfilter=owl_global_get_filter(&g, fe->field);
+  if (!subfilter) {
+    /* the filter does not exist, maybe because it was deleted.
+     * Default to not matching
+     */
+    return 0;
+  } 
+  return owl_filter_message_match(subfilter, m);
 }
 
-void owl_filterelement_create_or(owl_filterelement *fe)
+static int owl_filterelement_match_perl(owl_filterelement *fe, owl_message *m)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_OR;
+  char *subname, *perlrv;
+  int   tf=0;
+
+  subname = fe->field;
+  if (!owl_perlconfig_is_function(subname)) {
+    return 0;
+  }
+  perlrv = owl_perlconfig_call_with_message(subname, m);
+  if (perlrv) {
+    if (0 == strcmp(perlrv, "1")) {
+      tf=1;
+    }
+    owl_free(perlrv);
+  }
+  return tf;
 }
 
-void owl_filterelement_create_not(owl_filterelement *fe)
+static int owl_filterelement_match_group(owl_filterelement *fe, owl_message *m)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_NOT;
+  return owl_filterelement_match(fe->left, m);
 }
 
-void owl_filterelement_create_true(owl_filterelement *fe)
+/* XXX: Our boolea operators short-circuit here. The original owl did
+   not. Do we care?
+*/
+
+static int owl_filterelement_match_and(owl_filterelement *fe, owl_message *m)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_TRUE;
+  return owl_filterelement_match(fe->left, m) &&
+    owl_filterelement_match(fe->right, m);
 }
 
-void owl_filterelement_create_false(owl_filterelement *fe)
+static int owl_filterelement_match_or(owl_filterelement *fe, owl_message *m)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_FALSE;
+  return owl_filterelement_match(fe->left, m) ||
+    owl_filterelement_match(fe->right, m);
 }
 
-void owl_filterelement_create_re(owl_filterelement *fe, char *field, char *re)
+static int owl_filterelement_match_not(owl_filterelement *fe, owl_message *m)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_RE;
-  fe->field=owl_strdup(field);
-  owl_regex_create(&(fe->re), re);
+  return !owl_filterelement_match(fe->left, m);
 }
 
-void owl_filterelement_create_filter(owl_filterelement *fe, char *name)
+// Print methods
+
+static void owl_filterelement_print_true(owl_filterelement *fe, char *buf)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_FILTER;
-  fe->filtername=owl_strdup(name);
+  strcat(buf, "true");
 }
 
-void owl_filterelement_create_perl(owl_filterelement *fe, char *name)
+static void owl_filterelement_print_false(owl_filterelement *fe, char *buf)
 {
-  owl_filterelement_create_null(fe);
-  fe->type=OWL_FILTERELEMENT_PERL;
-  fe->filtername=owl_strdup(name);
+  strcat(buf, "false");
 }
 
-void owl_filterelement_free(owl_filterelement *fe)
+static void owl_filterelement_print_re(owl_filterelement *fe, char *buf)
 {
-  if (fe->field) owl_free(fe->field);
-  if (fe->filtername) owl_free(fe->filtername);
+  strcat(buf, fe->field);
+  strcat(buf, " ");
+  strcat(buf, owl_regex_get_string(&(fe->re)));
 }
 
-int owl_filterelement_is_null(owl_filterelement *fe)
+static void owl_filterelement_print_filter(owl_filterelement *fe, char *buf)
 {
-  if (fe->type==OWL_FILTERELEMENT_NULL) return(1);
-  return(0);
+  strcat(buf, "filter ");
+  strcat(buf, fe->field);
 }
 
-int owl_filterelement_is_openbrace(owl_filterelement *fe)
+static void owl_filterelement_print_perl(owl_filterelement *fe, char *buf)
 {
-  if (fe->type==OWL_FILTERELEMENT_OPENBRACE) return(1);
-  return(0);
+  strcat(buf, "perl ");
+  strcat(buf, fe->field);
 }
 
-int owl_filterelement_is_closebrace(owl_filterelement *fe)
+static void owl_filterelement_print_group(owl_filterelement *fe, char *buf)
 {
-  if (fe->type==OWL_FILTERELEMENT_CLOSEBRACE) return(1);
-  return(0);
+  strcat(buf, "( ");
+  owl_filterelement_print(fe->left, buf) ;
+  strcat(buf, " )");
 }
 
-int owl_filterelement_is_and(owl_filterelement *fe)
+static void owl_filterelement_print_or(owl_filterelement *fe, char *buf)
 {
-  if (fe->type==OWL_FILTERELEMENT_AND) return(1);
-  return(0);
+  owl_filterelement_print(fe->left, buf);
+  strcat(buf, " or ");
+  owl_filterelement_print(fe->right, buf);
 }
 
-int owl_filterelement_is_or(owl_filterelement *fe)
+static void owl_filterelement_print_and(owl_filterelement *fe, char *buf)
 {
-  if (fe->type==OWL_FILTERELEMENT_OR) return(1);
-  return(0);
+  owl_filterelement_print(fe->left, buf);
+  strcat(buf, " and ");
+  owl_filterelement_print(fe->right, buf);
 }
 
-int owl_filterelement_is_not(owl_filterelement *fe)
+static void owl_filterelement_print_not(owl_filterelement *fe, char *buf)
 {
-  if (fe->type==OWL_FILTERELEMENT_NOT) return(1);
-  return(0);
+  strcat(buf, " not ");
+  owl_filterelement_print(fe->left, buf);
 }
 
-int owl_filterelement_is_true(owl_filterelement *fe)
+// Constructors
+
+void owl_filterelement_create(owl_filterelement *fe) {
+  fe->field = NULL;
+  fe->left = fe->right = NULL;
+  fe->match_message = NULL;
+  fe->print_elt = NULL;
+  owl_regex_init(&(fe->re));
+}
+
+
+void owl_filterelement_create_true(owl_filterelement *fe)
 {
-  if (fe->type==OWL_FILTERELEMENT_TRUE) return(1);
-  return(0);
+  owl_filterelement_create(fe);
+  fe->match_message = owl_filterelement_match_true;
+  fe->print_elt = owl_filterelement_print_true;
 }
 
-int owl_filterelement_is_false(owl_filterelement *fe)
+void owl_filterelement_create_false(owl_filterelement *fe)
 {
-  if (fe->type==OWL_FILTERELEMENT_FALSE) return(1);
-  return(0);
+  owl_filterelement_create(fe);
+  fe->match_message = owl_filterelement_match_false;
+  fe->print_elt = owl_filterelement_print_false;
 }
 
-int owl_filterelement_is_re(owl_filterelement *fe)
+void owl_filterelement_create_re(owl_filterelement *fe, char *field, char *re)
 {
-  if (fe->type==OWL_FILTERELEMENT_RE) return(1);
-  return(0);
+  owl_filterelement_create(fe);
+  fe->field=owl_strdup(field);
+  owl_regex_create(&(fe->re), re);
+  fe->match_message = owl_filterelement_match_re;
+  fe->print_elt = owl_filterelement_print_re;
 }
 
-int owl_filterelement_is_perl(owl_filterelement *fe)
+void owl_filterelement_create_filter(owl_filterelement *fe, char *name)
 {
-  if (fe->type==OWL_FILTERELEMENT_PERL) return(1);
-  return(0);
+  owl_filterelement_create(fe);
+  fe->field=owl_strdup(name);
+  fe->match_message = owl_filterelement_match_filter;
+  fe->print_elt = owl_filterelement_print_filter;
 }
 
-owl_regex *owl_filterelement_get_re(owl_filterelement *fe)
+void owl_filterelement_create_perl(owl_filterelement *fe, char *name)
 {
-  return(&(fe->re));
+  owl_filterelement_create(fe);
+  fe->field=owl_strdup(name);
+  fe->match_message = owl_filterelement_match_perl;
+  fe->print_elt = owl_filterelement_print_perl;
 }
 
-int owl_filterelement_is_filter(owl_filterelement *fe)
+void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
 {
-  if (fe->type==OWL_FILTERELEMENT_FILTER) return(1);
-  return(0);
+  owl_filterelement_create(fe);
+  fe->left = in;
+  fe->match_message = owl_filterelement_match_group;
+  fe->print_elt = owl_filterelement_print_group;
 }
 
-char *owl_filterelement_get_field(owl_filterelement *fe)
+void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
 {
-  if (fe->field) return(fe->field);
-  return("unknown-field");
+  owl_filterelement_create(fe);
+  fe->left = in;
+  fe->match_message = owl_filterelement_match_not;
+  fe->print_elt = owl_filterelement_print_not;
 }
 
-char *owl_filterelement_get_filtername(owl_filterelement *fe)
+void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
 {
-  if (fe->filtername) return(fe->filtername);
-  return("unknown-filter");
+  owl_filterelement_create(fe);
+  fe->left = lhs;
+  fe->right = rhs;
+  fe->match_message = owl_filterelement_match_and;
+  fe->print_elt = owl_filterelement_print_and;
 }
 
-int owl_filterelement_is_value(owl_filterelement *fe)
+void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
 {
-  if ( (fe->type==OWL_FILTERELEMENT_TRUE) ||
-       (fe->type==OWL_FILTERELEMENT_FALSE) ||
-       (fe->type==OWL_FILTERELEMENT_RE) ||
-       (fe->type==OWL_FILTERELEMENT_PERL) ||
-       (fe->type==OWL_FILTERELEMENT_FILTER)) {
-    return(1);
+  owl_filterelement_create(fe);
+  fe->left = lhs;
+  fe->right = rhs;
+  fe->match_message = owl_filterelement_match_or;
+  fe->print_elt = owl_filterelement_print_or;
+}
+
+int owl_filterelement_match(owl_filterelement *fe, owl_message *m)
+{
+  if(!fe) return 0;
+  if(!fe->match_message) return 0;
+  return fe->match_message(fe, m);
+}
+
+int owl_filterelement_is_toodeep(owl_filter *f, owl_filterelement *fe)
+{
+  int one = 1;
+  owl_list nodes;
+  owl_dict filters;
+  owl_list_create(&nodes);
+  owl_dict_create(&filters);
+  
+  owl_list_append_element(&nodes, fe);
+  owl_dict_insert_element(&filters, f->name, &one, NULL);
+  while(owl_list_get_size(&nodes)) {
+    fe = owl_list_get_element(&nodes, 0);
+    owl_list_remove_element(&nodes, 0);
+    if(fe->left) owl_list_append_element(&nodes, fe->left);
+    if(fe->right) owl_list_append_element(&nodes, fe->right);
+    if(fe->match_message == owl_filterelement_match_filter) {
+      if(owl_dict_find_element(&filters, fe->field)) return 1;
+      owl_dict_insert_element(&filters, fe->field, &one, NULL);
+      f = owl_global_get_filter(&g, fe->field);
+      if(f) owl_list_append_element(&nodes, f->root);
+    }
   }
-  return(0);
+
+  owl_list_free_simple(&nodes);
+  owl_dict_free_simple(&filters);
+  return 0;
 }
 
-/* caller must free the return */
-char *owl_filterelement_to_string(owl_filterelement *fe)
+void owl_filterelement_free(owl_filterelement *fe)
 {
-  if (owl_filterelement_is_openbrace(fe)) {
-    return(owl_strdup("( "));
-  } else if (owl_filterelement_is_closebrace(fe)) {
-    return(owl_strdup(") "));
-  } else if (owl_filterelement_is_and(fe)) {
-    return(owl_strdup("and "));
-  } else if (owl_filterelement_is_or(fe)) {
-    return(owl_strdup("or "));
-  } else if (owl_filterelement_is_not(fe)) {
-    return(owl_strdup("not "));
-  } else if (owl_filterelement_is_true(fe)) {
-    return(owl_strdup("true "));
-  } else if (owl_filterelement_is_false(fe)) {
-    return(owl_strdup("false "));
-  } else if (owl_filterelement_is_re(fe)) {
-    return(owl_sprintf("%s %s ", fe->field, owl_regex_get_string(&(fe->re))));
-  } else if (owl_filterelement_is_filter(fe)) {
-    return(owl_sprintf("filter %s ", fe->filtername));
-  } else if (owl_filterelement_is_perl(fe)) {
-    return(owl_sprintf("perl %s ", fe->filtername));
+  if (fe->field) owl_free(fe->field);
+  if (fe->left) {
+    owl_filterelement_free(fe->left);
+    owl_free(fe->left);
   }
+  if (fe->right) {
+    owl_filterelement_free(fe->right);
+    owl_free(fe->right);
+  }
+  owl_regex_free(&(fe->re));
+}
 
-  return(owl_strdup("?"));
+void owl_filterelement_print(owl_filterelement *fe, char *buf)
+{
+  if(!fe || !fe->print_elt) return;
+  fe->print_elt(fe, buf);
 }

Modified: trunk/owl/global.c
===================================================================
--- trunk/owl/global.c	2006-12-26 06:00:43 UTC (rev 483)
+++ trunk/owl/global.c	2006-12-26 06:05:26 UTC (rev 484)
@@ -77,10 +77,6 @@
   owl_history_set_norepeats(&(g->cmdhist));
   g->nextmsgid=0;
 
-  owl_filterelement_create_true(&(g->fe_true));
-  owl_filterelement_create_false(&(g->fe_false));
-  owl_filterelement_create_null(&(g->fe_null));
-
   _owl_global_setup_windows(g);
 
   /* Fill in some variables which don't have constant defaults */
@@ -582,18 +578,6 @@
   return(&(g->current_view));
 }
 
-owl_filterelement *owl_global_get_filterelement_true(owl_global *g) {
-  return(&(g->fe_true));
-}
-
-owl_filterelement *owl_global_get_filterelement_false(owl_global *g) {
-  return(&(g->fe_false));
-}
-
-owl_filterelement *owl_global_get_filterelement_null(owl_global *g) {
-  return(&(g->fe_null));
-}
-
 /* has colors */
 
 int owl_global_get_hascolors(owl_global *g) {

Modified: trunk/owl/owl.c
===================================================================
--- trunk/owl/owl.c	2006-12-26 06:00:43 UTC (rev 483)
+++ trunk/owl/owl.c	2006-12-26 06:05:26 UTC (rev 484)
@@ -189,7 +189,7 @@
 
   /* owl global init */
   owl_global_init(&g);
-  if (debug) owl_global_set_debug_on(&g);
+    if (debug) owl_global_set_debug_on(&g);
   owl_function_debugmsg("startup: first available debugging message");
   owl_global_set_startupargs(&g, argcsave, argvsave);
   owl_global_set_haveaim(&g);

Modified: trunk/owl/owl.h
===================================================================
--- trunk/owl/owl.h	2006-12-26 06:00:43 UTC (rev 483)
+++ trunk/owl/owl.h	2006-12-26 06:05:26 UTC (rev 484)
@@ -399,16 +399,21 @@
 } owl_regex;
 
 typedef struct _owl_filterelement {
-  int type;
+  int (*match_message)(struct _owl_filterelement *fe, owl_message *m);
+  /* Append a string representation of the filterelement onto buf*/
+  void (*print_elt)(struct _owl_filterelement *fe, char * buf);
+  /* Operands for and,or,not*/
+  struct _owl_filterelement *left, *right;
+  /* For regex filters*/
+  owl_regex re;
+  /* Used by regexes, filter references, and perl */
   char *field;
-  owl_regex re;
-  char *filtername;  /* for maching on another filter */
 } owl_filterelement;
 
 typedef struct _owl_filter {
   char *name;
   int polarity;
-  owl_list fes; /* filterelements */
+  owl_filterelement * root;
   int color;
   int cachedmsgid;  /* cached msgid: should move into view eventually */
 } owl_filter;
@@ -554,9 +559,6 @@
   int newmsgproc_pid;
   int malloced, freed;
   char *searchstring;
-  owl_filterelement fe_true;
-  owl_filterelement fe_false;
-  owl_filterelement fe_null;
   aim_session_t aimsess;
   aim_conn_t bosconn;
   owl_timer aim_noop_timer;

Modified: trunk/owl/perl/modules/jabber.pl
===================================================================
--- trunk/owl/perl/modules/jabber.pl	2006-12-26 06:00:43 UTC (rev 483)
+++ trunk/owl/perl/modules/jabber.pl	2006-12-26 06:05:26 UTC (rev 484)
@@ -351,7 +351,7 @@
             my @result = $client->AuthSend( %{ $vars{jlogin_authhash} } );
 
             if ( $result[0] ne 'ok' ) {
-            if ( !$vars{jlogin_havepass} && $result[0] == 401 ) {
+            if ( !$vars{jlogin_havepass} && $result[0] eq '401' ) {
                 $vars{jlogin_havepass} = 1;
                 $conn->removeConnection($jidStr);
                 owl::start_password( "Password for $jidStr: ", \&do_login );
@@ -808,9 +808,7 @@
     $j->SetSubject( $vars{jwrite}{subject} ) if ( $vars{jwrite}{subject} );
 
     my $m = j2o( $j, { direction => 'out' } );
-    if ( $vars{jwrite}{type} ne 'groupchat' ) {
-
-        #XXX TODO: Check for displayoutgoing.
+    if ( $vars{jwrite}{type} ne 'groupchat' && owl::getvar('displayoutgoing') eq 'on') {
         owl::queue_message($m);
     }
 
@@ -1012,7 +1010,7 @@
           "jwrite " . ( ( $dir eq 'in' ) ? $props{from} : $props{to} );
         $props{replycmd} .=
           " -a " . ( ( $dir eq 'out' ) ? $props{from} : $props{to} );
-        $props{isprivate} = 1;
+        $props{private} = 1;
     }
     elsif ( $jtype eq 'groupchat' ) {
         my $nick = $props{nick} = $from->GetResource();
@@ -1031,7 +1029,7 @@
     }
     elsif ( $jtype eq 'normal' ) {
         $props{replycmd}  = undef;
-        $props{isprivate} = 1;
+        $props{private} = 1;
     }
     elsif ( $jtype eq 'headline' ) {
         $props{replycmd} = undef;

Modified: trunk/owl/regex.c
===================================================================
--- trunk/owl/regex.c	2006-12-26 06:00:43 UTC (rev 483)
+++ trunk/owl/regex.c	2006-12-26 06:05:26 UTC (rev 484)
@@ -85,7 +85,10 @@
 
 void owl_regex_free(owl_regex *re)
 {
-  if (re->string) owl_free(re->string);
+    if (re->string) {
+        owl_free(re->string);
+        regfree(&(re->re));
+    }
 
   /* do we need to free the regular expression? */
 }

Modified: trunk/owl/tester.c
===================================================================
--- trunk/owl/tester.c	2006-12-26 06:00:43 UTC (rev 483)
+++ trunk/owl/tester.c	2006-12-26 06:05:26 UTC (rev 484)
@@ -149,6 +149,7 @@
     numfailures += owl_util_regtest();
     numfailures += owl_dict_regtest();
     numfailures += owl_variable_regtest();
+    numfailures += owl_filter_regtest();
     if (numfailures) {
       fprintf(stderr, "*** WARNING: %d failures total\n", numfailures);
     }


home help back first fref pref prev next nref lref last post