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