Mercurial > irccd
view lib/irccd/rule.c @ 958:533639ec5e9c
misc: use sys/queue.h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 21 Jan 2021 23:15:20 +0100 |
parents | 9b167c5c4b78 |
children | 4af3140f234d |
line wrap: on
line source
/* * rule.c -- rule filtering * * Copyright (c) 2013-2021 David Demelier <markand@malikania.fr> * * 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 appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <assert.h> #include <ctype.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "rule.h" #include "util.h" static inline void lower(char *dst, const char *src) { while (*src) *dst++ = tolower(*src++); } static char * find(const char *str, const char *value) { char strlower[IRC_RULE_LEN] = {0}; char valuelower[IRC_RULE_LEN] = {0}; char *p; lower(strlower, str); lower(valuelower, value); if ((p = strstr(strlower, valuelower))) return (char *)&str[p - strlower]; return NULL; } static bool match(const char *str, const char *value) { size_t len; const char *p; if (!str[0]) return true; if (!value || (len = strlen(value)) == 0 || !(p = find(str, value))) return false; /* * Consider the following scenario: * * value = no * str = mlk:freenode: * p = ^ */ while (p != str && *p != ':') --p; if (*p == ':') ++p; return strncasecmp(p, value, len) == 0; } struct irc_rule * irc_rule_new(enum irc_rule_action action) { struct irc_rule *r; r = irc_util_calloc(1, sizeof (*r)); r->action = action; return r; } bool irc_rule_add(char *str, const char *value) { size_t slen, vlen; if (find(str, value)) return true; slen = strlen(str); vlen = strlen(value); if (vlen + 1 >= IRC_RULE_LEN - slen) { errno = ENOMEM; return false; } sprintf(&str[slen], "%s:", value); return true; } void irc_rule_remove(char *str, const char *value) { char *pos; size_t vlen, slen; if (!(pos = find(str, value))) return; slen = strlen(str); vlen = strlen(value) + 1; /* includes ':' */ assert(pos[vlen - 1] == ':'); memmove(&pos[0], &pos[vlen], IRC_RULE_LEN - (&pos[vlen] - str)); } bool irc_rule_match(const struct irc_rule *rule, const char *server, const char *channel, const char *origin, const char *plugin, const char *event) { return match(rule->servers, server) && match(rule->channels, channel) && match(rule->origins, origin) && match(rule->plugins, plugin) && match(rule->events, event); } bool irc_rule_matchlist(const struct irc_rule_list *rules, const char *server, const char *channel, const char *origin, const char *plugin, const char *event) { bool result = true; struct irc_rule *r; TAILQ_FOREACH(r, rules, link) if (irc_rule_match(r, server, channel, origin, plugin, event)) result = r->action == IRC_RULE_ACCEPT; return result; } void irc_rule_finish(struct irc_rule *rule) { assert(rule); free(rule); }