Changeset cb769bb


Ignore:
Timestamp:
Dec 26, 2006, 1:05:26 AM (17 years ago)
Author:
Nelson Elhage <nelhage@mit.edu>
Branches:
master, barnowl_perlaim, debian, release-1.10, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
446aa2b
Parents:
20eb22c
Message:
 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
 
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • filter.c

    rb699e9b rcb769bb  
    1919int owl_filter_init(owl_filter *f, char *name, int argc, char **argv)
    2020{
    21   int i, j, error;
    22   owl_filterelement *fe;
    23   char *regexstr;
    24   owl_list list;
    25    
    2621  f->name=owl_strdup(name);
    2722  f->polarity=0;
    2823  f->color=OWL_COLOR_DEFAULT;
    2924  f->cachedmsgid=-1;
    30   owl_list_create(&(f->fes));
    31  
     25
    3226  /* first take arguments that have to come first */
    3327  /* set the color */
     
    4135    argv+=2;
    4236  }
    43  
    44   /* then deal with the expression */
    45   for (i=0; i<argc; i++) {
    46     error=0;
    47     fe=owl_malloc(sizeof(owl_filterelement));
    48    
    49     /* all the 0 argument possibilities */
    50     if (!strcmp(argv[i], "(")) {
    51       owl_filterelement_create_openbrace(fe);
    52     } else if (!strcmp(argv[i], ")")) {
    53       owl_filterelement_create_closebrace(fe);
    54     } else if (!strcasecmp(argv[i], "and")) {
    55       owl_filterelement_create_and(fe);
    56     } else if (!strcasecmp(argv[i], "or")) {
    57       owl_filterelement_create_or(fe);
    58     } else if (!strcasecmp(argv[i], "not")) {
    59       owl_filterelement_create_not(fe);
    60     } else if (!strcasecmp(argv[i], "true")) {
    61       owl_filterelement_create_true(fe);
    62     } else if (!strcasecmp(argv[i], "false")) {
    63       owl_filterelement_create_false(fe);
    64      
    65     } else if (i==argc-1) { /* we need more than one arg at this point */
    66       error=1;
    67     } else {
    68       if (!strcasecmp(argv[i], "filter")) {
    69         owl_filterelement_create_filter(fe, argv[i+1]);
    70         i++;
    71       } else if (!strcasecmp(argv[i], "perl")) {
    72         owl_filterelement_create_perl(fe, argv[i+1]);
    73         i++;
    74       } else {
    75         regexstr=owl_text_substitute(argv[i+1], "%me%", owl_zephyr_get_sender());
    76         owl_filterelement_create_re(fe, argv[i], regexstr);
    77         owl_free(regexstr);
    78         i++;
    79       }
    80     }
    81 
    82     if (!error) {
    83       owl_list_append_element(&(f->fes), fe);
    84     } else {
    85       owl_free(fe);
    86       owl_filter_free(f);
    87       return(-1);
    88     }
    89   }
    90  
    91   /* Are we trying to use the filter we're creating?  Bad. */
    92   owl_list_create(&list);
    93   _owl_filter_get_subfilter_names(f, &list);
    94   j=owl_list_get_size(&list);
    95   for (i=0; i<j; i++) {
    96     if (!strcasecmp(name, owl_list_get_element(&list, i))) {
    97       owl_function_error("Filter loop.");
    98       owl_filter_free(f);
    99       owl_list_free_all(&list, owl_free);
    100       return(-1);
    101     }
    102   }
    103   owl_list_free_all(&list, owl_free);
    104 
    105   /* Now check for more subtle recursion. */
     37
     38  if(!(f->root = owl_filter_parse_expression(argc, argv, NULL)))
     39    return(-1);
     40
     41  /* Now check for recursion. */
    10642  if (owl_filter_is_toodeep(f)) {
    10743    owl_function_error("Filter loop or exceeds recursion depth");
     
    10945    return(-1);
    11046  }
    111  
     47
    11248  return(0);
     49}
     50
     51
     52/* A primitive expression is one without any toplevel ``and'' or ``or''s*/
     53
     54static owl_filterelement * owl_filter_parse_primitive_expression(int argc, char **argv, int *next)
     55{
     56  if(!argc) return NULL;
     57
     58  owl_filterelement * fe = owl_malloc(sizeof(owl_filterelement));
     59  owl_filterelement *op;
     60
     61  owl_filterelement_create(fe);
     62  int i = 0, skip;
     63
     64  if(!strcasecmp(argv[i], "(")) {
     65    i++;
     66    op = owl_filter_parse_expression(argc-i, argv+i, &skip);
     67    if(!op) goto err;
     68    i += skip;
     69    if(strcasecmp(argv[i++], ")")) goto err;
     70    owl_filterelement_create_group(fe, op);
     71  } else if(!strcasecmp(argv[i], "not")) {
     72    i++;
     73    op = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
     74    if(!op) goto err;
     75    i += skip;
     76    owl_filterelement_create_not(fe, op);
     77  } else if(!strcasecmp(argv[i], "true")) {
     78    i++;
     79    owl_filterelement_create_true(fe);
     80  } else if(!strcasecmp(argv[i], "false")) {
     81    i++;
     82    owl_filterelement_create_false(fe);
     83  } else {
     84    if(argc == 1) goto err;
     85    if(!strcasecmp(*argv, "filter")) {
     86      owl_filterelement_create_filter(fe, *(argv+1));
     87    } else if(!strcasecmp(*argv, "perl")) {
     88      owl_filterelement_create_perl(fe, *(argv+1));
     89    } else {
     90      owl_filterelement_create_re(fe, *argv, *(argv+1));
     91    }
     92    i += 2;
     93  }
     94
     95  if(next) {
     96    *next = i;
     97  } else if(i != argc) {
     98    goto err;
     99  }
     100  return fe;
     101err:
     102  owl_filterelement_free(fe);
     103  owl_free(fe);
     104  return NULL;
     105}
     106
     107owl_filterelement * owl_filter_parse_expression(int argc, char **argv, int *next)
     108{
     109  int i = 0, skip;
     110  owl_filterelement * op1 = NULL, * op2 = NULL;
     111
     112  op1 = owl_filter_parse_primitive_expression(argc-i, argv+i, &skip);
     113  i += skip;
     114  if(!op1) goto err;
     115
     116  while(i < argc) {
     117    if(strcasecmp(argv[i], "and") &&
     118       strcasecmp(argv[i], "or")) break;
     119    op2 = owl_filter_parse_primitive_expression(argc-i-1, argv+i+1, &skip);
     120    if(!op2) goto err;
     121    owl_filterelement * tmp = owl_malloc(sizeof(owl_filterelement));
     122    if(!strcasecmp(argv[i], "and")) {
     123      owl_filterelement_create_and(tmp, op1, op2);
     124    } else {
     125      owl_filterelement_create_or(tmp, op1, op2);
     126    }
     127    op1 = tmp;
     128    op2 = NULL;
     129    i += skip+1;
     130  }
     131
     132  if(next) {
     133    *next = i;
     134  } else if(i != argc) {
     135    goto err;
     136  }
     137  return op1;
     138err:
     139  if(op1) {
     140    owl_filterelement_free(op1);
     141    owl_free(op1);
     142  }
     143  return NULL;
    113144}
    114145
     
    153184int owl_filter_message_match(owl_filter *f, owl_message *m)
    154185{
    155   int i, j, tmp;
    156   owl_list work_fes, *fes;
    157   owl_filterelement *fe;
    158   char *field, *match;
    159 
    160   /* create the working list of expression elements */
    161   fes=&(f->fes);
    162   owl_list_create(&work_fes);
    163   j=owl_list_get_size(fes);
    164   for (i=0; i<j; i++) {
    165     owl_list_append_element(&work_fes, owl_list_get_element(fes, i));
    166   }
    167 
    168   /* first go thru and evaluate all RE elements to true or false */
    169   match="";
    170   for (i=0; i<j; i++) {
    171     fe=owl_list_get_element(&work_fes, i);
    172     if (!owl_filterelement_is_re(fe)) continue;
    173     field=owl_filterelement_get_field(fe);
    174     if (!strcasecmp(field, "class")) {
    175       match=owl_message_get_class(m);
    176     } else if (!strcasecmp(field, "instance")) {
    177       match=owl_message_get_instance(m);
    178     } else if (!strcasecmp(field, "sender")) {
    179       match=owl_message_get_sender(m);
    180     } else if (!strcasecmp(field, "recipient")) {
    181       match=owl_message_get_recipient(m);
    182     } else if (!strcasecmp(field, "body")) {
    183       match=owl_message_get_body(m);
    184     } else if (!strcasecmp(field, "opcode")) {
    185       match=owl_message_get_opcode(m);
    186     } else if (!strcasecmp(field, "realm")) {
    187       match=owl_message_get_realm(m);
    188     } else if (!strcasecmp(field, "type")) {
    189       match=owl_message_get_type(m);
    190     } else if (!strcasecmp(field, "hostname")) {
    191       match=owl_message_get_hostname(m);
    192     } else if (!strcasecmp(field, "direction")) {
    193       if (owl_message_is_direction_out(m)) {
    194         match="out";
    195       } else if (owl_message_is_direction_in(m)) {
    196         match="in";
    197       } else if (owl_message_is_direction_none(m)) {
    198         match="none";
    199       } else {
    200         match="";
    201       }
    202     } else if (!strcasecmp(field, "login")) {
    203       if (owl_message_is_login(m)) {
    204         match="login";
    205       } else if (owl_message_is_logout(m)) {
    206         match="logout";
    207       } else {
    208         match="none";
    209       }
    210     } else {
    211       match = owl_message_get_attribute_value(m,field);
    212       if(match == NULL) match = "";
    213     }
    214 
    215     tmp=owl_regex_compare(owl_filterelement_get_re(fe), match);
    216     if (!tmp) {
    217       owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
    218     } else {
    219       owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
    220     }
    221   }
    222 
    223   /* now subfilters and perl functions */
    224   for (i=0; i<j; i++) {
    225     owl_filter *subfilter;
    226                            
    227     fe=owl_list_get_element(&work_fes, i);
    228 
    229     if (owl_filterelement_is_filter(fe)) {
    230 
    231       subfilter=owl_global_get_filter(&g, owl_filterelement_get_filtername(fe));
    232       if (!subfilter) {
    233         /* the filter does not exist, maybe because it was deleted.
    234          * Default to not matching
    235          */
    236         owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
    237       } else if (owl_filter_message_match(subfilter, m)) {
    238         owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
    239       } else {
    240         owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
    241       }
    242 
    243     } else if (owl_filterelement_is_perl(fe)) {
    244       char *subname, *perlrv;
    245       int   tf=0;
    246 
    247       subname = owl_filterelement_get_filtername(fe);
    248       if (!owl_perlconfig_is_function(subname)) {
    249         owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
    250         continue;
    251       }
    252       perlrv = owl_perlconfig_call_with_message(subname, m);
    253       if (perlrv) {
    254         if (0 == strcmp(perlrv, "1")) {
    255           tf=1;
    256         }
    257         owl_free(perlrv);
    258       }
    259       if (tf) {
    260         owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
    261       } else {
    262         owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
    263       }
    264     }
    265   }
    266 
    267   /* call the recrsive helper */
    268   i=_owl_filter_message_match_recurse(f, m, &work_fes, 0, owl_list_get_size(&(f->fes))-1);
    269 
    270   /* now there will be only one TRUE / FALSE, find it among the NULL's */
    271   tmp=0;
    272   for (i=0; i<j; i++) {
    273     fe=owl_list_get_element(&work_fes, i);
    274     if (owl_filterelement_is_null(fe)) continue;
    275     if (owl_filterelement_is_true(fe)) {
    276       tmp=1;
    277       break;
    278     }
    279     if (owl_filterelement_is_false(fe)) {
    280       tmp=0;
    281       break;
    282     }
    283   } 
    284 
    285   /* reverse the answer if negative polarity is in use */
    286   if (f->polarity) tmp=!tmp;
    287 
    288   owl_list_free_simple(&work_fes);
    289   return(tmp);
    290 }
    291 
    292 int _owl_filter_message_match_recurse(owl_filter *f, owl_message *m, owl_list *fes, int start, int end)
    293 {
    294   int a=0, b=0, i, x, y, z, score, ret, type;
    295   owl_filterelement *fe, *tmpfe=NULL;
    296 
    297   /* Deal with parens first. */
    298   for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
    299     /* Find first open paren and matching close paren, store in x, y */
    300     score=x=y=0;
    301     for (i=start; i<=end; i++) {
    302       fe=owl_list_get_element(fes, i);
    303       if (owl_filterelement_is_openbrace(fe)) {
    304         if (score==0) x=i;
    305         score++;
    306       } else if (owl_filterelement_is_closebrace(fe)) {
    307         score--;
    308         if (score<0) {
    309           /* unblanaced parens */
    310           return(-1);
    311         } else if (score==0) {
    312           y=i; /* this is the matching close paren */
    313           break;
    314         }
    315       }
    316     }
    317     if (score>0) {
    318       /* unblanaced parens */
    319       return(-1);
    320     }
    321 
    322     /* Simply the parens by removing them and evaluating what was in between */
    323     if (y>0) {
    324       /* null out the parens */
    325       owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
    326       owl_list_replace_element(fes, y, owl_global_get_filterelement_null(&g));
    327 
    328       /* evaluate expression in between */
    329       ret=_owl_filter_message_match_recurse(f, m, fes, x+1, y-1);
    330       if (ret<0) return(-1);
    331 
    332       /* there may be more, so we continue */
    333       continue;
    334     } else {
    335       /* otherwise we're done with this part */
    336       break;
    337     }
    338   }
    339   if (i==OWL_FILTER_MAX_DEPTH) {
    340     /* hit the saftey limit, consider it invalid */
    341     return(-1);
    342   }
    343 
    344   /* Find AND / OR / NOT.
    345    *   For binary expressions (AND/OR):
    346    *     "type" is 1
    347    *     "x" will index first val, "y" the operator and "z" the second val
    348    *   For unary expressions (NOT):
    349    *     "type" is 2
    350    *     "x" will index the operator, "y" the value
    351    *   "score" tallys how many expression elements have been found so far
    352    */
    353   for (i=0; i<OWL_FILTER_MAX_DEPTH; i++) {
    354     type=score=x=y=z=0;
    355     for (i=start; i<=end; i++) {
    356       fe=owl_list_get_element(fes, i);
    357       if (owl_filterelement_is_null(fe)) continue;
    358       if (score==0) {
    359         if (owl_filterelement_is_value(fe)) {
    360           x=i;
    361           score=1;
    362           type=1;
    363         } else if (owl_filterelement_is_not(fe)) {
    364           x=i;
    365           score=1;
    366           type=2;
    367         }
    368       } else if (score==1) {
    369         if (type==1) {
    370           if (owl_filterelement_is_and(fe) || owl_filterelement_is_or(fe)) {
    371             score=2;
    372             y=i;
    373           } else {
    374             /* it's not a valid binary expression */
    375             x=y=z=score=0;
    376           }
    377         } else if (type==2) {
    378           if (owl_filterelement_is_value(fe)) {
    379             /* valid unary expression, we're done */
    380             y=i;
    381             break;
    382           }
    383         }
    384       } else if (score==2) {
    385         if (owl_filterelement_is_value(fe)) {
    386           /* valid binary expression, we're done */
    387           z=i;
    388           break;
    389         } else {
    390           x=y=z=score=0;
    391         }
    392       }
    393     }
    394 
    395     /* simplify AND / OR */
    396     if ((type==1) && (z>0)) {
    397       fe=owl_list_get_element(fes, x);
    398       if (owl_filterelement_is_true(fe)) {
    399         a=1;
    400       } else if (owl_filterelement_is_false(fe)) {
    401         a=0;
    402       }
    403 
    404       fe=owl_list_get_element(fes, z);
    405       if (owl_filterelement_is_true(fe)) {
    406         b=1;
    407       } else if (owl_filterelement_is_false(fe)) {
    408         b=0;
    409       }
    410 
    411       fe=owl_list_get_element(fes, y);
    412       if (owl_filterelement_is_and(fe)) {
    413         if (a && b) {
    414           tmpfe=owl_global_get_filterelement_true(&g);
    415         } else {
    416           tmpfe=owl_global_get_filterelement_false(&g);
    417         }
    418       } else if (owl_filterelement_is_or(fe)) {
    419         if (a || b) {
    420           tmpfe=owl_global_get_filterelement_true(&g);
    421         } else {
    422           tmpfe=owl_global_get_filterelement_false(&g);
    423         }
    424       }
    425       owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
    426       owl_list_replace_element(fes, y, tmpfe);
    427       owl_list_replace_element(fes, z, owl_global_get_filterelement_null(&g));
    428     } else if ((type==2) && (y>0)) {
    429       /* simplify NOT */
    430       fe=owl_list_get_element(fes, y);
    431       owl_list_replace_element(fes, x, owl_global_get_filterelement_null(&g));
    432       if (owl_filterelement_is_false(fe)) {
    433         owl_list_replace_element(fes, y, owl_global_get_filterelement_true(&g));
    434       } else {
    435         owl_list_replace_element(fes, y, owl_global_get_filterelement_false(&g));
    436       }
    437     } else {
    438       break;
    439     }
    440   }
    441   return(0);
    442 
    443 }
     186  if(!f->root) return 0;
     187  int ret = owl_filterelement_match(f->root, m);
     188  if(f->polarity) ret = !ret;
     189  return ret;
     190}
     191
    444192
    445193void owl_filter_print(owl_filter *f, char *out)
    446194{
    447   int i, j;
    448   owl_filterelement *fe;
    449   char *tmp;
    450 
    451   strcpy(out, owl_filter_get_name(f));
    452   strcat(out, ": ");
    453 
    454   if (f->color!=OWL_COLOR_DEFAULT) {
    455     strcat(out, "-c ");
    456     strcat(out, owl_util_color_to_string(f->color));
    457     strcat(out, " ");
    458   }
    459 
    460   j=owl_list_get_size(&(f->fes));
    461   for (i=0; i<j; i++) {
    462     fe=owl_list_get_element(&(f->fes), i);
    463     tmp=owl_filterelement_to_string(fe);
    464     strcat(out, tmp);
    465     owl_free(tmp);
    466   }
     195  strcpy(out, "");
     196  if(!f->root) return;
     197  owl_filterelement_print(f->root, out);
    467198  strcat(out, "\n");
    468199}
     
    480211}
    481212
    482 /* Private
    483  * 'list' should already be allocated and initialized
    484  * This function places into list the string names of all filters
    485  * used in the filter expression for 'f'.
    486  * Caller must do a full free on 'list', including elements.
    487  */
    488 void _owl_filter_get_subfilter_names(owl_filter *f, owl_list *list)
    489 {
    490   int i, j;
    491   owl_filterelement *fe;
    492 
    493   j=owl_list_get_size(&(f->fes));
    494   for (i=0; i<j; i++) {
    495     fe=owl_list_get_element(&(f->fes), i);
    496     if (owl_filterelement_is_filter(fe)) {
    497       owl_list_append_element(list, owl_strdup(owl_filterelement_get_filtername(fe)));
    498     }
    499   }
    500 }
    501213
    502214int owl_filter_is_toodeep(owl_filter *f)
    503215{
    504   owl_list seen, tocheck, tmp;
    505   int i, j, x, y;
    506   owl_filter *subfilter;
    507 
    508   owl_list_create(&seen);
    509   owl_list_create(&tocheck);
    510   owl_list_create(&tmp);
    511 
    512   /* seed 'tocheck' with the first set of filters */
    513   _owl_filter_get_subfilter_names(f, &tmp);
    514   j=owl_list_get_size(&tmp);
    515   for (i=0; i<j; i++) {
    516     owl_util_list_add_unique_string(&tocheck, owl_list_get_element(&tmp, i));
    517   }
    518   owl_list_free_all(&tmp, owl_free);
    519   owl_list_create(&tmp);
    520 
    521   /* add this list to the 'seen' list */
    522   owl_list_append_element(&seen, owl_strdup(owl_filter_get_name(f)));
    523 
    524   for (i=0; i<OWL_FILTER_MAXRECURSE; i++) {
    525     /* if anything in 'tocheck' is in 'seen' we have a loop */
    526     if (owl_util_common_strings_in_lists(&tocheck, &seen)) {
    527       owl_list_free_all(&tmp, owl_free);
    528       owl_list_free_all(&tocheck, owl_free);
    529       owl_list_free_all(&seen, owl_free);
    530       return(1);
    531     }
    532 
    533     /* if there's nothing to check, we're done */
    534     y=owl_list_get_size(&tocheck);
    535     if (y==0) {
    536       owl_list_free_all(&tmp, owl_free);
    537       owl_list_free_all(&tocheck, owl_free);
    538       owl_list_free_all(&seen, owl_free);
    539       return(0);
    540     }
    541 
    542     /* add everything in 'tocheck' to the 'seen' list */
    543     /* y=owl_list_get_size(&tocheck); */
    544     for (x=0; x<y; x++) {
    545       owl_list_append_element(&seen, owl_strdup(owl_list_get_element(&tocheck, x)));
    546     }
    547 
    548     /* make a new list into 'tmp' with the children of 'tocheck' */
    549     /* y=owl_list_get_size(&tocheck); */
    550     for (x=0; x<y; x++) {
    551       subfilter=owl_global_get_filter(&g, owl_list_get_element(&tocheck, x));
    552       if (!subfilter) return(0);
    553       _owl_filter_get_subfilter_names(subfilter, &tmp);
    554     }
    555 
    556     /* clean out 'tocheck' */
    557     owl_list_free_all(&tocheck, owl_free);
    558     owl_list_create(&tocheck);
    559 
    560     /* put 'tmp' into 'tocheck' */
    561     y=owl_list_get_size(&tmp);
    562     for (x=0; x<y; x++) {
    563       owl_util_list_add_unique_string(&tocheck, owl_list_get_element(&tmp, x));
    564     }
    565 
    566     /* clean out 'tmp' */
    567     owl_list_free_all(&tmp, owl_free);
    568     owl_list_create(&tmp);
    569   }
    570 
    571   owl_list_free_all(&tmp, owl_free);
    572   owl_list_free_all(&tocheck, owl_free);
    573   owl_list_free_all(&seen, owl_free);
    574 
    575   return(1);
     216  return owl_filterelement_is_toodeep(f, f->root);
    576217}
    577218
    578219void owl_filter_free(owl_filter *f)
    579220{
    580   void (*func)();
    581 
    582   func=&owl_filterelement_free;
    583  
     221  if(f->root) {
     222    owl_filterelement_free(f->root);
     223    owl_free(f->root);
     224  }
    584225  if (f->name) owl_free(f->name);
    585   owl_list_free_all(&(f->fes), func);
    586 }
     226}
     227
     228/**************************************************************************/
     229/************************* REGRESSION TESTS *******************************/
     230/**************************************************************************/
     231
     232#ifdef OWL_INCLUDE_REG_TESTS
     233
     234int owl_filter_test_string(char * filt, owl_message *m, int shouldmatch) /* noproto */ {
     235  owl_filter f;
     236  int ok;
     237  int failed = 0;
     238  if(owl_filter_init_fromstring(&f, "test-filter", filt)) {
     239    printf("\tFAIL: parse %s\n", filt);
     240    failed = 1;
     241    goto out;
     242  }
     243  ok = owl_filter_message_match(&f, m);
     244  if((shouldmatch && !ok) || (!shouldmatch && ok)) {
     245    printf("\tFAIL: match %s (got %d, expected %d)\n", filt, ok, shouldmatch);
     246    failed = 1;
     247  }
     248 out:
     249  owl_filter_free(&f);
     250  if(!failed) {
     251    printf("\tok  : %s %s\n", shouldmatch ? "matches" : "doesn't match", filt);
     252  }
     253  return failed;
     254}
     255
     256
     257#include "test.h"
     258
     259
     260int owl_filter_regtest(void) {
     261  owl_list_create(&(g.filterlist));
     262  int numfailed=0;
     263  owl_message m;
     264  owl_message_init(&m);
     265  owl_message_set_type_zephyr(&m);
     266  owl_message_set_direction_in(&m);
     267  owl_message_set_class(&m, "owl");
     268  owl_message_set_instance(&m, "tester");
     269  owl_message_set_sender(&m, "owl-user");
     270  owl_message_set_recipient(&m, "joe");
     271  owl_message_set_attribute(&m, "foo", "bar");
     272
     273#define TEST_FILTER(f, e) numfailed += owl_filter_test_string(f, &m, e)
     274
     275
     276  TEST_FILTER("true", 1);
     277  TEST_FILTER("false", 0);
     278  TEST_FILTER("( true )", 1);
     279  TEST_FILTER("not false", 1);
     280  TEST_FILTER("( true ) or ( false )", 1);
     281  TEST_FILTER("true and false", 0);
     282  TEST_FILTER("( true or true ) or ( ( false ) )", 1);
     283
     284  TEST_FILTER("class owl", 1);
     285  TEST_FILTER("class ^owl$", 1);
     286  TEST_FILTER("instance test", 1);
     287  TEST_FILTER("instance ^test$", 0);
     288  TEST_FILTER("instance ^tester$", 1);
     289
     290  TEST_FILTER("foo bar", 1);
     291  TEST_FILTER("class owl and instance tester", 1);
     292  TEST_FILTER("type ^zephyr$ and direction ^in$ and ( class ^owl$ or instance ^owl$ )", 1);
     293
     294  // Order of operations and precedence
     295  TEST_FILTER("not true or false", 0);
     296  TEST_FILTER("true or true and false", 0);
     297  TEST_FILTER("true and true and false or true", 1);
     298  TEST_FILTER("false and false or true", 1);
     299  TEST_FILTER("true and false or false", 0);
     300
     301  owl_filter f1, f2, f3, f4;
     302
     303  owl_filter_init_fromstring(&f1, "f1", "class owl");
     304  owl_global_add_filter(&g, &f1);
     305  TEST_FILTER("filter f1", 1);
     306
     307  // Test recursion prevention
     308  FAIL_UNLESS("self reference", owl_filter_init_fromstring(&f2, "test", "filter test"));
     309
     310  // mutual recursion
     311  owl_filter_init_fromstring(&f3, "f3", "filter f4");
     312  owl_global_add_filter(&g, &f3);
     313  FAIL_UNLESS("mutual recursion",   owl_filter_init_fromstring(&f4, "f4", "filter f3"));
     314
     315  return 0;
     316}
     317
     318
     319#endif /* OWL_INCLUDE_REG_TESTS */
  • filterelement.c

    r32eed98 rcb769bb  
    33static const char fileIdent[] = "$Id$";
    44
    5 #define OWL_FILTERELEMENT_NULL        0
    6 #define OWL_FILTERELEMENT_TRUE        1
    7 #define OWL_FILTERELEMENT_FALSE       2
    8 #define OWL_FILTERELEMENT_OPENBRACE   3
    9 #define OWL_FILTERELEMENT_CLOSEBRACE  4
    10 #define OWL_FILTERELEMENT_AND         5
    11 #define OWL_FILTERELEMENT_OR          6
    12 #define OWL_FILTERELEMENT_NOT         7
    13 #define OWL_FILTERELEMENT_RE          8
    14 #define OWL_FILTERELEMENT_FILTER      9
    15 #define OWL_FILTERELEMENT_PERL       10
    16 
    17 void owl_filterelement_create_null(owl_filterelement *fe)
    18 {
    19   fe->type=OWL_FILTERELEMENT_NULL;
    20   fe->field=NULL;
    21   fe->filtername=NULL;
    22 }
    23 
    24 void owl_filterelement_create_openbrace(owl_filterelement *fe)
    25 {
    26   owl_filterelement_create_null(fe);
    27   fe->type=OWL_FILTERELEMENT_OPENBRACE;
    28 }
    29 
    30 void owl_filterelement_create_closebrace(owl_filterelement *fe)
    31 {
    32   owl_filterelement_create_null(fe);
    33   fe->type=OWL_FILTERELEMENT_CLOSEBRACE;
    34 }
    35 
    36 void owl_filterelement_create_and(owl_filterelement *fe)
    37 {
    38   owl_filterelement_create_null(fe);
    39   fe->type=OWL_FILTERELEMENT_AND;
    40 }
    41 
    42 void owl_filterelement_create_or(owl_filterelement *fe)
    43 {
    44   owl_filterelement_create_null(fe);
    45   fe->type=OWL_FILTERELEMENT_OR;
    46 }
    47 
    48 void owl_filterelement_create_not(owl_filterelement *fe)
    49 {
    50   owl_filterelement_create_null(fe);
    51   fe->type=OWL_FILTERELEMENT_NOT;
    52 }
     5static char * owl_filterelement_get_field(owl_message *m, char * field)
     6{
     7  char *match;
     8  if (!strcasecmp(field, "class")) {
     9    match=owl_message_get_class(m);
     10  } else if (!strcasecmp(field, "instance")) {
     11    match=owl_message_get_instance(m);
     12  } else if (!strcasecmp(field, "sender")) {
     13    match=owl_message_get_sender(m);
     14  } else if (!strcasecmp(field, "recipient")) {
     15    match=owl_message_get_recipient(m);
     16  } else if (!strcasecmp(field, "body")) {
     17    match=owl_message_get_body(m);
     18  } else if (!strcasecmp(field, "opcode")) {
     19    match=owl_message_get_opcode(m);
     20  } else if (!strcasecmp(field, "realm")) {
     21    match=owl_message_get_realm(m);
     22  } else if (!strcasecmp(field, "type")) {
     23    match=owl_message_get_type(m);
     24  } else if (!strcasecmp(field, "hostname")) {
     25    match=owl_message_get_hostname(m);
     26  } else if (!strcasecmp(field, "direction")) {
     27    if (owl_message_is_direction_out(m)) {
     28      match="out";
     29    } else if (owl_message_is_direction_in(m)) {
     30      match="in";
     31    } else if (owl_message_is_direction_none(m)) {
     32      match="none";
     33    } else {
     34      match="";
     35    }
     36  } else if (!strcasecmp(field, "login")) {
     37    if (owl_message_is_login(m)) {
     38      match="login";
     39    } else if (owl_message_is_logout(m)) {
     40      match="logout";
     41    } else {
     42      match="none";
     43    }
     44  } else {
     45    match = owl_message_get_attribute_value(m,field);
     46    if(match == NULL) match = "";
     47  }
     48
     49  return match;
     50}
     51
     52static int owl_filterelement_match_false(owl_filterelement *fe, owl_message *m)
     53{
     54  return 0;
     55}
     56
     57static int owl_filterelement_match_true(owl_filterelement *fe, owl_message *m)
     58{
     59  return 1;
     60}
     61
     62static int owl_filterelement_match_re(owl_filterelement *fe, owl_message *m)
     63{
     64  char * val = owl_filterelement_get_field(m, fe->field);
     65  return !owl_regex_compare(&(fe->re), val);
     66}
     67
     68static int owl_filterelement_match_filter(owl_filterelement *fe, owl_message *m)
     69{
     70  owl_filter *subfilter;
     71  subfilter=owl_global_get_filter(&g, fe->field);
     72  if (!subfilter) {
     73    /* the filter does not exist, maybe because it was deleted.
     74     * Default to not matching
     75     */
     76    return 0;
     77  }
     78  return owl_filter_message_match(subfilter, m);
     79}
     80
     81static int owl_filterelement_match_perl(owl_filterelement *fe, owl_message *m)
     82{
     83  char *subname, *perlrv;
     84  int   tf=0;
     85
     86  subname = fe->field;
     87  if (!owl_perlconfig_is_function(subname)) {
     88    return 0;
     89  }
     90  perlrv = owl_perlconfig_call_with_message(subname, m);
     91  if (perlrv) {
     92    if (0 == strcmp(perlrv, "1")) {
     93      tf=1;
     94    }
     95    owl_free(perlrv);
     96  }
     97  return tf;
     98}
     99
     100static int owl_filterelement_match_group(owl_filterelement *fe, owl_message *m)
     101{
     102  return owl_filterelement_match(fe->left, m);
     103}
     104
     105/* XXX: Our boolea operators short-circuit here. The original owl did
     106   not. Do we care?
     107*/
     108
     109static int owl_filterelement_match_and(owl_filterelement *fe, owl_message *m)
     110{
     111  return owl_filterelement_match(fe->left, m) &&
     112    owl_filterelement_match(fe->right, m);
     113}
     114
     115static int owl_filterelement_match_or(owl_filterelement *fe, owl_message *m)
     116{
     117  return owl_filterelement_match(fe->left, m) ||
     118    owl_filterelement_match(fe->right, m);
     119}
     120
     121static int owl_filterelement_match_not(owl_filterelement *fe, owl_message *m)
     122{
     123  return !owl_filterelement_match(fe->left, m);
     124}
     125
     126// Print methods
     127
     128static void owl_filterelement_print_true(owl_filterelement *fe, char *buf)
     129{
     130  strcat(buf, "true");
     131}
     132
     133static void owl_filterelement_print_false(owl_filterelement *fe, char *buf)
     134{
     135  strcat(buf, "false");
     136}
     137
     138static void owl_filterelement_print_re(owl_filterelement *fe, char *buf)
     139{
     140  strcat(buf, fe->field);
     141  strcat(buf, " ");
     142  strcat(buf, owl_regex_get_string(&(fe->re)));
     143}
     144
     145static void owl_filterelement_print_filter(owl_filterelement *fe, char *buf)
     146{
     147  strcat(buf, "filter ");
     148  strcat(buf, fe->field);
     149}
     150
     151static void owl_filterelement_print_perl(owl_filterelement *fe, char *buf)
     152{
     153  strcat(buf, "perl ");
     154  strcat(buf, fe->field);
     155}
     156
     157static void owl_filterelement_print_group(owl_filterelement *fe, char *buf)
     158{
     159  strcat(buf, "( ");
     160  owl_filterelement_print(fe->left, buf) ;
     161  strcat(buf, " )");
     162}
     163
     164static void owl_filterelement_print_or(owl_filterelement *fe, char *buf)
     165{
     166  owl_filterelement_print(fe->left, buf);
     167  strcat(buf, " or ");
     168  owl_filterelement_print(fe->right, buf);
     169}
     170
     171static void owl_filterelement_print_and(owl_filterelement *fe, char *buf)
     172{
     173  owl_filterelement_print(fe->left, buf);
     174  strcat(buf, " and ");
     175  owl_filterelement_print(fe->right, buf);
     176}
     177
     178static void owl_filterelement_print_not(owl_filterelement *fe, char *buf)
     179{
     180  strcat(buf, " not ");
     181  owl_filterelement_print(fe->left, buf);
     182}
     183
     184// Constructors
     185
     186void owl_filterelement_create(owl_filterelement *fe) {
     187  fe->field = NULL;
     188  fe->left = fe->right = NULL;
     189  fe->match_message = NULL;
     190  fe->print_elt = NULL;
     191  owl_regex_init(&(fe->re));
     192}
     193
    53194
    54195void owl_filterelement_create_true(owl_filterelement *fe)
    55196{
    56   owl_filterelement_create_null(fe);
    57   fe->type=OWL_FILTERELEMENT_TRUE;
     197  owl_filterelement_create(fe);
     198  fe->match_message = owl_filterelement_match_true;
     199  fe->print_elt = owl_filterelement_print_true;
    58200}
    59201
    60202void owl_filterelement_create_false(owl_filterelement *fe)
    61203{
    62   owl_filterelement_create_null(fe);
    63   fe->type=OWL_FILTERELEMENT_FALSE;
     204  owl_filterelement_create(fe);
     205  fe->match_message = owl_filterelement_match_false;
     206  fe->print_elt = owl_filterelement_print_false;
    64207}
    65208
    66209void owl_filterelement_create_re(owl_filterelement *fe, char *field, char *re)
    67210{
    68   owl_filterelement_create_null(fe);
    69   fe->type=OWL_FILTERELEMENT_RE;
     211  owl_filterelement_create(fe);
    70212  fe->field=owl_strdup(field);
    71213  owl_regex_create(&(fe->re), re);
     214  fe->match_message = owl_filterelement_match_re;
     215  fe->print_elt = owl_filterelement_print_re;
    72216}
    73217
    74218void owl_filterelement_create_filter(owl_filterelement *fe, char *name)
    75219{
    76   owl_filterelement_create_null(fe);
    77   fe->type=OWL_FILTERELEMENT_FILTER;
    78   fe->filtername=owl_strdup(name);
     220  owl_filterelement_create(fe);
     221  fe->field=owl_strdup(name);
     222  fe->match_message = owl_filterelement_match_filter;
     223  fe->print_elt = owl_filterelement_print_filter;
    79224}
    80225
    81226void owl_filterelement_create_perl(owl_filterelement *fe, char *name)
    82227{
    83   owl_filterelement_create_null(fe);
    84   fe->type=OWL_FILTERELEMENT_PERL;
    85   fe->filtername=owl_strdup(name);
     228  owl_filterelement_create(fe);
     229  fe->field=owl_strdup(name);
     230  fe->match_message = owl_filterelement_match_perl;
     231  fe->print_elt = owl_filterelement_print_perl;
     232}
     233
     234void owl_filterelement_create_group(owl_filterelement *fe, owl_filterelement *in)
     235{
     236  owl_filterelement_create(fe);
     237  fe->left = in;
     238  fe->match_message = owl_filterelement_match_group;
     239  fe->print_elt = owl_filterelement_print_group;
     240}
     241
     242void owl_filterelement_create_not(owl_filterelement *fe, owl_filterelement *in)
     243{
     244  owl_filterelement_create(fe);
     245  fe->left = in;
     246  fe->match_message = owl_filterelement_match_not;
     247  fe->print_elt = owl_filterelement_print_not;
     248}
     249
     250void owl_filterelement_create_and(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
     251{
     252  owl_filterelement_create(fe);
     253  fe->left = lhs;
     254  fe->right = rhs;
     255  fe->match_message = owl_filterelement_match_and;
     256  fe->print_elt = owl_filterelement_print_and;
     257}
     258
     259void owl_filterelement_create_or(owl_filterelement *fe, owl_filterelement *lhs, owl_filterelement *rhs)
     260{
     261  owl_filterelement_create(fe);
     262  fe->left = lhs;
     263  fe->right = rhs;
     264  fe->match_message = owl_filterelement_match_or;
     265  fe->print_elt = owl_filterelement_print_or;
     266}
     267
     268int owl_filterelement_match(owl_filterelement *fe, owl_message *m)
     269{
     270  if(!fe) return 0;
     271  if(!fe->match_message) return 0;
     272  return fe->match_message(fe, m);
     273}
     274
     275int owl_filterelement_is_toodeep(owl_filter *f, owl_filterelement *fe)
     276{
     277  int one = 1;
     278  owl_list nodes;
     279  owl_dict filters;
     280  owl_list_create(&nodes);
     281  owl_dict_create(&filters);
     282 
     283  owl_list_append_element(&nodes, fe);
     284  owl_dict_insert_element(&filters, f->name, &one, NULL);
     285  while(owl_list_get_size(&nodes)) {
     286    fe = owl_list_get_element(&nodes, 0);
     287    owl_list_remove_element(&nodes, 0);
     288    if(fe->left) owl_list_append_element(&nodes, fe->left);
     289    if(fe->right) owl_list_append_element(&nodes, fe->right);
     290    if(fe->match_message == owl_filterelement_match_filter) {
     291      if(owl_dict_find_element(&filters, fe->field)) return 1;
     292      owl_dict_insert_element(&filters, fe->field, &one, NULL);
     293      f = owl_global_get_filter(&g, fe->field);
     294      if(f) owl_list_append_element(&nodes, f->root);
     295    }
     296  }
     297
     298  owl_list_free_simple(&nodes);
     299  owl_dict_free_simple(&filters);
     300  return 0;
    86301}
    87302
     
    89304{
    90305  if (fe->field) owl_free(fe->field);
    91   if (fe->filtername) owl_free(fe->filtername);
    92 }
    93 
    94 int owl_filterelement_is_null(owl_filterelement *fe)
    95 {
    96   if (fe->type==OWL_FILTERELEMENT_NULL) return(1);
    97   return(0);
    98 }
    99 
    100 int owl_filterelement_is_openbrace(owl_filterelement *fe)
    101 {
    102   if (fe->type==OWL_FILTERELEMENT_OPENBRACE) return(1);
    103   return(0);
    104 }
    105 
    106 int owl_filterelement_is_closebrace(owl_filterelement *fe)
    107 {
    108   if (fe->type==OWL_FILTERELEMENT_CLOSEBRACE) return(1);
    109   return(0);
    110 }
    111 
    112 int owl_filterelement_is_and(owl_filterelement *fe)
    113 {
    114   if (fe->type==OWL_FILTERELEMENT_AND) return(1);
    115   return(0);
    116 }
    117 
    118 int owl_filterelement_is_or(owl_filterelement *fe)
    119 {
    120   if (fe->type==OWL_FILTERELEMENT_OR) return(1);
    121   return(0);
    122 }
    123 
    124 int owl_filterelement_is_not(owl_filterelement *fe)
    125 {
    126   if (fe->type==OWL_FILTERELEMENT_NOT) return(1);
    127   return(0);
    128 }
    129 
    130 int owl_filterelement_is_true(owl_filterelement *fe)
    131 {
    132   if (fe->type==OWL_FILTERELEMENT_TRUE) return(1);
    133   return(0);
    134 }
    135 
    136 int owl_filterelement_is_false(owl_filterelement *fe)
    137 {
    138   if (fe->type==OWL_FILTERELEMENT_FALSE) return(1);
    139   return(0);
    140 }
    141 
    142 int owl_filterelement_is_re(owl_filterelement *fe)
    143 {
    144   if (fe->type==OWL_FILTERELEMENT_RE) return(1);
    145   return(0);
    146 }
    147 
    148 int owl_filterelement_is_perl(owl_filterelement *fe)
    149 {
    150   if (fe->type==OWL_FILTERELEMENT_PERL) return(1);
    151   return(0);
    152 }
    153 
    154 owl_regex *owl_filterelement_get_re(owl_filterelement *fe)
    155 {
    156   return(&(fe->re));
    157 }
    158 
    159 int owl_filterelement_is_filter(owl_filterelement *fe)
    160 {
    161   if (fe->type==OWL_FILTERELEMENT_FILTER) return(1);
    162   return(0);
    163 }
    164 
    165 char *owl_filterelement_get_field(owl_filterelement *fe)
    166 {
    167   if (fe->field) return(fe->field);
    168   return("unknown-field");
    169 }
    170 
    171 char *owl_filterelement_get_filtername(owl_filterelement *fe)
    172 {
    173   if (fe->filtername) return(fe->filtername);
    174   return("unknown-filter");
    175 }
    176 
    177 int owl_filterelement_is_value(owl_filterelement *fe)
    178 {
    179   if ( (fe->type==OWL_FILTERELEMENT_TRUE) ||
    180        (fe->type==OWL_FILTERELEMENT_FALSE) ||
    181        (fe->type==OWL_FILTERELEMENT_RE) ||
    182        (fe->type==OWL_FILTERELEMENT_PERL) ||
    183        (fe->type==OWL_FILTERELEMENT_FILTER)) {
    184     return(1);
    185   }
    186   return(0);
    187 }
    188 
    189 /* caller must free the return */
    190 char *owl_filterelement_to_string(owl_filterelement *fe)
    191 {
    192   if (owl_filterelement_is_openbrace(fe)) {
    193     return(owl_strdup("( "));
    194   } else if (owl_filterelement_is_closebrace(fe)) {
    195     return(owl_strdup(") "));
    196   } else if (owl_filterelement_is_and(fe)) {
    197     return(owl_strdup("and "));
    198   } else if (owl_filterelement_is_or(fe)) {
    199     return(owl_strdup("or "));
    200   } else if (owl_filterelement_is_not(fe)) {
    201     return(owl_strdup("not "));
    202   } else if (owl_filterelement_is_true(fe)) {
    203     return(owl_strdup("true "));
    204   } else if (owl_filterelement_is_false(fe)) {
    205     return(owl_strdup("false "));
    206   } else if (owl_filterelement_is_re(fe)) {
    207     return(owl_sprintf("%s %s ", fe->field, owl_regex_get_string(&(fe->re))));
    208   } else if (owl_filterelement_is_filter(fe)) {
    209     return(owl_sprintf("filter %s ", fe->filtername));
    210   } else if (owl_filterelement_is_perl(fe)) {
    211     return(owl_sprintf("perl %s ", fe->filtername));
    212   }
    213 
    214   return(owl_strdup("?"));
    215 }
     306  if (fe->left) {
     307    owl_filterelement_free(fe->left);
     308    owl_free(fe->left);
     309  }
     310  if (fe->right) {
     311    owl_filterelement_free(fe->right);
     312    owl_free(fe->right);
     313  }
     314  owl_regex_free(&(fe->re));
     315}
     316
     317void owl_filterelement_print(owl_filterelement *fe, char *buf)
     318{
     319  if(!fe || !fe->print_elt) return;
     320  fe->print_elt(fe, buf);
     321}
  • global.c

    rdb8b00b rcb769bb  
    7878  g->nextmsgid=0;
    7979
    80   owl_filterelement_create_true(&(g->fe_true));
    81   owl_filterelement_create_false(&(g->fe_false));
    82   owl_filterelement_create_null(&(g->fe_null));
    83 
    8480  _owl_global_setup_windows(g);
    8581
     
    583579}
    584580
    585 owl_filterelement *owl_global_get_filterelement_true(owl_global *g) {
    586   return(&(g->fe_true));
    587 }
    588 
    589 owl_filterelement *owl_global_get_filterelement_false(owl_global *g) {
    590   return(&(g->fe_false));
    591 }
    592 
    593 owl_filterelement *owl_global_get_filterelement_null(owl_global *g) {
    594   return(&(g->fe_null));
    595 }
    596 
    597581/* has colors */
    598582
  • owl.c

    r596c22df rcb769bb  
    190190  /* owl global init */
    191191  owl_global_init(&g);
    192   if (debug) owl_global_set_debug_on(&g);
     192    if (debug) owl_global_set_debug_on(&g);
    193193  owl_function_debugmsg("startup: first available debugging message");
    194194  owl_global_set_startupargs(&g, argcsave, argvsave);
  • owl.h

    r1b6b2f3 rcb769bb  
    400400
    401401typedef struct _owl_filterelement {
    402   int type;
     402  int (*match_message)(struct _owl_filterelement *fe, owl_message *m);
     403  /* Append a string representation of the filterelement onto buf*/
     404  void (*print_elt)(struct _owl_filterelement *fe, char * buf);
     405  /* Operands for and,or,not*/
     406  struct _owl_filterelement *left, *right;
     407  /* For regex filters*/
     408  owl_regex re;
     409  /* Used by regexes, filter references, and perl */
    403410  char *field;
    404   owl_regex re;
    405   char *filtername;  /* for maching on another filter */
    406411} owl_filterelement;
    407412
     
    409414  char *name;
    410415  int polarity;
    411   owl_list fes; /* filterelements */
     416  owl_filterelement * root;
    412417  int color;
    413418  int cachedmsgid;  /* cached msgid: should move into view eventually */
     
    555560  int malloced, freed;
    556561  char *searchstring;
    557   owl_filterelement fe_true;
    558   owl_filterelement fe_false;
    559   owl_filterelement fe_null;
    560562  aim_session_t aimsess;
    561563  aim_conn_t bosconn;
  • perl/modules/jabber.pl

    r20eb22c rcb769bb  
    352352
    353353            if ( $result[0] ne 'ok' ) {
    354             if ( !$vars{jlogin_havepass} && $result[0] == 401 ) {
     354            if ( !$vars{jlogin_havepass} && $result[0] eq '401' ) {
    355355                $vars{jlogin_havepass} = 1;
    356356                $conn->removeConnection($jidStr);
     
    809809
    810810    my $m = j2o( $j, { direction => 'out' } );
    811     if ( $vars{jwrite}{type} ne 'groupchat' ) {
    812 
    813         #XXX TODO: Check for displayoutgoing.
     811    if ( $vars{jwrite}{type} ne 'groupchat' && owl::getvar('displayoutgoing') eq 'on') {
    814812        owl::queue_message($m);
    815813    }
     
    10131011        $props{replycmd} .=
    10141012          " -a " . ( ( $dir eq 'out' ) ? $props{from} : $props{to} );
    1015         $props{isprivate} = 1;
     1013        $props{private} = 1;
    10161014    }
    10171015    elsif ( $jtype eq 'groupchat' ) {
     
    10321030    elsif ( $jtype eq 'normal' ) {
    10331031        $props{replycmd}  = undef;
    1034         $props{isprivate} = 1;
     1032        $props{private} = 1;
    10351033    }
    10361034    elsif ( $jtype eq 'headline' ) {
  • regex.c

    rbc08664 rcb769bb  
    8686void owl_regex_free(owl_regex *re)
    8787{
    88   if (re->string) owl_free(re->string);
     88    if (re->string) {
     89        owl_free(re->string);
     90        regfree(&(re->re));
     91    }
    8992
    9093  /* do we need to free the regular expression? */
  • tester.c

    r094009a rcb769bb  
    150150    numfailures += owl_dict_regtest();
    151151    numfailures += owl_variable_regtest();
     152    numfailures += owl_filter_regtest();
    152153    if (numfailures) {
    153154      fprintf(stderr, "*** WARNING: %d failures total\n", numfailures);
Note: See TracChangeset for help on using the changeset viewer.