/*
libutil -- read filter file and do filtering of messages

Written by Cornelius Krasel <krasel@wpxx02.toxi.uni-wuerzburg.de>.
Copyright 1998.

See file COPYING for restrictions on the use of this software.
*/

#include "leafnode.h"
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <pcre.h>

struct filterlist {
    struct filterlist *next;
    char *cleartext;
    pcre *expr;
};

static struct filterlist *filter;

/*
 * read filters into memory. Filters are just plain regexps
 */
void
readfilter(char *fifi)
{
    FILE *ff;
    char *l;
    const char *regex_errmsg;
    int regex_errpos;
    struct filterlist *f, *oldf;

    if (fifi == NULL || !strlen(fifi))
	return;
    filter = NULL;
    ff = fopen(fifi, "r");
    if (!ff) {
	syslog(LOG_ERR, "Unable to open filterfile %s: %m", fifi);
	printf("Unable to open filterfile %s\n", fifi);
	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");
#ifdef NEW_PCRE_COMPILE
	if ((f->expr = pcre_compile(l, PCRE_MULTILINE,
				    &regex_errmsg, &regex_errpos,
				    NULL)) == NULL) {
#else
	if ((f->expr = pcre_compile(l, PCRE_MULTILINE,
				    &regex_errmsg, &regex_errpos)) == NULL) {
#endif
	    syslog(LOG_ERR, "Invalid filter pattern %s: %s", l, regex_errmsg);
	    printf("Invalid filter pattern %s %s", l, regex_errmsg);
	    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(char *h)
{
    struct filterlist *f = filter;
    int match;

    match = -1;
    while (f && match == -1) {
#ifdef NEW_PCRE_EXEC
	match = pcre_exec(f->expr, NULL, h, strlen(h), 0, 0, NULL, 0);
#else
	match = pcre_exec(f->expr, NULL, h, strlen(h), 0, NULL, 0);
#endif
	if (debugmode > 1) {
	    syslog(LOG_DEBUG, "(\"%s\" =~ /%s/) = %d", h, f->cleartext, match);
	}
	if (match >= 0) {
	    return TRUE;
	}
	f = f->next;
    }
    return FALSE;		/* no match, or internal error */
}

void freefilter(void) {
    struct filterlist *f = filter, *g;

    while(f) {
	free(f->cleartext);
	pcre_free(f->expr);
	g = f->next;
	free(f);
	f = g;
    }
    filter = NULL;
}


syntax highlighted by Code2HTML, v. 0.9.1