diff --git a/Changes b/Changes index 7a5a08648..659992a15 100644 --- a/Changes +++ b/Changes @@ -2821,3 +2821,14 @@ seen. gmtime warning still there spamfilter::word to spamfilter::regex to make it even more clear (since we match on the whole line and have nothing to do with words.. 'word' doesn't make sense). - Updated docs with some better regex examples, reported by AngryWolf (#0001520). +- Added snomasks 'S' (Spamfilter) which notifies you of any spamfilter matches. +- [internal] always return after spamfilter match, don't continue looping trough + targets list (eg in case of: /msg #a,#b,#c spamspam), otherwise you would get + duplicate notification msgs. +- Added SENDSNO server command, similar to SENDUMODE but for snomasks, this is + used by the spamfilter snomask (+S) so you get network-wide notifications. +- Added "compiled for.." versioning system, this way a beta17 module can't be loaded + on beta18, etc... People often forgot to recompile their modules or had old ones + somewhere by mistake, therefore crashing after upgrades... this should fix this + (in the future). Module coders don't have to do anything for making this work, + it's done automatically (via modules.h). diff --git a/include/h.h b/include/h.h index 9696b34b3..51afc3966 100644 --- a/include/h.h +++ b/include/h.h @@ -451,6 +451,7 @@ extern long SNO_NICKCHANGE; extern long SNO_FNICKCHANGE; extern long SNO_QLINE; extern long SNO_SNOTICE; +extern long SNO_SPAMF; #ifdef EXTCMODE /* Extended chanmodes... */ @@ -651,7 +652,9 @@ extern char banact_valtochar(int val); extern int spamfilter_gettargets(char *s, aClient *sptr); extern char *spamfilter_target_inttostring(int v); extern Spamfilter *unreal_buildspamfilter(char *s); -extern int dospamfilter(aClient *sptr, char *str, int type); +extern int dospamfilter(aClient *sptr, char *str_in, int type, char *target); extern char *our_strcasestr(char *haystack, char *needle); extern int spamfilter_getconftargets(char *s); extern void remove_oper_snomasks(aClient *sptr); +extern char *spamfilter_inttostring_long(int v); +extern int check_channelmask(aClient *, aClient *, char *); diff --git a/include/modules.h b/include/modules.h index 85dfb6bef..cef93a2f8 100644 --- a/include/modules.h +++ b/include/modules.h @@ -562,4 +562,10 @@ int CallCmdoverride(Cmdoverride *ovr, aClient *cptr, aClient *sptr, int parc, ch #define MOD_UNLOAD(name) name##_Unload #endif +#ifdef DYNAMIC_LINKING +/* ugly alert!!!! */ +#include "version.h" +char Mod_Version[] = BASE_VERSION PATCH1 PATCH2 PATCH3 PATCH4 PATCH5 PATCH6 PATCH7 PATCH8 PATCH9; +#endif + #endif diff --git a/include/msg.h b/include/msg.h index a2a38056b..d28871c80 100644 --- a/include/msg.h +++ b/include/msg.h @@ -292,6 +292,9 @@ #define TOK_MODULE "BQ" /* BR and BT are in use */ +#define MSG_SENDSNO "SENDSNO" +#define TOK_SENDSNO "Ss" + #define MSG_EOS "EOS" #define TOK_EOS "ES" diff --git a/makefile.win32 b/makefile.win32 index 6dd97801f..9392738d6 100644 --- a/makefile.win32 +++ b/makefile.win32 @@ -146,7 +146,7 @@ MOD_FILES=SRC/L_COMMANDS.OBJ SRC/M_CHGHOST.OBJ SRC/M_SDESC.OBJ SRC/M_SETIDENT.OB SRC/M_UNSQLINE.OBJ SRC/M_UNZLINE.OBJ SRC/M_WHOIS.OBJ \ SRC/M_TKL.OBJ SRC/M_VHOST.OBJ \ SRC/M_CYCLE.OBJ SRC/M_SVSJOIN.OBJ SRC/M_SVSPART.OBJ SRC/M_SVSLUSERS.OBJ \ - SRC/M_SVSWATCH.OBJ SRC/M_SVSSILENCE.OBJ + SRC/M_SVSWATCH.OBJ SRC/M_SVSSILENCE.OBJ SRC/M_SENDSNO.OBJ ALL: CONF UNREAL.EXE WIRCD.EXE @@ -491,6 +491,9 @@ src/m_svswatch.obj: src/modules/m_svswatch.c $(INCLUDES) src/m_svssilence.obj: src/modules/m_svssilence.c $(INCLUDES) $(CC) $(CFLAGS) src/modules/m_svssilence.c +src/m_sendsno.obj: src/modules/m_sendsno.c $(INCLUDES) + $(CC) $(CFLAGS) src/modules/m_sendsno.c + src/win32/win32.res: src/win32/win32gui.rc $(RC) /l 0x409 /fosrc/win32/win32.res /i ./include /i ./src \ /d NDEBUG src/win32/win32gui.rc diff --git a/src/channel.c b/src/channel.c index 09e543932..317a12901 100644 --- a/src/channel.c +++ b/src/channel.c @@ -4006,7 +4006,7 @@ CMD_FUNC(m_part) } if (commentx) { - n = dospamfilter(sptr, commentx, SPAMF_PART); + n = dospamfilter(sptr, commentx, SPAMF_PART, name); if (n == FLUSH_BUFFER) return n; if (n < 0) diff --git a/src/modules.c b/src/modules.c index 2a99219c2..64c2904ae 100644 --- a/src/modules.c +++ b/src/modules.c @@ -144,6 +144,7 @@ char *Module_Create(char *path_) int (*Mod_Init)(); int (*Mod_Load)(); int (*Mod_Unload)(); + char *Mod_Version; static char errorbuf[1024]; char *path, *tmppath; ModuleHeader *mod_header; @@ -169,6 +170,16 @@ char *Module_Create(char *path_) if ((Mod = irc_dlopen(tmppath, RTLD_NOW))) { /* We have engaged the borg cube. Scan for lifesigns. */ + irc_dlsym(Mod, "Mod_Version", Mod_Version); + if (Mod_Version && strcmp(version, Mod_Version)) + { + snprintf(errorbuf, sizeof(errorbuf), + "Module was compiled for '%s', we are '%s', please recompile the module", + Mod_Version, version); + irc_dlclose(Mod); + remove(tmppath); + return errorbuf; + } irc_dlsym(Mod, "Mod_Header", mod_header); if (!mod_header) { diff --git a/src/modules/Makefile.in b/src/modules/Makefile.in index fa7bbfffe..d88251397 100644 --- a/src/modules/Makefile.in +++ b/src/modules/Makefile.in @@ -33,7 +33,7 @@ R_MODULES=m_sethost.so m_chghost.so m_chgident.so m_setname.so \ m_quit.so m_rakill.so m_rping.so m_sendumode.so m_sqline.so \ m_tsctl.so m_unkline.so m_unsqline.so m_unzline.so m_whois.so \ m_tkl.so m_vhost.so m_cycle.so m_svsjoin.so m_svspart.so \ - m_svswatch.so m_svssilence.so + m_svswatch.so m_svssilence.so m_sendsno.c COMMANDS=m_sethost.c m_chghost.c m_chgident.c m_setname.c m_setident.c \ m_sdesc.c m_svsmode.c m_swhois.c m_svsmotd.c m_svsnline.c \ @@ -43,7 +43,7 @@ COMMANDS=m_sethost.c m_chghost.c m_chgident.c m_setname.c m_setident.c \ m_quit.c m_rakill.c m_rping.c m_sendumode.c m_sqline.c \ m_tsctl.c m_unkline.c m_unsqline.c m_unzline.c m_whois.c \ m_tkl.c m_vhost.c m_cycle.c m_svsjoin.c m_svspart.c \ - m_svslusers.c m_svswatch.c m_svssilence.c + m_svslusers.c m_svswatch.c m_svssilence.c m_sendsno.c MODULES=commands.so $(R_MODULES) diff --git a/src/modules/l_commands.c b/src/modules/l_commands.c index 1ffc00c5b..57909599d 100644 --- a/src/modules/l_commands.c +++ b/src/modules/l_commands.c @@ -38,15 +38,18 @@ #ifdef STRIPBADWORDS #include "badwords.h" #endif -#ifdef _WIN32 #include "version.h" -#endif #ifndef STATIC_LINKING #define DYNAMIC_LINKING #else #undef DYNAMIC_LINKING #endif +/* l_commands.c/commands.so is a special case so we have to do this manually :p */ +#ifdef DYNAMIC_LINKING +char Mod_Version[] = BASE_VERSION PATCH1 PATCH2 PATCH3 PATCH4 PATCH5 PATCH6 PATCH7 PATCH8 PATCH9; +#endif + extern ModuleHeader m_svsnoop_Header; ModuleInfo *ModCmdsInfo; /* Place includes here */ @@ -87,6 +90,7 @@ extern int m_sqline_Init(ModuleInfo *modinfo), m_unsqline_Init(ModuleInfo *modin extern int m_vhost_Init(ModuleInfo *modinfo), m_cycle_Init(ModuleInfo *modinfo), m_svsjoin_Init(ModuleInfo *modinfo); extern int m_svspart_Init(ModuleInfo *modinfo), m_svslusers_Init(ModuleInfo *modinfo); extern int m_svswatch_Init(ModuleInfo *modinfo), m_svssilence_Init(ModuleInfo *modinfo); +extern int m_sendsno_Init(ModuleInfo *modinfo); #ifdef GUEST extern int m_guest_Init(ModuleInfo *modinfo); #endif @@ -107,6 +111,7 @@ extern int m_sqline_Load(int module_load), m_unsqline_Load(int module_load), m_t extern int m_vhost_Load(int module_load), m_cycle_Load(int module_load), m_svsjoin_Load(int module_load); extern int m_svspart_Load(int module_load), m_svslusers_Load(int module_load); extern int m_svswatch_Load(int module_load), m_svssilence_Load(int module_load); +extern int m_sendsno_Load(int module_load); #ifdef GUEST extern int m_guest_Load(int module_load); #endif @@ -123,6 +128,7 @@ extern int m_unzline_Unload(), m_unkline_Unload(); extern int m_sqline_Unload(), m_unsqline_Unload(), m_tkl_Unload(), m_vhost_Unload(); extern int m_cycle_Unload(), m_svsjoin_Unload(), m_svspart_Unload(), m_svslusers_Unload(); extern int m_svswatch_Unload(), m_svssilence_Unload(); +extern int m_sendsno_Unload(); #ifdef GUEST extern int m_guest_Unload(); #endif @@ -200,6 +206,7 @@ int l_commands_Init(ModuleInfo *modinfo) m_svswatch_Init(ModCmdsInfo); m_svssilence_Init(ModCmdsInfo); m_svslusers_Init(ModCmdsInfo); + m_sendsno_Init(ModCmdsInfo); #ifdef GUEST m_guest_Init(ModCmdsInfo); #endif @@ -256,6 +263,7 @@ int l_commands_Load(int module_load) m_svswatch_Load(module_load); m_svssilence_Load(module_load); m_svslusers_Load(module_load); + m_sendsno_Load(module_load); #ifdef GUEST m_guest_Load(module_load); #endif @@ -312,6 +320,7 @@ int l_commands_Unload(int module_unload) m_svswatch_Unload(); m_svssilence_Unload(); m_svslusers_Unload(); + m_sendsno_Unload(); #ifdef GUEST m_guest_Unload(); #endif diff --git a/src/modules/m_message.c b/src/modules/m_message.c index aded34081..063188218 100644 --- a/src/modules/m_message.c +++ b/src/modules/m_message.c @@ -122,6 +122,7 @@ DLLFUNC int m_message(aClient *cptr, aClient *sptr, int parc, char *parv[], int int cansend = 0; int prefix = 0; char pfixchan[CHANNELLEN + 32]; + int n; /* * Reasons why someone can't send to a channel @@ -221,7 +222,7 @@ DLLFUNC int m_message(aClient *cptr, aClient *sptr, int parc, char *parv[], int { ConfigItem_deny_dcc *fl; char *end, file[BUFSIZE]; - int size_string = 0, n; + int size_string = 0; if (sptr->flags & FLAGS_DCCBLOCK) { @@ -247,11 +248,8 @@ DLLFUNC int m_message(aClient *cptr, aClient *sptr, int parc, char *parv[], int strncpy(file, ctcp, size_string); file[size_string] = '\0'; - n = dospamfilter(sptr, file, SPAMF_DCC); - if (n == FLUSH_BUFFER) + if ((n = dospamfilter(sptr, file, SPAMF_DCC, acptr->name)) < 0) return n; - if (n < 0) - continue; if ((fl = (ConfigItem_deny_dcc *) @@ -319,11 +317,9 @@ DLLFUNC int m_message(aClient *cptr, aClient *sptr, int parc, char *parv[], int if (MyClient(sptr)) { - int n = dospamfilter(sptr, text, newcmd == MSG_NOTICE ? SPAMF_USERNOTICE : SPAMF_USERMSG); - if (n == FLUSH_BUFFER) - return FLUSH_BUFFER; + n = dospamfilter(sptr, text, newcmd == MSG_NOTICE ? SPAMF_USERNOTICE : SPAMF_USERMSG, acptr->name); if (n < 0) - continue; + return FLUSH_BUFFER; } for (tmphook = Hooks[HOOKTYPE_USERMSG]; tmphook; tmphook = tmphook->next) { @@ -442,11 +438,9 @@ DLLFUNC int m_message(aClient *cptr, aClient *sptr, int parc, char *parv[], int if (MyClient(sptr)) { - int n = dospamfilter(sptr, text, notice ? SPAMF_CHANNOTICE : SPAMF_CHANMSG); - if (n == FLUSH_BUFFER) - return FLUSH_BUFFER; + n = dospamfilter(sptr, text, notice ? SPAMF_CHANNOTICE : SPAMF_CHANMSG, chptr->chname); if (n < 0) - continue; + return n; } for (tmphook = Hooks[HOOKTYPE_CHANMSG]; tmphook; tmphook = tmphook->next) { diff --git a/src/modules/m_quit.c b/src/modules/m_quit.c index 7140fb3aa..dbf98005a 100644 --- a/src/modules/m_quit.c +++ b/src/modules/m_quit.c @@ -116,7 +116,7 @@ DLLFUNC int m_quit(aClient *cptr, aClient *sptr, int parc, char *parv[]) if (blocked) ocomment = parv[0]; #endif - n = dospamfilter(sptr, ocomment, SPAMF_QUIT); + n = dospamfilter(sptr, ocomment, SPAMF_QUIT, NULL); if (n == FLUSH_BUFFER) return n; if (n < 0) diff --git a/src/s_kline.c b/src/s_kline.c index 26a52302f..adc89d1e3 100644 --- a/src/s_kline.c +++ b/src/s_kline.c @@ -1090,7 +1090,7 @@ int place_host_ban(aClient *sptr, int action, char *reason, long duration) * (like from m_message, m_part, m_quit, etc). */ -int dospamfilter(aClient *sptr, char *str_in, int type) +int dospamfilter(aClient *sptr, char *str_in, int type, char *target) { aTKline *tk; int n; @@ -1106,6 +1106,21 @@ char *str = (char *)StripControlCodes(str_in); if (!regexec(&tk->spamf->expr, str, 0, NULL, 0)) { /* matched! */ + char buf[1024]; + char targetbuf[48]; + if (target) { + targetbuf[0] = ' '; + strlcpy(targetbuf+1, target, sizeof(targetbuf)-1); /* cut it off */ + } else + targetbuf[0] = '\0'; + ircsprintf(buf, "[Spamfilter] %s!%s@%s matches filter '%s': [%s%s: '%s']", + sptr->name, sptr->user->username, sptr->user->realhost, + tk->reason, + spamfilter_inttostring_long(type), targetbuf, str); + + sendto_snomask(SNO_SPAMF, "%s", buf); + sendto_serv_butone_token(NULL, me.name, MSG_SENDSNO, TOK_SENDSNO, "S :%s", buf); + if (tk->spamf->action != BAN_ACT_BLOCK) return place_host_ban(sptr, tk->spamf->action, SPAMFILTER_BAN_REASON, SPAMFILTER_BAN_TIME); else diff --git a/src/s_misc.c b/src/s_misc.c index c7c5b60b2..b6472f4a0 100644 --- a/src/s_misc.c +++ b/src/s_misc.c @@ -973,3 +973,25 @@ char *p = buf; *p = '\0'; return buf; } + +/* only used by dospamfilter() */ +char *spamfilter_inttostring_long(int v) +{ + switch(v) + { + case SPAMF_CHANMSG: + case SPAMF_USERMSG: + return "PRIVMSG"; + case SPAMF_USERNOTICE: + case SPAMF_CHANNOTICE: + return "NOTICE"; + case SPAMF_PART: + return "PART"; + case SPAMF_QUIT: + return "QUIT"; + case SPAMF_DCC: + return "DCC"; + default: + return "UNKNOWN"; + } +} diff --git a/src/umodes.c b/src/umodes.c index c7e68e8d7..a39f30941 100644 --- a/src/umodes.c +++ b/src/umodes.c @@ -89,6 +89,7 @@ long SNO_TKL = 0L; long SNO_NICKCHANGE = 0L; long SNO_FNICKCHANGE = 0L; long SNO_QLINE = 0L; +long SNO_SPAMF = 0L; long SNO_SNOTICE = 0L; long AllUmodes; /* All umodes */ @@ -156,6 +157,7 @@ void umode_init(void) SnomaskAdd(NULL, 'n', umode_allow_opers, &SNO_NICKCHANGE); SnomaskAdd(NULL, 'N', umode_allow_opers, &SNO_FNICKCHANGE); SnomaskAdd(NULL, 'q', umode_allow_opers, &SNO_QLINE); + SnomaskAdd(NULL, 'S', umode_allow_opers, &SNO_SPAMF); SnomaskAdd(NULL, 's', umode_allow_all, &SNO_SNOTICE); }