/* Copyright (C) 2000-1 drscholl@users.sourceforge.net
   This is free software distributed under the terms of the
   GNU Public License.  See the file COPYING for details.

   $Id: filter.c,v 1.11 2001/02/23 19:23:08 drscholl Exp $ */

/* simple filtering mechanism to weed out entries which have too many
 * matches.  this used to be hardcoded, but various servers will need
 * to tailor this to suit their own needs.  see sample.filter for an
 * example list of commonly occuring words
 */

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "opennap.h"
#include "debug.h"

#ifndef ROUTING_ONLY
#include "regex.h"

HASH   *Filter = 0;
static LIST *Block = 0;

static void
load_filter_internal (HASH * h, const char *file)
{
    char    path[_POSIX_PATH_MAX];
    char    buf[128], *token;
    int     len;
    FILE   *fp;

    snprintf (path, sizeof (path), "%s/%s", Config_Dir, file);
    fp = fopen (path, "r");
    if (!fp)
    {
        if (errno != ENOENT)
            log ("load_filter_internal: fopen: %s: %s (errno %d)",
                 path, strerror (errno), errno);
        return;
    }
    while (fgets (buf, sizeof (buf) - 1, fp))
    {
        len = strlen (buf);
        while (len > 0 && isspace (buf[len - 1]))
            len--;
        buf[len] = 0;
        /* no need to convert to lowercase since the hash table is
         * case-insensitive
         */
        token = STRDUP (buf);
        hash_add (h, token, token);
    }
    fclose (fp);
}

void
load_filter (void)
{
    if (Filter)
        free_hash (Filter);
    Filter = hash_init (257, free_pointer);
    load_filter_internal (Filter, "filter");
}

void
load_block (void)
{
    char    path[_POSIX_PATH_MAX];
    char    buf[256];
    char    err[256];
    char    exp[256];
    int     len;
    FILE   *fp;
    regex_t *rx;
    int     line = 0;
    LIST  **head = &Block;
    int     n;

    log ("load_block: free'g old list");

    while (*head)
    {
        LIST   *ptr = *head;

        *head = (*head)->next;
        regfree (ptr->data);
        FREE (ptr);
    }

    snprintf (path, sizeof (path), "%s/block", Config_Dir);
    fp = fopen (path, "r");
    if (!fp)
    {
        if (errno != ENOENT)
            log ("load_block: fopen: %s: %s (errno %d)",
                 path, strerror (errno), errno);
        return;
    }
    log ("load_block: reading %s", path);
    while (fgets (buf, sizeof (buf) - 1, fp))
    {
        line++;
        if (buf[0] == '#')
            continue;
        len = strlen (buf);
        while (len > 0 && isspace (buf[len - 1]))
            len--;
        buf[len] = 0;
        snprintf (exp, sizeof (exp), "(^|[^[:alpha:]])%s($|[^[:alpha:]])",
                  buf);
        rx = CALLOC (1, sizeof (regex_t));
        n = regcomp (rx, exp, REG_EXTENDED | REG_ICASE | REG_NOSUB);
        if (n)
        {
            regerror (n, rx, err, sizeof (err));
            log ("load_block:%s:%d:%s", path, line, err);
            continue;
        }
        *head = CALLOC (1, sizeof (LIST));
        (*head)->data = rx;
        head = &(*head)->next;
    }
    fclose (fp);
    log ("load_block: done");
}

int
is_filtered (char *s)
{
    return (hash_lookup (Filter, s) != 0);
}

int
is_blocked (char *s)
{
    LIST   *ptr = Block;

    for (; ptr; ptr = ptr->next)
        if (regexec (ptr->data, s, 0, NULL, 0) == 0)
        {
#if 0
            printf ("is_blocked: match: %s\n", s);
#endif
            return 1;
        }
    return 0;
}
#endif /* ! ROUTING_ONLY */
