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)
-- 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.
`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;
`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 ;
) 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
{"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}
};
#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"
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);
}
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;
}
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);
}
#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
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
#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
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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+ }
+}
--- /dev/null
+/* 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);
+}
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, \
`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
{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},
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;
};
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) {
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);
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);
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);
}
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;
+}
*/
#include "mysqlConn.h"
-#define DATABASE_VERSION "16"
+#define DATABASE_VERSION "17"
static void show_mysql_error();