· 6 years ago · Sep 08, 2019, 11:14 PM
1/*
2 Advanced Bans
3
4 Version 0.8.1
5
6 by Exolent
7
8
9
10 Plugin Thread:
11
12 - http://forums.alliedmods.net/showthread.php?t=80858
13
14
15
16 Description:
17
18 - This plugin revamps the current amx_ban, amx_banip, amx_banid, amx_unban admin commands.
19
20 - It uses Real Time on the server
21 (Eg. Banned for 10 minutes, you will be unbanned 10 minutes later, regardless of map changing).
22
23 - It includes a list of who is banned.
24
25 - It does not use the banned.cfg or listip.cfg. It uses its own file where bans are stored.
26
27 - It saves what admin banned the player (name), the admin's steamid, the reason, the ban time,
28 the banned player's name, the banned player's steamid (or IP), and the estimated time of unban.
29
30 - It will load your currently banned players from the banned.cfg and listip.cfg files.
31 (Only if the #define below is uncommented)
32
33 - If you use the menu to ban players, you will have to type a reason after you choose a player.
34
35 - If you use the vote system to ban players, you will have to type a reason after you execute the amx_voteban command.
36
37 - You can limit the ban time for admins based on their admin flags.
38
39 - You can monitor all ban history (admins banning, unbanning, and when ban times are up) in
40 the addons/amxmodx/logs/BAN_HISTORY_MMDDYYYY.log (MM = month, DD = day, YYYY = year)
41
42 - If you wish to have only 1 file for ban history, uncomment the line at the top of the .sma file and recompile.
43
44 - Supports SQL for banning.
45
46
47
48 Commands:
49
50 - amx_ban <nick, #userid, authid> <time in minutes> <reason>
51
52 - amx_banip <nick, #userid, authid> <time in minutes> <reason>
53
54 - amx_addban <name> <authid or ip> <time in minutes> <reason>
55
56 - amx_unban <authid or ip>
57
58 - amx_banlist
59 - Shows a list of who is banned
60
61 - amx_addbanlimit <flags> <time in minutes>
62 - Adds a max ban time to the list
63 - Note: Use this command in the amxx.cfg
64
65
66
67 Cvars:
68
69 - ab_website <website>
70 - This is the website displayed to the banned player if you have an unban request section on your website.
71 - Leave blank to not show a website.
72 - Default: blank
73
74 - ab_immunity <0|1|2>
75 - 0 - Any admin can ban an immunity admin (flag 'a').
76 - 1 - Immunity admins (flag 'a') cannot be banned.
77 - 2 - Immunity admins (flag 'a') can only be banned by other immunity admins (flag 'a').
78 - Default: 1
79
80 - ab_bandelay <seconds>
81 - Delay of banned players being disconnected.
82 - Default: 1
83
84 - ab_unbancheck <seconds>
85 - Interval of checking if a player is unbanned.
86 - Default: 5
87
88
89
90 Requirements:
91
92 - AMX Mod X version 1.8.0 or higher
93
94
95
96 Changelog:
97
98 - Version 0.1 (with updates included)
99 - Initial Release
100 - Changed to dynamic arrays to hold ban information
101 - Added option #2 for ab_immunity
102 - Added support for banning by IP
103 - Added compatability for banned.cfg and listip.cfg
104 - Added menu support (plmenu.amxx)
105 - Added ML support
106
107 - Version 0.2
108 - Added simple max ban time feature
109
110 - Version 0.3
111 - Added more cvars for max ban times
112 - Added cvar for delay of player to disconenct after being banned
113 - Added cvar for interval of checking for unban time of banned players
114 - Added more translations
115
116 - Version 0.4
117 - Fixed the possible infinite loop, causing servers to crash
118 - Added ban history
119 - Removed max ban time cvars
120 - Added max ban times per admin flags
121 - Added more translations
122
123 - Version 0.5
124 - Fixed information not being printed into console
125 - Fixed "amx_addban" using the admin's name as the SteamID when saving the ban
126 - Added option for ban history to be one file
127 - Added translations
128
129 - Version 0.5b
130 - Fixed players not being unbanned
131 - Added translations
132
133 - Version 0.6
134 - Added small optimization for unban checking
135 - Changed "UnBan Time" in the logs and chat messages to "Ban Length"
136 - Fixed small code error where unban time was generated was used when length was 0
137 - Changed IsValidIP() method to use regex (Thanks to arkshine)
138 - Added plugin information inside the .sma file
139 - Added a #define option to use maximum bans for compatability for AMXX < 1.8.0
140 - Changed admin messages in chat to work with amx_show_activity cvar
141 - Added translations
142
143 - Version 0.6b
144 - Fixed a small bug
145
146 - Version 0.6c
147 - Fixed amx_banlist for server consoles
148 - Changed IsValidAuthid() method to use regex
149
150 - Version 0.6d
151 - Fixed ban limit for permanent bans
152
153 - Version 0.7
154 - Changed the "unlimited bans" version to be faster (Thanks to joaquimandrade)
155 - Added check when adding bans if the player is already banned.
156
157 - Version 0.8
158 - Added SQL support.
159
160 - Version 0.8.1
161 - Added unban logging for non-SQL version
162
163
164
165 Notes:
166
167 - If you plan to use this plugin, go to the plugin's thread.
168
169 - The plugin's thread has more information about the plugin, along with the multilingual file.
170
171 - It also has a modified plmenu.amxx plugin that adds the ban reason to the menu.
172
173 - And it has a modified adminvote.amxx plugin that adds the ban reason to amx_voteban.
174*/
175
176
177
178#include <amxmodx>
179#include <amxmisc>
180#include <engine>
181#include <regex>
182
183#define PLUGIN_NAME "Advanced Bans"
184#define PLUGIN_VERSION "0.8.1"
185#define PLUGIN_AUTHOR "Exolent"
186
187#pragma semicolon 1
188
189
190
191// ===============================================
192// CUSTOMIZATION STARTS HERE
193// ===============================================
194
195
196// uncomment the line below if you want this plugin to
197// load old bans from the banned.cfg and listip.cfg files
198//#define KEEP_DEFAULT_BANS
199
200
201// uncomment the line below if you want the history to be in one file
202//#define HISTORY_ONE_FILE
203
204
205// if you must have a maximum amount of bans to be compatible with AMXX versions before 1.8.0
206// change this number to your maximum amount
207// if you would rather have unlimited (requires AMXX 1.8.0 or higher) then set it to 0
208#define MAX_BANS 0
209
210
211// if you want to use SQL for your server, then uncomment the line below
212//#define USING_SQL
213
214
215// ===============================================
216// CUSTOMIZATION ENDS HERE
217// ===============================================
218
219
220
221#if defined USING_SQL
222#include <sqlx>
223
224#define TABLE_NAME "advanced_bans"
225#define KEY_NAME "name"
226#define KEY_STEAMID "steamid"
227#define KEY_BANLENGTH "banlength"
228#define KEY_UNBANTIME "unbantime"
229#define KEY_REASON "reason"
230#define KEY_ADMIN_NAME "admin_name"
231#define KEY_ADMIN_STEAMID "admin_steamid"
232
233#define RELOAD_BANS_INTERVAL 60.0
234#endif
235
236#define REGEX_IP_PATTERN "\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
237#define REGEX_STEAMID_PATTERN "^^STEAM_(0|1):(0|1):\d+$"
238
239new Regex:g_IP_pattern;
240new Regex:g_SteamID_pattern;
241new g_regex_return;
242
243/*bool:IsValidIP(const ip[])
244{
245 return regex_match_c(ip, g_IP_pattern, g_regex_return) > 0;
246}*/
247
248#define IsValidIP(%1) (regex_match_c(%1, g_IP_pattern, g_regex_return) > 0)
249
250/*bool:IsValidAuthid(const authid[])
251{
252 return regex_match_c(authid, g_SteamID_pattern, g_regex_return) > 0;
253}*/
254
255#define IsValidAuthid(%1) (regex_match_c(%1, g_SteamID_pattern, g_regex_return) > 0)
256
257
258enum // for name displaying
259{
260 ACTIVITY_NONE, // nothing is shown
261 ACTIVITY_HIDE, // admin name is hidden
262 ACTIVITY_SHOW // admin name is shown
263};
264new const g_admin_activity[] =
265{
266 ACTIVITY_NONE, // amx_show_activity 0 = show nothing to everyone
267 ACTIVITY_HIDE, // amx_show_activity 1 = hide admin name from everyone
268 ACTIVITY_SHOW, // amx_show_activity 2 = show admin name to everyone
269 ACTIVITY_SHOW, // amx_show_activity 3 = show name to admins but hide it from normal users
270 ACTIVITY_SHOW, // amx_show_activity 4 = show name to admins but show nothing to normal users
271 ACTIVITY_HIDE // amx_show_activity 5 = hide name from admins but show nothing to normal users
272};
273new const g_normal_activity[] =
274{
275 ACTIVITY_NONE, // amx_show_activity 0 = show nothing to everyone
276 ACTIVITY_HIDE, // amx_show_activity 1 = hide admin name from everyone
277 ACTIVITY_SHOW, // amx_show_activity 2 = show admin name to everyone
278 ACTIVITY_HIDE, // amx_show_activity 3 = show name to admins but hide it from normal users
279 ACTIVITY_NONE, // amx_show_activity 4 = show name to admins but show nothing to normal users
280 ACTIVITY_NONE // amx_show_activity 5 = hide name from admins but show nothing to normal users
281};
282
283
284#if MAX_BANS <= 0
285enum _:BannedData
286{
287 bd_name[32],
288 bd_steamid[35],
289 bd_banlength,
290 bd_unbantime[32],
291 bd_reason[128],
292 bd_admin_name[64],
293 bd_admin_steamid[35]
294};
295
296new Trie:g_trie;
297new Array:g_array;
298#else
299new g_names[MAX_BANS][32];
300new g_steamids[MAX_BANS][35];
301new g_banlengths[MAX_BANS];
302new g_unbantimes[MAX_BANS][32];
303new g_reasons[MAX_BANS][128];
304new g_admin_names[MAX_BANS][64];
305new g_admin_steamids[MAX_BANS][35];
306#endif
307new g_total_bans;
308
309#if !defined USING_SQL
310new g_ban_file[64];
311#else
312new Handle:g_sql_tuple;
313new bool:g_loading_bans = true;
314#endif
315
316new ab_website;
317new ab_immunity;
318new ab_bandelay;
319new ab_unbancheck;
320
321new amx_show_activity;
322
323#if MAX_BANS <= 0
324new Array:g_maxban_times;
325new Array:g_maxban_flags;
326#else
327#define MAX_BANLIMITS 30
328new g_maxban_times[MAX_BANLIMITS];
329new g_maxban_flags[MAX_BANLIMITS];
330#endif
331new g_total_maxban_times;
332
333new g_unban_entity;
334
335new g_max_clients;
336
337new g_msgid_SayText;
338
339public plugin_init()
340{
341 register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR);
342 register_cvar("advanced_bans", PLUGIN_VERSION, FCVAR_SPONLY);
343
344 register_dictionary("advanced_bans.txt");
345
346 register_concmd("amx_ban", "CmdBan", ADMIN_BAN, "<nick, #userid, authid> <time in minutes> <reason>");
347 register_concmd("amx_banip", "CmdBanIp", ADMIN_BAN, "<nick, #userid, authid> <time in minutes> <reason>");
348 register_concmd("amx_addban", "CmdAddBan", ADMIN_BAN, "<name> <authid or ip> <time in minutes> <reason>");
349 register_concmd("amx_unban", "CmdUnban", ADMIN_BAN, "<authid or ip>");
350 register_concmd("amx_banlist", "CmdBanList", ADMIN_BAN, "[start] -- shows everyone who is banned");
351 register_srvcmd("amx_addbanlimit", "CmdAddBanLimit", -1, "<flag> <time in minutes>");
352
353 ab_website = register_cvar("ab_website", "");
354 ab_immunity = register_cvar("ab_immunity", "1");
355 ab_bandelay = register_cvar("ab_bandelay", "1.0");
356 ab_unbancheck = register_cvar("ab_unbancheck", "5.0");
357
358 amx_show_activity = register_cvar("amx_show_activity", "2");
359
360 #if MAX_BANS <= 0
361 g_trie = TrieCreate();
362 g_array = ArrayCreate(BannedData);
363 #endif
364
365 #if !defined MAX_BANLIMITS
366 g_maxban_times = ArrayCreate(1);
367 g_maxban_flags = ArrayCreate(1);
368 #endif
369
370 #if !defined USING_SQL
371 get_datadir(g_ban_file, sizeof(g_ban_file) - 1);
372 add(g_ban_file, sizeof(g_ban_file) - 1, "/advanced_bans.txt");
373
374 LoadBans();
375 #else
376 g_sql_tuple = SQL_MakeStdTuple();
377 PrepareTable();
378 #endif
379
380 new error[2];
381 g_IP_pattern = regex_compile(REGEX_IP_PATTERN, g_regex_return, error, sizeof(error) - 1);
382 g_SteamID_pattern = regex_compile(REGEX_STEAMID_PATTERN, g_regex_return, error, sizeof(error) - 1);
383
384 g_max_clients = get_maxplayers();
385
386 g_msgid_SayText = get_user_msgid("SayText");
387}
388
389#if defined USING_SQL
390PrepareTable()
391{
392 new query[128];
393 formatex(query, sizeof(query) - 1,\
394 "CREATE TABLE IF NOT EXISTS `%s` (`%s` varchar(32) NOT NULL, `%s` varchar(35) NOT NULL, `%s` int(10) NOT NULL, `%s` varchar(32) NOT NULL, `%s` varchar(128) NOT NULL, `%s` varchar(64) NOT NULL, `%s` varchar(35) NOT NULL);",\
395 TABLE_NAME, KEY_NAME, KEY_STEAMID, KEY_BANLENGTH, KEY_UNBANTIME, KEY_REASON, KEY_ADMIN_NAME, KEY_ADMIN_STEAMID
396 );
397
398 SQL_ThreadQuery(g_sql_tuple, "QueryCreateTable", query);
399}
400
401public QueryCreateTable(failstate, Handle:query, error[], errcode, data[], datasize, Float:queuetime)
402{
403 if( failstate == TQUERY_CONNECT_FAILED )
404 {
405 set_fail_state("Could not connect to database.");
406 }
407 else if( failstate == TQUERY_QUERY_FAILED )
408 {
409 set_fail_state("Query failed.");
410 }
411 else if( errcode )
412 {
413 log_amx("Error on query: %s", error);
414 }
415 else
416 {
417 LoadBans();
418 }
419}
420#endif
421
422public plugin_cfg()
423{
424 CreateUnbanEntity();
425}
426
427public CreateUnbanEntity()
428{
429 static failtimes;
430
431 g_unban_entity = create_entity("info_target");
432
433 if( !is_valid_ent(g_unban_entity) )
434 {
435 ++failtimes;
436
437 log_amx("[ERROR] Failed to create unban entity (%i/10)", failtimes);
438
439 if( failtimes < 10 )
440 {
441 set_task(1.0, "CreateUnbanEntity");
442 }
443 else
444 {
445 log_amx("[ERROR] Could not create unban entity!");
446 }
447
448 return;
449 }
450
451 entity_set_string(g_unban_entity, EV_SZ_classname, "unban_entity");
452 entity_set_float(g_unban_entity, EV_FL_nextthink, get_gametime() + 1.0);
453
454 register_think("unban_entity", "FwdThink");
455}
456
457public client_authorized(client)
458{
459 static authid[35];
460 get_user_authid(client, authid, sizeof(authid) - 1);
461
462 static ip[35];
463 get_user_ip(client, ip, sizeof(ip) - 1, 1);
464
465 #if MAX_BANS > 0
466 static banned_authid[35], bool:is_ip;
467 for( new i = 0; i < g_total_bans; i++ )
468 {
469 copy(banned_authid, sizeof(banned_authid) - 1, g_steamids[i]);
470
471 is_ip = bool:(containi(banned_authid, ".") != -1);
472
473 if( is_ip && equal(ip, banned_authid) || !is_ip && equal(authid, banned_authid) )
474 {
475 static name[32], reason[128], unbantime[32], admin_name[32], admin_steamid[64];
476 copy(name, sizeof(name) - 1, g_names[i]);
477 copy(reason, sizeof(reason) - 1, g_reasons[i]);
478 new banlength = g_banlengths[i];
479 copy(unbantime, sizeof(unbantime) - 1, g_unbantimes[i]);
480 copy(admin_name, sizeof(admin_name) - 1, g_admin_names[i]);
481 copy(admin_steamid, sizeof(admin_steamid) - 1, g_admin_steamids[i]);
482
483 PrintBanInformation(client, name, banned_authid, reason, banlength, unbantime, admin_name, admin_steamid, true, true);
484
485 set_task(get_pcvar_float(ab_bandelay), "TaskDisconnectPlayer", client);
486 break;
487 }
488 }
489 #else
490 static array_pos;
491
492 if( TrieGetCell(g_trie, authid, array_pos) || TrieGetCell(g_trie, ip, array_pos) )
493 {
494 static data[BannedData];
495 ArrayGetArray(g_array, array_pos, data);
496
497 PrintBanInformation(client, data[bd_name], data[bd_steamid], data[bd_reason], data[bd_banlength], data[bd_unbantime], data[bd_admin_name], data[bd_admin_steamid], true, true);
498
499 set_task(get_pcvar_float(ab_bandelay), "TaskDisconnectPlayer", client);
500 }
501 #endif
502}
503
504public CmdBan(client, level, cid)
505{
506 if( !cmd_access(client, level, cid, 4) ) return PLUGIN_HANDLED;
507
508 static arg[128];
509 read_argv(1, arg, sizeof(arg) - 1);
510
511 new target = cmd_target(client, arg, GetTargetFlags(client));
512 if( !target ) return PLUGIN_HANDLED;
513
514 static target_authid[35];
515 get_user_authid(target, target_authid, sizeof(target_authid) - 1);
516
517 if( !IsValidAuthid(target_authid) )
518 {
519 console_print(client, "[AdvancedBans] %L", client, "AB_NOT_AUTHORIZED");
520 return PLUGIN_HANDLED;
521 }
522
523 #if MAX_BANS <= 0
524 if( TrieKeyExists(g_trie, target_authid) )
525 {
526 console_print(client, "[AdvancedBans] %L", client, "AB_ALREADY_BANNED_STEAMID");
527 return PLUGIN_HANDLED;
528 }
529 #else
530 for( new i = 0; i < g_total_bans; i++ )
531 {
532 if( !strcmp(target_authid, g_steamids[i], 1) )
533 {
534 console_print(client, "[AdvancedBans] %L", client, "AB_ALREADY_BANNED_STEAMID");
535 return PLUGIN_HANDLED;
536 }
537 }
538 #endif
539
540 read_argv(2, arg, sizeof(arg) - 1);
541
542 new length = str_to_num(arg);
543 new maxlength = GetMaxBanTime(client);
544
545 if( maxlength && (!length || length > maxlength) )
546 {
547 console_print(client, "[AdvancedBans] %L", client, "AB_MAX_BAN_TIME", maxlength);
548 return PLUGIN_HANDLED;
549 }
550
551 static unban_time[64];
552 if( length == 0 )
553 {
554 formatex(unban_time, sizeof(unban_time) - 1, "%L", client, "AB_PERMANENT_BAN");
555 }
556 else
557 {
558 GenerateUnbanTime(length, unban_time, sizeof(unban_time) - 1);
559 }
560
561 read_argv(3, arg, sizeof(arg) - 1);
562
563 static admin_name[64], target_name[32];
564 get_user_name(client, admin_name, sizeof(admin_name) - 1);
565 get_user_name(target, target_name, sizeof(target_name) - 1);
566
567 static admin_authid[35];
568 get_user_authid(client, admin_authid, sizeof(admin_authid) - 1);
569
570 AddBan(target_name, target_authid, arg, length, unban_time, admin_name, admin_authid);
571
572 PrintBanInformation(target, target_name, target_authid, arg, length, unban_time, admin_name, admin_authid, true, true);
573 PrintBanInformation(client, target_name, target_authid, arg, length, unban_time, admin_name, admin_authid, false, false);
574
575 set_task(get_pcvar_float(ab_bandelay), "TaskDisconnectPlayer", target);
576
577 GetBanTime(length, unban_time, sizeof(unban_time) - 1);
578
579 PrintActivity(admin_name, "^x04[AdvancedBans] $name^x01 :^x03 banned %s. Reason: %s. Ban Length: %s", target_name, arg, unban_time);
580
581 Log("%s <%s> banned %s <%s> || Reason: ^"%s^" || Ban Length: %s", admin_name, admin_authid, target_name, target_authid, arg, unban_time);
582
583 return PLUGIN_HANDLED;
584}
585
586public CmdBanIp(client, level, cid)
587{
588 if( !cmd_access(client, level, cid, 4) ) return PLUGIN_HANDLED;
589
590 static arg[128];
591 read_argv(1, arg, sizeof(arg) - 1);
592
593 new target = cmd_target(client, arg, GetTargetFlags(client));
594 if( !target ) return PLUGIN_HANDLED;
595
596 static target_ip[35];
597 get_user_ip(target, target_ip, sizeof(target_ip) - 1, 1);
598
599 #if MAX_BANS <= 0
600 if( TrieKeyExists(g_trie, target_ip) )
601 {
602 console_print(client, "[AdvancedBans] %L", client, "AB_ALREADY_BANNED_IP");
603 return PLUGIN_HANDLED;
604 }
605 #else
606 for( new i = 0; i < g_total_bans; i++ )
607 {
608 if( !strcmp(target_ip, g_steamids[i], 1) )
609 {
610 console_print(client, "[AdvancedBans] %L", client, "AB_ALREADY_BANNED_IP");
611 return PLUGIN_HANDLED;
612 }
613 }
614 #endif
615
616 read_argv(2, arg, sizeof(arg) - 1);
617
618 new length = str_to_num(arg);
619 new maxlength = GetMaxBanTime(client);
620
621 if( maxlength && (!length || length > maxlength) )
622 {
623 console_print(client, "[AdvancedBans] %L", client, "AB_MAX_BAN_TIME", maxlength);
624 return PLUGIN_HANDLED;
625 }
626
627 static unban_time[32];
628
629 if( length == 0 )
630 {
631 formatex(unban_time, sizeof(unban_time) - 1, "%L", client, "AB_PERMANENT_BAN");
632 }
633 else
634 {
635 GenerateUnbanTime(length, unban_time, sizeof(unban_time) - 1);
636 }
637
638 read_argv(3, arg, sizeof(arg) - 1);
639
640 static admin_name[64], target_name[32];
641 get_user_name(client, admin_name, sizeof(admin_name) - 1);
642 get_user_name(target, target_name, sizeof(target_name) - 1);
643
644 static admin_authid[35];
645 get_user_authid(client, admin_authid, sizeof(admin_authid) - 1);
646
647 AddBan(target_name, target_ip, arg, length, unban_time, admin_name, admin_authid);
648
649 PrintBanInformation(target, target_name, target_ip, arg, length, unban_time, admin_name, admin_authid, true, true);
650 PrintBanInformation(client, target_name, target_ip, arg, length, unban_time, admin_name, admin_authid, false, false);
651
652 set_task(get_pcvar_float(ab_bandelay), "TaskDisconnectPlayer", target);
653
654 GetBanTime(length, unban_time, sizeof(unban_time) - 1);
655
656 PrintActivity(admin_name, "^x04[AdvancedBans] $name^x01 :^x03 banned %s. Reason: %s. Ban Length: %s", target_name, arg, unban_time);
657
658 Log("%s <%s> banned %s <%s> || Reason: ^"%s^" || Ban Length: %s", admin_name, admin_authid, target_name, target_ip, arg, unban_time);
659
660 return PLUGIN_HANDLED;
661}
662
663public CmdAddBan(client, level, cid)
664{
665 if( !cmd_access(client, level, cid, 5) ) return PLUGIN_HANDLED;
666
667 static target_name[32], target_authid[35], bantime[10], reason[128];
668 read_argv(1, target_name, sizeof(target_name) - 1);
669 read_argv(2, target_authid, sizeof(target_authid) - 1);
670 read_argv(3, bantime, sizeof(bantime) - 1);
671 read_argv(4, reason, sizeof(reason) - 1);
672
673 new bool:is_ip = bool:(containi(target_authid, ".") != -1);
674
675 if( !is_ip && !IsValidAuthid(target_authid) )
676 {
677 console_print(client, "[AdvancedBans] %L", client, "AB_INVALID_STEAMID");
678 console_print(client, "[AdvancedBans] %L", client, "AB_VALID_STEAMID_FORMAT");
679
680 return PLUGIN_HANDLED;
681 }
682 else if( is_ip )
683 {
684 new pos = contain(target_authid, ":");
685 if( pos > 0 )
686 {
687 target_authid[pos] = 0;
688 }
689
690 if( !IsValidIP(target_authid) )
691 {
692 console_print(client, "[AdvancedBans] %L", client, "AB_INVALID_IP");
693
694 return PLUGIN_HANDLED;
695 }
696 }
697
698 #if MAX_BANS <= 0
699 if( TrieKeyExists(g_trie, target_authid) )
700 {
701 console_print(client, "[AdvancedBans] %L", client, is_ip ? "AB_ALREADY_BANNED_IP" : "AB_ALREADY_BANNED_STEAMID");
702 return PLUGIN_HANDLED;
703 }
704 #else
705 for( new i = 0; i < g_total_bans; i++ )
706 {
707 if( !strcmp(target_authid, g_steamids[i], 1) )
708 {
709 console_print(client, "[AdvancedBans] %L", client, is_ip ? "AB_ALREADY_BANNED_IP" : "AB_ALREADY_BANNED_STEAMID");
710 return PLUGIN_HANDLED;
711 }
712 }
713 #endif
714
715 new length = str_to_num(bantime);
716 new maxlength = GetMaxBanTime(client);
717
718 if( maxlength && (!length || length > maxlength) )
719 {
720 console_print(client, "[AdvancedBans] %L", client, "AB_MAX_BAN_TIME", maxlength);
721 return PLUGIN_HANDLED;
722 }
723
724 if( is_user_connected(find_player(is_ip ? "d" : "c", target_authid)) )
725 {
726 client_cmd(client, "amx_ban ^"%s^" %i ^"%s^"", target_authid, length, reason);
727 return PLUGIN_HANDLED;
728 }
729
730 static unban_time[32];
731 if( length == 0 )
732 {
733 formatex(unban_time, sizeof(unban_time) - 1, "%L", client, "AB_PERMANENT_BAN");
734 }
735 else
736 {
737 GenerateUnbanTime(length, unban_time, sizeof(unban_time) - 1);
738 }
739
740 static admin_name[64], admin_authid[35];
741 get_user_name(client, admin_name, sizeof(admin_name) - 1);
742 get_user_authid(client, admin_authid, sizeof(admin_authid) - 1);
743
744 AddBan(target_name, target_authid, reason, length, unban_time, admin_name, admin_authid);
745
746 PrintBanInformation(client, target_name, target_authid, reason, length, unban_time, "", "", false, false);
747
748 GetBanTime(length, unban_time, sizeof(unban_time) - 1);
749
750 PrintActivity(admin_name, "^x04[AdvancedBans] $name^x01 :^x03 banned %s %s. Reason: %s. Ban Length: %s", is_ip ? "IP" : "SteamID", target_authid, reason, unban_time);
751
752 Log("%s <%s> banned %s <%s> || Reason: ^"%s^" || Ban Length: %s", admin_name, admin_authid, target_name, target_authid, reason, unban_time);
753
754 return PLUGIN_HANDLED;
755}
756
757public CmdUnban(client, level, cid)
758{
759 if( !cmd_access(client, level, cid, 2) ) return PLUGIN_HANDLED;
760
761 static arg[35];
762 read_argv(1, arg, sizeof(arg) - 1);
763
764 #if MAX_BANS > 0
765 static banned_authid[35];
766 for( new i = 0; i < g_total_bans; i++ )
767 {
768 copy(banned_authid, sizeof(banned_authid) - 1, g_steamids[i]);
769
770 if( equal(arg, banned_authid) )
771 {
772 static admin_name[64];
773 get_user_name(client, admin_name, sizeof(admin_name) - 1);
774
775 static name[32], reason[128];
776 copy(name, sizeof(name) - 1, g_names[i]);
777 copy(reason, sizeof(reason) - 1, g_reasons[i]);
778
779 PrintActivity(admin_name, "^x04[AdvancedBans] $name^x01 :^x03 unbanned %s^x01 [%s] [Ban Reason: %s]", name, arg, reason);
780
781 static authid[35];
782 get_user_authid(client, authid, sizeof(authid) - 1);
783
784 Log("%s <%s> unbanned %s <%s> || Ban Reason: ^"%s^"", admin_name, authid, name, arg, reason);
785
786 RemoveBan(i);
787
788 return PLUGIN_HANDLED;
789 }
790 }
791 #else
792 if( TrieKeyExists(g_trie, arg) )
793 {
794 static array_pos;
795 TrieGetCell(g_trie, arg, array_pos);
796
797 static data[BannedData];
798 ArrayGetArray(g_array, array_pos, data);
799
800 static unban_name[32];
801 get_user_name(client, unban_name, sizeof(unban_name) - 1);
802
803 PrintActivity(unban_name, "^x04[AdvancedBans] $name^x01 :^x03 unbanned %s^x01 [%s] [Ban Reason: %s]", data[bd_name], data[bd_steamid], data[bd_reason]);
804
805 static admin_name[64];
806 get_user_name(client, admin_name, sizeof(admin_name) - 1);
807
808 static authid[35];
809 get_user_authid(client, authid, sizeof(authid) - 1);
810
811 Log("%s <%s> unbanned %s <%s> || Ban Reason: ^"%s^"", admin_name, authid, data[bd_name], data[bd_steamid], data[bd_reason]);
812
813 RemoveBan(array_pos, data[bd_steamid]);
814
815 return PLUGIN_HANDLED;
816 }
817 #endif
818
819 console_print(client, "[AdvancedBans] %L", client, "AB_NOT_IN_BAN_LIST", arg);
820
821 return PLUGIN_HANDLED;
822}
823
824public CmdBanList(client, level, cid)
825{
826 if( !cmd_access(client, level, cid, 1) ) return PLUGIN_HANDLED;
827
828 if( !g_total_bans )
829 {
830 console_print(client, "[AdvancedBans] %L", client, "AB_NO_BANS");
831 return PLUGIN_HANDLED;
832 }
833
834 static start;
835
836 if( read_argc() > 1 )
837 {
838 static arg[5];
839 read_argv(1, arg, sizeof(arg) - 1);
840
841 start = min(str_to_num(arg), g_total_bans) - 1;
842 }
843 else
844 {
845 start = 0;
846 }
847
848 new last = min(start + 10, g_total_bans);
849
850 if( client == 0 )
851 {
852 server_cmd("echo ^"%L^"", client, "AB_BAN_LIST_NUM", start + 1, last);
853 }
854 else
855 {
856 client_cmd(client, "echo ^"%L^"", client, "AB_BAN_LIST_NUM", start + 1, last);
857 }
858
859 for( new i = start; i < last; i++ )
860 {
861 #if MAX_BANS <= 0
862 static data[BannedData];
863 ArrayGetArray(g_array, i, data);
864
865 PrintBanInformation(client, data[bd_name], data[bd_steamid], data[bd_reason], data[bd_banlength], data[bd_unbantime], data[bd_admin_name], data[bd_admin_steamid], true, false);
866 #else
867 static name[32], steamid[35], reason[128], banlength, unbantime[32], admin_name[32], admin_steamid[35];
868
869 copy(name, sizeof(name) - 1, g_names[i]);
870 copy(steamid, sizeof(steamid) - 1, g_steamids[i]);
871 copy(reason, sizeof(reason) - 1, g_reasons[i]);
872 banlength = g_banlengths[i];
873 copy(unbantime, sizeof(unbantime) - 1, g_unbantimes[i]);
874 copy(admin_name, sizeof(admin_name) - 1, g_admin_names[i]);
875 copy(admin_steamid, sizeof(admin_steamid) - 1, g_admin_steamids[i]);
876
877 PrintBanInformation(client, name, steamid, reason, banlength, unbantime, admin_name, admin_steamid, true, false);
878 #endif
879 }
880
881 if( ++last < g_total_bans )
882 {
883 if( client == 0 )
884 {
885 server_cmd("echo ^"%L^"", client, "AB_BAN_LIST_NEXT", last);
886 }
887 else
888 {
889 client_cmd(client, "echo ^"%L^"", client, "AB_BAN_LIST_NEXT", last);
890 }
891 }
892
893 return PLUGIN_HANDLED;
894}
895
896public CmdAddBanLimit()
897{
898 if( read_argc() != 3 )
899 {
900 log_amx("amx_addbanlimit was used with incorrect parameters!");
901 log_amx("Usage: amx_addbanlimit <flags> <time in minutes>");
902 return PLUGIN_HANDLED;
903 }
904
905 static arg[16];
906
907 read_argv(1, arg, sizeof(arg) - 1);
908 new flags = read_flags(arg);
909
910 read_argv(2, arg, sizeof(arg) - 1);
911 new minutes = str_to_num(arg);
912
913 #if !defined MAX_BANLIMITS
914 ArrayPushCell(g_maxban_flags, flags);
915 ArrayPushCell(g_maxban_times, minutes);
916 #else
917 if( g_total_maxban_times >= MAX_BANLIMITS )
918 {
919 static notified;
920 if( !notified )
921 {
922 log_amx("The amx_addbanlimit has reached its maximum!");
923 notified = 1;
924 }
925 return PLUGIN_HANDLED;
926 }
927
928 g_maxban_flags[g_total_maxban_times] = flags;
929 g_maxban_times[g_total_maxban_times] = minutes;
930 #endif
931 g_total_maxban_times++;
932
933 return PLUGIN_HANDLED;
934}
935
936public FwdThink(entity)
937{
938 if( entity != g_unban_entity ) return;
939
940 #if defined USING_SQL
941 if( g_total_bans > 0 && !g_loading_bans )
942 #else
943 if( g_total_bans > 0 )
944 #endif
945 {
946 static _hours[5], _minutes[5], _seconds[5], _month[5], _day[5], _year[7];
947 format_time(_hours, sizeof(_hours) - 1, "%H");
948 format_time(_minutes, sizeof(_minutes) - 1, "%M");
949 format_time(_seconds, sizeof(_seconds) - 1, "%S");
950 format_time(_month, sizeof(_month) - 1, "%m");
951 format_time(_day, sizeof(_day) - 1, "%d");
952 format_time(_year, sizeof(_year) - 1, "%Y");
953
954 // c = current
955 // u = unban
956
957 new c_hours = str_to_num(_hours);
958 new c_minutes = str_to_num(_minutes);
959 new c_seconds = str_to_num(_seconds);
960 new c_month = str_to_num(_month);
961 new c_day = str_to_num(_day);
962 new c_year = str_to_num(_year);
963
964 static unban_time[32];
965 static u_hours, u_minutes, u_seconds, u_month, u_day, u_year;
966
967 for( new i = 0; i < g_total_bans; i++ )
968 {
969 #if MAX_BANS <= 0
970 static data[BannedData];
971 ArrayGetArray(g_array, i, data);
972
973 if( data[bd_banlength] == 0 ) continue;
974 #else
975 if( g_banlengths[i] == 0 ) continue;
976 #endif
977
978 #if MAX_BANS <= 0
979 copy(unban_time, sizeof(unban_time) - 1, data[bd_unbantime]);
980 #else
981 copy(unban_time, sizeof(unban_time) - 1, g_unbantimes[i]);
982 #endif
983 replace_all(unban_time, sizeof(unban_time) - 1, ":", " ");
984 replace_all(unban_time, sizeof(unban_time) - 1, "/", " ");
985
986 parse(unban_time,\
987 _hours, sizeof(_hours) - 1,\
988 _minutes, sizeof(_minutes) - 1,\
989 _seconds, sizeof(_seconds) - 1,\
990 _month, sizeof(_month) - 1,\
991 _day, sizeof(_day) - 1,\
992 _year, sizeof(_year) - 1
993 );
994
995 u_hours = str_to_num(_hours);
996 u_minutes = str_to_num(_minutes);
997 u_seconds = str_to_num(_seconds);
998 u_month = str_to_num(_month);
999 u_day = str_to_num(_day);
1000 u_year = str_to_num(_year);
1001
1002 if( u_year < c_year
1003 || u_year == c_year && u_month < c_month
1004 || u_year == c_year && u_month == c_month && u_day < c_day
1005 || u_year == c_year && u_month == c_month && u_day == c_day && u_hours < c_hours
1006 || u_year == c_year && u_month == c_month && u_day == c_day && u_hours == c_hours && u_minutes < c_minutes
1007 || u_year == c_year && u_month == c_month && u_day == c_day && u_hours == c_hours && u_minutes == c_minutes && u_seconds <= c_seconds )
1008 {
1009 #if MAX_BANS <= 0
1010 Log("Ban time is up for: %s [%s]", data[bd_name], data[bd_steamid]);
1011
1012 Print("^x04[AdvancedBans]^x03 %s^x01[^x04%s^x01]^x03 ban time is up!^x01 [Ban Reason: %s]", data[bd_name], data[bd_steamid], data[bd_reason]);
1013
1014 RemoveBan(i, data[bd_steamid]);
1015 #else
1016 Log("Ban time is up for: %s [%s]", g_names[i], g_steamids[i]);
1017
1018 Print("^x04[AdvancedBans]^x03 %s^x01[^x04%s^x01]^x03 ban time is up!^x01 [Ban Reason: %s]", g_names[i], g_steamids[i], g_reasons[i]);
1019
1020 RemoveBan(i);
1021 #endif
1022
1023 i--; // current pos was replaced with another ban, so we need to check it again.
1024 }
1025 }
1026 }
1027
1028 entity_set_float(g_unban_entity, EV_FL_nextthink, get_gametime() + get_pcvar_float(ab_unbancheck));
1029}
1030
1031public TaskDisconnectPlayer(client)
1032{
1033 server_cmd("kick #%i ^"You are banned from this server. Check your console^"", get_user_userid(client));
1034}
1035
1036AddBan(const target_name[], const target_steamid[], const reason[], const length, const unban_time[], const admin_name[], const admin_steamid[])
1037{
1038 #if MAX_BANS > 0
1039 if( g_total_bans == MAX_BANS )
1040 {
1041 log_amx("Ban list is full! (%i)", g_total_bans);
1042 return;
1043 }
1044 #endif
1045
1046 #if defined USING_SQL
1047 static target_name2[32], reason2[128], admin_name2[32];
1048 MakeStringSQLSafe(target_name, target_name2, sizeof(target_name2) - 1);
1049 MakeStringSQLSafe(reason, reason2, sizeof(reason2) - 1);
1050 MakeStringSQLSafe(admin_name, admin_name2, sizeof(admin_name2) - 1);
1051
1052 static query[512];
1053 formatex(query, sizeof(query) - 1,\
1054 "INSERT INTO `%s` (`%s`, `%s`, `%s`, `%s`, `%s`, `%s`, `%s`) VALUES ('%s', '%s', '%i', '%s', '%s', '%s', '%s');",\
1055 TABLE_NAME, KEY_NAME, KEY_STEAMID, KEY_BANLENGTH, KEY_UNBANTIME, KEY_REASON, KEY_ADMIN_NAME, KEY_ADMIN_STEAMID,\
1056 target_name2, target_steamid, length, unban_time, reason2, admin_name2, admin_steamid
1057 );
1058
1059 SQL_ThreadQuery(g_sql_tuple, "QueryAddBan", query);
1060 #else
1061 new f = fopen(g_ban_file, "a+");
1062
1063 fprintf(f, "^"%s^" ^"%s^" %i ^"%s^" ^"%s^" ^"%s^" ^"%s^"^n",\
1064 target_steamid,\
1065 target_name,\
1066 length,\
1067 unban_time,\
1068 reason,\
1069 admin_name,\
1070 admin_steamid
1071 );
1072
1073 fclose(f);
1074 #endif
1075
1076 #if MAX_BANS <= 0
1077 static data[BannedData];
1078 copy(data[bd_name], sizeof(data[bd_name]) - 1, target_name);
1079 copy(data[bd_steamid], sizeof(data[bd_steamid]) - 1, target_steamid);
1080 data[bd_banlength] = length;
1081 copy(data[bd_unbantime], sizeof(data[bd_unbantime]) - 1, unban_time);
1082 copy(data[bd_reason], sizeof(data[bd_reason]) - 1, reason);
1083 copy(data[bd_admin_name], sizeof(data[bd_admin_name]) - 1, admin_name);
1084 copy(data[bd_admin_steamid], sizeof(data[bd_admin_steamid]) - 1, admin_steamid);
1085
1086 TrieSetCell(g_trie, target_steamid, g_total_bans);
1087 ArrayPushArray(g_array, data);
1088 #else
1089 copy(g_names[g_total_bans], sizeof(g_names[]) - 1, target_name);
1090 copy(g_steamids[g_total_bans], sizeof(g_steamids[]) - 1, target_steamid);
1091 g_banlengths[g_total_bans] = length;
1092 copy(g_unbantimes[g_total_bans], sizeof(g_unbantimes[]) - 1, unban_time);
1093 copy(g_reasons[g_total_bans], sizeof(g_reasons[]) - 1, reason);
1094 copy(g_admin_names[g_total_bans], sizeof(g_admin_names[]) - 1, admin_name);
1095 copy(g_admin_steamids[g_total_bans], sizeof(g_admin_steamids[]) - 1, admin_steamid);
1096 #endif
1097
1098 g_total_bans++;
1099
1100 #if MAX_BANS > 0
1101 if( g_total_bans == MAX_BANS )
1102 {
1103 log_amx("Ban list is full! (%i)", g_total_bans);
1104 }
1105 #endif
1106}
1107
1108#if defined USING_SQL
1109public QueryAddBan(failstate, Handle:query, error[], errcode, data[], datasize, Float:queuetime)
1110{
1111 if( failstate == TQUERY_CONNECT_FAILED )
1112 {
1113 set_fail_state("Could not connect to database.");
1114 }
1115 else if( failstate == TQUERY_QUERY_FAILED )
1116 {
1117 set_fail_state("Query failed.");
1118 }
1119 else if( errcode )
1120 {
1121 log_amx("Error on query: %s", error);
1122 }
1123 else
1124 {
1125 // Yay, ban was added! We can all rejoice!
1126 }
1127}
1128
1129public QueryDeleteBan(failstate, Handle:query, error[], errcode, data[], datasize, Float:queuetime)
1130{
1131 if( failstate == TQUERY_CONNECT_FAILED )
1132 {
1133 set_fail_state("Could not connect to database.");
1134 }
1135 else if( failstate == TQUERY_QUERY_FAILED )
1136 {
1137 set_fail_state("Query failed.");
1138 }
1139 else if( errcode )
1140 {
1141 log_amx("Error on query: %s", error);
1142 }
1143 else
1144 {
1145 // Yay, ban was deleted! We can all rejoice!
1146 }
1147}
1148
1149public QueryLoadBans(failstate, Handle:query, error[], errcode, data[], datasize, Float:queuetime)
1150{
1151 if( failstate == TQUERY_CONNECT_FAILED )
1152 {
1153 set_fail_state("Could not connect to database.");
1154 }
1155 else if( failstate == TQUERY_QUERY_FAILED )
1156 {
1157 set_fail_state("Query failed.");
1158 }
1159 else if( errcode )
1160 {
1161 log_amx("Error on query: %s", error);
1162 }
1163 else
1164 {
1165 if( SQL_NumResults(query) )
1166 {
1167 #if MAX_BANS <= 0
1168 static data[BannedData];
1169 while( SQL_MoreResults(query) )
1170 #else
1171 while( SQL_MoreResults(query) && g_total_bans < MAX_BANS )
1172 #endif
1173 {
1174 #if MAX_BANS <= 0
1175 SQL_ReadResult(query, 0, data[bd_name], sizeof(data[bd_name]) - 1);
1176 SQL_ReadResult(query, 1, data[bd_steamid], sizeof(data[bd_steamid]) - 1);
1177 data[bd_banlength] = SQL_ReadResult(query, 2);
1178 SQL_ReadResult(query, 3, data[bd_unbantime], sizeof(data[bd_unbantime]) - 1);
1179 SQL_ReadResult(query, 4, data[bd_reason], sizeof(data[bd_reason]) - 1);
1180 SQL_ReadResult(query, 5, data[bd_admin_name], sizeof(data[bd_admin_name]) - 1);
1181 SQL_ReadResult(query, 6, data[bd_admin_steamid], sizeof(data[bd_admin_steamid]) - 1);
1182
1183 ArrayPushArray(g_array, data);
1184 TrieSetCell(g_trie, data[bd_steamid], g_total_bans);
1185 #else
1186 SQL_ReadResult(query, 0, g_names[g_total_bans], sizeof(g_names[]) - 1);
1187 SQL_ReadResult(query, 1, g_steamids[g_total_bans], sizeof(g_steamids[]) - 1);
1188 g_banlengths[g_total_bans] = SQL_ReadResult(query, 2);
1189 SQL_ReadResult(query, 3, g_unbantimes[g_total_bans], sizeof(g_unbantimes[]) - 1);
1190 SQL_ReadResult(query, 4, g_reasons[g_total_bans], sizeof(g_reasons[]) - 1);
1191 SQL_ReadResult(query, 5, g_admin_names[g_total_bans], sizeof(g_admin_names[]) - 1);
1192 SQL_ReadResult(query, 6, g_admin_steamids[g_total_bans], sizeof(g_admin_steamids[]) - 1);
1193 #endif
1194
1195 g_total_bans++;
1196
1197 SQL_NextRow(query);
1198 }
1199 }
1200
1201 set_task(RELOAD_BANS_INTERVAL, "LoadBans");
1202
1203 g_loading_bans = false;
1204 }
1205}
1206#endif
1207
1208#if MAX_BANS > 0
1209RemoveBan(remove)
1210{
1211 #if defined USING_SQL
1212 static query[128];
1213 formatex(query, sizeof(query) - 1,\
1214 "DELETE FROM `%s` WHERE `%s` = '%s';",\
1215 TABLE_NAME, KEY_STEAMID, g_steamids[remove]
1216 );
1217
1218 SQL_ThreadQuery(g_sql_tuple, "QueryDeleteBan", query);
1219 #endif
1220
1221 for( new i = remove; i < g_total_bans; i++ )
1222 {
1223 if( (i + 1) == g_total_bans )
1224 {
1225 copy(g_names[i], sizeof(g_names[]) - 1, "");
1226 copy(g_steamids[i], sizeof(g_steamids[]) - 1, "");
1227 g_banlengths[i] = 0;
1228 copy(g_unbantimes[i], sizeof(g_unbantimes[]) - 1, "");
1229 copy(g_reasons[i], sizeof(g_reasons[]) - 1, "");
1230 copy(g_admin_names[i], sizeof(g_admin_names[]) - 1, "");
1231 copy(g_admin_steamids[i], sizeof(g_admin_steamids[]) - 1, "");
1232 }
1233 else
1234 {
1235 copy(g_names[i], sizeof(g_names[]) - 1, g_names[i + 1]);
1236 copy(g_steamids[i], sizeof(g_steamids[]) - 1, g_steamids[i + 1]);
1237 g_banlengths[i] = g_banlengths[i + 1];
1238 copy(g_unbantimes[i], sizeof(g_unbantimes[]) - 1, g_unbantimes[i + 1]);
1239 copy(g_reasons[i], sizeof(g_reasons[]) - 1, g_reasons[i + 1]);
1240 copy(g_admin_names[i], sizeof(g_admin_names[]) - 1, g_admin_names[i + 1]);
1241 copy(g_admin_steamids[i], sizeof(g_admin_steamids[]) - 1, g_admin_steamids[i + 1]);
1242 }
1243 }
1244
1245 g_total_bans--;
1246
1247 #if !defined USING_SQL
1248 new f = fopen(g_ban_file, "wt");
1249
1250 static name[32], steamid[35], banlength, unbantime[32], reason[128], admin_name[32], admin_steamid[35];
1251 for( new i = 0; i < g_total_bans; i++ )
1252 {
1253 copy(name, sizeof(name) - 1, g_names[i]);
1254 copy(steamid, sizeof(steamid) - 1, g_steamids[i]);
1255 banlength = g_banlengths[i];
1256 copy(unbantime, sizeof(unbantime) - 1, g_unbantimes[i]);
1257 copy(reason, sizeof(reason) - 1, g_reasons[i]);
1258 copy(admin_name, sizeof(admin_name) - 1, g_admin_names[i]);
1259 copy(admin_steamid, sizeof(admin_steamid) - 1, g_admin_steamids[i]);
1260
1261 fprintf(f, "^"%s^" ^"%s^" %i ^"%s^" ^"%s^" ^"%s^" ^"%s^"^n",\
1262 steamid,\
1263 name,\
1264 banlength,\
1265 unbantime,\
1266 reason,\
1267 admin_name,\
1268 admin_steamid
1269 );
1270 }
1271
1272 fclose(f);
1273 #endif
1274}
1275#else
1276RemoveBan(pos, const authid[])
1277{
1278 TrieDeleteKey(g_trie, authid);
1279 ArrayDeleteItem(g_array, pos);
1280
1281 g_total_bans--;
1282
1283 #if defined USING_SQL
1284 static query[128];
1285 formatex(query, sizeof(query) - 1,\
1286 "DELETE FROM `%s` WHERE `%s` = '%s';",\
1287 TABLE_NAME, KEY_STEAMID, authid
1288 );
1289
1290 SQL_ThreadQuery(g_sql_tuple, "QueryDeleteBan", query);
1291
1292 new data[BannedData];
1293 for( new i = 0; i < g_total_bans; i++ )
1294 {
1295 ArrayGetArray(g_array, i, data);
1296 TrieSetCell(g_trie, data[bd_steamid], i);
1297 }
1298 #else
1299 new f = fopen(g_ban_file, "wt");
1300
1301 new data[BannedData];
1302 for( new i = 0; i < g_total_bans; i++ )
1303 {
1304 ArrayGetArray(g_array, i, data);
1305 TrieSetCell(g_trie, data[bd_steamid], i);
1306
1307 fprintf(f, "^"%s^" ^"%s^" %i ^"%s^" ^"%s^" ^"%s^" ^"%s^"^n",\
1308 data[bd_steamid],\
1309 data[bd_name],\
1310 data[bd_banlength],\
1311 data[bd_unbantime],\
1312 data[bd_reason],\
1313 data[bd_admin_name],\
1314 data[bd_admin_steamid]
1315 );
1316 }
1317
1318 fclose(f);
1319 #endif
1320}
1321#endif
1322
1323#if defined KEEP_DEFAULT_BANS
1324LoadOldBans(filename[])
1325{
1326 if( file_exists(filename) )
1327 {
1328 new f = fopen(filename, "rt");
1329
1330 static data[96];
1331 static command[10], minutes[10], steamid[35], length, unban_time[32];
1332
1333 while( !feof(f) )
1334 {
1335 fgets(f, data, sizeof(data) - 1);
1336 if( !data[0] ) continue;
1337
1338 parse(data, command, sizeof(command) - 1, minutes, sizeof(minutes) - 1, steamid, sizeof(steamid) - 1);
1339 if( filename[0] == 'b' && !equali(command, "banid") || filename[0] == 'l' && !equali(command, "addip") ) continue;
1340
1341 length = str_to_num(minutes);
1342 GenerateUnbanTime(length, unban_time, sizeof(unban_time) - 1);
1343
1344 AddBan("", steamid, "", length, unban_time, "", "");
1345 }
1346
1347 fclose(f);
1348
1349 static filename2[32];
1350
1351 // copy current
1352 copy(filename2, sizeof(filename2) - 1, filename);
1353
1354 // cut off at the "."
1355 // banned.cfg = banned
1356 // listip.cfg = listip
1357 filename2[containi(filename2, ".")] = 0;
1358
1359 // add 2.cfg
1360 // banned = banned2.cfg
1361 // listip = listip2.cfg
1362 add(filename2, sizeof(filename2) - 1, "2.cfg");
1363
1364 // rename file so that it isnt loaded again
1365 while( !rename_file(filename, filename2, 1) ) { }
1366 }
1367}
1368#endif
1369
1370public LoadBans()
1371{
1372 if( g_total_bans )
1373 {
1374 #if MAX_BANS <= 0
1375 TrieClear(g_trie);
1376 ArrayClear(g_array);
1377 #endif
1378
1379 g_total_bans = 0;
1380 }
1381
1382 #if defined USING_SQL
1383 static query[128];
1384 formatex(query, sizeof(query) - 1,\
1385 "SELECT * FROM `%s`;",\
1386 TABLE_NAME
1387 );
1388
1389 SQL_ThreadQuery(g_sql_tuple, "QueryLoadBans", query);
1390
1391 g_loading_bans = true;
1392 #else
1393 if( file_exists(g_ban_file) )
1394 {
1395 new f = fopen(g_ban_file, "rt");
1396
1397 static filedata[512], length[10];
1398
1399 #if MAX_BANS <= 0
1400 static data[BannedData];
1401 while( !feof(f) )
1402 #else
1403 while( !feof(f) && g_total_bans < MAX_BANS )
1404 #endif
1405 {
1406 fgets(f, filedata, sizeof(filedata) - 1);
1407
1408 if( !filedata[0] ) continue;
1409
1410 #if MAX_BANS <= 0
1411 parse(filedata,\
1412 data[bd_steamid], sizeof(data[bd_steamid]) - 1,\
1413 data[bd_name], sizeof(data[bd_name]) - 1,\
1414 length, sizeof(length) - 1,\
1415 data[bd_unbantime], sizeof(data[bd_unbantime]) - 1,\
1416 data[bd_reason], sizeof(data[bd_reason]) - 1,\
1417 data[bd_admin_name], sizeof(data[bd_admin_name]) - 1,\
1418 data[bd_admin_steamid], sizeof(data[bd_admin_steamid]) - 1
1419 );
1420
1421 data[bd_banlength] = str_to_num(length);
1422
1423 ArrayPushArray(g_array, data);
1424 TrieSetCell(g_trie, data[bd_steamid], g_total_bans);
1425 #else
1426 static steamid[35], name[32], unbantime[32], reason[128], admin_name[32], admin_steamid[35];
1427
1428 parse(filedata,\
1429 steamid, sizeof(steamid) - 1,\
1430 name, sizeof(name) - 1,\
1431 length, sizeof(length) - 1,\
1432 unbantime, sizeof(unbantime) - 1,\
1433 reason, sizeof(reason) - 1,\
1434 admin_name, sizeof(admin_name) - 1,\
1435 admin_steamid, sizeof(admin_steamid) - 1
1436 );
1437
1438 copy(g_names[g_total_bans], sizeof(g_names[]) - 1, name);
1439 copy(g_steamids[g_total_bans], sizeof(g_steamids[]) - 1, steamid);
1440 g_banlengths[g_total_bans] = str_to_num(length);
1441 copy(g_unbantimes[g_total_bans], sizeof(g_unbantimes[]) - 1, unbantime);
1442 copy(g_reasons[g_total_bans], sizeof(g_reasons[]) - 1, reason);
1443 copy(g_admin_names[g_total_bans], sizeof(g_admin_names[]) - 1, admin_name);
1444 copy(g_admin_steamids[g_total_bans], sizeof(g_admin_steamids[]) - 1, admin_steamid);
1445 #endif
1446
1447 g_total_bans++;
1448 }
1449
1450 fclose(f);
1451 }
1452 #endif
1453
1454 // load these after, so when they are added to the file with AddBan(), they aren't loaded again from above.
1455
1456 #if defined KEEP_DEFAULT_BANS
1457 LoadOldBans("banned.cfg");
1458 LoadOldBans("listip.cfg");
1459 #endif
1460}
1461
1462#if defined USING_SQL
1463MakeStringSQLSafe(const input[], output[], len)
1464{
1465 copy(output, len, input);
1466 replace_all(output, len, "'", "*");
1467 replace_all(output, len, "^"", "*");
1468 replace_all(output, len, "`", "*");
1469}
1470#endif
1471
1472GetBanTime(const bantime, length[], len)
1473{
1474 new minutes = bantime;
1475 new hours = 0;
1476 new days = 0;
1477
1478 while( minutes >= 60 )
1479 {
1480 minutes -= 60;
1481 hours++;
1482 }
1483
1484 while( hours >= 24 )
1485 {
1486 hours -= 24;
1487 days++;
1488 }
1489
1490 new bool:add_before;
1491 if( minutes )
1492 {
1493 formatex(length, len, "%i minute%s", minutes, minutes == 1 ? "" : "s");
1494
1495 add_before = true;
1496 }
1497 if( hours )
1498 {
1499 if( add_before )
1500 {
1501 format(length, len, "%i hour%s, %s", hours, hours == 1 ? "" : "s", length);
1502 }
1503 else
1504 {
1505 formatex(length, len, "%i hour%s", hours, hours == 1 ? "" : "s");
1506
1507 add_before = true;
1508 }
1509 }
1510 if( days )
1511 {
1512 if( add_before )
1513 {
1514 format(length, len, "%i day%s, %s", days, days == 1 ? "" : "s", length);
1515 }
1516 else
1517 {
1518 formatex(length, len, "%i day%s", days, days == 1 ? "" : "s");
1519
1520 add_before = true;
1521 }
1522 }
1523 if( !add_before )
1524 {
1525 // minutes, hours, and days = 0
1526 // assume permanent ban
1527 copy(length, len, "Permanent Ban");
1528 }
1529}
1530
1531GenerateUnbanTime(const bantime, unban_time[], len)
1532{
1533 static _hours[5], _minutes[5], _seconds[5], _month[5], _day[5], _year[7];
1534 format_time(_hours, sizeof(_hours) - 1, "%H");
1535 format_time(_minutes, sizeof(_minutes) - 1, "%M");
1536 format_time(_seconds, sizeof(_seconds) - 1, "%S");
1537 format_time(_month, sizeof(_month) - 1, "%m");
1538 format_time(_day, sizeof(_day) - 1, "%d");
1539 format_time(_year, sizeof(_year) - 1, "%Y");
1540
1541 new hours = str_to_num(_hours);
1542 new minutes = str_to_num(_minutes);
1543 new seconds = str_to_num(_seconds);
1544 new month = str_to_num(_month);
1545 new day = str_to_num(_day);
1546 new year = str_to_num(_year);
1547
1548 minutes += bantime;
1549
1550 while( minutes >= 60 )
1551 {
1552 minutes -= 60;
1553 hours++;
1554 }
1555
1556 while( hours >= 24 )
1557 {
1558 hours -= 24;
1559 day++;
1560 }
1561
1562 new max_days = GetDaysInMonth(month, year);
1563 while( day > max_days )
1564 {
1565 day -= max_days;
1566 month++;
1567 }
1568
1569 while( month > 12 )
1570 {
1571 month -= 12;
1572 year++;
1573 }
1574
1575 formatex(unban_time, len, "%i:%02i:%02i %i/%i/%i", hours, minutes, seconds, month, day, year);
1576}
1577
1578GetDaysInMonth(month, year=0)
1579{
1580 switch( month )
1581 {
1582 case 1: return 31; // january
1583 case 2: return ((year % 4) == 0) ? 29 : 28; // february
1584 case 3: return 31; // march
1585 case 4: return 30; // april
1586 case 5: return 31; // may
1587 case 6: return 30; // june
1588 case 7: return 31; // july
1589 case 8: return 31; // august
1590 case 9: return 30; // september
1591 case 10: return 31; // october
1592 case 11: return 30; // november
1593 case 12: return 31; // december
1594 }
1595
1596 return 30;
1597}
1598
1599GetTargetFlags(client)
1600{
1601 static const flags_no_immunity = (CMDTARGET_ALLOW_SELF|CMDTARGET_NO_BOTS);
1602 static const flags_immunity = (CMDTARGET_ALLOW_SELF|CMDTARGET_NO_BOTS|CMDTARGET_OBEY_IMMUNITY);
1603
1604 switch( get_pcvar_num(ab_immunity) )
1605 {
1606 case 1: return flags_immunity;
1607 case 2: return access(client, ADMIN_IMMUNITY) ? flags_no_immunity : flags_immunity;
1608 }
1609
1610 return flags_no_immunity;
1611}
1612
1613GetMaxBanTime(client)
1614{
1615 if( !g_total_maxban_times ) return 0;
1616
1617 new flags = get_user_flags(client);
1618
1619 for( new i = 0; i < g_total_maxban_times; i++ )
1620 {
1621 #if !defined MAX_BANLIMITS
1622 if( flags & ArrayGetCell(g_maxban_flags, i) )
1623 {
1624 return ArrayGetCell(g_maxban_times, i);
1625 }
1626 #else
1627 if( flags & g_maxban_flags[i] )
1628 {
1629 return g_maxban_times[i];
1630 }
1631 #endif
1632 }
1633
1634 return 0;
1635}
1636
1637PrintBanInformation(client, const target_name[], const target_authid[], const reason[], const length, const unban_time[], const admin_name[], const admin_authid[], bool:show_admin, bool:show_website)
1638{
1639 static website[64], ban_length[64];
1640 if( client == 0 )
1641 {
1642 server_print("************************************************");
1643 server_print("%L", client, "AB_BAN_INFORMATION");
1644 server_print("%L: %s", client, "AB_NAME", target_name);
1645 server_print("%L: %s", client, IsValidAuthid(target_authid) ? "AB_STEAMID" : "AB_IP", target_authid);
1646 server_print("%L: %s", client, "AB_REASON", reason);
1647 if( length > 0 )
1648 {
1649 GetBanTime(length, ban_length, sizeof(ban_length) - 1);
1650 server_print("%L: %s", client, "AB_BAN_LENGTH", ban_length);
1651 }
1652 server_print("%L: %s", client, "AB_UNBAN_TIME", unban_time);
1653 if( show_admin )
1654 {
1655 server_print("%L: %s", client, "AB_ADMIN_NAME", admin_name);
1656 server_print("%L: %s", client, "AB_ADMIN_STEAMID", admin_authid);
1657 }
1658 if( show_website )
1659 {
1660 get_pcvar_string(ab_website, website, sizeof(website) - 1);
1661 if( website[0] )
1662 {
1663 server_print("");
1664 server_print("%L", client, "AB_WEBSITE");
1665 server_print("%s", website);
1666 }
1667 }
1668 server_print("************************************************");
1669 }
1670 else
1671 {
1672 client_cmd(client, "echo ^"************************************************^"");
1673 client_cmd(client, "echo ^"%L^"", client, "AB_BAN_INFORMATION");
1674 client_cmd(client, "echo ^"%L: %s^"", client, "AB_NAME", target_name);
1675 client_cmd(client, "echo ^"%L: %s^"", client, IsValidAuthid(target_authid) ? "AB_STEAMID" : "AB_IP", target_authid);
1676 client_cmd(client, "echo ^"%L: %s^"", client, "AB_REASON", reason);
1677 if( length > 0 )
1678 {
1679 GetBanTime(length, ban_length, sizeof(ban_length) - 1);
1680 client_cmd(client, "echo ^"%L: %s^"", client, "AB_BAN_LENGTH", ban_length);
1681 }
1682 client_cmd(client, "echo ^"%L: %s^"", client, "AB_UNBAN_TIME", unban_time);
1683 if( show_admin )
1684 {
1685 client_cmd(client, "echo ^"%L: %s^"", client, "AB_ADMIN_NAME", admin_name);
1686 client_cmd(client, "echo ^"%L: %s^"", client, "AB_ADMIN_STEAMID", admin_authid);
1687 }
1688 if( show_website )
1689 {
1690 get_pcvar_string(ab_website, website, sizeof(website) - 1);
1691 if( website[0] )
1692 {
1693 client_cmd(client, "echo ^"^"");
1694 client_cmd(client, "echo ^"%L^"", client, "AB_WEBSITE");
1695 client_cmd(client, "echo ^"%s^"", website);
1696 }
1697 }
1698 client_cmd(client, "echo ^"************************************************^"");
1699 }
1700}
1701
1702PrintActivity(const admin_name[], const message_fmt[], any:...)
1703{
1704 if( !get_playersnum() ) return;
1705
1706 new activity = get_pcvar_num(amx_show_activity);
1707 if( !(0 <= activity <= 5) )
1708 {
1709 set_pcvar_num(amx_show_activity, (activity = 2));
1710 }
1711
1712 static message[192], temp[192];
1713 vformat(message, sizeof(message) - 1, message_fmt, 3);
1714
1715 for( new client = 1; client <= g_max_clients; client++ )
1716 {
1717 if( !is_user_connected(client) ) continue;
1718
1719 switch( is_user_admin(client) ? g_admin_activity[activity] : g_normal_activity[activity] )
1720 {
1721 case ACTIVITY_NONE:
1722 {
1723
1724 }
1725 case ACTIVITY_HIDE:
1726 {
1727 copy(temp, sizeof(temp) - 1, message);
1728 replace(temp, sizeof(temp) - 1, "$name", "ADMIN");
1729
1730 message_begin(MSG_ONE_UNRELIABLE, g_msgid_SayText, _, client);
1731 write_byte(client);
1732 write_string(temp);
1733 message_end();
1734 }
1735 case ACTIVITY_SHOW:
1736 {
1737 copy(temp, sizeof(temp) - 1, message);
1738 replace(temp, sizeof(temp) - 1, "$name", admin_name);
1739
1740 message_begin(MSG_ONE_UNRELIABLE, g_msgid_SayText, _, client);
1741 write_byte(client);
1742 write_string(temp);
1743 message_end();
1744 }
1745 }
1746 }
1747}
1748
1749Print(const message_fmt[], any:...)
1750{
1751 if( !get_playersnum() ) return;
1752
1753 static message[192];
1754 vformat(message, sizeof(message) - 1, message_fmt, 2);
1755
1756 for( new client = 1; client <= g_max_clients; client++ )
1757 {
1758 if( !is_user_connected(client) ) continue;
1759
1760 message_begin(MSG_ONE_UNRELIABLE, g_msgid_SayText, _, client);
1761 write_byte(client);
1762 write_string(message);
1763 message_end();
1764 }
1765}
1766
1767Log(const message_fmt[], any:...)
1768{
1769 static message[256];
1770 vformat(message, sizeof(message) - 1, message_fmt, 2);
1771
1772 static filename[96];
1773 #if defined HISTORY_ONE_FILE
1774 if( !filename[0] )
1775 {
1776 get_basedir(filename, sizeof(filename) - 1);
1777 add(filename, sizeof(filename) - 1, "/logs/ban_history.log");
1778 }
1779 #else
1780 static dir[64];
1781 if( !dir[0] )
1782 {
1783 get_basedir(dir, sizeof(dir) - 1);
1784 add(dir, sizeof(dir) - 1, "/logs");
1785 }
1786
1787 format_time(filename, sizeof(filename) - 1, "%m%d%Y");
1788 format(filename, sizeof(filename) - 1, "%s/BAN_HISTORY_%s.log", dir, filename);
1789 #endif
1790
1791 log_amx("%s", message);
1792 log_to_file(filename, "%s", message);
1793}
1794/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
1795*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1033\\ f0\\ fs16 \n\\ par }
1796*/