From 3e82313bfb3eaf4f2b59dfc165372e3174be838b Mon Sep 17 00:00:00 2001 From: pk910 Date: Sun, 19 Feb 2012 02:35:31 +0100 Subject: [PATCH] added NeonSpam Badword scanner --- Makefile.am | 3 + database.defaults.sql | 4 +- database.sql | 25 +++ database.upgrade.sql | 26 ++++ src/modules/NeonSpam.mod/bot_NeonSpam.c | 44 +++++- src/modules/NeonSpam.mod/bot_NeonSpam.h | 37 ++++- src/modules/NeonSpam.mod/cmd_neonspam.c | 4 + src/modules/NeonSpam.mod/cmd_neonspam.h | 3 + .../NeonSpam.mod/cmd_neonspam_addbad.c | 57 +++++++ .../NeonSpam.mod/cmd_neonspam_badwords.c | 106 +++++++++++++ .../NeonSpam.mod/cmd_neonspam_delbad.c | 49 ++++++ src/modules/NeonSpam.mod/cmd_neonspam_set.c | 14 +- .../NeonSpam.mod/event_neonspam_chanmsg.c | 145 +++++++++++++++++- src/mysqlConn.c | 2 +- 14 files changed, 498 insertions(+), 21 deletions(-) create mode 100644 src/modules/NeonSpam.mod/cmd_neonspam_addbad.c create mode 100644 src/modules/NeonSpam.mod/cmd_neonspam_badwords.c create mode 100644 src/modules/NeonSpam.mod/cmd_neonspam_delbad.c diff --git a/Makefile.am b/Makefile.am index c312545..d3f96fe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -138,6 +138,9 @@ libNeonServ_la_LIBADD = $(MYSQL_LIBS) libNeonSpam_la_SOURCES = src/modules/NeonSpam.mod/bot_NeonSpam.c \ src/modules/NeonSpam.mod/cmd_neonspam.c \ src/modules/NeonSpam.mod/cmd_neonspam_set.c \ + src/modules/NeonSpam.mod/cmd_neonspam_addbad.c \ + src/modules/NeonSpam.mod/cmd_neonspam_delbad.c \ + src/modules/NeonSpam.mod/cmd_neonspam_badwords.c \ src/modules/NeonSpam.mod/module.c libNeonSpam_la_LDFLAGS = -module -rpath /nowhere -avoid-version -no-undefined libNeonSpam_la_LIBADD = $(MYSQL_LIBS) diff --git a/database.defaults.sql b/database.defaults.sql index 2f78e4d..5aa092e 100644 --- a/database.defaults.sql +++ b/database.defaults.sql @@ -234,8 +234,8 @@ INSERT INTO `bot_binds` (`id`, `botclass`, `botid`, `command`, `function`, `para -- Daten für Tabelle `channels` -- -INSERT INTO `channels` (`channel_id`, `channel_name`, `channel_key`, `channel_maxusers`, `channel_lastvisit`, `channel_lastgiveowner`, `channel_pubcmd`, `channel_nodelete`, `channel_nogaccess`, `channel_canadd`, `channel_candel`, `channel_canclvl`, `channel_cankick`, `channel_canban`, `channel_staticban`, `channel_protect`, `channel_canop`, `channel_canhalfop`, `channel_canvoice`, `channel_getop`, `channel_gethalfop`, `channel_getvoice`, `channel_greeting`, `channel_usergreeting`, `channel_userinfo`, `channel_dynlimit`, `channel_getinvite`, `channel_topicmask`, `channel_exttopic`, `channel_exttopic_topic`, `channel_defaulttopic`, `channel_wipeinfo`, `channel_modes`, `channel_enfmodes`, `channel_enftopic`, `channel_topicsnarf`, `channel_changetopic`, `channel_setters`, `channel_canresync`, `channel_cansuspend`, `channel_notice`, `channel_noticereaction`, `channel_ctcp`, `channel_ctcpreaction`, `channel_registered`, `channel_registrator`, `channel_toys`, `channel_scanner`, `channel_spam_limit`, `channel_spam_reaction`, `channel_spam_reaction_duration`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_reaction`, `channel_join_reaction_duration`, `channel_join_except`, `channel_botnet_bantime`, `channel_botnet_except`, `channel_caps_percent`, `channel_caps_reaction`, `channel_caps_reaction_duration`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_reaction`, `channel_digit_reaction_duration`, `channel_digit_except`) VALUES -(NULL, 'defaults', '', 0, 0, 0, 0, 0, 0, 300, 300, 300, 200, 200, 250, 0, 200, 200, 200, 200, 150, 100, '', '', 1, 0, 1, '', 0, '', '', 300, '+', 400, 400, 501, 200, 400, 200, 300, 0, 0, 0, 0, 0, 0, 0, '', 4, 0, 120, 400, 5, 3, 0, 120, 400, 4, 20, 2, 300, 400, 1800, 1, 60, 0, 60, 200, 60, 0, 60, 200), +INSERT INTO `channels` (`channel_id`, `channel_name`, `channel_key`, `channel_maxusers`, `channel_lastvisit`, `channel_lastgiveowner`, `channel_pubcmd`, `channel_nodelete`, `channel_nogaccess`, `channel_canadd`, `channel_candel`, `channel_canclvl`, `channel_cankick`, `channel_canban`, `channel_staticban`, `channel_protect`, `channel_canop`, `channel_canhalfop`, `channel_canvoice`, `channel_getop`, `channel_gethalfop`, `channel_getvoice`, `channel_greeting`, `channel_usergreeting`, `channel_userinfo`, `channel_dynlimit`, `channel_getinvite`, `channel_topicmask`, `channel_exttopic`, `channel_exttopic_topic`, `channel_defaulttopic`, `channel_wipeinfo`, `channel_modes`, `channel_enfmodes`, `channel_enftopic`, `channel_topicsnarf`, `channel_changetopic`, `channel_setters`, `channel_canresync`, `channel_cansuspend`, `channel_notice`, `channel_noticereaction`, `channel_ctcp`, `channel_ctcpreaction`, `channel_registered`, `channel_registrator`, `channel_toys`, `channel_scanner`, `channel_spam_limit`, `channel_spam_reaction`, `channel_spam_reaction_duration`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_reaction`, `channel_join_reaction_duration`, `channel_join_except`, `channel_botnet_bantime`, `channel_botnet_except`, `channel_caps_percent`, `channel_caps_reaction`, `channel_caps_reaction_duration`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_reaction`, `channel_digit_reaction_duration`, `channel_digit_except`, `channel_badword_reaction`, `channel_badword_reaction_duration`, `channel_badword_except`) VALUES +(NULL, 'defaults', '', 0, 0, 0, 0, 0, 0, 300, 300, 300, 200, 200, 250, 0, 200, 200, 200, 200, 150, 100, '', '', 1, 0, 1, '', 0, '', '', 300, '+', 400, 400, 501, 200, 400, 200, 300, 0, 0, 0, 0, 0, 0, 0, '', 4, 0, 120, 400, 5, 3, 0, 120, 400, 4, 20, 2, 300, 400, 1800, 1, 60, 0, 60, 200, 60, 0, 60, 200, 0, 60, 400), -- -- please run language.php for help and language entries. diff --git a/database.sql b/database.sql index d3d9156..45cb784 100644 --- a/database.sql +++ b/database.sql @@ -157,6 +157,9 @@ CREATE TABLE IF NOT EXISTS `channels` ( `channel_digit_reaction` tinyint(1) DEFAULT NULL, `channel_digit_reaction_duration` mediumint(7) DEFAULT NULL, `channel_digit_except` smallint(3) DEFAULT NULL, + `channel_badword_reaction` tinyint(1) DEFAULT NULL, + `channel_badword_reaction_duration` mediumint(7) DEFAULT NULL, + `channel_badword_except` smallint(3) DEFAULT NULL, PRIMARY KEY (`channel_id`), UNIQUE KEY `channel_name` (`channel_name`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; @@ -412,3 +415,25 @@ CREATE TABLE IF NOT EXISTS `settings` ( `value` text NOT NULL, PRIMARY KEY (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `spamserv_badwords` +-- + +CREATE TABLE IF NOT EXISTS `spamserv_badwords` ( + `badword_id` int(11) NOT NULL AUTO_INCREMENT, + `badword_cid` int(11) NOT NULL, + `badword_match` varchar(128) NOT NULL, + `badword_uid` int(11) NOT NULL, + `badword_use_default` tinyint(1) NOT NULL, + `badword_exceptlevel` smallint(3) NOT NULL, + `badword_scan_ops` tinyint(1) NOT NULL, + `badword_scan_voice` tinyint(1) NOT NULL, + `badword_use_default_reaction` tinyint(1) NOT NULL, + `badword_reaction` tinyint(1) NOT NULL, + `badword_reaction_time` int(20) NOT NULL, + PRIMARY KEY (`badword_id`), + KEY `badword_cid` (`badword_cid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; diff --git a/database.upgrade.sql b/database.upgrade.sql index 7d08cd8..c8f34f3 100644 --- a/database.upgrade.sql +++ b/database.upgrade.sql @@ -147,3 +147,29 @@ CREATE TABLE IF NOT EXISTS `settings` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -- version: 16 + +CREATE TABLE IF NOT EXISTS `spamserv_badwords` ( + `badword_id` int(11) NOT NULL AUTO_INCREMENT, + `badword_cid` int(11) NOT NULL, + `badword_match` varchar(128) NOT NULL, + `badword_uid` int(11) NOT NULL, + `badword_use_default` tinyint(1) NOT NULL, + `badword_exceptlevel` smallint(3) NOT NULL, + `badword_scan_ops` tinyint(1) NOT NULL, + `badword_scan_voice` tinyint(1) NOT NULL, + `badword_use_default_reaction` tinyint(1) NOT NULL, + `badword_reaction` tinyint(1) NOT NULL, + `badword_reaction_time` int(20) NOT NULL, + PRIMARY KEY (`badword_id`), + KEY `badword_cid` (`badword_cid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +ALTER TABLE `channels` ADD `channel_badword_reaction` TINYINT( 1 ) NULL , +ADD `channel_badword_reaction_duration` MEDIUMINT( 7 ) NULL AFTER `channel_badword_reaction` , +ADD `channel_badword_except` SMALLINT( 3 ) NULL AFTER `channel_badword_reaction_duration`; + +UPDATE `channels` SET `channel_badword_reaction` = '0', +`channel_badword_reaction_duration` = '60', +`channel_badword_except` = '400' WHERE `channel_name` = 'defaults'; + +--version: 17 diff --git a/src/modules/NeonSpam.mod/bot_NeonSpam.c b/src/modules/NeonSpam.mod/bot_NeonSpam.c index 5ccfbc2..10b4083 100644 --- a/src/modules/NeonSpam.mod/bot_NeonSpam.c +++ b/src/modules/NeonSpam.mod/bot_NeonSpam.c @@ -63,6 +63,19 @@ static const struct default_language_entry msgtab[] = { {"SS_SET_OPTION_DigitReaction_0", "Kick"}, {"SS_SET_OPTION_DigitReaction_1", "KickBan"}, {"SS_SET_OPTION_DigitReaction_2", "Timed Ban"}, + {"SS_SET_OPTION_BadwordReaction_0", "Kick"}, + {"SS_SET_OPTION_BadwordReaction_1", "KickBan"}, + {"SS_SET_OPTION_BadwordReaction_2", "Timed Ban"}, + {"SS_BADWORD_ADDED", "Badword '%s' added. (ID: %d)"}, /* {ARGS: "NeonServ is bad", 1} */ + {"SS_BADWORD_ID_UNKNOWN", "Badword ID %d was not found in %s."}, /* {ARGS: 1, "#channel"} */ + {"SS_BADWORD_DELETED", "Badword '%s' deleted. (ID: %d)"}, /* {ARGS: "NeonServ is bad", 1} */ + {"SS_BADWORDS_REACTION_0", "Kick"}, + {"SS_BADWORDS_REACTION_1", "KickBan"}, + {"SS_BADWORDS_REACTION_2", "Timed Ban"}, + {"SS_BADWORDS_ID", "Id"}, + {"SS_BADWORDS_PATTERN", "Pattern"}, + {"SS_BADWORDS_SCAN", "Scan"}, + {"SS_BADWORDS_REACTION", "Reaction"}, {NULL, NULL} }; @@ -84,6 +97,7 @@ static struct NeonSpamJoinNode *getNeonSpamJoinNode(struct ChanUser *chanuser); #define SPAMSERV_MSG_BOTNET "BotNet detected." #define SPAMSERV_MSG_CAPS "Using too many chars in UPPER CASE" #define SPAMSERV_MSG_DIGIT "Using too many numeric chars" +#define SPAMSERV_MSG_BADWORD "Your message contained a forbidden word." //EVENTS #include "event_neonspam_join.c" @@ -235,13 +249,11 @@ int loadNeonSpamSettings(struct ChanNode *chan) { MYSQL_RES *res; MYSQL_ROW row, defaults = NULL; loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) - return 0; - printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except`, `channel_badword_except` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); res = mysql_use(); row = mysql_fetch_row(res); if(!row[0] || !row[1] || !row[2] || !row[3] || !row[4] || !row[5] || !row[6] || !row[7] || !row[8] || !row[9] || !row[10] || !row[11] || !row[12]) { - printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except` FROM `channels` WHERE `channel_name` = 'defaults'"); + printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except`, `channel_badword_except` FROM `channels` WHERE `channel_name` = 'defaults'"); res = mysql_use(); defaults = mysql_fetch_row(res); } @@ -258,11 +270,29 @@ int loadNeonSpamSettings(struct ChanNode *chan) { settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] = atoi(row[10] ? row[10] : defaults[10]); settings->percent[SPAMSETTINGS_DIGITPERCENTINDEX] = atoi(row[11] ? row[11] : defaults[11]); settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] = atoi(row[12] ? row[12] : defaults[12]); + settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX] = atoi(row[13] ? row[13] : defaults[13]); settings->join_nodes = NULL; settings->lastmsg_time = 0; int i; for(i = 0; i < BOTNETSCAN_USERS; i++) settings->botnicks[i] = NULL; + settings->badwords = NULL; + printf_mysql_query("SELECT `badword_match`, `badword_reaction`, `badword_reaction_time`, `badword_id`, `badword_scan_ops`, `badword_scan_voice`, `badword_exceptlevel`, `badword_use_default`, `badword_use_default_reaction` FROM `spamserv_badwords` WHERE `badword_cid` = '%d'", chan->channel_id); + res = mysql_use(); + while((row = mysql_fetch_row(res))) { + struct NeonSpamBadword *badword = malloc(sizeof(*badword)); + badword->id = atoi(row[3]); + badword->badword = strdup(row[0]); + badword->use_defaults = atoi(row[7]); + badword->exceptlevel = atoi(row[6]); + badword->scan_ops = atoi(row[4]); + badword->scan_voice = atoi(row[5]); + badword->use_default_reaction = atoi(row[8]); + badword->reaction = atoi(row[1]); + badword->reaction_time = atoi(row[2]); + badword->next = settings->badwords; + settings->badwords = badword; + } chan->spam_settings = settings; return 1; } @@ -273,6 +303,12 @@ void freeNeonSpamSettings(struct NeonSpamSettings *settings) { nextjoinnode = joinnode->next; freeJoinNode(joinnode); } + struct NeonSpamBadword *badword, *nextbadword; + for(badword = settings->badwords; badword; badword = nextbadword) { + nextbadword = badword->next; + free(badword->badword); + free(badword); + } free(settings); } diff --git a/src/modules/NeonSpam.mod/bot_NeonSpam.h b/src/modules/NeonSpam.mod/bot_NeonSpam.h index aaeca2b..1d4c68f 100644 --- a/src/modules/NeonSpam.mod/bot_NeonSpam.h +++ b/src/modules/NeonSpam.mod/bot_NeonSpam.h @@ -69,17 +69,23 @@ struct ChanNode; #define SPAMSETTINGS_DIGITEXCINDEX 5 #define SPAMSETTINGS_DIGITPERCENTINDEX 1 - -#define SPAMSETTINGS_CHARS SPAMSETTINGS_SPAMCHARS SPAMSETTINGS_FLOODCHARS SPAMSETTINGS_JOINCHARS SPAMSETTINGS_BOTNETCHARS SPAMSETTINGS_CAPSCHARS SPAMSETTINGS_DIGITCHARS -#define SPAMSETTINGS_FLAGS 0x07ffff /* all flags that can be stored in the database */ -#define SPAMSETTINGS_EXCEPTINDEXES 6 +//BADWORDSCAN +#define SPAMSETTINGS_BADWORDSCAN 0x080000 +#define SPAMSETTINGS_BADWORDSCAN_OPS 0x100000 +#define SPAMSETTINGS_BADWORDSCAN_VOICE 0x200000 +#define SPAMSETTINGS_BADWORDCHARS "tuv" +#define SPAMSETTINGS_BADWORDEXCINDEX 6 + +#define SPAMSETTINGS_CHARS SPAMSETTINGS_SPAMCHARS SPAMSETTINGS_FLOODCHARS SPAMSETTINGS_JOINCHARS SPAMSETTINGS_BOTNETCHARS SPAMSETTINGS_CAPSCHARS SPAMSETTINGS_DIGITCHARS SPAMSETTINGS_BADWORDCHARS +#define SPAMSETTINGS_FLAGS 0x7fffff /* all flags that can be stored in the database */ +#define SPAMSETTINGS_EXCEPTINDEXES 7 #define SPAMSETTINGS_SENSIBILITYINDEXES 2 #define SPAMSETTINGS_PERCENTINDEXES 2 //SCRIPT FLAGS -#define SPAMSETTINGS_KICKEDBOTQUEUE 0x080000 -#define SPAMSETTINGS_ISTIMEBAN 0x100000 -#define SPAMSETTINGS_SETTIMEBAN 0x200000 +#define SPAMSETTINGS_KICKEDBOTQUEUE 0x0400000 +#define SPAMSETTINGS_ISTIMEBAN 0x0800000 +#define SPAMSETTINGS_SETTIMEBAN 0x1000000 #define MAX_FLOOD_AMOUNT 300 #define MIN_FLOOD_AMOUNT 2 @@ -108,8 +114,23 @@ struct NeonSpamSettings { time_t lastmsg_time; char *botnicks[BOTNETSCAN_USERS]; - + //badword scan + struct NeonSpamBadword *badwords; }; + +struct NeonSpamBadword { + int id; + char *badword; + unsigned char use_defaults : 1; + unsigned int exceptlevel : 9; + unsigned char scan_ops : 1; + unsigned char scan_voice : 1; + unsigned char use_default_reaction : 1; + unsigned int reaction; + unsigned int reaction_time; + struct NeonSpamBadword *next; +}; + /* PENALTY SYSTEM * user gets MAX_FLOOD_TIME points per message * points get removed each loop diff --git a/src/modules/NeonSpam.mod/cmd_neonspam.c b/src/modules/NeonSpam.mod/cmd_neonspam.c index f5a520f..d0241c4 100644 --- a/src/modules/NeonSpam.mod/cmd_neonspam.c +++ b/src/modules/NeonSpam.mod/cmd_neonspam.c @@ -27,6 +27,10 @@ void register_commands() { #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(2, NAME, module_id, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) // NAME FUNCTION PARAMS PRIVS FLAGS USER_COMMAND("set", neonspam_cmd_set, 0, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("addbad", neonspam_cmd_addbad, 1, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("delbad", neonspam_cmd_delbad, 1, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("badwords", neonspam_cmd_badwords, 0, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + #undef USER_COMMAND } \ No newline at end of file diff --git a/src/modules/NeonSpam.mod/cmd_neonspam.h b/src/modules/NeonSpam.mod/cmd_neonspam.h index d238110..9b8006e 100644 --- a/src/modules/NeonSpam.mod/cmd_neonspam.h +++ b/src/modules/NeonSpam.mod/cmd_neonspam.h @@ -41,6 +41,9 @@ void register_commands(); +CMD_BIND(neonspam_cmd_addbad); +CMD_BIND(neonspam_cmd_badwords); +CMD_BIND(neonspam_cmd_delbad); CMD_BIND(neonspam_cmd_set); #endif \ No newline at end of file diff --git a/src/modules/NeonSpam.mod/cmd_neonspam_addbad.c b/src/modules/NeonSpam.mod/cmd_neonspam_addbad.c new file mode 100644 index 0000000..d6ca60c --- /dev/null +++ b/src/modules/NeonSpam.mod/cmd_neonspam_addbad.c @@ -0,0 +1,57 @@ +/* cmd_neonspam_addbad.c - NeonServ v5.4 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 . + */ + +#include "cmd_neonspam.h" + +CMD_BIND(neonspam_cmd_addbad) { + char *cbadword = merge_argv(argv, 0, argc); + MYSQL_RES *res; + MYSQL_ROW row, defaults; + loadChannelSettings(chan); + loadNeonSpamSettings(chan); + struct NeonSpamSettings *settings = chan->spam_settings; + if(!settings) return; + printf_mysql_query("SELECT `channel_badword_reaction`, `channel_badword_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_badword_reaction`, `channel_badword_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + int reaction = atoi((row[0] ? row[0] : defaults[0])) + 1; + int reaction_time = atoi((row[1] ? row[1] : defaults[1])); + if(strlen(cbadword) > 128) + cbadword[128] = 0; + int scan_ops = ((settings->flags & SPAMSETTINGS_BADWORDSCAN_OPS) ? 1 : 0); + int scan_voice = ((settings->flags & SPAMSETTINGS_BADWORDSCAN_VOICE) ? 1 : 0); + printf_mysql_query("INSERT INTO `spamserv_badwords` (`badword_cid`, `badword_match`, `badword_use_default`, `badword_exceptlevel`, `badword_scan_ops`, `badword_scan_voice`, `badword_use_default_reaction`, `badword_reaction`, `badword_reaction_time`) VALUES ('%d', '%s', '1', '%d', '%d', '%d', '1', '%d', '%d')", chan->channel_id, escape_string(cbadword), settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX], scan_ops, scan_voice, reaction, reaction_time); + int badword_id = (int) mysql_insert_id(get_mysql_conn()); + struct NeonSpamBadword *badword = malloc(sizeof(*badword)); + badword->id = badword_id; + badword->badword = strdup(cbadword); + badword->use_defaults = 1; + badword->exceptlevel = settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX]; + badword->scan_ops = scan_ops; + badword->scan_voice = scan_voice; + badword->use_default_reaction = 1; + badword->reaction = reaction; + badword->reaction_time = reaction_time; + badword->next = settings->badwords; + settings->badwords = badword; + reply(getTextBot(), user, "SS_BADWORD_ADDED", cbadword, badword_id); +} diff --git a/src/modules/NeonSpam.mod/cmd_neonspam_badwords.c b/src/modules/NeonSpam.mod/cmd_neonspam_badwords.c new file mode 100644 index 0000000..9767e35 --- /dev/null +++ b/src/modules/NeonSpam.mod/cmd_neonspam_badwords.c @@ -0,0 +1,106 @@ +/* cmd_neonspam_badwords.c - NeonServ v5.4 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 . + */ + +#include "cmd_neonspam.h" + +CMD_BIND(neonspam_cmd_badwords) { + MYSQL_RES *res; + MYSQL_ROW row, defaults; + loadChannelSettings(chan); + loadNeonSpamSettings(chan); + struct NeonSpamSettings *settings = chan->spam_settings; + if(!settings) return; + if(argc > 0) { + int badword_id = atoi(argv[0]); + printf_mysql_query("SELECT `badword_match` FROM `spamserv_badwords` WHERE `badword_id` = '%d' AND `badword_cid` = '%d'", badword_id, chan->channel_id); + res = mysql_use(); + if(!(row = mysql_fetch_row(res))) { + reply(getTextBot(), user, "SS_BADWORD_ID_UNKNOWN", badword_id, chan->name); + return; + } + //to be continued... + + } else { + struct Table *table; + printf_mysql_query("SELECT `channel_badword_reaction`, `channel_badword_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_badword_reaction`, `channel_badword_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + int default_reaction = atoi((row[0] ? row[0] : defaults[0])); + int default_reaction_time = atoi((row[1] ? row[1] : defaults[1])); + printf_mysql_query("SELECT `badword_id`, `badword_match`, `badword_use_default`, `badword_exceptlevel`, `badword_scan_ops`, `badword_scan_voice`, `badword_use_default_reaction`, `badword_reaction`, `badword_reaction_time` FROM `spamserv_badwords` WHERE `badword_cid` = '%d' ORDER BY `badword_id` ASC", chan->channel_id); + res = mysql_use(); + table = table_init(4, mysql_num_rows(res) + 1, 0); + char *content[4]; + content[0] = get_language_string(user, "SS_BADWORDS_ID"); + content[1] = get_language_string(user, "SS_BADWORDS_PATTERN"); + content[2] = get_language_string(user, "SS_BADWORDS_SCAN"); + content[3] = get_language_string(user, "SS_BADWORDS_REACTION"); + table_add(table, content); + char default_exception[100]; + char exception_buf[100], reaction_buf[100], reaction_time_buf[100]; + int exception_pos = 0, reaction_pos; + int reaction, reaction_time; + if(settings->flags & SPAMSETTINGS_BADWORDSCAN_OPS) + exception_pos += sprintf(default_exception+exception_pos, (exception_pos ? " & @" : "@")); + if(settings->flags & SPAMSETTINGS_BADWORDSCAN_VOICE) + exception_pos += sprintf(default_exception+exception_pos, (exception_pos ? " & +" : "+")); + if(settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX]) + exception_pos += sprintf(default_exception+exception_pos, (exception_pos ? " & <%d" : "<%d"), settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX]); + while ((row = mysql_fetch_row(res)) != NULL) { + content[0] = row[0]; + content[1] = row[1]; + exception_pos = 0; + if(strcmp(row[2], "0")) { + exception_pos += sprintf(exception_buf, "\00314%s\003", default_exception); + } else { + if(!strcmp(row[4], "1")) + exception_pos += sprintf(exception_buf+exception_pos, (exception_pos ? " & @" : "@")); + if(!strcmp(row[5], "1")) + exception_pos += sprintf(exception_buf+exception_pos, (exception_pos ? " & +" : "+")); + if(atoi(row[3])) + exception_pos += sprintf(exception_buf+exception_pos, (exception_pos ? " & <%d" : "<%d"), atoi(row[3])); + } + content[2] = exception_buf; + reaction_pos = 0; + if(strcmp(row[6], "0")) { + reaction = default_reaction; + reaction_time = default_reaction_time; + } else { + reaction = atoi(row[7]); + reaction_time = atoi(row[8]); + } + sprintf(reaction_buf, "SS_BADWORDS_REACTION_%d", reaction); + reaction_pos += sprintf(reaction_buf, "%s", get_language_string(user, reaction_buf)); + if(reaction == 2) { + reaction_pos += sprintf(reaction_buf+reaction_pos, " (%s)", timeToStr(user, reaction_time, 2, reaction_time_buf)); + } + content[3] = reaction_buf; + table_add(table, content); + } + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); + } +} diff --git a/src/modules/NeonSpam.mod/cmd_neonspam_delbad.c b/src/modules/NeonSpam.mod/cmd_neonspam_delbad.c new file mode 100644 index 0000000..0a34d02 --- /dev/null +++ b/src/modules/NeonSpam.mod/cmd_neonspam_delbad.c @@ -0,0 +1,49 @@ +/* cmd_neonspam_delbad.c - NeonServ v5.4 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 . + */ + +#include "cmd_neonspam.h" + +CMD_BIND(neonspam_cmd_delbad) { + MYSQL_RES *res; + MYSQL_ROW row; + loadChannelSettings(chan); + loadNeonSpamSettings(chan); + struct NeonSpamSettings *settings = chan->spam_settings; + if(!settings) return; + int badword_id = atoi(argv[0]); + printf_mysql_query("SELECT `badword_match` FROM `spamserv_badwords` WHERE `badword_id` = '%d' AND `badword_cid` = '%d'", badword_id, chan->channel_id); + res = mysql_use(); + if(!(row = mysql_fetch_row(res))) { + reply(getTextBot(), user, "SS_BADWORD_ID_UNKNOWN", badword_id, chan->name); + return; + } + struct NeonSpamBadword *badword, *prev = NULL; + for(badword = settings->badwords; badword; badword = badword->next) { + if(badword->id == badword_id) { + if(prev) + prev->next = badword->next; + else + settings->badwords = badword->next; + free(badword->badword); + free(badword); + break; + } else + prev = badword; + } + printf_mysql_query("DELETE FROM `spamserv_badwords` WHERE `badword_id` = '%d'", badword_id); + reply(getTextBot(), user, "SS_BADWORD_DELETED", row[0], badword_id); +} diff --git a/src/modules/NeonSpam.mod/cmd_neonspam_set.c b/src/modules/NeonSpam.mod/cmd_neonspam_set.c index 6b8cd3d..30df302 100644 --- a/src/modules/NeonSpam.mod/cmd_neonspam_set.c +++ b/src/modules/NeonSpam.mod/cmd_neonspam_set.c @@ -31,7 +31,7 @@ static char* neonspam_cmd_setscanvoice(struct ClientSocket *client, struct UserN static char* neonspam_cmd_setscanexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); static MYSQL_ROW neonspam_settings_row, neonspam_settings_defaults; -#define SPAMSERV_SETTINGS_QUERY "`channel_spam_reaction`, `channel_spam_reaction_duration`, `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_join_reaction`, `channel_join_reaction_duration`, `channel_botnet_bantime`, `channel_caps_reaction`, `channel_caps_reaction_duration`, `channel_digit_reaction`, `channel_digit_reaction_duration`" +#define SPAMSERV_SETTINGS_QUERY "`channel_spam_reaction`, `channel_spam_reaction_duration`, `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_join_reaction`, `channel_join_reaction_duration`, `channel_botnet_bantime`, `channel_caps_reaction`, `channel_caps_reaction_duration`, `channel_digit_reaction`, `channel_digit_reaction_duration`, `channel_badword_reaction`, `channel_badword_reaction_duration`" #define SPAMSERV_SETTINGS_RESET "\ `channel_scanner` = NULL, \ `channel_spam_limit` = NULL, \ @@ -57,7 +57,10 @@ static MYSQL_ROW neonspam_settings_row, neonspam_settings_defaults; `channel_digit_percent` = NULL, \ `channel_digit_reaction` = NULL, \ `channel_digit_reaction_duration` = NULL, \ -`channel_digit_except` = NULL " +`channel_digit_except` = NULL, \ +`channel_badword_reaction` = NULL, \ +`channel_badword_reaction_duration` = NULL, \ +`channel_badword_except` = NULL " #define SET_HELP 0x0001 #define SET_BOOL 0x0002 @@ -127,6 +130,13 @@ static const struct { {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_DIGITEXCINDEX, "channel_digit_except", SET_HELP | SET_SCANEXCEPT}, + {0, 0, "BadwordScan", neonspam_cmd_setflags, SPAMSETTINGS_BADWORDSCAN, NULL, SET_BOOL}, + {SPAMSETTINGS_BADWORDSCAN | SPAMSETTINGS_SETTIMEBAN,2, "BadwordReaction", neonspam_cmd_set_reaction, 11, "channel_badword_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, + {SPAMSETTINGS_BADWORDSCAN | SPAMSETTINGS_ISTIMEBAN,4, "BadwordBanDuration",neonspam_cmd_set_reaction_time, 12, "channel_badword_reaction_duration", 0}, + {SPAMSETTINGS_BADWORDSCAN, 2, "BadwordScanChanOps",neonspam_cmd_setflags, SPAMSETTINGS_BADWORDSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, + {SPAMSETTINGS_BADWORDSCAN, 2, "BadwordScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_BADWORDSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, + {SPAMSETTINGS_BADWORDSCAN, 2, "BadwordScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_BADWORDEXCINDEX, "channel_badword_except", SET_HELP | SET_SCANEXCEPT}, + {0, 0, "GlobalScanChanOps", neonspam_cmd_setscanops, 0, NULL, SET_BOOL}, {0, 0, "GlobalScanVoice", neonspam_cmd_setscanvoice, 0, NULL, SET_BOOL}, {0, 0, "GlobalScanExcept", neonspam_cmd_setscanexcept, 0, NULL, SET_HELP}, diff --git a/src/modules/NeonSpam.mod/event_neonspam_chanmsg.c b/src/modules/NeonSpam.mod/event_neonspam_chanmsg.c index 4ab7c83..b70a7a5 100644 --- a/src/modules/NeonSpam.mod/event_neonspam_chanmsg.c +++ b/src/modules/NeonSpam.mod/event_neonspam_chanmsg.c @@ -20,14 +20,16 @@ static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser static int neonspam_botnetscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); static int neonspam_capsscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); static int neonspam_digitscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); +static int neonspam_badwordscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message, int punish_now, int uaccess); static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup); -static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, unsigned int warn, unsigned int punish); +static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, char *message, unsigned int warn, unsigned int punish); struct neonspam_event_chanmsg_cache { struct ClientSocket *client; struct ChanUser *chanuser; struct NeonSpamSettings *settings; + char *message; unsigned int warn; unsigned int punish; }; @@ -127,12 +129,28 @@ static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan, break; } } + if((settings->flags & SPAMSETTINGS_BADWORDSCAN)) { + if(user->flags & USERFLAG_ISAUTHED) { + result = neonspam_badwordscan(client, settings, chanuser, message, 1, getChannelAccess(chanuser->user, chanuser->chan)); + } else + result = neonspam_badwordscan(client, settings, chanuser, message, 0, 0); + switch(result) { + case SPAMSERV_CHECK_DEAD: + return; + case SPAMSERV_CHECK_IGNORE: + break; + case SPAMSERV_CHECK_PUNISH: + punish |= SPAMSETTINGS_BADWORDSCAN; + needwho = 1; + break; + } + } //some other checks? if(warn || punish) { //whois the user to check against exceptlevel if(!needwho || (user->flags & USERFLAG_ISAUTHED)) { - neonspam_event_chanmsg_punish(client, chanuser, settings, warn, punish); + neonspam_event_chanmsg_punish(client, chanuser, settings, message, warn, punish); } else { struct neonspam_event_chanmsg_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -142,6 +160,7 @@ static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan, cache->client = client; cache->chanuser = chanuser; cache->settings = settings; + cache->message = strdup(message); cache->warn = warn; cache->punish = punish; get_userauth(user, module_id, neonspam_event_chanmsg_nick_lookup, cache); @@ -156,11 +175,12 @@ static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan, static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup) { struct neonspam_event_chanmsg_cache *cache = data; - neonspam_event_chanmsg_punish(cache->client, cache->chanuser, cache->settings, cache->warn, cache->punish); + neonspam_event_chanmsg_punish(cache->client, cache->chanuser, cache->settings, cache->message, cache->warn, cache->punish); + free(cache->message); free(cache); } -static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, unsigned int warn, unsigned int punish) { +static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, char *message, unsigned int warn, unsigned int punish) { MYSQL_RES *res; MYSQL_ROW row, defaults; loadChannelSettings(chanuser->chan); @@ -223,6 +243,16 @@ static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct Ch punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; punish_time = atoi((row[1] ? row[1] : defaults[1])); } + if(!punishment && (punish & SPAMSETTINGS_BADWORDSCAN)) { + int result = neonspam_badwordscan(client, settings, chanuser, message, 1, uaccess); + switch(result) { + case SPAMSERV_CHECK_DEAD: + return; + case SPAMSERV_CHECK_IGNORE: + break; + } + + } if(!punishment && (warn & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) { sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM); } @@ -390,3 +420,110 @@ static int neonspam_digitscan(struct NeonSpamSettings *settings, struct ChanUser return SPAMSERV_CHECK_IGNORE; } +static int neonspam_badwordscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message, int punish_now, int uaccess) { + struct NeonSpamBadword *badword; + int kick_user = 0; + int ban_user = 0; + int staticban_user = 0; + int ban_duration = 0; + int checked_defaults = 0; + int apply_default_reaction = 0; + for(badword = settings->badwords; badword; badword = badword->next) { + if(!match(badword->badword, message)) { + if(badword->use_defaults) { + if(checked_defaults == 2) continue; + else if(!checked_defaults) { + if(!(settings->flags & SPAMSETTINGS_BADWORDSCAN_OPS) && (chanuser->flags & CHANUSERFLAG_OPPED)) { + checked_defaults = 2; + continue; + } + if(!(settings->flags & SPAMSETTINGS_BADWORDSCAN_VOICE) && (chanuser->flags & CHANUSERFLAG_VOICED)) { + checked_defaults = 2; + continue; + } + if(settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX] && settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX] < 501) { + if(!punish_now) + return SPAMSERV_CHECK_PUNISH; + if(settings->exceptlevel[SPAMSETTINGS_BADWORDEXCINDEX] <= uaccess) { + checked_defaults = 2; + continue; + } + } + checked_defaults = 1; + } + } else { + if(!badword->scan_ops && (chanuser->flags & CHANUSERFLAG_OPPED)) continue; + if(!badword->scan_voice && (chanuser->flags & CHANUSERFLAG_VOICED)) continue; + if(badword->exceptlevel && badword->exceptlevel < 501) { + if(!punish_now) + return SPAMSERV_CHECK_PUNISH; + if(badword->exceptlevel <= uaccess) { + checked_defaults = 2; + continue; + } + } + } + if(badword->use_default_reaction) { + apply_default_reaction = 1; + } else { + switch(badword->reaction) { + case 2: + staticban_user = 1; + if(badword->reaction_time > ban_duration) + ban_duration = badword->reaction_time; + case 1: + ban_user = 1; + case 0: + kick_user = 1; + } + } + } + } + if(apply_default_reaction) { + MYSQL_RES *res; + MYSQL_ROW row, defaults; + loadChannelSettings(chanuser->chan); + printf_mysql_query("SELECT `channel_badword_reaction`, `channel_badword_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_badword_reaction`, `channel_badword_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + int reaction = atoi((row[0] ? row[0] : defaults[0])); + int reaction_time = atoi((row[1] ? row[1] : defaults[1])); + switch(reaction) { + case 2: + staticban_user = 1; + if(reaction_time > ban_duration) + ban_duration = reaction_time; + case 1: + ban_user = 1; + case 0: + kick_user = 1; + } + } + if(!kick_user) return SPAMSERV_CHECK_IGNORE; + char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; + char *banmask = NULL; + if(staticban_user) { + banmask = generate_banmask(chanuser->user, banmaskBuf); + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (ban_duration ? (time(0) + ban_duration) : 0), 0, escape_string(SPAMSERV_MSG_BADWORD)); + if(ban_duration) { + int banid = (int) mysql_insert_id(get_mysql_conn()); + char nameBuf[MAXLEN]; + char banidBuf[20]; + sprintf(nameBuf, "ban_%d", banid); + sprintf(banidBuf, "%d", banid); + timeq_add_name(nameBuf, ban_duration, module_id, channel_ban_timeout, strdup(banidBuf)); + } + } + if(ban_user) { + if(!banmask) + banmask = generate_banmask(chanuser->user, banmaskBuf); + putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask); + } + putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, SPAMSERV_MSG_BADWORD); + return SPAMSERV_CHECK_DEAD; +} diff --git a/src/mysqlConn.c b/src/mysqlConn.c index 163ae12..c2f3fcb 100644 --- a/src/mysqlConn.c +++ b/src/mysqlConn.c @@ -16,7 +16,7 @@ */ #include "mysqlConn.h" -#define DATABASE_VERSION "16" +#define DATABASE_VERSION "17" static void show_mysql_error(); -- 2.20.1