Changeset 40458b9


Ignore:
Timestamp:
Dec 24, 2003, 7:35:21 PM (20 years ago)
Author:
James M. Kretchmar <kretch@mit.edu>
Branches:
master, barnowl_perlaim, debian, owl, release-1.10, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
5c1393d
Parents:
dad943e
Message:
Filters of filters now work
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • ChangeLog

    rc3acb0b r40458b9  
    11$Id$
    22
     32.1.1-pre-3
     4        Filters of filters now work.
     5       
    362.1.1-pre-2
    47        Added the 'aim search' command.  The popup on callback may be
  • commands.c

    r25b5b4b r40458b9  
    523523              "    type       -  message type (zephyr, aim, admin)\n"
    524524              "    direction  -  either 'in' 'out' or 'none'\n"
    525               "    login      -  either 'login' 'logout' or 'none'\n"
     525              "    login      -  either 'login' 'logout' or 'none'\n"
     526              "Also you may match on the validity of another filter:\n"
     527              "    filter <filtername>\n"
    526528              "Valid operators are:\n"
    527529              "    and\n"
  • filter.c

    r12c35df r40458b9  
    33
    44static const char fileIdent[] = "$Id$";
     5
     6#define OWL_FILTER_MAXRECURSE 20
     7
     8int filter_depth;
    59
    610int owl_filter_init_fromstring(owl_filter *f, char *name, char *string)
     
    1721int owl_filter_init(owl_filter *f, char *name, int argc, char **argv)
    1822{
    19   int i, error;
     23  int i, j, error;
    2024  owl_filterelement *fe;
    2125  char *regexstr;
     26  owl_list list;
    2227   
    2328  f->name=owl_strdup(name);
     
    6065      owl_filterelement_create_false(fe);
    6166     
    62     } else if (i==argc-1) {
     67    } else if (i==argc-1) { /* we need more than one arg at this point */
    6368      error=1;
    6469    } else {
     
    7883        owl_free(regexstr);
    7984        i++;
     85      } else if (!strcasecmp(argv[i], "filter")) {
     86        owl_filterelement_create_filter(fe, argv[i+1]);
     87        i++;
    8088      } else {
    8189        error=1;
     
    9098      return(-1);
    9199    }
    92 
    93   }
     100  }
     101 
     102  /* Are we trying to use the filter we're creating?  Bad. */
     103  owl_list_create(&list);
     104  _owl_filter_get_subfilter_names(f, &list);
     105  j=owl_list_get_size(&list);
     106  for (i=0; i<j; i++) {
     107    if (!strcasecmp(name, owl_list_get_element(&list, i))) {
     108      owl_function_error("Filter loop.");
     109      owl_filter_free(f);
     110      owl_list_free_all(&list, owl_free);
     111      return(-1);
     112    }
     113  }
     114  owl_list_free_all(&list, owl_free);
     115
     116  /* Now check for more subtle recursion. */
     117  if (owl_filter_is_toodeep(f)) {
     118    owl_function_error("Filter loop or exceeds recursion depth");
     119    owl_filter_free(f);
     120    return(-1);
     121  }
     122 
    94123  return(0);
    95124}
     
    188217      }
    189218    }
    190    
     219
    191220    tmp=owl_regex_compare(owl_filterelement_get_re(fe), match);
    192221    if (!tmp) {
     222      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
     223    } else {
     224      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
     225    }
     226  }
     227
     228  /* now subfilters */
     229  for (i=0; i<j; i++) {
     230    owl_filter *subfilter;
     231                           
     232    fe=owl_list_get_element(&work_fes, i);
     233    if (!owl_filterelement_is_filter(fe)) continue;
     234
     235    subfilter=owl_global_get_filter(&g, owl_filterelement_get_filtername(fe));
     236    if (!subfilter) {
     237      /* the filter does not exist, maybe because it was deleted.
     238       * Default to not matching
     239       */
     240      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_false(&g));
     241    } else if (owl_filter_message_match(subfilter, m)) {
    193242      owl_list_replace_element(&work_fes, i, owl_global_get_filterelement_true(&g));
    194243    } else {
     
    400449}
    401450
     451/* Return 1 if the filters 'a' and 'b' are equivalent, 0 otherwise */
    402452int owl_filter_equiv(owl_filter *a, owl_filter *b)
    403453{
     
    408458
    409459  if (!strcmp(buff, buff2)) return(1);
     460  return(0);
     461}
     462
     463/* Private
     464 * 'list' should already be allocated and initialized
     465 * This function places into list the string names of all filters
     466 * used in the filter expression for 'f'.
     467 * Caller must do a full free on 'list', including elements.
     468 */
     469void _owl_filter_get_subfilter_names(owl_filter *f, owl_list *list)
     470{
     471  int i, j;
     472  owl_filterelement *fe;
     473
     474  j=owl_list_get_size(&(f->fes));
     475  for (i=0; i<j; i++) {
     476    fe=owl_list_get_element(&(f->fes), i);
     477    if (owl_filterelement_is_filter(fe)) {
     478      owl_list_append_element(list, owl_strdup(owl_filterelement_get_filtername(fe)));
     479    }
     480  }
     481}
     482
     483int owl_filter_is_toodeep(owl_filter *f)
     484{
     485  owl_list seen, tocheck, tmp;
     486  int i, j, x, y;
     487  owl_filter *subfilter;
     488
     489  owl_list_create(&seen);
     490  owl_list_create(&tocheck);
     491  owl_list_create(&tmp);
     492
     493  /* seed 'tocheck' with the first set of filters */
     494  _owl_filter_get_subfilter_names(f, &tmp);
     495  j=owl_list_get_size(&tmp);
     496  for (i=0; i<j; i++) {
     497    owl_util_list_add_unique_string(&tocheck, owl_list_get_element(&tmp, i));
     498  }
     499  owl_list_free_all(&tmp, owl_free);
     500  owl_list_create(&tmp);
     501
     502  /* add this list to the 'seen' list */
     503  owl_list_append_element(&seen, owl_strdup(owl_filter_get_name(f)));
     504
     505  for (i=0; i<OWL_FILTER_MAXRECURSE; i++) {
     506    /* if anything in 'tocheck' is in 'seen' we have a loop */
     507    if (owl_util_common_strings_in_lists(&tocheck, &seen)) {
     508      owl_list_free_all(&tmp, owl_free);
     509      owl_list_free_all(&tocheck, owl_free);
     510      owl_list_free_all(&seen, owl_free);
     511      return(1);
     512    }
     513
     514    /* if there's nothing to check, we're done */
     515    y=owl_list_get_size(&tocheck);
     516    if (y==0) {
     517      owl_list_free_all(&tmp, owl_free);
     518      owl_list_free_all(&tocheck, owl_free);
     519      owl_list_free_all(&seen, owl_free);
     520      return(0);
     521    }
     522
     523    /* add everything in 'tocheck' to the 'seen' list */
     524    /* y=owl_list_get_size(&tocheck); */
     525    for (x=0; x<y; x++) {
     526      owl_list_append_element(&seen, owl_strdup(owl_list_get_element(&tocheck, x)));
     527    }
     528
     529    /* make a new list into 'tmp' with the children of 'tocheck' */
     530    /* y=owl_list_get_size(&tocheck); */
     531    for (x=0; x<y; x++) {
     532      subfilter=owl_global_get_filter(&g, owl_list_get_element(&tocheck, x));
     533      if (!subfilter) return(0);
     534      _owl_filter_get_subfilter_names(subfilter, &tmp);
     535    }
     536
     537    /* clean out 'tocheck' */
     538    owl_list_free_all(&tocheck, owl_free);
     539    owl_list_create(&tocheck);
     540
     541    /* put 'tmp' into 'tocheck' */
     542    y=owl_list_get_size(&tmp);
     543    for (x=0; x<y; x++) {
     544      owl_util_list_add_unique_string(&tocheck, owl_list_get_element(&tmp, x));
     545    }
     546
     547    /* clean out 'tmp' */
     548    owl_list_free_all(&tmp, owl_free);
     549    owl_list_create(&tmp);
     550  }
     551
     552  owl_list_free_all(&tmp, owl_free);
     553  owl_list_free_all(&tocheck, owl_free);
     554  owl_list_free_all(&seen, owl_free);
     555
     556  return(1);
     557}
     558
     559/* If the filter exceeds the max recursion depth, due to filters of
     560 * filters with possible loops, return 1.  Otherwise, return 0.
     561 */
     562int owl_filter_is_toodeep_old(owl_filter *f)
     563{
     564  int ret;
     565
     566  owl_function_debugmsg("owl_filter_is_toodeep: checking depth");
     567  filter_depth=0;
     568  ret=_owl_filter_toodeep_recurse(f);
     569  if (ret || (filter_depth>OWL_FILTER_MAXRECURSE)) {
     570    owl_function_debugmsg("owl_filter_is_toodeep: too deep");
     571    return(1);
     572  }
     573  owl_function_debugmsg("owl_filter_is_toodeep: ok");
     574  return(0);
     575}
     576
     577int _owl_filter_toodeep_recurse(owl_filter *f)
     578{
     579  owl_list list;
     580  owl_filter *subfilter;
     581  int i, j;
     582
     583  owl_function_debugmsg("_owl_filter_toodeep_recurse: filter_depth on entrance is  %i", filter_depth);
     584
     585  owl_list_create(&list);
     586  _owl_filter_get_subfilter_names(f, &list);
     587  j=owl_list_get_size(&list);
     588  if (j>0) {
     589    filter_depth++;
     590    if (filter_depth>OWL_FILTER_MAXRECURSE) {
     591      owl_list_free_all(&list, owl_free);
     592      return(1);
     593    }
     594    for (i=0; i<j; i++) {
     595      subfilter=owl_global_get_filter(&g, owl_list_get_element(&list, i));
     596      if (!subfilter) {
     597        owl_function_error("_owl_filter_toodeep_recurse: subfilter %s does not exist",
     598                           owl_list_get_element(&list, i));
     599        return(1);
     600      }
     601      return(_owl_filter_toodeep_recurse(subfilter));
     602    }
     603  }
     604  owl_list_free_all(&list, owl_free);
    410605  return(0);
    411606}
  • filterelement.c

    re187445 r40458b9  
    1212#define OWL_FILTERELEMENT_NOT         7
    1313#define OWL_FILTERELEMENT_RE          8
    14 
     14#define OWL_FILTERELEMENT_FILTER      9
    1515
    1616void owl_filterelement_create_null(owl_filterelement *fe)
     
    1818  fe->type=OWL_FILTERELEMENT_NULL;
    1919  fe->field=NULL;
     20  fe->filtername=NULL;
    2021}
    2122
    2223void owl_filterelement_create_openbrace(owl_filterelement *fe)
    2324{
     25  owl_filterelement_create_null(fe);
    2426  fe->type=OWL_FILTERELEMENT_OPENBRACE;
    25   fe->field=NULL;
    2627}
    2728
    2829void owl_filterelement_create_closebrace(owl_filterelement *fe)
    2930{
     31  owl_filterelement_create_null(fe);
    3032  fe->type=OWL_FILTERELEMENT_CLOSEBRACE;
    31   fe->field=NULL;
    3233}
    3334
    3435void owl_filterelement_create_and(owl_filterelement *fe)
    3536{
     37  owl_filterelement_create_null(fe);
    3638  fe->type=OWL_FILTERELEMENT_AND;
    37   fe->field=NULL;
    3839}
    3940
    4041void owl_filterelement_create_or(owl_filterelement *fe)
    4142{
     43  owl_filterelement_create_null(fe);
    4244  fe->type=OWL_FILTERELEMENT_OR;
    43   fe->field=NULL;
    4445}
    4546
    4647void owl_filterelement_create_not(owl_filterelement *fe)
    4748{
     49  owl_filterelement_create_null(fe);
    4850  fe->type=OWL_FILTERELEMENT_NOT;
    49   fe->field=NULL;
    5051}
    5152
    5253void owl_filterelement_create_true(owl_filterelement *fe)
    5354{
     55  owl_filterelement_create_null(fe);
    5456  fe->type=OWL_FILTERELEMENT_TRUE;
    55   fe->field=NULL;
    5657}
    5758
    5859void owl_filterelement_create_false(owl_filterelement *fe)
    5960{
     61  owl_filterelement_create_null(fe);
    6062  fe->type=OWL_FILTERELEMENT_FALSE;
    61   fe->field=NULL;
    6263}
    6364
    6465void owl_filterelement_create_re(owl_filterelement *fe, char *field, char *re)
    6566{
     67  owl_filterelement_create_null(fe);
    6668  fe->type=OWL_FILTERELEMENT_RE;
    6769  fe->field=owl_strdup(field);
     
    6971}
    7072
     73void owl_filterelement_create_filter(owl_filterelement *fe, char *name)
     74{
     75  owl_filterelement_create_null(fe);
     76  fe->type=OWL_FILTERELEMENT_FILTER;
     77  fe->filtername=owl_strdup(name);
     78}
     79
    7180void owl_filterelement_free(owl_filterelement *fe)
    7281{
    7382  if (fe->field) owl_free(fe->field);
     83  if (fe->filtername) owl_free(fe->filtername);
    7484}
    7585
     
    133143}
    134144
     145int owl_filterelement_is_filter(owl_filterelement *fe)
     146{
     147  if (fe->type==OWL_FILTERELEMENT_FILTER) return(1);
     148  return(0);
     149}
     150
    135151char *owl_filterelement_get_field(owl_filterelement *fe)
    136152{
    137   return(fe->field);
     153  if (fe->field) return(fe->field);
     154  return("unknown-field");
     155}
     156
     157char *owl_filterelement_get_filtername(owl_filterelement *fe)
     158{
     159  if (fe->filtername) return(fe->filtername);
     160  return("unknown-filter");
    138161}
    139162
     
    142165  if ( (fe->type==OWL_FILTERELEMENT_TRUE) ||
    143166       (fe->type==OWL_FILTERELEMENT_FALSE) ||
    144        (fe->type==OWL_FILTERELEMENT_RE) ) {
     167       (fe->type==OWL_FILTERELEMENT_RE) ||
     168       (fe->type==OWL_FILTERELEMENT_FILTER)) {
    145169    return(1);
    146170  }
     
    148172}
    149173
    150 
     174/* caller must free the return */
    151175char *owl_filterelement_to_string(owl_filterelement *fe)
    152176{
    153   /* return must be freed by caller */
    154  
    155177  if (owl_filterelement_is_openbrace(fe)) {
    156178    return(owl_strdup("( "));
     
    168190    return(owl_strdup("false "));
    169191  } else if (owl_filterelement_is_re(fe)) {
    170     char *buff;
    171     buff=owl_malloc(LINE);
    172     sprintf(buff, "%s %s ", fe->field, owl_regex_get_string(&(fe->re)));
    173     return(buff);
     192    return(owl_sprintf("%s %s ", fe->field, owl_regex_get_string(&(fe->re))));
     193  } else if (owl_filterelement_is_filter(fe)) {
     194    return(owl_sprintf("filter %s ", fe->filtername));
    174195  }
    175   return(owl_strdup(""));
     196
     197  return(owl_strdup("?"));
    176198}
  • functions.c

    r25b5b4b r40458b9  
    23862386  if (ret==-1) {
    23872387    owl_free(f);
    2388     owl_function_error("Invalid filter syntax");
     2388    owl_function_error("Invalid filter");
    23892389    return;
    23902390  }
  • owl.h

    r4b660cc r40458b9  
    2020static const char owl_h_fileIdent[] = "$Id$";
    2121
    22 #define OWL_VERSION         2.1.1-pre-2
    23 #define OWL_VERSION_STRING "2.1.1-pre-2"
     22#define OWL_VERSION         2.1.1-pre-3
     23#define OWL_VERSION_STRING "2.1.1-pre-3"
    2424
    2525/* Feature that is being tested to redirect stderr through a pipe.
     
    339339  char *field;
    340340  owl_regex re;
     341  char *filtername;  /* for maching on another filter */
    341342} owl_filterelement;
    342343
  • util.c

    r4b660cc r40458b9  
    697697}
    698698
     699/* add the string 'str' to the list 'list' of strings, only if it
     700 * is not already present
     701 */
     702void owl_util_list_add_unique_string(owl_list *list, char *str)
     703{
     704  int i, j;
     705
     706  j=owl_list_get_size(list);
     707  for (i=0; i<j; i++) {
     708    if (!strcmp(str, owl_list_get_element(list, i))) return;
     709  }
     710  owl_list_append_element(list, owl_strdup(str));
     711}
     712
     713int owl_util_common_strings_in_lists(owl_list *a, owl_list *b)
     714{
     715  int i, j, x, y;
     716
     717  j=owl_list_get_size(a);
     718  for (i=0; i<j; i++) {
     719    y=owl_list_get_size(b);
     720    for (x=0; x<y; x++) {
     721      if (!strcmp(owl_list_get_element(a, i), owl_list_get_element(b, x))) return(1);
     722    }
     723  }
     724  return(0);
     725}
     726
    699727/**************************************************************************/
    700728/************************* REGRESSION TESTS *******************************/
Note: See TracChangeset for help on using the changeset viewer.