/*
 * dsyslog - a dumb syslog (e.g. syslog for people who have a clue)
 * Copyright (c) 2008 William Pitcock <nenolod@sacredspiral.co.uk>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "dsyslog.h"

struct dsyslog_filter_type_map {
        gchar *type;
        dsyslog_filter_handler_t hdl;
};

static GList *filter_list_ = NULL;
static GList *filter_type_list_ = NULL;

void
dsyslog_filter_add(dsyslog_filter_t *filter)
{
	GList *n;

	_ENTER;

	for (n = filter_type_list_; n != NULL; n = g_list_next(n)) {
		struct dsyslog_filter_type_map *m = (struct dsyslog_filter_type_map *) n->data;

		if (!g_ascii_strcasecmp(m->type, filter->type)) {
			filter->handler = m->hdl;
			break;
		}
	}

	filter_list_ = g_list_append(filter_list_, filter);
	dsyslog_perfctr.filters++;

	_LEAVE;
}

void
dsyslog_filter_remove(dsyslog_filter_t *filter)
{
	_ENTER;

	filter_list_ = g_list_remove_all(filter_list_, filter);

	if (filter->destructor)
		filter->destructor(filter);

	g_free(filter->type);
	g_free(filter->search);
	g_free(filter->replace);
	g_free(filter->program);
	g_free(filter->message);

	g_slice_free(dsyslog_filter_t, filter);
	dsyslog_perfctr.filters--;

	_LEAVE;
}

void
dsyslog_filter_type_register(gchar *type, dsyslog_filter_handler_t hdl)
{
	struct dsyslog_filter_type_map *m;

	_ENTER;

	m = g_slice_new(struct dsyslog_filter_type_map);
	m->type = type;
	m->hdl = hdl;

	filter_type_list_ = g_list_prepend(filter_type_list_, m);

	_LEAVE;
}

void
dsyslog_filter_type_unregister(gchar *type)
{
	GList *n;

	_ENTER;

	for (n = filter_type_list_; n != NULL; n = g_list_next(n)) {
		struct dsyslog_filter_type_map *m = (struct dsyslog_filter_type_map *) n->data;

		if (!g_ascii_strcasecmp(type, m->type)) {
			filter_type_list_ = g_list_remove_all(filter_type_list_, m);
			g_slice_free(struct dsyslog_filter_type_map, m);

			_LEAVE;
		}
	}

	_LEAVE;
}

gboolean
dsyslog_filter_process(dsyslog_event_t *event)
{
	GList *n;
	gboolean ret = TRUE;

	_ENTER;

	for (n = filter_list_; n != NULL; n = g_list_next(n)) {
		dsyslog_filter_t *filter = (dsyslog_filter_t *) n->data;

		if (filter->handler(event, filter))
			ret = FALSE;
	}

	_LEAVE ret;
}

void
dsyslog_filter_clear(void)
{
	GList *n, *n2;

	_ENTER;

	for (n = filter_list_, n2 = g_list_next(filter_list_); n != NULL; n = n2, n2 = g_list_next(n2)) {
		dsyslog_filter_t *filter = (dsyslog_filter_t *) n->data;

		dsyslog_filter_remove(filter);
	}

	filter_list_ = NULL;

	_LEAVE;
}
