added NeonSpam Badword scanner
authorpk910 <philipp@zoelle1.de>
Sun, 19 Feb 2012 01:35:31 +0000 (02:35 +0100)
committerpk910 <philipp@zoelle1.de>
Mon, 20 Feb 2012 00:54:20 +0000 (01:54 +0100)
14 files changed:
Makefile.am
database.defaults.sql
database.sql
database.upgrade.sql
src/modules/NeonSpam.mod/bot_NeonSpam.c
src/modules/NeonSpam.mod/bot_NeonSpam.h
src/modules/NeonSpam.mod/cmd_neonspam.c
src/modules/NeonSpam.mod/cmd_neonspam.h
src/modules/NeonSpam.mod/cmd_neonspam_addbad.c [new file with mode: 0644]
src/modules/NeonSpam.mod/cmd_neonspam_badwords.c [new file with mode: 0644]
src/modules/NeonSpam.mod/cmd_neonspam_delbad.c [new file with mode: 0644]
src/modules/NeonSpam.mod/cmd_neonspam_set.c
src/modules/NeonSpam.mod/event_neonspam_chanmsg.c
src/mysqlConn.c

index c312545d8e9d18cf6651383aabb8fcf493f5f6d3..d3f96fed532618df49e6a7b72a59b35e3f02d46c 100644 (file)
@@ -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)
index 2f78e4d88309b647c7214ead3dbdf66a1b83880e..5aa092ee2b6750d9f61b47d4de5616b2ec0cc930 100644 (file)
@@ -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.
index d3d9156e3be87e535b9885b749a47226482dc45c..45cb784168f73ee4bb9beac0e927da41b13b5d9b 100644 (file)
@@ -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 ;
index 7d08cd83a6961e598437faaf093626b217d40b51..c8f34f3cd15c902ccf4fde86b0dc692032442e7e 100644 (file)
@@ -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
index 5ccfbc2d82138e4028cd5beb6b6da11b12737745..10b4083e9010e81d811f879d41ba209f01437361 100644 (file)
@@ -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);
 }
 
index aaeca2b25a256a60acf22a6d2dece667236d6a4d..1d4c68f6d7249215336447abdcbe8595da18f30f 100644 (file)
@@ -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
index f5a520f5a97387617a236963e8a0ce71a31396a6..d0241c44cefeb6bfd96f4d68478dfc006f2e9e94 100644 (file)
@@ -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
index d23811088ff67965075f75629f4738f73ca609d3..9b8006e8fc27a74027ff172eb43ae0f1fa81f22d 100644 (file)
@@ -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 (file)
index 0000000..d6ca60c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..9767e35
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..0a34d02
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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);
+}
index 6b8cd3d1d7ddca8e8972f1298712d8d278fd68a7..30df3027497c933baaef39d04beca11ded6243ba 100644 (file)
@@ -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},
index 4ab7c833b23c72867924953d6419845066df6a3e..b70a7a5f565bcf7d1935640df3dfd5c4bf50a6ef 100644 (file)
@@ -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;
+}
index 163ae12f0f04d3ff5fa6d757fe7a9bc861bce12e..c2f3fcb69604378d7fa0fc96c2408ee51df64825 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #include "mysqlConn.h"
-#define DATABASE_VERSION "16"
+#define DATABASE_VERSION "17"
 
 static void show_mysql_error();