summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/battle_athena.conf18
-rw-r--r--src/map/battle.c33
-rw-r--r--src/map/battle.h5
-rw-r--r--src/map/clif.c51
-rw-r--r--src/map/map.h7
-rw-r--r--src/map/pc.c3
6 files changed, 114 insertions, 3 deletions
diff --git a/conf/battle_athena.conf b/conf/battle_athena.conf
index a272a60..e456003 100644
--- a/conf/battle_athena.conf
+++ b/conf/battle_athena.conf
@@ -707,5 +707,23 @@ max_cloth_color: 4
// Visible area size (how many squares away from a player can they see)
area_size: 14
+// chat system:
+// 2 anti spam systems works together, one is a time based system and the
+// other is a repeat based system. Both count up individually, and if one
+// surpasses the spam_threshold, players is auto-banned for spam_ban hours
+
+// how many hours to auto ban spammer, 0 to disable [0-32767]. Default 6.
+spam_ban: 6
+
+// how many ms must the message be within to hit threshold counter [1-32767]. Default 3000.
+spam_time: 3000
+
+// how many unpaused lines/repeats in a row before ban trigger [1-32767]. Default 10.
+spam_threshold: 10
+
+// Maximum line lengt, if a message is above chat_maxline, its dropped [1-512]. Default 255.
+chat_maxline: 255
+
+
import: conf/import/battle_conf.txt
diff --git a/src/map/battle.c b/src/map/battle.c
index 7a6dd47..8577a29 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -5016,6 +5016,11 @@ int battle_config_read(const char *cfgName)
battle_config.area_size = 14;
+ battle_config.spam_ban = 6;
+ battle_config.spam_time = 3000;
+ battle_config.spam_threshold = 10;
+ battle_config.chat_maxline = 255;
+
//SQL-only options start
#ifndef TXT_ONLY
battle_config.mail_system = 0;
@@ -5238,7 +5243,11 @@ int battle_config_read(const char *cfgName)
{ "max_cloth_color", &battle_config.max_cloth_color }, // added by [MouseJstr]
{ "castrate_dex_scale", &battle_config.castrate_dex_scale }, // added by [MouseJstr]
{ "area_size", &battle_config.area_size }, // added by [MouseJstr]
- { "muting_players", &battle_config.muting_players}, // added by [Apple]
+ { "muting_players", &battle_config.muting_players}, // added by [Apple]
+ { "spam_ban", &battle_config.spam_ban },
+ { "spam_time", &battle_config.spam_time },
+ { "spam_threshold", &battle_config.spam_threshold },
+ { "chat_maxline", &battle_config.chat_maxline },
//SQL-only options start
#ifndef TXT_ONLY
{ "mail_system", &battle_config.mail_system }, // added by [Valaris]
@@ -5363,6 +5372,28 @@ int battle_config_read(const char *cfgName)
else if (battle_config.any_warp_GM_min_level > 100)
battle_config.any_warp_GM_min_level = 100;
+
+ if (battle_config.spam_ban < 0)
+ battle_config.spam_ban = 0;
+ else if (battle_config.spam_ban > 32767)
+ battle_config.spam_ban = 32767;
+
+ if (battle_config.spam_time < 0)
+ battle_config.spam_time = 0;
+ else if (battle_config.spam_time > 32767)
+ battle_config.spam_time = 32767;
+
+ if (battle_config.spam_threshold < 0)
+ battle_config.spam_threshold = 0;
+ else if (battle_config.spam_threshold > 32767)
+ battle_config.spam_threshold = 32767;
+
+ if (battle_config.chat_maxline < 1)
+ battle_config.chat_maxline = 1;
+ else if (battle_config.chat_maxline > 512)
+ battle_config.chat_maxline = 512;
+
+
// at least 1 client must be accepted
if ((battle_config.packet_ver_flag & 63) == 0) // added by [Yor]
battle_config.packet_ver_flag = 63; // accept all clients
diff --git a/src/map/battle.h b/src/map/battle.h
index 8f09d22..27e1e6f 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -331,6 +331,11 @@ extern struct Battle_Config {
int castrate_dex_scale; // added by [MouseJstr]
int area_size; // added by [MouseJstr]
+ int spam_ban;
+ int spam_time;
+ int spam_threshold;
+ int chat_maxline;
+
#ifndef TXT_ONLY /* SQL-only options */
int mail_system; // [Valaris]
#endif
diff --git a/src/map/clif.c b/src/map/clif.c
index f847a56..0a6559c 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -7397,7 +7397,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c <len>.w <str>.?B
char *message = (char *) malloc(RFIFOW(fd,2) + 128);
char *buf = (char *) malloc(RFIFOW(fd,2) + 4);
-
+ int tick,elapsed = 0;
nullpo_retv(sd);
memset(message, '\0', RFIFOW(fd,2) + 128);
@@ -7413,6 +7413,55 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c <
return;
}
+ if (!pc_isGM(sd))
+ {
+ tick = gettick();
+ elapsed = tick - sd->chat_lastmsg_time;
+ sd->chat_lastmsg_time = tick;
+
+ if (elapsed < battle_config.spam_time)
+ sd->chat_threshold++;
+
+ sd->chat_threshold -= (int)(elapsed / (battle_config.spam_time/2));
+
+ if (sd->chat_threshold < 0)
+ sd->chat_threshold = 0;
+
+ if (strncmp(sd->chat_lastmsg, RFIFOP(fd,4), battle_config.chat_maxline) == 0)
+ sd->chat_repeatmsg++;
+ else
+ sd->chat_repeatmsg--;
+
+ if (sd->chat_repeatmsg < 0)
+ sd->chat_repeatmsg = 0;
+
+ strncpy((char*)sd->chat_lastmsg, RFIFOP(fd,4), battle_config.chat_maxline);
+
+ if (sd->chat_threshold > battle_config.spam_threshold || sd->chat_repeatmsg > battle_config.spam_threshold) {
+ sprintf(message, "Spam detected from character '%s' (account: %d), threshold was exceeded.", sd->status.name, sd->status.account_id);
+ printf("%s\n", message);
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message, strlen(message) + 1);
+
+ if (battle_config.spam_ban > 0)
+ sprintf(message, " This player has been banned for %d hours(s).", battle_config.spam_ban);
+ else
+ sprintf(message, " This player hasn't been banned (Ban option is disabled).");
+ printf("%s\n", message);
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message, strlen(message) + 1);
+
+ if (battle_config.spam_ban > 0)
+ {
+ chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, battle_config.spam_ban, 0, 0); // type: 2 - ban (year, month, day, hour, minute, second)
+ clif_setwaitclose(fd); // forced to disconnect
+ }
+ else
+ return; // just ignore, dont ban.
+ }
+
+ if (strlen(RFIFOP(fd,4)) >= battle_config.chat_maxline)
+ return; // ignore lines exceeding the max length in config.
+ }
+
//printf("clif_parse_GlobalMessage: message: '%s'.\n", RFIFOP(fd,4));
if (strncmp(RFIFOP(fd,4), sd->status.name, strlen(sd->status.name)) != 0) {
printf("Hack on global message: character '%s' (account: %d), use an other name to send a (normal) message.\n", sd->status.name, sd->status.account_id);
diff --git a/src/map/map.h b/src/map/map.h
index 703bbb6..3c7e2de 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -308,7 +308,12 @@ struct map_session_data {
} ignore[80];
int ignoreAll;
short sg_count;
-
+
+ unsigned int chat_lastmsg_time;
+ char chat_lastmsg[513];
+ int chat_threshold;
+ int chat_repeatmsg;
+
#ifndef TXT_ONLY
int mail_counter; // mail counter for mail system [Valaris]
#endif
diff --git a/src/map/pc.c b/src/map/pc.c
index 790fc32..9a96008 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -836,6 +836,9 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
}
}
+ sd->chat_lastmsg_time = sd->chat_threshold = sd->chat_repeatmsg = 0;
+ sd->chat_lastmsg[0] = '\0';
+
#ifndef TXT_ONLY
if(battle_config.mail_system)
mail_check(sd,1); // check mail at login [Valaris]