/* filterutil.c -- read filter file and do filtering of messages Written by Cornelius Krasel . Copyright 1998. Modified and Copyright of modifications 2001-2021 by Matthias Andree See file COPYING for restrictions on the use of this software. */ #include "leafnode.h" #include #include #include #include #include #include #include "ln_log.h" struct filterlist { struct filterlist *next; char *cleartext; pcre2_code_8 *re; }; static struct filterlist *filter; /* * read filters into memory. Filters are just plain regexps */ void readfilter(char *fifi) { FILE *ff; char *l; int regex_errcode; size_t regex_errpos; struct filterlist *f, *oldf; if (fifi == NULL || !strlen(fifi)) return; filter = NULL; ff = fopen(fifi, "r"); if (!ff) { int e = errno; syslog(LOG_ERR, "Unable to open filterfile %s: %m", fifi); printf("Unable to open filterfile %s: %s\n", fifi, strerror(e)); return; } oldf = NULL; debug = 0; while ((l = getaline(ff)) != NULL) { if (*l == '#' || *l == '\0') continue; f = (struct filterlist *)critmalloc(sizeof(struct filterlist), "Allocating filterlist space"); if (NULL == (f->re = pcre2_compile_8((u_char *)l, PCRE2_ZERO_TERMINATED, PCRE2_MULTILINE, ®ex_errcode, ®ex_errpos, NULL))) { unsigned char buf[SIZE_lineout]; int len = pcre2_get_error_message_8(regex_errcode, buf, sizeof(buf)); syslog(LOG_ERR, "Invalid filter pattern %s: %s%s", l, buf, len == PCRE2_ERROR_NOMEMORY ? "[...]" : ""); printf("Invalid filter pattern %s %s%s", l, buf, len == PCRE2_ERROR_NOMEMORY ? "[...]" : ""); free(f); } else { f->next = NULL; f->cleartext = critstrdup(l, "readfilter"); if (!filter) filter = f; else oldf->next = f; oldf = f; } } debug = debugmode; fclose(ff); } /* * read and filter headers. * Return true if headers matched pattern, false if not */ int dofilter(unsigned char *h) { struct filterlist *f = filter; int match; pcre2_match_data_8 *match_data = pcre2_match_data_create_8(1, NULL); if (NULL == match_data) { ln_log(LNLOG_SERR, LNLOG_CTOP, "filterutil.c::dofilter: out of memory allocating match_data"); return -1; } match = PCRE2_ERROR_NOMATCH; while (f && 0 > match) { match = pcre2_match_8(f->re, h, PCRE2_ZERO_TERMINATED, /*offset*/ 0, /*options*/ 0, match_data, /*ctx*/ NULL); if (debugmode > 1) { syslog(LOG_DEBUG, "(\"%s\" =~ /%s/) = %d", h, f->cleartext, match); } if (match >= 0) { pcre2_match_data_free_8(match_data); return TRUE; } f = f->next; } pcre2_match_data_free_8(match_data); return FALSE; /* no match, or internal error */ } void freefilter(void) { struct filterlist *f = filter, *g; while(f) { free(f->cleartext); pcre2_code_free_8(f->re); g = f->next; free(f); f = g; } filter = NULL; }