From 5a490945ea221cc94b05e2ed6e872a2ecbefe175 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Sat, 16 Jan 2021 13:30:59 -0500 Subject: Rename ignore code to filter --- Makefile | 2 +- README.7 | 4 +-- chat.c | 2 +- chat.h | 15 ++++----- command.c | 23 +++++++------- filter.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ handle.c | 16 +++++----- ignore.c | 104 ------------------------------------------------------------- 8 files changed, 137 insertions(+), 134 deletions(-) create mode 100644 filter.c delete mode 100644 ignore.c diff --git a/Makefile b/Makefile index 2c3061d..5caa3ba 100644 --- a/Makefile +++ b/Makefile @@ -13,8 +13,8 @@ OBJS += command.o OBJS += complete.o OBJS += config.o OBJS += edit.o +OBJS += filter.o OBJS += handle.o -OBJS += ignore.o OBJS += irc.o OBJS += log.o OBJS += ui.o diff --git a/README.7 b/README.7 index 0261d3e..03a535d 100644 --- a/README.7 +++ b/README.7 @@ -1,4 +1,4 @@ -.Dd November 11, 2020 +.Dd January 16, 2021 .Dt README 7 .Os "Causal Agency" .\" To view this file, run: man ./README.7 @@ -167,7 +167,7 @@ line editing tab complete .It Pa url.c URL detection -.It Pa ignore.c +.It Pa filter.c message filtering .It Pa log.c chat logging diff --git a/chat.c b/chat.c index b4458be..cdea9a0 100644 --- a/chat.c +++ b/chat.c @@ -243,7 +243,7 @@ int main(int argc, char *argv[]) { break; case 'e': sasl = true; break; case 'g': genCert(optarg); break; case 'h': host = optarg; - break; case 'i': ignoreAdd(optarg); + break; case 'i': filterAdd(Ice, optarg); break; case 'j': self.join = optarg; break; case 'k': priv = optarg; break; case 'l': logEnable = true; diff --git a/chat.h b/chat.h index e027fa5..1b1c338 100644 --- a/chat.h +++ b/chat.h @@ -361,17 +361,18 @@ void urlCopyMatch(uint id, const char *str); int urlSave(FILE *file); void urlLoad(FILE *file, size_t version); -enum { IgnoreCap = 64 }; -extern struct Ignore { +enum { FilterCap = 64 }; +extern struct Filter { + enum Heat heat; char *mask; char *cmd; char *chan; char *mesg; -} ignores[IgnoreCap]; -struct Ignore ignoreParse(char *pattern); -struct Ignore ignoreAdd(const char *pattern); -bool ignoreRemove(struct Ignore ignore); -enum Heat ignoreCheck(enum Heat heat, uint id, const struct Message *msg); +} filters[FilterCap]; +struct Filter filterParse(enum Heat heat, char *pattern); +struct Filter filterAdd(enum Heat heat, const char *pattern); +bool filterRemove(struct Filter filter); +enum Heat filterCheck(enum Heat heat, uint id, const struct Message *msg); extern bool logEnable; void logFormat(uint id, const time_t *time, const char *format, ...) diff --git a/command.c b/command.c index f6db311..f266878 100644 --- a/command.c +++ b/command.c @@ -388,19 +388,20 @@ static void commandCopy(uint id, char *params) { static void commandIgnore(uint id, char *params) { if (params) { - struct Ignore ignore = ignoreAdd(params); + struct Filter filter = filterAdd(Ice, params); uiFormat( id, Cold, NULL, "Ignoring \3%02d%s %s %s %s", - Brown, ignore.mask, - (ignore.cmd ?: ""), (ignore.chan ?: ""), (ignore.mesg ?: "") + Brown, filter.mask, + (filter.cmd ?: ""), (filter.chan ?: ""), (filter.mesg ?: "") ); } else { - for (size_t i = 0; i < IgnoreCap && ignores[i].mask; ++i) { + for (size_t i = 0; i < FilterCap && filters[i].mask; ++i) { + if (filters[i].heat != Ice) continue; uiFormat( Network, Warm, NULL, "Ignoring \3%02d%s %s %s %s", - Brown, ignores[i].mask, - (ignores[i].cmd ?: ""), (ignores[i].chan ?: ""), - (ignores[i].mesg ?: "") + Brown, filters[i].mask, + (filters[i].cmd ?: ""), (filters[i].chan ?: ""), + (filters[i].mesg ?: "") ); } } @@ -408,12 +409,12 @@ static void commandIgnore(uint id, char *params) { static void commandUnignore(uint id, char *params) { if (!params) return; - struct Ignore ignore = ignoreParse(params); - bool found = ignoreRemove(ignore); + struct Filter filter = filterParse(Ice, params); + bool found = filterRemove(filter); uiFormat( id, Cold, NULL, "%s ignoring \3%02d%s %s %s %s", - (found ? "No longer" : "Not"), Brown, ignore.mask, - (ignore.cmd ?: ""), (ignore.chan ?: ""), (ignore.mesg ?: "") + (found ? "No longer" : "Not"), Brown, filter.mask, + (filter.cmd ?: ""), (filter.chan ?: ""), (filter.mesg ?: "") ); } diff --git a/filter.c b/filter.c new file mode 100644 index 0000000..2a7d564 --- /dev/null +++ b/filter.c @@ -0,0 +1,105 @@ +/* Copyright (C) 2020 C. McEnroe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this Program, or any covered work, by linking or + * combining it with OpenSSL (or a modified version of that library), + * containing parts covered by the terms of the OpenSSL License and the + * original SSLeay license, the licensors of this Program grant you + * additional permission to convey the resulting work. Corresponding + * Source for a non-source form of such a combination shall include the + * source code for the parts of OpenSSL used as well as that of the + * covered work. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "chat.h" + +struct Filter filters[FilterCap]; +static size_t len; + +struct Filter filterParse(enum Heat heat, char *pattern) { + struct Filter filter = { .heat = heat }; + filter.mask = strsep(&pattern, " "); + filter.cmd = strsep(&pattern, " "); + filter.chan = strsep(&pattern, " "); + filter.mesg = pattern; + return filter; +} + +struct Filter filterAdd(enum Heat heat, const char *pattern) { + if (len == FilterCap) errx(EX_CONFIG, "filter limit exceeded"); + char *own; + if (!strchr(pattern, '!') && !strchr(pattern, ' ')) { + int n = asprintf(&own, "%s!*@*", pattern); + if (n < 0) err(EX_OSERR, "asprintf"); + } else { + own = strdup(pattern); + if (!own) err(EX_OSERR, "strdup"); + } + struct Filter filter = filterParse(heat, own); + filters[len++] = filter; + return filter; +} + +bool filterRemove(struct Filter filter) { + bool found = false; + for (size_t i = len - 1; i < len; --i) { + if (filters[i].heat != filter.heat) continue; + if (!filters[i].cmd != !filter.cmd) continue; + if (!filters[i].chan != !filter.chan) continue; + if (!filters[i].mesg != !filter.mesg) continue; + if (strcasecmp(filters[i].mask, filter.mask)) continue; + if (filter.cmd && strcasecmp(filters[i].cmd, filter.cmd)) continue; + if (filter.chan && strcasecmp(filters[i].chan, filter.chan)) continue; + if (filter.mesg && strcasecmp(filters[i].mesg, filter.mesg)) continue; + free(filters[i].mask); + filters[i] = filters[--len]; + filters[len] = (struct Filter) {0}; + found = true; + } + return found; +} + +static bool filterTest( + struct Filter filter, const char *mask, uint id, const struct Message *msg +) { + if (fnmatch(filter.mask, mask, FNM_CASEFOLD)) return false; + if (!filter.cmd) return true; + if (fnmatch(filter.cmd, msg->cmd, FNM_CASEFOLD)) return false; + if (!filter.chan) return true; + if (fnmatch(filter.chan, idNames[id], FNM_CASEFOLD)) return false; + if (!filter.mesg) return true; + if (!msg->params[1]) return false; + return !fnmatch(filter.mesg, msg->params[1], FNM_CASEFOLD); +} + +enum Heat filterCheck(enum Heat heat, uint id, const struct Message *msg) { + if (!len) return heat; + char mask[512]; + snprintf(mask, sizeof(mask), "%s!%s@%s", msg->nick, msg->user, msg->host); + for (size_t i = 0; i < len; ++i) { + if (filterTest(filters[i], mask, id, msg)) return filters[i].heat; + } + return heat; +} diff --git a/handle.c b/handle.c index 9c5fac3..702196b 100644 --- a/handle.c +++ b/handle.c @@ -343,7 +343,7 @@ static void handleJoin(struct Message *msg) { msg->params[2] = NULL; } uiFormat( - id, ignoreCheck(Cold, id, msg), tagTime(msg), + id, filterCheck(Cold, id, msg), tagTime(msg), "\3%02d%s\3\t%s%s%sarrives in \3%02d%s\3", hash(msg->user), msg->nick, (msg->params[2] ? "(" : ""), @@ -373,7 +373,7 @@ static void handlePart(struct Message *msg) { completeClear(id); } completeRemove(id, msg->nick); - enum Heat heat = ignoreCheck(Cold, id, msg); + enum Heat heat = filterCheck(Cold, id, msg); if (heat > Ice) urlScan(id, msg->nick, msg->params[1]); uiFormat( id, heat, tagTime(msg), @@ -423,7 +423,7 @@ static void handleNick(struct Message *msg) { set(&idNames[id], msg->params[0]); } uiFormat( - id, ignoreCheck(Cold, id, msg), tagTime(msg), + id, filterCheck(Cold, id, msg), tagTime(msg), "\3%02d%s\3\tis now known as \3%02d%s\3", hash(msg->user), msg->nick, hash(msg->user), msg->params[0] ); @@ -440,7 +440,7 @@ static void handleSetname(struct Message *msg) { require(msg, true, 1); for (uint id; (id = completeID(msg->nick));) { uiFormat( - id, ignoreCheck(Cold, id, msg), tagTime(msg), + id, filterCheck(Cold, id, msg), tagTime(msg), "\3%02d%s\3\tis now known as \3%02d%s\3 (%s)", hash(msg->user), msg->nick, hash(msg->user), msg->nick, msg->params[0] @@ -451,7 +451,7 @@ static void handleSetname(struct Message *msg) { static void handleQuit(struct Message *msg) { require(msg, true, 0); for (uint id; (id = completeID(msg->nick));) { - enum Heat heat = ignoreCheck(Cold, id, msg); + enum Heat heat = filterCheck(Cold, id, msg); if (heat > Ice) urlScan(id, msg->nick, msg->params[0]); uiFormat( id, heat, tagTime(msg), @@ -473,7 +473,7 @@ static void handleInvite(struct Message *msg) { require(msg, true, 2); if (!strcmp(msg->params[0], self.nick)) { uiFormat( - Network, ignoreCheck(Hot, Network, msg), tagTime(msg), + Network, filterCheck(Hot, Network, msg), tagTime(msg), "\3%02d%s\3\tinvites you to \3%02d%s\3", hash(msg->user), msg->nick, hash(msg->params[1]), msg->params[1] ); @@ -1199,7 +1199,7 @@ static void handlePrivmsg(struct Message *msg) { bool notice = (msg->cmd[0] == 'N'); bool action = isAction(msg); bool mention = !mine && isMention(msg); - enum Heat heat = ignoreCheck((mention || query ? Hot : Warm), id, msg); + enum Heat heat = filterCheck((mention || query ? Hot : Warm), id, msg); if (!notice && !mine && heat > Ice) { completeTouch(id, msg->nick, hash(msg->user)); } @@ -1212,7 +1212,7 @@ static void handlePrivmsg(struct Message *msg) { logFormat(id, tagTime(msg), "-%s- %s", msg->nick, msg->params[1]); } uiFormat( - id, ignoreCheck(Warm, id, msg), tagTime(msg), + id, filterCheck(Warm, id, msg), tagTime(msg), "\3%d-%s-\3%d\t%s", hash(msg->user), msg->nick, LightGray, msg->params[1] ); diff --git a/ignore.c b/ignore.c deleted file mode 100644 index 5a9d296..0000000 --- a/ignore.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2020 C. McEnroe - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this Program, or any covered work, by linking or - * combining it with OpenSSL (or a modified version of that library), - * containing parts covered by the terms of the OpenSSL License and the - * original SSLeay license, the licensors of this Program grant you - * additional permission to convey the resulting work. Corresponding - * Source for a non-source form of such a combination shall include the - * source code for the parts of OpenSSL used as well as that of the - * covered work. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "chat.h" - -struct Ignore ignores[IgnoreCap]; -static size_t len; - -struct Ignore ignoreParse(char *pattern) { - struct Ignore ignore = {0}; - ignore.mask = strsep(&pattern, " "); - ignore.cmd = strsep(&pattern, " "); - ignore.chan = strsep(&pattern, " "); - ignore.mesg = pattern; - return ignore; -} - -struct Ignore ignoreAdd(const char *pattern) { - if (len == IgnoreCap) errx(EX_CONFIG, "ignore limit exceeded"); - char *own; - if (!strchr(pattern, '!') && !strchr(pattern, ' ')) { - int n = asprintf(&own, "%s!*@*", pattern); - if (n < 0) err(EX_OSERR, "asprintf"); - } else { - own = strdup(pattern); - if (!own) err(EX_OSERR, "strdup"); - } - struct Ignore ignore = ignoreParse(own); - ignores[len++] = ignore; - return ignore; -} - -bool ignoreRemove(struct Ignore ignore) { - bool found = false; - for (size_t i = len - 1; i < len; --i) { - if (!ignores[i].cmd != !ignore.cmd) continue; - if (!ignores[i].chan != !ignore.chan) continue; - if (!ignores[i].mesg != !ignore.mesg) continue; - if (strcasecmp(ignores[i].mask, ignore.mask)) continue; - if (ignore.cmd && strcasecmp(ignores[i].cmd, ignore.cmd)) continue; - if (ignore.chan && strcasecmp(ignores[i].chan, ignore.chan)) continue; - if (ignore.mesg && strcasecmp(ignores[i].mesg, ignore.mesg)) continue; - free(ignores[i].mask); - ignores[i] = ignores[--len]; - ignores[len] = (struct Ignore) {0}; - found = true; - } - return found; -} - -static bool ignoreTest( - struct Ignore ignore, const char *mask, uint id, const struct Message *msg -) { - if (fnmatch(ignore.mask, mask, FNM_CASEFOLD)) return false; - if (!ignore.cmd) return true; - if (fnmatch(ignore.cmd, msg->cmd, FNM_CASEFOLD)) return false; - if (!ignore.chan) return true; - if (fnmatch(ignore.chan, idNames[id], FNM_CASEFOLD)) return false; - if (!ignore.mesg) return true; - if (!msg->params[1]) return false; - return !fnmatch(ignore.mesg, msg->params[1], FNM_CASEFOLD); -} - -enum Heat ignoreCheck(enum Heat heat, uint id, const struct Message *msg) { - if (!len) return heat; - char mask[512]; - snprintf(mask, sizeof(mask), "%s!%s@%s", msg->nick, msg->user, msg->host); - for (size_t i = 0; i < len; ++i) { - if (ignoreTest(ignores[i], mask, id, msg)) return Ice; - } - return heat; -} -- cgit 1.4.1