From 669cf6e1895ef8048be2a49cec2d0fb8aab0c90b Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Wed, 25 Feb 2004 20:49:00 +0000 Subject: [PATCH] - Fixed an issue where chanmode +f was often set by the server again in a netjoin when there was no need to (nothing to synch). - Added spamfilter::except which allows you to specify targets (eg: channels) where spamfilter should not take action. Requested by Fury (#0001586). Ex: set { spamfilter { except "#spamreport,#help"; }; }; --- Changes | 5 +++++ doc/example.conf | 18 +++++++++++++++--- doc/unreal32docs.html | 3 +++ include/dynconf.h | 3 +++ include/struct.h | 6 ++++++ src/modules/m_sjoin.c | 17 ++++++++++++++++- src/modules/m_stats.c | 3 +++ src/s_conf.c | 32 ++++++++++++++++++++++++++++++-- src/s_kline.c | 20 ++++++++++++++++++++ 9 files changed, 101 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index 516fd6c8e..c36d7fc23 100644 --- a/Changes +++ b/Changes @@ -2972,3 +2972,8 @@ seen. gmtime warning still there - '0' tkltime in spamfilter now really means 'perm', not '*line for 0 seconds' or something. Reported by Certus. - Fixed a bug in individual m_*.so loading, 39 new modules were affected. +- Fixed an issue where chanmode +f was often set by the server again + in a netjoin when there was no need to (nothing to synch). +- Added spamfilter::except which allows you to specify targets + (eg: channels) where spamfilter should not take action. Requested by Fury + (#0001586). Ex: set { spamfilter { except "#spamreport,#help"; }; }; diff --git a/doc/example.conf b/doc/example.conf index ee8eff25f..87887127b 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -32,10 +32,15 @@ loadmodule "src/modules/commands.so"; /* - * You can also include other configuration files. help.conf contains all the - * /helpop text so you probably want this include: + * You can also include other configuration files. + * help.conf contains all the /helpop text. The badwords.*.conf + * files contain all the badword entries for mode +G... + * You probably want to include them: */ include "help.conf"; +include "badwords.channel.conf"; +include "badwords.message.conf"; +include "badwords.quit.conf"; /* * NEW: me {} @@ -743,7 +748,7 @@ set { * Some admins might want to remove the 'kGs' to allow normal users to list * klines, glines and shuns. */ - oper-only-stats "okGsMRUEelLCXzdD"; + oper-only-stats "okfGsMRUEelLCXzdD"; /* Throttling: this example sets a limit of 3 connections per 60s (per host). */ throttle { @@ -756,6 +761,13 @@ set { nick-flood 3:60; /* 3 nickchanges per 60 seconds (the default) */ }; + /* Spam filter */ + spamfilter { + ban-time 1d; /* default duration of a *line ban set by spamfilter */ + ban-reason "Spam/Advertising"; /* default reason */ + virus-help-channel "#help"; /* channel to use for 'viruschan' action */ + /* except "#help"; channel to exempt from filtering */ + }; }; /* diff --git a/doc/unreal32docs.html b/doc/unreal32docs.html index 0dbd43cf1..1f208e746 100644 --- a/doc/unreal32docs.html +++ b/doc/unreal32docs.html @@ -2146,6 +2146,9 @@ set { Reason to be used for *lines added by spamfilter

set::spamfilter::virus-help-channel <channel>
The channel to use for the 'viruschan' action in spamfilter

+

set::spamfilter::except <target(s)>
+ These targets are exempt from spam filtering (no action will be taken), + can be single target or comma seperated list.. Ex: except "#help,#spamreport"

5 – Additional Files

diff --git a/include/dynconf.h b/include/dynconf.h index 72e62f3ec..7c8b9b29e 100644 --- a/include/dynconf.h +++ b/include/dynconf.h @@ -134,6 +134,8 @@ struct zConfiguration { long spamfilter_ban_time; char *spamfilter_ban_reason; char *spamfilter_virus_help_channel; + SpamExcept *spamexcept; + char *spamexcept_line; aNetwork network; }; @@ -232,3 +234,4 @@ extern aConfiguration iConf; #define SPAMFILTER_BAN_TIME iConf.spamfilter_ban_time #define SPAMFILTER_BAN_REASON iConf.spamfilter_ban_reason #define SPAMFILTER_VIRUSCHAN iConf.spamfilter_virus_help_channel +#define SPAMFILTER_EXCEPT iConf.spamexcept_line diff --git a/include/struct.h b/include/struct.h index e76ff5393..c2717bbdf 100644 --- a/include/struct.h +++ b/include/struct.h @@ -77,6 +77,7 @@ typedef struct aloopStruct LoopStruct; typedef struct ConfItem aConfItem; typedef struct t_kline aTKline; typedef struct _spamfilter Spamfilter; +typedef struct _spamexcept SpamExcept; /* New Config Stuff */ typedef struct _configentry ConfigEntry; typedef struct _configfile ConfigFile; @@ -775,6 +776,11 @@ struct t_kline { TS expire_at, set_at; }; +struct _spamexcept { + SpamExcept *prev, *next; + char name[1]; +}; + typedef struct ircstatsx { int clients; /* total */ int invisible; /* invisible */ diff --git a/src/modules/m_sjoin.c b/src/modules/m_sjoin.c index 20b82c900..f785811a6 100644 --- a/src/modules/m_sjoin.c +++ b/src/modules/m_sjoin.c @@ -107,6 +107,21 @@ aParv *mp2parv(char *xmbuf, char *parmbuf) return (&pparv); } +/* Checks if 2 ChanFloodProt modes (chmode +f) are different. + * This is a bit more complicated than 1 simple memcmp(a,b,..) because + * counters are also stored in this struct so we have to do + * it manually :( -- Syzop. + */ +static int compare_floodprot_modes(ChanFloodProt *a, ChanFloodProt *b) +{ + if (memcmp(a->l, b->l, sizeof(a->l)) || + memcmp(a->a, b->a, sizeof(a->a)) || + memcmp(a->r, b->r, sizeof(a->r))) + return 1; + else + return 0; +} + /* ** m_sjoin ** @@ -761,7 +776,7 @@ CMD_FUNC(m_sjoin) char *x; int i; - if (memcmp(chptr->mode.floodprot, oldmode.floodprot, sizeof(ChanFloodProt))) + if (compare_floodprot_modes(chptr->mode.floodprot, oldmode.floodprot)) { chptr->mode.floodprot->per = MAX(chptr->mode.floodprot->per, oldmode.floodprot->per); for (i=0; i < NUMFLD; i++) diff --git a/src/modules/m_stats.c b/src/modules/m_stats.c index cead81901..425fc8798 100644 --- a/src/modules/m_stats.c +++ b/src/modules/m_stats.c @@ -1321,6 +1321,9 @@ int stats_set(aClient *sptr, char *para) sptr->name, SPAMFILTER_BAN_REASON); sendto_one(sptr, ":%s %i %s :spamfilter::virus-help-channel: %s", me.name, RPL_TEXT, sptr->name, SPAMFILTER_VIRUSCHAN); + if (SPAMFILTER_EXCEPT) + sendto_one(sptr, ":%s %i %s :spamfilter::except: %s", me.name, RPL_TEXT, + sptr->name, SPAMFILTER_EXCEPT); sendto_one(sptr, ":%s %i %s :hosts::global: %s", me.name, RPL_TEXT, sptr->name, oper_host); sendto_one(sptr, ":%s %i %s :hosts::admin: %s", me.name, RPL_TEXT, diff --git a/src/s_conf.c b/src/s_conf.c index 1424aa997..70e3ce0d2 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1339,6 +1339,7 @@ void free_iConf(aConfiguration *i) ircfree(i->network.x_stats_server); ircfree(i->spamfilter_ban_reason); ircfree(i->spamfilter_virus_help_channel); + ircfree(i->spamexcept_line); } int config_test(); @@ -1591,6 +1592,7 @@ void config_rehash() OperStat *os_ptr; ListStruct *next, *next2; aTKline *tk, *tk_next; + SpamExcept *spamex_ptr; USE_BAN_VERSION = 0; /* clean out stuff that we don't use */ @@ -1892,6 +1894,12 @@ void config_rehash() MyFree(os_ptr); } iConf.oper_only_stats_ext = NULL; + for (spamex_ptr = iConf.spamexcept; spamex_ptr; spamex_ptr = (SpamExcept *)next) + { + next = (ListStruct *)spamex_ptr->next; + MyFree(spamex_ptr); + } + iConf.spamexcept = NULL; for (of_ptr = conf_offchans; of_ptr; of_ptr = (ConfigItem_offchans *)next) { next = (ListStruct *)of_ptr->next; @@ -5543,7 +5551,7 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce) { for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) { - OperStat *os = MyMalloc(sizeof(OperStat)); + OperStat *os = MyMallocEx(sizeof(OperStat)); ircstrdup(os->flag, cepp->ce_varname); AddListItem(os, tempiConf.oper_only_stats_ext); } @@ -5726,6 +5734,23 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce) ircstrdup(tempiConf.spamfilter_ban_reason, cepp->ce_vardata); if (!strcmp(cepp->ce_varname, "virus-help-channel")) ircstrdup(tempiConf.spamfilter_virus_help_channel, cepp->ce_vardata); + if (!strcmp(cepp->ce_varname, "except")) + { + char *name, *p; + SpamExcept *e; + ircstrdup(tempiConf.spamexcept_line, cepp->ce_vardata); + for (name = strtoken(&p, cepp->ce_vardata, ","); name; name = strtoken(&p, NULL, ",")) + { + if (*name == ' ') + name++; + if (*name) + { + e = MyMallocEx(sizeof(SpamExcept) + strlen(name)); + strcpy(e->name, name); + AddListItem(e, tempiConf.spamexcept); + } + } + } } } else if (!strcmp(cep->ce_varname, "default-bantime")) @@ -6344,7 +6369,10 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce) errors++; continue; } - } else { + } else + if (!strcmp(cepp->ce_varname, "except")) + { } else + { config_error("%s:%i: unknown directive set::spamfilter::%s", cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname); errors++; diff --git a/src/s_kline.c b/src/s_kline.c index 97454a192..b18a10cde 100644 --- a/src/s_kline.c +++ b/src/s_kline.c @@ -1319,6 +1319,21 @@ int place_host_ban(aClient *sptr, int action, char *reason, long duration) return -1; } +/** Checks if 'target' is on the spamfilter exception list. + * RETURNS 1 if found in list, 0 if not. + */ +int target_is_spamexcept(char *target) +{ +SpamExcept *e; + + for (e = iConf.spamexcept; e; e = e->next) + { + if (!match(e->name, target)) + return 1; + } + return 0; +} + /** dospamfilter: executes the spamfilter onto the string. * str: the text (eg msg text, notice text, part text, quit text, etc * type: the spamfilter type (SPAMF_*) @@ -1352,6 +1367,11 @@ char *str = (char *)StripControlCodes(str_in); strlcpy(targetbuf+1, target, sizeof(targetbuf)-1); /* cut it off */ } else targetbuf[0] = '\0'; + + /* Hold on.. perhaps it's on the exceptions list... */ + if (target && target_is_spamexcept(target)) + return 0; /* No problem! */ + ircsprintf(buf, "[Spamfilter] %s!%s@%s matches filter '%s': [%s%s: '%s'] [%s]", sptr->name, sptr->user->username, sptr->user->realhost, tk->reason,