bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen#include "lib.h"
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen#include "array.h"
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen#include "llist.h"
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen#include "str.h"
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen#include "strescape.h"
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen#include "wildcard-match.h"
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen#include "lib-event-private.h"
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen#include "event-filter.h"
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenenum event_filter_code {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen EVENT_FILTER_CODE_NAME = 'n',
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen EVENT_FILTER_CODE_SOURCE = 's',
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen EVENT_FILTER_CODE_CATEGORY = 'c',
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen EVENT_FILTER_CODE_FIELD = 'f',
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen};
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstruct event_filter_category {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char *name;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* Pointer to the event_category. NULL if the category isn't
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen registered yet. If it becomes registered, this will be filled out
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen by the category register callback. */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_category *category;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen};
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstruct event_filter_query_internal {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int categories_count;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int fields_count;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen bool has_unregistered_categories;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_category *categories;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_field *fields;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char *name;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char *source_filename;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int source_linenum;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen void *context;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen};
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstruct event_filter {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter *prev, *next;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen pool_t pool;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int refcount;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen ARRAY(struct event_filter_query_internal) queries;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen bool named_queries_only;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen};
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic struct event_filter *event_filters = NULL;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstruct event_filter *event_filter_create(void)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter *filter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen pool_t pool = pool_alloconly_create("event filter", 256);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen filter = p_new(pool, struct event_filter, 1);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen filter->pool = pool;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen filter->refcount = 1;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen filter->named_queries_only = TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen p_array_init(&filter->queries, pool, 4);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen DLLIST_PREPEND(&event_filters, filter);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return filter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid event_filter_ref(struct event_filter *filter)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i_assert(filter->refcount > 0);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen filter->refcount++;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid event_filter_unref(struct event_filter **_filter)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter *filter = *_filter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (filter == NULL)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i_assert(filter->refcount > 0);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen *_filter = NULL;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (--filter->refcount > 0)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen DLLIST_REMOVE(&event_filters, filter);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen pool_unref(&filter->pool);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic void
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_add_categories(struct event_filter *filter,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_query_internal *int_query,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char *const *categories)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int categories_count = str_array_length(categories);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_category *cat;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int i;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (categories_count == 0)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* copy strings */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen cat = p_new(filter->pool, struct event_filter_category,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen categories_count);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (i = 0; i < categories_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen cat[i].name = p_strdup(filter->pool, categories[i]);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen cat[i].category = event_category_find_registered(categories[i]);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (cat[i].category == NULL)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->has_unregistered_categories = TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->categories_count = categories_count;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->categories = cat;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic void
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_add_fields(struct event_filter *filter,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_query_internal *int_query,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_filter_field *fields)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_field *int_fields;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int i, count;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (count = 0; fields[count].key != NULL; count++) ;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (count == 0)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_fields = p_new(filter->pool, struct event_field, count);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (i = 0; i < count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_fields[i].key = p_strdup(filter->pool, fields[i].key);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* Filter currently supports only comparing strings
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen and numbers. */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_fields[i].value.str = p_strdup(filter->pool, fields[i].value);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (str_to_intmax(fields[i].value, &int_fields[i].value.intmax) < 0) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* not a number - no problem */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->fields_count = count;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->fields = int_fields;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid event_filter_add(struct event_filter *filter,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_filter_query *query)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_query_internal *int_query;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query = array_append_space(&filter->queries);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->context = query->context;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->name != NULL)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->name = p_strdup(filter->pool, query->name);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen else
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen filter->named_queries_only = FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->source_filename =
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen p_strdup_empty(filter->pool, query->source_filename);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen int_query->source_linenum = query->source_linenum;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->categories != NULL)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_add_categories(filter, int_query, query->categories);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->fields != NULL)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_add_fields(filter, int_query, query->fields);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid event_filter_merge(struct event_filter *dest,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_filter *src)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_filter_query_internal *int_query;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_query query;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int i;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_foreach(&src->queries, int_query) T_BEGIN {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i_zero(&query);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.context = int_query->context;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.name = int_query->name;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.source_filename = int_query->source_filename;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.source_linenum = int_query->source_linenum;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (int_query->categories_count > 0) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen ARRAY_TYPE(const_string) categories;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen t_array_init(&categories, int_query->categories_count);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (i = 0; i < int_query->categories_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_append(&categories,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen &int_query->categories[i].name, 1);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_append_zero(&categories);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.categories = array_idx(&categories, 0);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (int_query->fields_count > 0) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen ARRAY(struct event_filter_field) fields;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen t_array_init(&fields, int_query->fields_count);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (i = 0; i < int_query->fields_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_field *field =
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_append_space(&fields);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen field->key = p_strdup(dest->pool, int_query->fields[i].key);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen field->value = p_strdup(dest->pool, int_query->fields[i].value.str);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_append_zero(&fields);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.fields = array_idx(&fields, 0);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_add(dest, &query);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen } T_END;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic void
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_export_query(const struct event_filter_query_internal *query,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen string_t *dest)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int i;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->name != NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, EVENT_FILTER_CODE_NAME);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_tabescaped(dest, query->name);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, '\t');
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->source_filename != NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, EVENT_FILTER_CODE_SOURCE);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_tabescaped(dest, query->source_filename);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_printfa(dest, "\t%u\t", query->source_linenum);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (i = 0; i < query->categories_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, EVENT_FILTER_CODE_CATEGORY);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_tabescaped(dest, query->categories[i].name);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, '\t');
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (i = 0; i < query->fields_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, EVENT_FILTER_CODE_FIELD);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_tabescaped(dest, query->fields[i].key);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, '\t');
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_tabescaped(dest, query->fields[i].value.str);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, '\t');
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid event_filter_export(struct event_filter *filter, string_t *dest)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_filter_query_internal *query;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen bool first = TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_foreach(&filter->queries, query) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!first)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen str_append_c(dest, '\t');
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen first = FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_export_query(query, dest);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenbool event_filter_import(struct event_filter *filter, const char *str,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char **error_r)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return event_filter_import_unescaped(filter,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen t_strsplit_tabescaped(str), error_r);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenbool event_filter_import_unescaped(struct event_filter *filter,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char *const *args,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char **error_r)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_query query;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen ARRAY_TYPE(const_string) categories;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen ARRAY(struct event_filter_field) fields;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen bool changed;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen t_array_init(&categories, 8);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen t_array_init(&fields, 8);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i_zero(&query);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen changed = FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (unsigned int i = 0; args[i] != NULL; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char *arg = args[i];
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (arg[0] == '\0') {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* finish the query */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (array_count(&categories) > 0) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_append_zero(&categories);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.categories = array_idx(&categories, 0);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (array_count(&fields) > 0) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_append_zero(&fields);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.fields = array_idx(&fields, 0);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_add(filter, &query);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* start the next query */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i_zero(&query);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_clear(&categories);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_clear(&fields);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen changed = FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen continue;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen enum event_filter_code code = arg[0];
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen arg++;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen switch (code) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen case EVENT_FILTER_CODE_NAME:
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.name = arg;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen break;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen case EVENT_FILTER_CODE_SOURCE:
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query.source_filename = arg;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i++;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (args[i] == NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen *error_r = "Source line number missing";
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (str_to_uint(args[i], &query.source_linenum) < 0) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen *error_r = "Invalid Source line number";
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen break;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen case EVENT_FILTER_CODE_CATEGORY:
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_append(&categories, &arg, 1);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen break;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen case EVENT_FILTER_CODE_FIELD: {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_field *field;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen field = array_append_space(&fields);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen field->key = arg;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i++;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (args[i] == NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen *error_r = "Field value missing";
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen field->value = args[i];
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen break;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen changed = TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (changed) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen *error_r = "Expected TAB at the end";
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic bool
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_has_category(struct event *event, struct event_category *wanted_category)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_category *const *catp;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i_assert(wanted_category != NULL);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen while (event != NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (array_is_created(&event->categories)) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_foreach(&event->categories, catp) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (*catp == wanted_category)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* try also the parent events */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event = event_get_parent(event);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic bool
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_query_match_categories(const struct event_filter_query_internal *query,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event *event)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->has_unregistered_categories) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* At least one of the categories in the filter hasn't even
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen been registered yet. This filter can't match. */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (unsigned int i = 0; i < query->categories_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!event_has_category(event, query->categories[i].category))
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic bool
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_match_field(struct event *event, const struct event_field *wanted_field)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_field *field;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* wanted_field has the value in all available formats */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen while ((field = event_find_field(event, wanted_field->key)) == NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event = event_get_parent(event);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (event == NULL)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen switch (field->value_type) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen case EVENT_FIELD_VALUE_TYPE_STR:
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return wildcard_match_icase(field->value.str, wanted_field->value.str);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen case EVENT_FIELD_VALUE_TYPE_INTMAX:
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return field->value.intmax == wanted_field->value.intmax;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen case EVENT_FIELD_VALUE_TYPE_TIMEVAL:
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* there's no point to support matching exact timestamps */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i_unreached();
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic bool
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_query_match_fields(const struct event_filter_query_internal *query,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event *event)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (unsigned int i = 0; i < query->fields_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!event_match_field(event, &query->fields[i]))
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic bool
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_query_match(const struct event_filter_query_internal *query,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event *event, const char *source_filename,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int source_linenum)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->name != NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (event->sending_name == NULL ||
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen strcmp(event->sending_name, query->name) != 0)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->source_filename != NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (source_linenum != query->source_linenum ||
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen source_filename == NULL ||
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen strcmp(event->source_filename, query->source_filename) != 0)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!event_filter_query_match_categories(query, event))
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!event_filter_query_match_fields(query, event))
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic bool
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_match_fastpath(struct event_filter *filter, struct event *event)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (filter->named_queries_only && event->sending_name == NULL) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen /* No debug logging is enabled. Only named events may be wanted
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for stats. This event doesn't have a name, so we don't need
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen to check any further. */
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenbool event_filter_match(struct event_filter *filter, struct event *event)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return event_filter_match_source(filter, event, event->source_filename,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event->source_linenum);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenbool event_filter_match_source(struct event_filter *filter, struct event *event,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const char *source_filename,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int source_linenum)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_filter_query_internal *query;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!event_filter_match_fastpath(filter, event))
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_foreach(&filter->queries, query) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (event_filter_query_match(query, event, source_filename,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen source_linenum))
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstruct event_filter_match_iter {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter *filter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event *event;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int idx;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen};
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstruct event_filter_match_iter *
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_match_iter_init(struct event_filter *filter, struct event *event)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_match_iter *iter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen iter = i_new(struct event_filter_match_iter, 1);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen iter->filter = filter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen iter->event = event;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!event_filter_match_fastpath(filter, event))
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen iter->idx = UINT_MAX;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return iter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid *event_filter_match_iter_next(struct event_filter_match_iter *iter)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_filter_query_internal *queries;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen unsigned int count;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen queries = array_get(&iter->filter->queries, &count);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen while (iter->idx < count) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen const struct event_filter_query_internal *query =
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen &queries[iter->idx];
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen iter->idx++;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->context != NULL &&
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_query_match(query, iter->event,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen iter->event->source_filename,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen iter->event->source_linenum))
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return query->context;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return NULL;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid event_filter_match_iter_deinit(struct event_filter_match_iter **_iter)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_match_iter *iter = *_iter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen *_iter = NULL;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen i_free(iter);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic void
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_query_remove_category(struct event_filter_query_internal *query,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_category *category)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (unsigned int i = 0; i < query->categories_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->categories[i].category == category) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query->categories[i].category = NULL;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query->has_unregistered_categories = TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic void
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_remove_category(struct event_filter *filter,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_category *category)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_query_internal *query;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_foreach_modifiable(&filter->queries, query)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_query_remove_category(query, category);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic void
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_query_add_missing_category(struct event_filter_query_internal *query,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_category *category)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!query->has_unregistered_categories)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen return;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query->has_unregistered_categories = FALSE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (unsigned int i = 0; i < query->categories_count; i++) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (query->categories[i].category != NULL)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen continue;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (strcmp(query->categories[i].name, category->name) == 0)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query->categories[i].category = category;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen else
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen query->has_unregistered_categories = TRUE;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic void
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenevent_filter_add_missing_category(struct event_filter *filter,
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_category *category)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter_query_internal *query;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen array_foreach_modifiable(&filter->queries, query)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_query_add_missing_category(query, category);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenstatic void event_filter_category_registered(struct event_category *category)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen struct event_filter *filter;
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen for (filter = event_filters; filter != NULL; filter = filter->next) {
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen if (!category->registered)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_remove_category(filter, category);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen else
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_filter_add_missing_category(filter, category);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen }
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid event_filter_init(void)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_category_register_callback(event_filter_category_registered);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen
918384d458981e7db4aadc283212eb19912d5709Timo Sirainenvoid event_filter_deinit(void)
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen{
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen event_category_unregister_callback(event_filter_category_registered);
918384d458981e7db4aadc283212eb19912d5709Timo Sirainen}