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;
+}