Changeset cb769bb
- Timestamp:
- Dec 26, 2006, 1:05:26 AM (18 years ago)
- 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
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
filter.c
rb699e9b rcb769bb 19 19 int owl_filter_init(owl_filter *f, char *name, int argc, char **argv) 20 20 { 21 int i, j, error;22 owl_filterelement *fe;23 char *regexstr;24 owl_list list;25 26 21 f->name=owl_strdup(name); 27 22 f->polarity=0; 28 23 f->color=OWL_COLOR_DEFAULT; 29 24 f->cachedmsgid=-1; 30 owl_list_create(&(f->fes)); 31 25 32 26 /* first take arguments that have to come first */ 33 27 /* set the color */ … … 41 35 argv+=2; 42 36 } 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. */ 106 42 if (owl_filter_is_toodeep(f)) { 107 43 owl_function_error("Filter loop or exceeds recursion depth"); … … 109 45 return(-1); 110 46 } 111 47 112 48 return(0); 49 } 50 51 52 /* A primitive expression is one without any toplevel ``and'' or ``or''s*/ 53 54 static 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; 101 err: 102 owl_filterelement_free(fe); 103 owl_free(fe); 104 return NULL; 105 } 106 107 owl_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; 138 err: 139 if(op1) { 140 owl_filterelement_free(op1); 141 owl_free(op1); 142 } 143 return NULL; 113 144 } 114 145 … … 153 184 int owl_filter_message_match(owl_filter *f, owl_message *m) 154 185 { 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 444 192 445 193 void owl_filter_print(owl_filter *f, char *out) 446 194 { 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); 467 198 strcat(out, "\n"); 468 199 } … … 480 211 } 481 212 482 /* Private483 * 'list' should already be allocated and initialized484 * This function places into list the string names of all filters485 * 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 }501 213 502 214 int owl_filter_is_toodeep(owl_filter *f) 503 215 { 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); 576 217 } 577 218 578 219 void owl_filter_free(owl_filter *f) 579 220 { 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 } 584 225 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 234 int 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 260 int 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 3 3 static const char fileIdent[] = "$Id$"; 4 4 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 } 5 static 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 52 static int owl_filterelement_match_false(owl_filterelement *fe, owl_message *m) 53 { 54 return 0; 55 } 56 57 static int owl_filterelement_match_true(owl_filterelement *fe, owl_message *m) 58 { 59 return 1; 60 } 61 62 static 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 68 static 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 81 static 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 100 static 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 109 static 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 115 static 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 121 static 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 128 static void owl_filterelement_print_true(owl_filterelement *fe, char *buf) 129 { 130 strcat(buf, "true"); 131 } 132 133 static void owl_filterelement_print_false(owl_filterelement *fe, char *buf) 134 { 135 strcat(buf, "false"); 136 } 137 138 static 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 145 static void owl_filterelement_print_filter(owl_filterelement *fe, char *buf) 146 { 147 strcat(buf, "filter "); 148 strcat(buf, fe->field); 149 } 150 151 static void owl_filterelement_print_perl(owl_filterelement *fe, char *buf) 152 { 153 strcat(buf, "perl "); 154 strcat(buf, fe->field); 155 } 156 157 static 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 164 static 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 171 static 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 178 static 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 186 void 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 53 194 54 195 void owl_filterelement_create_true(owl_filterelement *fe) 55 196 { 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; 58 200 } 59 201 60 202 void owl_filterelement_create_false(owl_filterelement *fe) 61 203 { 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; 64 207 } 65 208 66 209 void owl_filterelement_create_re(owl_filterelement *fe, char *field, char *re) 67 210 { 68 owl_filterelement_create_null(fe); 69 fe->type=OWL_FILTERELEMENT_RE; 211 owl_filterelement_create(fe); 70 212 fe->field=owl_strdup(field); 71 213 owl_regex_create(&(fe->re), re); 214 fe->match_message = owl_filterelement_match_re; 215 fe->print_elt = owl_filterelement_print_re; 72 216 } 73 217 74 218 void owl_filterelement_create_filter(owl_filterelement *fe, char *name) 75 219 { 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; 79 224 } 80 225 81 226 void owl_filterelement_create_perl(owl_filterelement *fe, char *name) 82 227 { 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 234 void 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 242 void 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 250 void 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 259 void 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 268 int 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 275 int 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; 86 301 } 87 302 … … 89 304 { 90 305 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 317 void 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 78 78 g->nextmsgid=0; 79 79 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 84 80 _owl_global_setup_windows(g); 85 81 … … 583 579 } 584 580 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 597 581 /* has colors */ 598 582 -
owl.c
r596c22df rcb769bb 190 190 /* owl global init */ 191 191 owl_global_init(&g); 192 if (debug) owl_global_set_debug_on(&g);192 if (debug) owl_global_set_debug_on(&g); 193 193 owl_function_debugmsg("startup: first available debugging message"); 194 194 owl_global_set_startupargs(&g, argcsave, argvsave); -
owl.h
r1b6b2f3 rcb769bb 400 400 401 401 typedef 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 */ 403 410 char *field; 404 owl_regex re;405 char *filtername; /* for maching on another filter */406 411 } owl_filterelement; 407 412 … … 409 414 char *name; 410 415 int polarity; 411 owl_ list fes; /* filterelements */416 owl_filterelement * root; 412 417 int color; 413 418 int cachedmsgid; /* cached msgid: should move into view eventually */ … … 555 560 int malloced, freed; 556 561 char *searchstring; 557 owl_filterelement fe_true;558 owl_filterelement fe_false;559 owl_filterelement fe_null;560 562 aim_session_t aimsess; 561 563 aim_conn_t bosconn; -
perl/modules/jabber.pl
r20eb22c rcb769bb 352 352 353 353 if ( $result[0] ne 'ok' ) { 354 if ( !$vars{jlogin_havepass} && $result[0] == 401) {354 if ( !$vars{jlogin_havepass} && $result[0] eq '401' ) { 355 355 $vars{jlogin_havepass} = 1; 356 356 $conn->removeConnection($jidStr); … … 809 809 810 810 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') { 814 812 owl::queue_message($m); 815 813 } … … 1013 1011 $props{replycmd} .= 1014 1012 " -a " . ( ( $dir eq 'out' ) ? $props{from} : $props{to} ); 1015 $props{ isprivate} = 1;1013 $props{private} = 1; 1016 1014 } 1017 1015 elsif ( $jtype eq 'groupchat' ) { … … 1032 1030 elsif ( $jtype eq 'normal' ) { 1033 1031 $props{replycmd} = undef; 1034 $props{ isprivate} = 1;1032 $props{private} = 1; 1035 1033 } 1036 1034 elsif ( $jtype eq 'headline' ) { -
regex.c
rbc08664 rcb769bb 86 86 void owl_regex_free(owl_regex *re) 87 87 { 88 if (re->string) owl_free(re->string); 88 if (re->string) { 89 owl_free(re->string); 90 regfree(&(re->re)); 91 } 89 92 90 93 /* do we need to free the regular expression? */ -
tester.c
r094009a rcb769bb 150 150 numfailures += owl_dict_regtest(); 151 151 numfailures += owl_variable_regtest(); 152 numfailures += owl_filter_regtest(); 152 153 if (numfailures) { 153 154 fprintf(stderr, "*** WARNING: %d failures total\n", numfailures);
Note: See TracChangeset
for help on using the changeset viewer.