· 6 years ago · Sep 21, 2019, 01:34 PM
1#pragma semicolon 1
2
3#include <sourcemod>
4#include <sourcebanspp>
5
6#undef REQUIRE_PLUGIN
7#include <adminmenu>
8#tryinclude <updater>
9
10#pragma newdecls required
11
12#define SB_VERSION "1.0"
13
14#if defined _updater_included
15#define UPDATE_URL "https://sbpp.github.io/updater/updatefile.txt"
16#endif
17
18//GLOBAL DEFINES
19#define YELLOW 0x01
20#define NAMECOLOR 0x02
21#define TEAMCOLOR 0x03
22#define GREEN 0x04
23
24#define DISABLE_ADDBAN 1
25#define DISABLE_UNBAN 2
26
27#define FLAG_LETTERS_SIZE 26
28
29//#define DEBUG
30
31enum State/* ConfigState */
32{
33 ConfigStateNone = 0,
34 ConfigStateConfig,
35 ConfigStateReasons,
36 ConfigStateHacking,
37 ConfigStateTime
38}
39
40State ConfigState;
41
42#define Prefix "[SourceBans++] "
43
44/* Admin Stuff*/
45AdminCachePart loadPart;
46
47AdminFlag g_FlagLetters[FLAG_LETTERS_SIZE];
48
49/* Cvar handle*/
50ConVar
51 CvarHostIp
52 , CvarPort;
53
54/* Database handle */
55Database DB;
56Database SQLiteDB;
57
58char
59 ServerIp[24]
60 , ServerPort[7]
61 , DatabasePrefix[10] = "sb"
62 , WebsiteAddress[128]
63 , groupsLoc[128] /* Admin KeyValues */
64 , adminsLoc[128]
65 , overridesLoc[128]
66 , logFile[256]; /* Log Stuff */
67
68float RetryTime = 15.0;
69
70bool
71 loadAdmins /* Admin Stuff*/
72 , loadGroups
73 , loadOverrides
74 , LateLoaded
75 , AutoAdd
76 , g_bConnecting = false
77 , requireSiteLogin = false /* Require a lastvisited from SB site */
78 , backupConfig = true
79 , enableAdmins = true
80 , PlayerStatus[MAXPLAYERS + 1]; /* Player ban check status */
81
82int
83 g_BanTarget[MAXPLAYERS + 1] = { -1, ... }
84 , g_BanTime[MAXPLAYERS + 1] = { -1, ... }
85 , curLoading
86 , serverID = -1
87 , ProcessQueueTime = 5
88 , g_ownReasons[MAXPLAYERS + 1] = { false, ... } /* Own Chat Reason */
89 , CommandDisable; /* Disable of addban and unban */
90
91
92SMCParser ConfigParser;
93
94Handle
95 g_hFwd_OnBanAdded
96 , g_hFwd_OnReportAdded
97 , PlayerRecheck[MAXPLAYERS + 1] = { INVALID_HANDLE, ... }; /* Timer handle */
98
99DataPack PlayerDataPack[MAXPLAYERS + 1] = { null, ... };
100
101TopMenu hTopMenu = null;
102
103Menu
104 TimeMenuHandle
105 , ReasonMenuHandle
106 , HackingMenuHandle;
107
108public Plugin myinfo =
109{
110 name = "[CSGO] SourceBans - Main",
111 author = "SourceBans Development Team, SourceBans++ Dev Team, edited by somebody.",
112 description = "SourceBans - Main",
113 version = SB_VERSION,
114 url = "http://sourcemod.net"
115};
116
117public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
118{
119 RegPluginLibrary("sourcebans++");
120
121 CreateNative("SBBanPlayer", Native_SBBanPlayer);
122 CreateNative("SBPP_BanPlayer", Native_SBBanPlayer);
123 CreateNative("SBPP_ReportPlayer", Native_SBReportPlayer);
124
125 g_hFwd_OnBanAdded = CreateGlobalForward("SBPP_OnBanPlayer", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_String);
126 g_hFwd_OnReportAdded = CreateGlobalForward("SBPP_OnReportPlayer", ET_Ignore, Param_Cell, Param_Cell, Param_String);
127
128 LateLoaded = late;
129
130 return APLRes_Success;
131}
132
133public void OnPluginStart()
134{
135 LoadTranslations("common.phrases");
136 LoadTranslations("plugin.basecommands");
137 LoadTranslations("sbpp_main.phrases");
138 LoadTranslations("basebans.phrases");
139 loadAdmins = loadGroups = loadOverrides = false;
140
141 CvarHostIp = FindConVar("hostip");
142 CvarPort = FindConVar("hostport");
143 CreateConVar("sb_version", SB_VERSION, _, FCVAR_SPONLY | FCVAR_REPLICATED | FCVAR_NOTIFY);
144 RegServerCmd("sm_rehash", sm_rehash, "Reload SQL admins");
145 RegAdminCmd("sm_ban", CommandBan, ADMFLAG_BAN, "sm_ban <#userid|name> <minutes|0> [reason]", "sourcebans");
146 RegAdminCmd("sm_banip", CommandBanIp, ADMFLAG_BAN, "sm_banip <ip|#userid|name> <time> [reason]", "sourcebans");
147 RegAdminCmd("sm_addban", CommandAddBan, ADMFLAG_RCON, "sm_addban <time> <steamid> [reason]", "sourcebans");
148 RegAdminCmd("sm_unban", CommandUnban, ADMFLAG_UNBAN, "sm_unban <steamid|ip> [reason]", "sourcebans");
149 RegAdminCmd("sb_reload",
150 _CmdReload,
151 ADMFLAG_RCON,
152 "Reload sourcebans config and ban reason menu options",
153 "sourcebans");
154
155 RegConsoleCmd("say", ChatHook);
156 RegConsoleCmd("say_team", ChatHook);
157
158 if ((TimeMenuHandle = CreateMenu(MenuHandler_BanTimeList, MenuAction_Select|MenuAction_Cancel|MenuAction_DrawItem)) != INVALID_HANDLE)
159 {
160 TimeMenuHandle.Pagination = 8;
161 TimeMenuHandle.ExitBackButton = true;
162 }
163
164 if ((ReasonMenuHandle = new Menu(ReasonSelected)) != INVALID_HANDLE)
165 {
166 ReasonMenuHandle.Pagination = 8;
167 ReasonMenuHandle.ExitBackButton = true;
168 }
169
170 if ((HackingMenuHandle = new Menu(HackingSelected)) != INVALID_HANDLE)
171 {
172 HackingMenuHandle.Pagination = 8;
173 HackingMenuHandle.ExitBackButton = true;
174 }
175
176 g_FlagLetters = CreateFlagLetters();
177
178 BuildPath(Path_SM, logFile, sizeof(logFile), "logs/sourcebans.log");
179 g_bConnecting = true;
180
181 // Catch config error and show link to FAQ
182 if (!SQL_CheckConfig("sourcebans"))
183 {
184 if (ReasonMenuHandle != INVALID_HANDLE)
185 CloseHandle(ReasonMenuHandle);
186 if (HackingMenuHandle != INVALID_HANDLE)
187 CloseHandle(HackingMenuHandle);
188 LogToFile(logFile, "Database failure: Could not find Database conf \"sourcebans\". See Docs: https://sbpp.github.io/docs/");
189 SetFailState("Database failure: Could not find Database conf \"sourcebans\"");
190 return;
191 }
192
193 Database.Connect(GotDatabase, "sourcebans");
194
195 BuildPath(Path_SM, groupsLoc, sizeof(groupsLoc), "configs/sourcebans/sb_admin_groups.cfg");
196
197 BuildPath(Path_SM, adminsLoc, sizeof(adminsLoc), "configs/sourcebans/sb_admins.cfg");
198
199 BuildPath(Path_SM, overridesLoc, sizeof(overridesLoc), "configs/sourcebans/overrides_backup.cfg");
200
201 InitializeBackupDB();
202
203 // This timer is what processes the SQLite queue when the database is unavailable
204 CreateTimer(float(ProcessQueueTime * 60), ProcessQueue);
205
206 if (LateLoaded)
207 {
208 AccountForLateLoading();
209 }
210
211 #if defined _updater_included
212 if (LibraryExists("updater"))
213 {
214 Updater_AddPlugin(UPDATE_URL);
215 }
216 #endif
217}
218
219#if defined _updater_included
220public void OnLibraryAdded(const char[] name)
221{
222 if (StrEqual(name, "updater"))
223 {
224 Updater_AddPlugin(UPDATE_URL);
225 }
226}
227#endif
228
229public void OnAllPluginsLoaded()
230{
231 TopMenu topmenu;
232 #if defined DEBUG
233 LogToFile(logFile, "OnAllPluginsLoaded()");
234 #endif
235
236 if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE))
237 {
238 OnAdminMenuReady(topmenu);
239 }
240}
241
242public void OnConfigsExecuted()
243{
244 char filename[200];
245 BuildPath(Path_SM, filename, sizeof(filename), "plugins/basebans.smx");
246 if (FileExists(filename))
247 {
248 char newfilename[200];
249 BuildPath(Path_SM, newfilename, sizeof(newfilename), "plugins/disabled/basebans.smx");
250 ServerCommand("sm plugins unload basebans");
251 if (FileExists(newfilename))
252 DeleteFile(newfilename);
253 RenameFile(newfilename, filename);
254 LogToFile(logFile, "plugins/basebans.smx was unloaded and moved to plugins/disabled/basebans.smx");
255 }
256}
257
258public void OnMapStart()
259{
260 ResetSettings();
261}
262
263public void OnMapEnd()
264{
265 for (int i = 0; i <= MaxClients; i++)
266 {
267 if (PlayerDataPack[i] != null)
268 {
269 /* Need to close reason pack */
270 delete PlayerDataPack[i];
271 }
272 }
273}
274
275// CLIENT CONNECTION FUNCTIONS //
276
277public Action OnClientPreAdminCheck(int client)
278{
279 if (!DB || GetUserAdmin(client) != INVALID_ADMIN_ID)
280 return Plugin_Continue;
281
282 return curLoading > 0 ? Plugin_Handled : Plugin_Continue;
283}
284
285public void OnClientDisconnect(int client)
286{
287 if (PlayerRecheck[client] != INVALID_HANDLE)
288 {
289 KillTimer(PlayerRecheck[client]);
290 PlayerRecheck[client] = INVALID_HANDLE;
291 }
292 g_ownReasons[client] = false;
293}
294
295public bool OnClientConnect(int client, char[] rejectmsg, int maxlen)
296{
297 PlayerStatus[client] = false;
298 return true;
299}
300
301public void OnClientAuthorized(int client, const char[] auth)
302{
303 /* Do not check bots nor check player with lan steamid. */
304 if (auth[0] == 'B' || auth[9] == 'L' || DB == INVALID_HANDLE)
305 {
306 PlayerStatus[client] = true;
307 return;
308 }
309
310 char Query[256], ip[30];
311
312 GetClientIP(client, ip, sizeof(ip));
313
314 FormatEx(Query, sizeof(Query), "SELECT bid, ip FROM %s_bans WHERE ((type = 0 AND authid REGEXP '^STEAM_[0-9]:%s$') OR (type = 1 AND ip = '%s')) AND (length = '0' OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL", DatabasePrefix, auth[8], ip);
315
316 #if defined DEBUG
317 LogToFile(logFile, "Checking ban for: %s", auth);
318 #endif
319
320 DB.Query(VerifyBan, Query, GetClientUserId(client), DBPrio_High);
321}
322
323public void OnRebuildAdminCache(AdminCachePart part)
324{
325 loadPart = part;
326 switch (loadPart)
327 {
328 case AdminCache_Overrides:
329 loadOverrides = true;
330 case AdminCache_Groups:
331 loadGroups = true;
332 case AdminCache_Admins:
333 loadAdmins = true;
334 }
335 if (DB == INVALID_HANDLE) {
336 if (!g_bConnecting) {
337 g_bConnecting = true;
338 Database.Connect(GotDatabase, "sourcebans");
339 }
340 }
341 else {
342 GotDatabase(DB, "", 0);
343 }
344}
345
346// COMMAND CODE //
347
348public Action ChatHook(int client, int args)
349{
350 // is this player preparing to ban someone
351 if (g_ownReasons[client])
352 {
353 // get the reason
354 char reason[512];
355 GetCmdArgString(reason, sizeof(reason));
356 StripQuotes(reason);
357
358 g_ownReasons[client] = false;
359
360 if (StrEqual(reason[0], "!noreason"))
361 {
362 PrintToChat(client, "%c[%cSourceBans%c]%c %t", GREEN, NAMECOLOR, GREEN, NAMECOLOR, "Chat Reason Aborted");
363 return Plugin_Handled;
364 }
365
366 // ban him!
367 PrepareBan(client, g_BanTarget[client], g_BanTime[client], reason, sizeof(reason));
368
369 // block the reason to be sent in chat
370 return Plugin_Handled;
371 }
372 return Plugin_Continue;
373}
374
375public Action _CmdReload(int client, int args)
376{
377 ResetSettings();
378 return Plugin_Handled;
379}
380
381public Action CommandBan(int client, int args)
382{
383 if (args < 2)
384 {
385 if ((GetCmdReplySource() == SM_REPLY_TO_CHAT) && (client != 0) && (args == 0))
386 {
387 DisplayBanTargetMenu(client);
388 }
389 else
390 {
391 ReplyToCommand(client, "%sUsage: sm_ban <#userid|name> <time|0> [reason]", Prefix);
392 }
393 return Plugin_Handled;
394 }
395
396 // This is mainly for me sanity since client used to be called admin and target used to be called client
397 int admin = client;
398
399 // Get the target, find target returns a message on failure so we do not
400 char buffer[100];
401
402 GetCmdArg(1, buffer, sizeof(buffer));
403
404 int target = FindTarget(client, buffer, true);
405
406 if (target == -1)
407 {
408 return Plugin_Handled;
409 }
410
411 // Get the ban time
412 GetCmdArg(2, buffer, sizeof(buffer));
413
414 int time = StringToInt(buffer);
415
416 if (!time && client && !(CheckCommandAccess(client, "sm_unban", ADMFLAG_UNBAN | ADMFLAG_ROOT)))
417 {
418 ReplyToCommand(client, "You do not have Perm Ban Permission");
419 return Plugin_Handled;
420 }
421
422 // Get the reason
423 char reason[128];
424
425 if (args >= 3)
426 {
427 GetCmdArg(3, reason, sizeof(reason));
428 for (int i = 4; i <= args; i++)
429 {
430 GetCmdArg(i, buffer, sizeof(buffer));
431 Format(reason, sizeof(reason), "%s %s", reason, buffer);
432 }
433 }
434 else
435 {
436 reason[0] = '\0';
437 }
438
439 g_BanTarget[client] = target;
440 g_BanTime[client] = time;
441
442 if (!PlayerStatus[target])
443 {
444 // The target has not been banned verify. It must be completed before you can ban anyone.
445 ReplyToCommand(admin, "%c[%cSourceBans%c]%c %t", GREEN, NAMECOLOR, GREEN, NAMECOLOR, "Ban Not Verified");
446 return Plugin_Handled;
447 }
448
449
450 CreateBan(client, target, time, reason);
451 return Plugin_Handled;
452}
453
454public Action CommandBanIp(int client, int args)
455{
456 if (args < 2)
457 {
458 ReplyToCommand(client, "%sUsage: sm_banip <ip|#userid|name> <time> [reason]", Prefix);
459 return Plugin_Handled;
460 }
461
462 int len, next_len;
463 char Arguments[256], arg[50], time[20];
464
465 GetCmdArgString(Arguments, sizeof(Arguments));
466 len = BreakString(Arguments, arg, sizeof(arg));
467
468 if ((next_len = BreakString(Arguments[len], time, sizeof(time))) != -1)
469 {
470 len += next_len;
471 }
472 else
473 {
474 len = 0;
475 Arguments[0] = '\0';
476 }
477
478 char target_name[MAX_TARGET_LENGTH];
479 int target_list[1];
480 bool tn_is_ml;
481
482 int target = -1;
483
484 if (ProcessTargetString(
485 arg,
486 client,
487 target_list,
488 1,
489 COMMAND_FILTER_CONNECTED | COMMAND_FILTER_NO_MULTI,
490 target_name,
491 sizeof(target_name),
492 tn_is_ml) > 0)
493 {
494 target = target_list[0];
495
496 if (!IsFakeClient(target) && CanUserTarget(client, target))
497 GetClientIP(target, arg, sizeof(arg));
498 }
499
500 char adminIp[24], adminAuth[64];
501
502 int minutes = StringToInt(time);
503
504 if (!minutes && client && !(CheckCommandAccess(client, "sm_unban", ADMFLAG_UNBAN | ADMFLAG_ROOT)))
505 {
506 ReplyToCommand(client, "You do not have Perm Ban Permission");
507 return Plugin_Handled;
508 }
509 if (!client)
510 {
511 // setup dummy adminAuth and adminIp for server
512 strcopy(adminAuth, sizeof(adminAuth), "STEAM_ID_SERVER");
513 strcopy(adminIp, sizeof(adminIp), ServerIp);
514 } else {
515 GetClientIP(client, adminIp, sizeof(adminIp));
516 GetClientAuthId(client, AuthId_Steam2, adminAuth, sizeof(adminAuth));
517 }
518
519 // Pack everything into a data pack so we can retain it
520 DataPack dataPack = new DataPack();
521 dataPack.WriteCell(client);
522 dataPack.WriteCell(minutes);
523 dataPack.WriteString(Arguments[len]);
524 dataPack.WriteString(arg);
525 dataPack.WriteString(adminAuth);
526 dataPack.WriteString(adminIp);
527
528 char sQuery[256];
529
530 FormatEx(sQuery, sizeof(sQuery), "SELECT bid FROM %s_bans WHERE type = 1 AND ip = '%s' AND (length = 0 OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL",
531 DatabasePrefix, arg);
532
533 DB.Query(SelectBanIpCallback, sQuery, dataPack, DBPrio_High);
534
535 return Plugin_Handled;
536}
537
538public Action CommandUnban(int client, int args)
539{
540 if (args < 1)
541 {
542 ReplyToCommand(client, "%sUsage: sm_unban <steamid|ip> [reason]", Prefix);
543 return Plugin_Handled;
544 }
545
546 if (CommandDisable & DISABLE_UNBAN)
547 {
548 // They must go to the website to unban people
549 ReplyToCommand(client, "%s%t", Prefix, "Can Not Unban", WebsiteAddress);
550 return Plugin_Handled;
551 }
552
553 int len;
554 char Arguments[256], arg[50], adminAuth[64];
555
556 GetCmdArgString(Arguments, sizeof(Arguments));
557
558 if ((len = BreakString(Arguments, arg, sizeof(arg))) == -1)
559 {
560 len = 0;
561 Arguments[0] = '\0';
562 }
563 if (!client)
564 {
565 // setup dummy adminAuth and adminIp for server
566 strcopy(adminAuth, sizeof(adminAuth), "STEAM_ID_SERVER");
567 } else {
568 GetClientAuthId(client, AuthId_Steam2, adminAuth, sizeof(adminAuth));
569 }
570
571 // Pack everything into a data pack so we can retain it
572 DataPack dataPack = new DataPack();
573 dataPack.WriteCell(client);
574 dataPack.WriteString(Arguments[len]);
575 dataPack.WriteString(arg);
576 dataPack.WriteString(adminAuth);
577
578 char query[200];
579
580 if (strncmp(arg, "STEAM_", 6) == 0)
581 {
582 Format(query, sizeof(query), "SELECT bid FROM %s_bans WHERE (type = 0 AND authid = '%s') AND (length = '0' OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL", DatabasePrefix, arg);
583 } else {
584 Format(query, sizeof(query), "SELECT bid FROM %s_bans WHERE (type = 1 AND ip = '%s') AND (length = '0' OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL", DatabasePrefix, arg);
585 }
586
587 DB.Query(SelectUnbanCallback, query, dataPack);
588
589 return Plugin_Handled;
590}
591
592public Action CommandAddBan(int client, int args)
593{
594 if (args < 2)
595 {
596 ReplyToCommand(client, "%sUsage: sm_addban <time> <steamid> [reason]", Prefix);
597 return Plugin_Handled;
598 }
599
600 if (CommandDisable & DISABLE_ADDBAN)
601 {
602 // They must go to the website to add bans
603 ReplyToCommand(client, "%s%t", Prefix, "Can Not Add Ban", WebsiteAddress);
604 return Plugin_Handled;
605 }
606
607 char arg_string[256], time[50], authid[50];
608
609 GetCmdArgString(arg_string, sizeof(arg_string));
610
611 int len, total_len;
612
613 /* Get time */
614 if ((len = BreakString(arg_string, time, sizeof(time))) == -1)
615 {
616 ReplyToCommand(client, "%sUsage: sm_addban <time> <steamid> [reason]", Prefix);
617 return Plugin_Handled;
618 }
619 total_len += len;
620
621 /* Get steamid */
622 if ((len = BreakString(arg_string[total_len], authid, sizeof(authid))) != -1)
623 {
624 total_len += len;
625 }
626 else
627 {
628 total_len = 0;
629 arg_string[0] = '\0';
630 }
631
632 char adminIp[24], adminAuth[64];
633
634 int minutes = StringToInt(time);
635
636 if (!minutes && client && !(CheckCommandAccess(client, "sm_unban", ADMFLAG_UNBAN | ADMFLAG_ROOT)))
637 {
638 ReplyToCommand(client, "You do not have Perm Ban Permission");
639 return Plugin_Handled;
640 }
641 if (!client)
642 {
643 // setup dummy adminAuth and adminIp for server
644 strcopy(adminAuth, sizeof(adminAuth), "STEAM_ID_SERVER");
645 strcopy(adminIp, sizeof(adminIp), ServerIp);
646 } else {
647 GetClientIP(client, adminIp, sizeof(adminIp));
648 GetClientAuthId(client, AuthId_Steam2, adminAuth, sizeof(adminAuth));
649 }
650
651 // Pack everything into a data pack so we can retain it
652 DataPack dataPack = new DataPack();
653 dataPack.WriteCell(client);
654 dataPack.WriteCell(minutes);
655 dataPack.WriteString(arg_string[total_len]);
656 dataPack.WriteString(authid);
657 dataPack.WriteString(adminAuth);
658 dataPack.WriteString(adminIp);
659
660 char sQuery[256];
661
662 FormatEx(sQuery, sizeof sQuery, "SELECT bid FROM %s_bans WHERE type = 0 AND authid = '%s' AND (length = 0 OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL",
663 DatabasePrefix, authid);
664
665 DB.Query(SelectAddbanCallback, sQuery, dataPack, DBPrio_High);
666
667 return Plugin_Handled;
668}
669
670public Action sm_rehash(int args)
671{
672 if (enableAdmins)
673 DumpAdminCache(AdminCache_Groups, true);
674 DumpAdminCache(AdminCache_Overrides, true);
675 return Plugin_Handled;
676}
677
678
679
680// MENU CODE //
681
682public void OnAdminMenuReady(Handle hTemp)
683{
684 TopMenu topmenu = view_as<TopMenu>(hTemp);
685 #if defined DEBUG
686 LogToFile(logFile, "OnAdminMenuReady()");
687 #endif
688
689 /* Block us from being called twice */
690 if (topmenu == hTopMenu)
691 {
692 return;
693 }
694
695 /* Save the Handle */
696 hTopMenu = topmenu;
697
698 /* Find the "Player Commands" category */
699 TopMenuObject player_commands = hTopMenu.FindCategory(ADMINMENU_PLAYERCOMMANDS);
700
701 if (player_commands != INVALID_TOPMENUOBJECT)
702 {
703 // just to avoid "unused variable 'res'" warning
704 #if defined DEBUG
705 TopMenuObject res = hTopMenu.AddItem(
706 "sm_ban", // Name
707 AdminMenu_Ban, // Handler function
708 player_commands, // We are a submenu of Player Commands
709 "sm_ban", // The command to be finally called (Override checks)
710 ADMFLAG_BAN); // What flag do we need to see the menu option
711 char temp[125];
712 Format(temp, 125, "Result of AddToTopMenu: %d", res);
713 LogToFile(logFile, temp);
714 LogToFile(logFile, "Added Ban option to admin menu");
715 #else
716 hTopMenu.AddItem(
717 "sm_ban", // Name
718 AdminMenu_Ban, // Handler function
719 player_commands, // We are a submenu of Player Commands
720 "sm_ban", // The command to be finally called (Override checks)
721 ADMFLAG_BAN); // What flag do we need to see the menu option
722 #endif
723 }
724}
725
726public void AdminMenu_Ban(TopMenu topmenu,
727 TopMenuAction action, // Action being performed
728 TopMenuObject object_id, // The object ID (if used)
729 int param, // client idx of admin who chose the option (if used)
730 char[] buffer, // Output buffer (if used)
731 int maxlength) // Output buffer (if used)
732{
733 /* Clear the Ownreason bool, so he is able to chat again;) */
734 g_ownReasons[param] = false;
735
736 #if defined DEBUG
737 LogToFile(logFile, "AdminMenu_Ban()");
738 #endif
739
740 switch (action)
741 {
742 // We are only being displayed, We only need to show the option name
743 case TopMenuAction_DisplayOption:
744 {
745 FormatEx(buffer, maxlength, "%T", "Ban player", param);
746
747 #if defined DEBUG
748 LogToFile(logFile, "AdminMenu_Ban() -> Formatted the Ban option text");
749 #endif
750 }
751
752 case TopMenuAction_SelectOption:
753 {
754 DisplayBanTargetMenu(param); // Someone chose to ban someone, show the list of users menu
755
756 #if defined DEBUG
757 LogToFile(logFile, "AdminMenu_Ban() -> DisplayBanTargetMenu()");
758 #endif
759 }
760 }
761}
762
763public int ReasonSelected(Menu menu, MenuAction action, int param1, int param2)
764{
765 switch (action)
766 {
767 case MenuAction_Select:
768 {
769 char info[128], key[128];
770
771 menu.GetItem(param2, key, sizeof(key), _, info, sizeof(info));
772
773 if (StrEqual("Hacking", key))
774 {
775 HackingMenuHandle.Display(param1, MENU_TIME_FOREVER);
776 return;
777 }
778
779 else if (StrEqual("Own Reason", key)) // admin wants to use his own reason
780 {
781 g_ownReasons[param1] = true;
782 PrintToChat(param1, "%c[%cSourceBans%c]%c %t", GREEN, NAMECOLOR, GREEN, NAMECOLOR, "Chat Reason");
783 return;
784 }
785
786 else if (g_BanTarget[param1] != -1 && g_BanTime[param1] != -1)
787 PrepareBan(param1, g_BanTarget[param1], g_BanTime[param1], info, sizeof(info));
788 }
789
790 case MenuAction_Cancel:
791 {
792 if (param2 == MenuCancel_Disconnected)
793 {
794 if (PlayerDataPack[param1] != null)
795 {
796 delete PlayerDataPack[param1];
797 }
798 }
799
800 else
801 {
802 DisplayBanTimeMenu(param1);
803 }
804 }
805 }
806}
807
808public int HackingSelected(Menu menu, MenuAction action, int param1, int param2)
809{
810 switch (action)
811 {
812 case MenuAction_Select:
813 {
814 char info[128], key[128];
815
816 menu.GetItem(param2, key, sizeof(key), _, info, sizeof(info));
817
818 if (g_BanTarget[param1] != -1 && g_BanTime[param1] != -1)
819 PrepareBan(param1, g_BanTarget[param1], g_BanTime[param1], info, sizeof(info));
820 }
821
822 case MenuAction_Cancel:
823 {
824 if (param2 == MenuCancel_Disconnected)
825 {
826 DataPack Pack = PlayerDataPack[param1];
827
828 if (Pack != null)
829 {
830 Pack.ReadCell(); // admin index
831 Pack.ReadCell(); // target index
832 Pack.ReadCell(); // admin userid
833 Pack.ReadCell(); // target userid
834 Pack.ReadCell(); // time
835
836 DataPack ReasonPack = Pack.ReadCell();
837
838 if (ReasonPack != INVALID_HANDLE)
839 {
840 CloseHandle(ReasonPack);
841 }
842
843 delete Pack;
844 PlayerDataPack[param1] = null;
845 }
846 }
847
848 else
849 {
850 DisplayMenu(ReasonMenuHandle, param1, MENU_TIME_FOREVER);
851 }
852 }
853 }
854}
855
856public int MenuHandler_BanPlayerList(Menu menu, MenuAction action, int param1, int param2)
857{
858 #if defined DEBUG
859 LogToFile(logFile, "MenuHandler_BanPlayerList()");
860 #endif
861
862 switch (action)
863 {
864 case MenuAction_End:
865 {
866 delete menu;
867 }
868
869 case MenuAction_Cancel:
870 {
871 if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
872 {
873 hTopMenu.Display(param1, TopMenuPosition_LastCategory);
874 }
875 }
876
877 case MenuAction_Select:
878 {
879 char info[32], name[32];
880 int userid, target;
881
882 menu.GetItem(param2, info, sizeof(info), _, name, sizeof(name));
883 userid = StringToInt(info);
884
885 if ((target = GetClientOfUserId(userid)) == 0)
886 {
887 PrintToChat(param1, "%s%t", Prefix, "Player no longer available");
888 }
889 else if (!CanUserTarget(param1, target))
890 {
891 PrintToChat(param1, "%s%t", Prefix, "Unable to target");
892 }
893 else
894 {
895 g_BanTarget[param1] = target;
896 DisplayBanTimeMenu(param1);
897 }
898 }
899 }
900}
901
902public int MenuHandler_BanTimeList(Menu menu, MenuAction action, int param1, int param2)
903{
904 #if defined DEBUG
905 LogToFile(logFile, "MenuHandler_BanTimeList()");
906 #endif
907
908 switch (action)
909 {
910 case MenuAction_Cancel:
911 {
912 if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
913 {
914 hTopMenu.Display(param1, TopMenuPosition_LastCategory);
915 }
916 }
917
918 case MenuAction_Select:
919 {
920 char info[32];
921
922 menu.GetItem(param2, info, sizeof(info));
923 g_BanTime[param1] = StringToInt(info);
924
925 //DisplayBanReasonMenu(param1);
926 ReasonMenuHandle.Display(param1, MENU_TIME_FOREVER);
927 }
928
929 case MenuAction_DrawItem:
930 {
931 char time[16];
932
933 menu.GetItem(param2, time, sizeof(time));
934
935 return (StringToInt(time) > 0 || CheckCommandAccess(param1, "sm_unban", ADMFLAG_UNBAN | ADMFLAG_ROOT)) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
936 }
937 }
938
939 return 0;
940}
941
942stock void DisplayBanTargetMenu(int client)
943{
944 #if defined DEBUG
945 LogToFile(logFile, "DisplayBanTargetMenu()");
946 #endif
947
948 Menu menu = new Menu(MenuHandler_BanPlayerList); // Create a new menu, pass it the handler.
949
950 char title[100];
951
952 FormatEx(title, sizeof(title), "%T:", "Ban player", client);
953
954 menu.SetTitle(title); // Set the title
955 menu.ExitBackButton = true; // Yes we want back/exit
956
957 AddTargetsToMenu(menu, // Add clients to our menu
958 client, // The client that called the display
959 false, // We want to see people connecting
960 false); // And dead people
961
962 menu.Display(client, MENU_TIME_FOREVER); // Show the menu to the client FOREVER!
963}
964
965stock void DisplayBanTimeMenu(int client)
966{
967 #if defined DEBUG
968 LogToFile(logFile, "DisplayBanTimeMenu()");
969 #endif
970
971 char title[100];
972 FormatEx(title, sizeof(title), "%T:", "Ban player", client);
973 SetMenuTitle(TimeMenuHandle, title);
974
975 DisplayMenu(TimeMenuHandle, client, MENU_TIME_FOREVER);
976}
977
978stock void ResetMenu()
979{
980 if (TimeMenuHandle != INVALID_HANDLE)
981 {
982 RemoveAllMenuItems(TimeMenuHandle);
983 }
984
985 if (ReasonMenuHandle != INVALID_HANDLE)
986 {
987 RemoveAllMenuItems(ReasonMenuHandle);
988 }
989
990 if (HackingMenuHandle != INVALID_HANDLE)
991 {
992 RemoveAllMenuItems(HackingMenuHandle);
993 }
994}
995
996// QUERY CALL BACKS //
997
998public void GotDatabase(Database db, const char[] error, any data)
999{
1000 if (db == INVALID_HANDLE)
1001 {
1002 LogToFile(logFile, "Database failure: %s. See Docs: https://sbpp.github.io/docs/", error);
1003 g_bConnecting = false;
1004
1005 // Parse the overrides backup!
1006 ParseBackupConfig_Overrides();
1007 return;
1008 }
1009
1010 DB = db;
1011
1012 char query[1024];
1013
1014 Format(query, sizeof(query), "SET NAMES utf8mb4");
1015 DB.Query(ErrorCheckCallback, query);
1016
1017 InsertServerInfo();
1018
1019 //CreateTimer(900.0, PruneBans);
1020
1021 if (loadOverrides)
1022 {
1023 Format(query, 1024, "SELECT type, name, flags FROM %s_overrides", DatabasePrefix);
1024 DB.Query(OverridesDone, query);
1025 loadOverrides = false;
1026 }
1027
1028 if (loadGroups && enableAdmins)
1029 {
1030 FormatEx(query, 1024, "SELECT name, flags, immunity, groups_immune \
1031 FROM %s_srvgroups ORDER BY id", DatabasePrefix);
1032 curLoading++;
1033 DB.Query(GroupsDone, query);
1034
1035 #if defined DEBUG
1036 LogToFile(logFile, "Fetching Group List");
1037 #endif
1038 loadGroups = false;
1039 }
1040
1041 if (loadAdmins && enableAdmins)
1042 {
1043 char queryLastLogin[50] = "";
1044
1045 if (requireSiteLogin)
1046 queryLastLogin = "lastvisit IS NOT NULL AND lastvisit != '' AND";
1047
1048 if (serverID == -1)
1049 {
1050 FormatEx(query, 1024, "SELECT authid, srv_password, (SELECT name FROM %s_srvgroups WHERE name = srv_group AND flags != '') AS srv_group, srv_flags, user, immunity \
1051 FROM %s_admins_servers_groups AS asg \
1052 LEFT JOIN %s_admins AS a ON a.aid = asg.admin_id \
1053 WHERE %s (server_id = (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1) \
1054 OR srv_group_id = ANY (SELECT group_id FROM %s_servers_groups WHERE server_id = (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1))) \
1055 GROUP BY aid, authid, srv_password, srv_group, srv_flags, user",
1056 DatabasePrefix, DatabasePrefix, DatabasePrefix, queryLastLogin, DatabasePrefix, ServerIp, ServerPort, DatabasePrefix, DatabasePrefix, ServerIp, ServerPort);
1057 } else {
1058 FormatEx(query, 1024, "SELECT authid, srv_password, (SELECT name FROM %s_srvgroups WHERE name = srv_group AND flags != '') AS srv_group, srv_flags, user, immunity \
1059 FROM %s_admins_servers_groups AS asg \
1060 LEFT JOIN %s_admins AS a ON a.aid = asg.admin_id \
1061 WHERE %s server_id = %d \
1062 OR srv_group_id = ANY (SELECT group_id FROM %s_servers_groups WHERE server_id = %d) \
1063 GROUP BY aid, authid, srv_password, srv_group, srv_flags, user",
1064 DatabasePrefix, DatabasePrefix, DatabasePrefix, queryLastLogin, serverID, DatabasePrefix, serverID);
1065 }
1066 curLoading++;
1067 DB.Query(AdminsDone, query);
1068
1069 #if defined DEBUG
1070 LogToFile(logFile, "Fetching Admin List");
1071 LogToFile(logFile, query);
1072 #endif
1073 loadAdmins = false;
1074 }
1075 g_bConnecting = false;
1076}
1077
1078public void VerifyInsert(Database db, DBResultSet results, const char[] error, DataPack dataPack)
1079{
1080 if (dataPack == INVALID_HANDLE)
1081 {
1082 LogToFile(logFile, "Ban Failed: %s", error);
1083 return;
1084 }
1085
1086 if (results == null)
1087 {
1088 LogToFile(logFile, "Verify Insert Query Failed: %s", error);
1089
1090 int admin = dataPack.ReadCell();
1091 dataPack.ReadCell(); // target
1092 dataPack.ReadCell(); // admin userid
1093 dataPack.ReadCell(); // target userid
1094 int time = dataPack.ReadCell();
1095
1096 DataPack reasonPack = dataPack.ReadCell();
1097
1098 char reason[128], name[50], auth[30], ip[20], adminAuth[30], adminIp[20];
1099
1100 reasonPack.ReadString(reason, sizeof reason);
1101
1102 dataPack.ReadString(name, sizeof name);
1103 dataPack.ReadString(auth, sizeof auth);
1104 dataPack.ReadString(ip, sizeof ip);
1105 dataPack.ReadString(adminAuth, sizeof adminAuth);
1106 dataPack.ReadString(adminIp, sizeof adminIp);
1107
1108 dataPack.Reset();
1109 reasonPack.Reset();
1110
1111 PlayerDataPack[admin] = null;
1112 UTIL_InsertTempBan(time, name, auth, ip, reason, adminAuth, adminIp, dataPack);
1113 return;
1114 }
1115
1116 int admin = dataPack.ReadCell();
1117 int client = dataPack.ReadCell();
1118
1119 if (!IsClientConnected(client) || IsFakeClient(client))
1120 return;
1121
1122 dataPack.ReadCell(); // admin userid
1123
1124 int UserId = dataPack.ReadCell();
1125 int time = dataPack.ReadCell();
1126
1127 DataPack ReasonPack = dataPack.ReadCell();
1128
1129 char Name[64], Reason[128];
1130
1131 dataPack.ReadString(Name, sizeof(Name));
1132 ReasonPack.ReadString(Reason, sizeof(Reason));
1133
1134 if (!time)
1135 {
1136 if (Reason[0] == '\0')
1137 {
1138 ShowActivityEx(admin, Prefix, "%t", "Permabanned player", Name);
1139 } else {
1140 ShowActivityEx(admin, Prefix, "%t", "Permabanned player reason", Name, Reason);
1141 }
1142 } else {
1143 if (Reason[0] == '\0')
1144 {
1145 ShowActivityEx(admin, Prefix, "%t", "Banned player", Name, time);
1146 } else {
1147 ShowActivityEx(admin, Prefix, "%t", "Banned player reason", Name, time, Reason);
1148 }
1149 }
1150
1151 LogAction(admin, client, "\"%L\" banned \"%L\" (minutes \"%d\") (reason \"%s\")", admin, client, time, Reason);
1152
1153 if (PlayerDataPack[admin] != INVALID_HANDLE)
1154 {
1155 delete PlayerDataPack[admin];
1156 delete ReasonPack;
1157 }
1158
1159 // Kick player
1160 if (GetClientUserId(client) == UserId)
1161 {
1162 char length[32];
1163 if(time == 0)
1164 FormatEx(length, sizeof(length), "permament");
1165 else
1166 FormatEx(length, sizeof(length), "%d %s", time, time == 1 ? "minute" : "minutes");
1167 KickClient(client, "%t\n\n%t", "Banned Check Site", WebsiteAddress, "Kick Reason", admin, Reason, length);
1168 }
1169}
1170
1171public void SelectBanIpCallback(Database db, DBResultSet results, const char[] error, DataPack dataPack)
1172{
1173 int admin, minutes;
1174 char adminAuth[30], adminIp[30], banReason[256], ip[16], Query[512];
1175 char reason[128];
1176
1177 dataPack.Reset();
1178 admin = dataPack.ReadCell();
1179 minutes = dataPack.ReadCell();
1180 dataPack.ReadString(reason, sizeof(reason));
1181 dataPack.ReadString(ip, sizeof(ip));
1182 dataPack.ReadString(adminAuth, sizeof(adminAuth));
1183 dataPack.ReadString(adminIp, sizeof(adminIp));
1184 DB.Escape(reason, banReason, sizeof(banReason));
1185
1186 if (results == null)
1187 {
1188 LogToFile(logFile, "Ban IP Select Query Failed: %s", error);
1189 if (admin && IsClientInGame(admin))
1190 PrintToChat(admin, "%sFailed to ban %s.", Prefix, ip);
1191 else
1192 PrintToServer("%sFailed to ban %s.", Prefix, ip);
1193 return;
1194 }
1195 if (results.RowCount)
1196 {
1197 if (admin && IsClientInGame(admin))
1198 PrintToChat(admin, "%s%s is already banned.", Prefix, ip);
1199 else
1200 PrintToServer("%s%s is already banned.", Prefix, ip);
1201 return;
1202 }
1203 if (serverID == -1)
1204 {
1205 FormatEx(Query, sizeof(Query), "INSERT INTO %s_bans (type, ip, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
1206 (1, '%s', '', UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
1207 (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1), ' ')",
1208 DatabasePrefix, ip, (minutes * 60), (minutes * 60), banReason, DatabasePrefix, adminAuth, adminAuth[8], adminIp, DatabasePrefix, ServerIp, ServerPort);
1209 } else {
1210 FormatEx(Query, sizeof(Query), "INSERT INTO %s_bans (type, ip, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
1211 (1, '%s', '', UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
1212 %d, ' ')",
1213 DatabasePrefix, ip, (minutes * 60), (minutes * 60), banReason, DatabasePrefix, adminAuth, adminAuth[8], adminIp, serverID);
1214 }
1215
1216 db.Query(InsertBanIpCallback, Query, dataPack, DBPrio_High);
1217}
1218
1219public void InsertBanIpCallback(Database db, DBResultSet results, const char[] error, DataPack dataPack)
1220{
1221 // if the pack is good unpack it and close the handle
1222 int admin, minutes;
1223 char reason[128];
1224 char arg[30];
1225
1226 if (dataPack != null)
1227 {
1228 dataPack.Reset();
1229 admin = dataPack.ReadCell();
1230 minutes = dataPack.ReadCell();
1231 dataPack.ReadString(reason, sizeof(reason));
1232 dataPack.ReadString(arg, sizeof(arg));
1233 delete dataPack;
1234 } else {
1235 // Technically this should not be possible
1236 ThrowError("Invalid Handle in InsertBanIpCallback");
1237 }
1238
1239 // If error is not an empty string the query failed
1240 if (results == null)
1241 {
1242 LogToFile(logFile, "Ban IP Insert Query Failed: %s", error);
1243 if (admin && IsClientInGame(admin))
1244 PrintToChat(admin, "%ssm_banip failed", Prefix);
1245 return;
1246 }
1247
1248 LogAction(admin,
1249 -1,
1250 "\"%L\" added ban (minutes \"%d\") (ip \"%s\") (reason \"%s\")",
1251 admin,
1252 minutes,
1253 arg,
1254 reason);
1255 if (admin && IsClientInGame(admin))
1256 PrintToChat(admin, "%s%s successfully banned", Prefix, arg);
1257 else
1258 PrintToServer("%s%s successfully banned", Prefix, arg);
1259}
1260
1261public void SelectUnbanCallback(Database db, DBResultSet results, const char[] error, DataPack dataPack)
1262{
1263 int admin;
1264 char arg[30], adminAuth[30], unbanReason[256];
1265 char reason[128];
1266
1267 dataPack.Reset();
1268 admin = dataPack.ReadCell();
1269 dataPack.ReadString(reason, sizeof(reason));
1270 dataPack.ReadString(arg, sizeof(arg));
1271 dataPack.ReadString(adminAuth, sizeof(adminAuth));
1272 delete dataPack;
1273
1274 db.Escape(reason, unbanReason, sizeof(unbanReason));
1275
1276 // If error is not an empty string the query failed
1277 if (results == null)
1278 {
1279 LogToFile(logFile, "Unban Select Query Failed: %s", error);
1280 if (admin && IsClientInGame(admin))
1281 {
1282 PrintToChat(admin, "%ssm_unban failed", Prefix);
1283 }
1284 return;
1285 }
1286
1287 // If there was no results then a ban does not exist for that id
1288 if (!results.RowCount)
1289 {
1290 if (admin && IsClientInGame(admin))
1291 {
1292 PrintToChat(admin, "%sNo active bans found for that filter", Prefix);
1293 } else {
1294 PrintToServer("%sNo active bans found for that filter", Prefix);
1295 }
1296 return;
1297 }
1298
1299 // There is ban
1300 if (results != null && results.FetchRow())
1301 {
1302 // Get the values from the existing ban record
1303 int bid = results.FetchInt(0);
1304
1305 char query[1000];
1306 Format(query, sizeof(query), "UPDATE %s_bans SET RemovedBy = (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), RemoveType = 'U', RemovedOn = UNIX_TIMESTAMP(), ureason = '%s' WHERE bid = %d",
1307 DatabasePrefix, DatabasePrefix, adminAuth, adminAuth[8], unbanReason, bid);
1308
1309 db.Query(InsertUnbanCallback, query, dataPack);
1310 }
1311 return;
1312}
1313
1314public void InsertUnbanCallback(Database db, DBResultSet results, const char[] error, DataPack dataPack)
1315{
1316 // if the pack is good unpack it and close the handle
1317 int admin;
1318 char arg[30];
1319 char reason[128];
1320
1321 if (dataPack != null)
1322 {
1323 dataPack.Reset();
1324 admin = dataPack.ReadCell();
1325 dataPack.ReadString(reason, sizeof(reason));
1326 dataPack.ReadString(arg, sizeof(arg));
1327 delete dataPack;
1328 } else {
1329 // Technically this should not be possible
1330 ThrowError("Invalid Handle in InsertUnbanCallback");
1331 }
1332
1333 // If error is not an empty string the query failed
1334 if (results == null)
1335 {
1336 LogToFile(logFile, "Unban Insert Query Failed: %s", error);
1337 if (admin && IsClientInGame(admin))
1338 {
1339 PrintToChat(admin, "%ssm_unban failed", Prefix);
1340 }
1341 return;
1342 }
1343
1344 LogAction(admin, -1, "\"%L\" removed ban (filter \"%s\") (reason \"%s\")", admin, arg, reason);
1345 if (admin && IsClientInGame(admin))
1346 {
1347 PrintToChat(admin, "%s%s successfully unbanned", Prefix, arg);
1348 } else {
1349 PrintToServer("%s%s successfully unbanned", Prefix, arg);
1350 }
1351}
1352
1353public void SelectAddbanCallback(Database db, DBResultSet results, const char[] error, DataPack dataPack)
1354{
1355 int admin, minutes;
1356 char adminAuth[30], adminIp[30], authid[20], banReason[256], Query[512];
1357 char reason[128];
1358
1359 dataPack.Reset();
1360 admin = dataPack.ReadCell();
1361 minutes = dataPack.ReadCell();
1362 dataPack.ReadString(reason, sizeof(reason));
1363 dataPack.ReadString(authid, sizeof(authid));
1364 dataPack.ReadString(adminAuth, sizeof(adminAuth));
1365 dataPack.ReadString(adminIp, sizeof(adminIp));
1366 db.Escape(reason, banReason, sizeof(banReason));
1367
1368 if (results == null)
1369 {
1370 LogToFile(logFile, "Add Ban Select Query Failed: %s", error);
1371 if (admin && IsClientInGame(admin))
1372 PrintToChat(admin, "%sFailed to ban %s.", Prefix, authid);
1373 else
1374 PrintToServer("%sFailed to ban %s.", Prefix, authid);
1375 return;
1376 }
1377 if (results.RowCount)
1378 {
1379 if (admin && IsClientInGame(admin))
1380 PrintToChat(admin, "%s%s is already banned.", Prefix, authid);
1381 else
1382 PrintToServer("%s%s is already banned.", Prefix, authid);
1383 return;
1384 }
1385 if (serverID == -1)
1386 {
1387 FormatEx(Query, sizeof(Query), "INSERT INTO %s_bans (authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
1388 ('%s', '', UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
1389 (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1), ' ')",
1390 DatabasePrefix, authid, (minutes * 60), (minutes * 60), banReason, DatabasePrefix, adminAuth, adminAuth[8], adminIp, DatabasePrefix, ServerIp, ServerPort);
1391 } else {
1392 FormatEx(Query, sizeof(Query), "INSERT INTO %s_bans (authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
1393 ('%s', '', UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
1394 %d, ' ')",
1395 DatabasePrefix, authid, (minutes * 60), (minutes * 60), banReason, DatabasePrefix, adminAuth, adminAuth[8], adminIp, serverID);
1396 }
1397
1398 db.Query(InsertAddbanCallback, Query, dataPack, DBPrio_High);
1399}
1400
1401public void InsertAddbanCallback(Database db, DBResultSet results, const char[] error, DataPack dataPack)
1402{
1403 int admin, minutes;
1404 char authid[20];
1405 char reason[128];
1406
1407 dataPack.Reset();
1408 admin = dataPack.ReadCell();
1409 minutes = dataPack.ReadCell();
1410 dataPack.ReadString(reason, sizeof(reason));
1411 dataPack.ReadString(authid, sizeof(authid));
1412 delete dataPack;
1413
1414 // If error is not an empty string the query failed
1415 if (results == null)
1416 {
1417 LogToFile(logFile, "Add Ban Insert Query Failed: %s", error);
1418 if (admin && IsClientInGame(admin))
1419 {
1420 PrintToChat(admin, "%ssm_addban failed", Prefix);
1421 }
1422 return;
1423 }
1424
1425 LogAction(admin,
1426 -1,
1427 "\"%L\" added ban (minutes \"%i\") (id \"%s\") (reason \"%s\")",
1428 admin,
1429 minutes,
1430 authid,
1431 reason);
1432 if (admin && IsClientInGame(admin))
1433 {
1434 PrintToChat(admin, "%s%s successfully banned", Prefix, authid);
1435 } else {
1436 PrintToServer("%s%s successfully banned", Prefix, authid);
1437 }
1438}
1439
1440// ProcessQueueCallback is called as the result of selecting all the rows from the queue table
1441public void ProcessQueueCallback(Database db, DBResultSet results, const char[] error, any data)
1442{
1443 if (results == null)
1444 {
1445 LogToFile(logFile, "Failed to retrieve queued bans from sqlite database, %s", error);
1446 return;
1447 }
1448
1449 char auth[30];
1450 int time;
1451 int startTime;
1452 char reason[128];
1453 char name[64];
1454 char ip[20];
1455 char adminAuth[30];
1456 char adminIp[20];
1457 char query[1024];
1458 char banName[128];
1459 char banReason[256];
1460 while (results.MoreRows)
1461 {
1462 // Oh noes! What happened?!
1463 if (!results.FetchRow())
1464 continue;
1465
1466 // if we get to here then there are rows in the queue pending processing
1467 results.FetchString(0, auth, sizeof(auth));
1468 time = results.FetchInt(1);
1469 startTime = results.FetchInt(2);
1470 results.FetchString(3, reason, sizeof(reason));
1471 results.FetchString(4, name, sizeof(name));
1472 results.FetchString(5, ip, sizeof(ip));
1473 results.FetchString(6, adminAuth, sizeof(adminAuth));
1474 results.FetchString(7, adminIp, sizeof(adminIp));
1475 db.Escape(name, banName, sizeof(banName));
1476 db.Escape(reason, banReason, sizeof(banReason));
1477 if (startTime + time * 60 > GetTime() || time == 0)
1478 {
1479 // This ban is still valid and should be entered into the db
1480 if (serverID == -1)
1481 {
1482 FormatEx(query, sizeof(query),
1483 "INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid) VALUES \
1484 ('%s', '%s', '%s', %d, %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
1485 (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1))",
1486 DatabasePrefix, ip, auth, banName, startTime, startTime + time * 60, time * 60, banReason, DatabasePrefix, adminAuth, adminAuth[8], adminIp, DatabasePrefix, ServerIp, ServerPort);
1487 }
1488 else
1489 {
1490 FormatEx(query, sizeof(query),
1491 "INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid) VALUES \
1492 ('%s', '%s', '%s', %d, %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
1493 %d)",
1494 DatabasePrefix, ip, auth, banName, startTime, startTime + time * 60, time * 60, banReason, DatabasePrefix, adminAuth, adminAuth[8], adminIp, serverID);
1495 }
1496 DataPack authPack = new DataPack();
1497 authPack.WriteString(auth);
1498 authPack.Reset();
1499 db.Query(AddedFromSQLiteCallback, query, authPack);
1500 } else {
1501 // The ban is no longer valid and should be deleted from the queue
1502 FormatEx(query, sizeof(query), "DELETE FROM queue WHERE steam_id = '%s'", auth);
1503 SQLiteDB.Query(ErrorCheckCallback, query);
1504 }
1505 }
1506 // We have finished processing the queue but should process again in ProcessQueueTime minutes
1507 CreateTimer(float(ProcessQueueTime * 60), ProcessQueue);
1508}
1509
1510public void AddedFromSQLiteCallback(Database db, DBResultSet results, const char[] error, DataPack dataPack)
1511{
1512 char buffer[512];
1513 char auth[40];
1514
1515 dataPack.ReadString(auth, sizeof(auth));
1516 if (results == null)
1517 {
1518 // The insert was successful so delete the record from the queue
1519 FormatEx(buffer, sizeof(buffer), "DELETE FROM queue WHERE steam_id = '%s'", auth);
1520 SQLiteDB.Query(ErrorCheckCallback, buffer);
1521
1522 // They are added to main banlist, so remove the temp ban
1523 RemoveBan(auth, BANFLAG_AUTHID);
1524
1525 } else {
1526 // the insert failed so we leave the record in the queue and increase our temporary ban
1527 FormatEx(buffer, sizeof(buffer), "banid %d %s", ProcessQueueTime, auth);
1528 ServerCommand(buffer);
1529 }
1530 delete dataPack;
1531}
1532
1533public void ServerInfoCallback(Database db, DBResultSet results, const char[] error, any data)
1534{
1535 if (results == null)
1536 {
1537 LogToFile(logFile, "Server Select Query Failed: %s", error);
1538 return;
1539 }
1540
1541 if (!results.RowCount)
1542 {
1543 // get the game folder name used to determine the mod
1544 char desc[64], query[200];
1545 GetGameFolderName(desc, sizeof(desc));
1546 FormatEx(query, sizeof(query), "INSERT INTO %s_servers (ip, port, rcon, modid) VALUES ('%s', '%s', '', (SELECT mid FROM %s_mods WHERE modfolder = '%s'))", DatabasePrefix, ServerIp, ServerPort, DatabasePrefix, desc);
1547 db.Query(ErrorCheckCallback, query);
1548 }
1549}
1550
1551public void ErrorCheckCallback(Database db, DBResultSet results, const char[] error, any data)
1552{
1553 if (results == null)
1554 {
1555 LogToFile(logFile, "Query Failed: %s", error);
1556 }
1557}
1558
1559public void VerifyBan(Database db, DBResultSet results, const char[] error, int userid)
1560{
1561 char clientName[64], clientAuth[64], clientIp[64];
1562
1563 int client = GetClientOfUserId(userid);
1564
1565 if (!client)
1566 return;
1567
1568 /* Failure happen. Do retry with delay */
1569 if (results == null)
1570 {
1571 LogToFile(logFile, "Verify Ban Query Failed: %s", error);
1572 PlayerRecheck[client] = CreateTimer(RetryTime, ClientRecheck, client);
1573 return;
1574 }
1575
1576 GetClientIP(client, clientIp, sizeof(clientIp));
1577 GetClientAuthId(client, AuthId_Steam2, clientAuth, sizeof(clientAuth));
1578 GetClientName(client, clientName, sizeof(clientName));
1579
1580 if (results.RowCount > 0)
1581 {
1582 char buffer[40], Name[128], Query[512];
1583
1584 // Amending to ban record's IP field
1585 if (results.FetchRow())
1586 {
1587 char sIP[32];
1588
1589 int iBid = results.FetchInt(0);
1590 results.FetchString(1, sIP, sizeof sIP);
1591
1592 if (StrEqual(sIP, ""))
1593 {
1594 char sQuery[256];
1595
1596 FormatEx(sQuery, sizeof sQuery, "UPDATE %s_bans SET `ip` = '%s' WHERE `bid` = '%d'", DatabasePrefix, clientIp, iBid);
1597
1598 DB.Query(SQL_OnIPMend, sQuery, client);
1599 }
1600 }
1601
1602 DB.Escape(clientName, Name, sizeof Name);
1603
1604 if (serverID == -1)
1605 {
1606 FormatEx(Query, sizeof(Query), "INSERT INTO %s_banlog (sid ,time ,name ,bid) VALUES \
1607 ((SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1), UNIX_TIMESTAMP(), '%s', \
1608 (SELECT bid FROM %s_bans WHERE ((type = 0 AND authid REGEXP '^STEAM_[0-9]:%s$') OR (type = 1 AND ip = '%s')) AND RemoveType IS NULL LIMIT 0,1))",
1609 DatabasePrefix, DatabasePrefix, ServerIp, ServerPort, Name, DatabasePrefix, clientAuth[8], clientIp);
1610 }
1611 else
1612 {
1613 FormatEx(Query, sizeof(Query), "INSERT INTO %s_banlog (sid ,time ,name ,bid) VALUES \
1614 (%d, UNIX_TIMESTAMP(), '%s', \
1615 (SELECT bid FROM %s_bans WHERE ((type = 0 AND authid REGEXP '^STEAM_[0-9]:%s$') OR (type = 1 AND ip = '%s')) AND RemoveType IS NULL LIMIT 0,1))",
1616 DatabasePrefix, serverID, Name, DatabasePrefix, clientAuth[8], clientIp);
1617 }
1618
1619 db.Query(ErrorCheckCallback, Query, client, DBPrio_High);
1620
1621 FormatEx(buffer, sizeof(buffer), "banid 5 %s", clientAuth);
1622 ServerCommand(buffer);
1623 KickClient(client, "%t", "Banned Check Site", WebsiteAddress);
1624
1625 return;
1626 }
1627
1628 #if defined DEBUG
1629 LogToFile(logFile, "%s is NOT banned.", clientAuth);
1630 #endif
1631
1632 PlayerStatus[client] = true;
1633}
1634
1635public void SQL_OnIPMend(Database db, DBResultSet results, const char[] error, int iClient)
1636{
1637 if (results == null)
1638 {
1639 char sIP[32], sSteamID[32];
1640
1641 GetClientAuthId(iClient, AuthId_Steam3, sSteamID, sizeof sSteamID);
1642 GetClientIP(iClient, sIP, sizeof sIP);
1643
1644 LogToFile(logFile, "Failed to mend IP address for %s (%s): %s", sSteamID, sIP, error);
1645 }
1646}
1647
1648public void AdminsDone(Database db, DBResultSet results, const char[] error, any data)
1649{
1650 //SELECT authid, srv_password , srv_group, srv_flags, user
1651 if (results == null)
1652 {
1653 --curLoading;
1654 CheckLoadAdmins();
1655 LogToFile(logFile, "Failed to retrieve admins from the database, %s", error);
1656 return;
1657 }
1658 char authType[] = "steam";
1659 char identity[66];
1660 char password[66];
1661 char groups[256];
1662 char flags[32];
1663 char name[66];
1664 int admCount = 0;
1665 int Immunity = 0;
1666 AdminId curAdm = INVALID_ADMIN_ID;
1667 KeyValues adminsKV = new KeyValues("Admins");
1668
1669 while (results.FetchRow())
1670 {
1671 if (results.IsFieldNull(0))
1672 continue; // Sometimes some rows return NULL due to some setups
1673
1674 results.FetchString(0, identity, 66);
1675 results.FetchString(1, password, 66);
1676 results.FetchString(2, groups, 256);
1677 results.FetchString(3, flags, 32);
1678 results.FetchString(4, name, 66);
1679
1680 Immunity = results.FetchInt(5);
1681
1682 TrimString(name);
1683 TrimString(identity);
1684 TrimString(groups);
1685 TrimString(flags);
1686
1687 // Disable writing to file if they chose to
1688 if (backupConfig)
1689 {
1690 adminsKV.JumpToKey(name, true);
1691
1692 adminsKV.SetString("auth", authType);
1693 adminsKV.SetString("identity", identity);
1694
1695 if (strlen(flags) > 0)
1696 adminsKV.SetString("flags", flags);
1697
1698 if (strlen(groups) > 0)
1699 adminsKV.SetString("group", groups);
1700
1701 if (strlen(password) > 0)
1702 adminsKV.SetString("password", password);
1703
1704 if (Immunity > 0)
1705 adminsKV.SetNum("immunity", Immunity);
1706
1707 adminsKV.Rewind();
1708 }
1709
1710 // find or create the admin using that identity
1711 if ((curAdm = FindAdminByIdentity(authType, identity)) == INVALID_ADMIN_ID)
1712 {
1713 curAdm = CreateAdmin(name);
1714 // That should never happen!
1715 if (!curAdm.BindIdentity(authType, identity))
1716 {
1717 LogToFile(logFile, "Unable to bind admin %s to identity %s", name, identity);
1718 RemoveAdmin(curAdm);
1719 continue;
1720 }
1721 }
1722
1723 #if defined DEBUG
1724 LogToFile(logFile, "Given %s (%s) admin", name, identity);
1725 #endif
1726
1727 int curPos = 0;
1728 GroupId curGrp = INVALID_GROUP_ID;
1729 int numGroups;
1730 char iterGroupName[64];
1731
1732 // Who thought this comma seperated group parsing would be a good idea?!
1733 /*
1734 decl String:grp[64];
1735 new nextPos = 0;
1736 while ((nextPos = SplitString(groups[curPos],",",grp,64)) != -1)
1737 {
1738 curPos += nextPos;
1739 curGrp = FindAdmGroup(grp);
1740 if (curGrp == INVALID_GROUP_ID)
1741 {
1742 LogToFile(logFile, "Unknown group \"%s\"",grp);
1743 }
1744 else
1745 {
1746 // Check, if he's not in the group already.
1747 numGroups = GetAdminGroupCount(curAdm);
1748 for(new i=0;i<numGroups;i++)
1749 {
1750 GetAdminGroup(curAdm, i, iterGroupName, sizeof(iterGroupName));
1751 // Admin is already part of the group, so don't try to inherit its permissions.
1752 if(StrEqual(iterGroupName, grp))
1753 {
1754 numGroups = -2;
1755 break;
1756 }
1757 }
1758 // Only try to inherit the group, if it's a new one.
1759 if (numGroups != -2 && !AdminInheritGroup(curAdm,curGrp))
1760 {
1761 LogToFile(logFile, "Unable to inherit group \"%s\"",grp);
1762 }
1763 }
1764 }*/
1765
1766 if (strcmp(groups[curPos], "") != 0)
1767 {
1768 curGrp = FindAdmGroup(groups[curPos]);
1769 if (curGrp == INVALID_GROUP_ID)
1770 {
1771 LogToFile(logFile, "Unknown group \"%s\"", groups[curPos]);
1772 }
1773 else
1774 {
1775 // Check, if he's not in the group already.
1776 numGroups = curAdm.GroupCount;
1777 for (int i = 0; i < numGroups; i++)
1778 {
1779 curAdm.GetGroup(i, iterGroupName, sizeof(iterGroupName));
1780 // Admin is already part of the group, so don't try to inherit its permissions.
1781 if (StrEqual(iterGroupName, groups[curPos]))
1782 {
1783 numGroups = -2;
1784 break;
1785 }
1786 }
1787
1788 // Only try to inherit the group, if it's a new one.
1789 if (numGroups != -2 && !curAdm.InheritGroup(curGrp))
1790 {
1791 LogToFile(logFile, "Unable to inherit group \"%s\"", groups[curPos]);
1792 }
1793
1794 if (curAdm.ImmunityLevel < Immunity)
1795 {
1796 curAdm.ImmunityLevel = Immunity;
1797 }
1798 #if defined DEBUG
1799 LogToFile(logFile, "Admin %s (%s) has %d immunity", name, identity, Immunity);
1800 #endif
1801 }
1802 }
1803
1804 if (strlen(password) > 0)
1805 curAdm.SetPassword(password);
1806
1807 for (int i = 0; i < strlen(flags); ++i)
1808 {
1809 if (flags[i] < 'a' || flags[i] > 'z')
1810 continue;
1811
1812 if (g_FlagLetters[flags[i]-'a'] < Admin_Reservation)
1813 continue;
1814
1815 curAdm.SetFlag(g_FlagLetters[flags[i]-'a'], true);
1816 }
1817 ++admCount;
1818 }
1819
1820 if (backupConfig)
1821 adminsKV.ExportToFile(adminsLoc);
1822 delete adminsKV;
1823
1824 #if defined DEBUG
1825 LogToFile(logFile, "Finished loading %i admins.", admCount);
1826 #endif
1827
1828 --curLoading;
1829 CheckLoadAdmins();
1830}
1831
1832public void GroupsDone(Database db, DBResultSet results, const char[] error, any data)
1833{
1834 if (results == null)
1835 {
1836 curLoading--;
1837 CheckLoadAdmins();
1838 LogToFile(logFile, "Failed to retrieve groups from the database, %s", error);
1839 return;
1840 }
1841
1842 char grpName[128], immuneGrpName[128];
1843 char grpFlags[32];
1844 int Immunity;
1845 int grpCount = 0;
1846 KeyValues groupsKV = new KeyValues("Groups");
1847
1848 GroupId curGrp = INVALID_GROUP_ID;
1849 while (results.FetchRow())
1850 {
1851 if (results.IsFieldNull(0))
1852 continue; // Sometimes some rows return NULL due to some setups
1853 results.FetchString(0, grpName, 128);
1854 results.FetchString(1, grpFlags, 32);
1855 Immunity = results.FetchInt(2);
1856 results.FetchString(3, immuneGrpName, 128);
1857
1858 TrimString(grpName);
1859 TrimString(grpFlags);
1860 TrimString(immuneGrpName);
1861
1862 // Ignore empty rows..
1863 if (!strlen(grpName))
1864 continue;
1865
1866 curGrp = CreateAdmGroup(grpName);
1867
1868 if (backupConfig)
1869 {
1870 groupsKV.JumpToKey(grpName, true);
1871 if (strlen(grpFlags) > 0)
1872 groupsKV.SetString("flags", grpFlags);
1873 if (Immunity > 0)
1874 groupsKV.SetNum("immunity", Immunity);
1875
1876 groupsKV.Rewind();
1877 }
1878
1879 if (curGrp == INVALID_GROUP_ID)
1880 { //This occurs when the group already exists
1881 curGrp = FindAdmGroup(grpName);
1882 }
1883
1884 for (int i = 0; i < strlen(grpFlags); ++i)
1885 {
1886 if (grpFlags[i] < 'a' || grpFlags[i] > 'z')
1887 continue;
1888
1889 if (g_FlagLetters[grpFlags[i]-'a'] < Admin_Reservation)
1890 continue;
1891
1892 curGrp.SetFlag(g_FlagLetters[grpFlags[i]-'a'], true);
1893 }
1894
1895 // Set the group immunity.
1896 if (Immunity > 0)
1897 {
1898 curGrp.ImmunityLevel = Immunity;
1899 #if defined DEBUG
1900 LogToFile(logFile, "Group %s has %d immunity", grpName, Immunity);
1901 #endif
1902 }
1903
1904 grpCount++;
1905 }
1906
1907 if (backupConfig)
1908 groupsKV.ExportToFile(groupsLoc);
1909 delete groupsKV;
1910
1911 #if defined DEBUG
1912 LogToFile(logFile, "Finished loading %i groups.", grpCount);
1913 #endif
1914
1915 // Load the group overrides
1916 char query[512];
1917 FormatEx(query, 512, "SELECT sg.name, so.type, so.name, so.access FROM %s_srvgroups_overrides so LEFT JOIN %s_srvgroups sg ON sg.id = so.group_id ORDER BY sg.id", DatabasePrefix, DatabasePrefix);
1918 db.Query(LoadGroupsOverrides, query);
1919
1920 /*if (reparse)
1921 {
1922 decl String:query[512];
1923 FormatEx(query,512,"SELECT name, immunity, groups_immune FROM %s_srvgroups ORDER BY id",DatabasePrefix);
1924 db.Query(GroupsSecondPass,query);
1925 }
1926 else
1927 {
1928 curLoading--;
1929 CheckLoadAdmins();
1930 }*/
1931}
1932
1933// Reparse to apply inherited immunity
1934public void GroupsSecondPass(Database db, DBResultSet results, const char[] error, any data)
1935{
1936 if (results == null)
1937 {
1938 curLoading--;
1939 CheckLoadAdmins();
1940 LogToFile(logFile, "Failed to retrieve groups from the database, %s", error);
1941 return;
1942 }
1943
1944 char grpName[128], immunityGrpName[128];
1945
1946 GroupId curGrp = INVALID_GROUP_ID;
1947 GroupId immuneGrp = INVALID_GROUP_ID;
1948 while (results.FetchRow())
1949 {
1950 if (results.IsFieldNull(0))
1951 continue; // Sometimes some rows return NULL due to some setups
1952
1953 results.FetchString(0, grpName, 128);
1954 TrimString(grpName);
1955 if (strlen(grpName) == 0)
1956 continue;
1957
1958 results.FetchString(2, immunityGrpName, sizeof(immunityGrpName));
1959 TrimString(immunityGrpName);
1960
1961 curGrp = FindAdmGroup(grpName);
1962 if (curGrp == INVALID_GROUP_ID)
1963 continue;
1964
1965 immuneGrp = FindAdmGroup(immunityGrpName);
1966 if (immuneGrp == INVALID_GROUP_ID)
1967 continue;
1968
1969 curGrp.AddGroupImmunity(immuneGrp);
1970
1971 #if defined DEBUG
1972 LogToFile(logFile, "Group %s inhertied immunity from group %s", grpName, immunityGrpName);
1973 #endif
1974 }
1975 --curLoading;
1976 CheckLoadAdmins();
1977}
1978
1979public void LoadGroupsOverrides(Database db, DBResultSet results, const char[] error, any data)
1980{
1981 if (results == null)
1982 {
1983 curLoading--;
1984 CheckLoadAdmins();
1985 LogToFile(logFile, "Failed to retrieve group overrides from the database, %s", error);
1986 return;
1987 }
1988
1989 char sGroupName[128], sType[16], sCommand[64], sAllowed[16];
1990 OverrideRule iRule;
1991 OverrideType iType;
1992
1993 KeyValues groupsKV = new KeyValues("Groups");
1994 groupsKV.ImportFromFile(groupsLoc);
1995
1996 GroupId curGrp = INVALID_GROUP_ID;
1997 while (results.FetchRow())
1998 {
1999 if (results.IsFieldNull(0))
2000 continue; // Sometimes some rows return NULL due to some setups
2001
2002 results.FetchString(0, sGroupName, sizeof(sGroupName));
2003 TrimString(sGroupName);
2004 if (strlen(sGroupName) == 0)
2005 continue;
2006
2007 results.FetchString(1, sType, sizeof(sType));
2008 results.FetchString(2, sCommand, sizeof(sCommand));
2009 results.FetchString(3, sAllowed, sizeof(sAllowed));
2010
2011 curGrp = FindAdmGroup(sGroupName);
2012 if (curGrp == INVALID_GROUP_ID)
2013 continue;
2014
2015 iRule = StrEqual(sAllowed, "allow") ? Command_Allow : Command_Deny;
2016 iType = StrEqual(sType, "group") ? Override_CommandGroup : Override_Command;
2017
2018 #if defined DEBUG
2019 PrintToServer("AddAdmGroupCmdOverride(%i, %s, %i, %i)", curGrp, sCommand, iType, iRule);
2020 #endif
2021
2022 // Save overrides into admin_groups.cfg backup
2023 if (groupsKV.JumpToKey(sGroupName))
2024 {
2025 groupsKV.JumpToKey("Overrides", true);
2026 if (iType == Override_Command)
2027 groupsKV.SetString(sCommand, sAllowed);
2028 else
2029 {
2030 Format(sCommand, sizeof(sCommand), "@%s", sCommand);
2031 groupsKV.SetString(sCommand, sAllowed);
2032 }
2033 groupsKV.Rewind();
2034 }
2035
2036 curGrp.AddCommandOverride(sCommand, iType, iRule);
2037 }
2038 curLoading--;
2039 CheckLoadAdmins();
2040
2041 if (backupConfig)
2042 groupsKV.ExportToFile(groupsLoc);
2043 delete groupsKV;
2044}
2045
2046public void OverridesDone(Database db, DBResultSet results, const char[] error, any data)
2047{
2048 if (results == null)
2049 {
2050 LogToFile(logFile, "Failed to retrieve overrides from the database, %s", error);
2051 ParseBackupConfig_Overrides();
2052 return;
2053 }
2054
2055 KeyValues hKV = new KeyValues("SB_Overrides");
2056
2057 char sFlags[32], sName[64], sType[64];
2058 while (results.FetchRow())
2059 {
2060 results.FetchString(0, sType, sizeof(sType));
2061 results.FetchString(1, sName, sizeof(sName));
2062 results.FetchString(2, sFlags, sizeof(sFlags));
2063
2064 // KeyValuesToFile won't add that key, if the value is ""..
2065 if (sFlags[0] == '\0')
2066 {
2067 sFlags[0] = ' ';
2068 sFlags[1] = '\0';
2069 }
2070
2071 #if defined DEBUG
2072 LogToFile(logFile, "Adding override (%s, %s, %s)", sType, sName, sFlags);
2073 #endif
2074
2075 if (StrEqual(sType, "command"))
2076 {
2077 AddCommandOverride(sName, Override_Command, ReadFlagString(sFlags));
2078 hKV.JumpToKey("override_commands", true);
2079 hKV.SetString(sName, sFlags);
2080 hKV.GoBack();
2081 }
2082 else if (StrEqual(sType, "group"))
2083 {
2084 AddCommandOverride(sName, Override_CommandGroup, ReadFlagString(sFlags));
2085 hKV.JumpToKey("override_groups", true);
2086 hKV.SetString(sName, sFlags);
2087 hKV.GoBack();
2088 }
2089 }
2090
2091 hKV.Rewind();
2092
2093 if (backupConfig)
2094 hKV.ExportToFile(overridesLoc);
2095 delete hKV;
2096}
2097
2098// TIMER CALL BACKS //
2099
2100public Action ClientRecheck(Handle timer, any client)
2101{
2102 char Authid[64];
2103 if (!PlayerStatus[client] && IsClientConnected(client) && GetClientAuthId(client, AuthId_Steam2, Authid, sizeof(Authid)))
2104 {
2105 OnClientAuthorized(client, Authid);
2106 }
2107
2108 PlayerRecheck[client] = INVALID_HANDLE;
2109 return Plugin_Stop;
2110}
2111
2112/*
2113public Action PruneBans(Handle timer)
2114{
2115 char Query[512];
2116 FormatEx(Query, sizeof(Query),
2117 "UPDATE %s_bans SET RemovedBy = 0, RemoveType = 'E', RemovedOn = UNIX_TIMESTAMP() WHERE length != '0' AND ends < UNIX_TIMESTAMP()",
2118 DatabasePrefix);
2119
2120 DB.Query(ErrorCheckCallback, Query);
2121 return Plugin_Continue;
2122}
2123*/
2124
2125public Action ProcessQueue(Handle timer, any data)
2126{
2127 char buffer[512];
2128 Format(buffer, sizeof(buffer), "SELECT steam_id, time, start_time, reason, name, ip, admin_id, admin_ip FROM queue");
2129 SQLiteDB.Query(ProcessQueueCallback, buffer);
2130}
2131
2132// PARSER //
2133
2134static void InitializeConfigParser()
2135{
2136 if (ConfigParser == null)
2137 {
2138 ConfigParser = new SMCParser();
2139 ConfigParser.OnEnterSection = ReadConfig_NewSection;
2140 ConfigParser.OnKeyValue = ReadConfig_KeyValue;
2141 ConfigParser.OnLeaveSection = ReadConfig_EndSection;
2142 }
2143}
2144
2145static void InternalReadConfig(const char[] path)
2146{
2147 ConfigState = ConfigStateNone;
2148
2149 SMCError err = ConfigParser.ParseFile(path);
2150
2151 if (err != SMCError_Okay)
2152 {
2153 char buffer[64];
2154 PrintToServer("%s", ConfigParser.GetErrorString(err, buffer, sizeof(buffer)) ? buffer : "Fatal parse error");
2155 }
2156}
2157
2158public SMCResult ReadConfig_NewSection(SMCParser smc, const char[] name, bool opt_quotes)
2159{
2160 if (name[0])
2161 {
2162 if (strcmp("Config", name, false) == 0) {
2163 ConfigState = ConfigStateConfig;
2164 } else if (strcmp("BanReasons", name, false) == 0) {
2165 ConfigState = ConfigStateReasons;
2166 } else if (strcmp("HackingReasons", name, false) == 0) {
2167 ConfigState = ConfigStateHacking;
2168 } else if (strcmp("BanTime", name, false) == 0) {
2169 ConfigState = ConfigStateTime;
2170 }
2171 }
2172 return SMCParse_Continue;
2173}
2174
2175public SMCResult ReadConfig_KeyValue(SMCParser smc, const char[] key, const char[] value, bool key_quotes, bool value_quotes)
2176{
2177 if (!key[0])
2178 return SMCParse_Continue;
2179
2180 switch (ConfigState)
2181 {
2182 case ConfigStateConfig:
2183 {
2184 if (strcmp("website", key, false) == 0)
2185 {
2186 strcopy(WebsiteAddress, sizeof(WebsiteAddress), value);
2187 }
2188 else if (strcmp("Addban", key, false) == 0)
2189 {
2190 if (StringToInt(value) == 0)
2191 {
2192 CommandDisable |= DISABLE_ADDBAN;
2193 }
2194 }
2195 else if (strcmp("AutoAddServer", key, false) == 0)
2196 {
2197 AutoAdd = StringToInt(value) == 1;
2198 }
2199 else if (strcmp("Unban", key, false) == 0)
2200 {
2201 if (StringToInt(value) == 0)
2202 {
2203 CommandDisable |= DISABLE_UNBAN;
2204 }
2205 }
2206 else if (strcmp("DatabasePrefix", key, false) == 0)
2207 {
2208 strcopy(DatabasePrefix, sizeof(DatabasePrefix), value);
2209
2210 if (DatabasePrefix[0] == '\0')
2211 {
2212 DatabasePrefix = "sb";
2213 }
2214 }
2215 else if (strcmp("RetryTime", key, false) == 0)
2216 {
2217 RetryTime = StringToFloat(value);
2218 if (RetryTime < 15.0)
2219 {
2220 RetryTime = 15.0;
2221 } else if (RetryTime > 60.0) {
2222 RetryTime = 60.0;
2223 }
2224 }
2225 else if (strcmp("ProcessQueueTime", key, false) == 0)
2226 {
2227 ProcessQueueTime = StringToInt(value);
2228 }
2229 else if (strcmp("BackupConfigs", key, false) == 0)
2230 {
2231 backupConfig = StringToInt(value) == 1;
2232 }
2233 else if (strcmp("EnableAdmins", key, false) == 0)
2234 {
2235 enableAdmins = StringToInt(value) == 1;
2236 }
2237 else if (strcmp("RequireSiteLogin", key, false) == 0)
2238 {
2239 requireSiteLogin = StringToInt(value) == 1;
2240 }
2241 else if (strcmp("ServerID", key, false) == 0)
2242 {
2243 serverID = StringToInt(value);
2244 }
2245 }
2246
2247 case ConfigStateReasons:
2248 {
2249 if (ReasonMenuHandle != INVALID_HANDLE)
2250 {
2251 AddMenuItem(ReasonMenuHandle, key, value);
2252 }
2253 }
2254 case ConfigStateHacking:
2255 {
2256 if (HackingMenuHandle != INVALID_HANDLE)
2257 {
2258 AddMenuItem(HackingMenuHandle, key, value);
2259 }
2260 }
2261 case ConfigStateTime:
2262 {
2263 if (StringToInt(key) > -1 && TimeMenuHandle != INVALID_HANDLE)
2264 {
2265 AddMenuItem(TimeMenuHandle, key, value);
2266 }
2267 }
2268 }
2269 return SMCParse_Continue;
2270}
2271
2272public SMCResult ReadConfig_EndSection(SMCParser smc)
2273{
2274 return SMCParse_Continue;
2275}
2276
2277
2278/*********************************************************
2279 * Ban Player from server
2280 *
2281 * @param client The client index of the player to ban
2282 * @param time The time to ban the player for (in minutes, 0 = permanent)
2283 * @param reason The reason to ban the player from the server
2284 * @noreturn
2285 *********************************************************/
2286public int Native_SBBanPlayer(Handle plugin, int numParams)
2287{
2288 int client = GetNativeCell(1);
2289 int target = GetNativeCell(2);
2290 int time = GetNativeCell(3);
2291 char reason[128];
2292 GetNativeString(4, reason, 128);
2293
2294 if (reason[0] == '\0')
2295 strcopy(reason, sizeof(reason), "Banned by SourceBans");
2296
2297 if (client && IsClientInGame(client))
2298 {
2299 AdminId aid = GetUserAdmin(client);
2300 if (aid == INVALID_ADMIN_ID)
2301 {
2302 ThrowNativeError(SP_ERROR_NATIVE, "Ban Error: Player is not an admin.");
2303 return 0;
2304 }
2305
2306 if (!aid.HasFlag(Admin_Ban))
2307 {
2308 ThrowNativeError(SP_ERROR_NATIVE, "Ban Error: Player does not have BAN flag.");
2309 return 0;
2310 }
2311 }
2312
2313 PrepareBan(client, target, time, reason, sizeof(reason));
2314 return true;
2315}
2316
2317public int Native_SBReportPlayer(Handle plugin, int numParams)
2318{
2319 if (numParams < 3)
2320 {
2321 ThrowNativeError(SP_ERROR_NATIVE, "Invalid amount of arguments. Received %d arguments", numParams);
2322 return;
2323 }
2324
2325 int iReporter = GetNativeCell(1)
2326 , iTarget = GetNativeCell(2)
2327 , iReasonLen;
2328
2329 int iTime = GetTime();
2330
2331 GetNativeStringLength(3, iReasonLen);
2332
2333 iReasonLen++;
2334
2335 char[] sReason = new char[iReasonLen];
2336
2337 GetNativeString(3, sReason, iReasonLen);
2338
2339 char sRAuth[32], sTAuth[32], sRName[MAX_NAME_LENGTH + 1], sTName[MAX_NAME_LENGTH + 1],
2340 sRIP[16], sTIP[16], sREscapedName[MAX_NAME_LENGTH * 2 + 1], sTEscapedName[MAX_NAME_LENGTH * 2 + 1];
2341
2342 char[] sEscapedReason = new char[iReasonLen * 2 + 1];
2343
2344 GetClientAuthId(iReporter, AuthId_Steam2, sRAuth, sizeof sRAuth);
2345 GetClientAuthId(iTarget, AuthId_Steam2, sTAuth, sizeof sTAuth);
2346
2347 GetClientName(iReporter, sRName, sizeof sRName);
2348 GetClientName(iTarget, sTName, sizeof sTName);
2349
2350 GetClientIP(iReporter, sRIP, sizeof sRIP);
2351 GetClientIP(iTarget, sTIP, sizeof sTIP);
2352
2353 DB.Escape(sRName, sREscapedName, sizeof sREscapedName);
2354 DB.Escape(sTName, sTEscapedName, sizeof sTEscapedName);
2355 DB.Escape(sReason, sEscapedReason, iReasonLen * 2 + 1);
2356
2357 char[] sQuery = new char[512 + (iReasonLen * 2 + 1)];
2358
2359 Format(sQuery, 512 + (iReasonLen * 2 + 1), "INSERT INTO %s_submissions (`submitted`, `modid`, `SteamId`, `name`, `email`, `reason`, `ip`, `subname`, `sip`, `archiv`, `server`)"
2360 ... "VALUES ('%d', 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0, '%d')", DatabasePrefix, iTime, sTAuth, sTEscapedName, sRAuth, sEscapedReason, sRIP, sREscapedName, sTIP, (serverID != -1) ? serverID : 0);
2361
2362 DataPack dataPack = new DataPack();
2363
2364 dataPack.WriteCell(iReporter);
2365 dataPack.WriteCell(iTarget);
2366 dataPack.WriteCell(iReasonLen);
2367 dataPack.WriteString(sReason);
2368
2369 DB.Query(SQL_OnReportPlayer, sQuery, dataPack);
2370}
2371
2372public void SQL_OnReportPlayer(Database db, DBResultSet results, const char[] error, DataPack dataPack)
2373{
2374 if (results == null)
2375 LogToFile(logFile, "Failed to submit report: %s", error);
2376 else
2377 {
2378 dataPack.Reset();
2379
2380 int iReporter = dataPack.ReadCell();
2381 int iTarget = dataPack.ReadCell();
2382 int iReasonLen = dataPack.ReadCell();
2383
2384 char[] sReason = new char[iReasonLen];
2385
2386 dataPack.ReadString(sReason, iReasonLen);
2387 delete dataPack;
2388
2389 Call_StartForward(g_hFwd_OnReportAdded);
2390 Call_PushCell(iReporter);
2391 Call_PushCell(iTarget);
2392 Call_PushString(sReason);
2393 Call_Finish();
2394 }
2395}
2396
2397// STOCK FUNCTIONS //
2398
2399public void InitializeBackupDB()
2400{
2401 char error[255];
2402
2403 SQLiteDB = SQLite_UseDatabase("sourcebans-queue", error, sizeof(error));
2404 if (SQLiteDB == INVALID_HANDLE)
2405 SetFailState(error);
2406
2407 SQL_LockDatabase(SQLiteDB);
2408 SQL_FastQuery(SQLiteDB, "CREATE TABLE IF NOT EXISTS queue (steam_id TEXT PRIMARY KEY ON CONFLICT REPLACE, time INTEGER, start_time INTEGER, reason TEXT, name TEXT, ip TEXT, admin_id TEXT, admin_ip TEXT);");
2409 SQL_UnlockDatabase(SQLiteDB);
2410}
2411
2412public bool CreateBan(int client, int target, int time, const char[] reason)
2413{
2414 char adminIp[24], adminAuth[64];
2415 int admin = client;
2416
2417 // The server is the one calling the ban
2418 if (!admin)
2419 {
2420 if (reason[0] == '\0')
2421 {
2422 // We cannot pop the reason menu if the command was issued from the server
2423 PrintToServer("%s%T", Prefix, "Include Reason", LANG_SERVER);
2424 return false;
2425 }
2426
2427 // setup dummy adminAuth and adminIp for server
2428 strcopy(adminAuth, sizeof(adminAuth), "STEAM_ID_SERVER");
2429 strcopy(adminIp, sizeof(adminIp), ServerIp);
2430 } else {
2431 GetClientIP(admin, adminIp, sizeof(adminIp));
2432 GetClientAuthId(admin, AuthId_Steam2, adminAuth, sizeof(adminAuth));
2433 }
2434
2435 // target information
2436 char ip[24], auth[64], name[64];
2437
2438 GetClientName(target, name, sizeof(name));
2439 GetClientIP(target, ip, sizeof(ip));
2440 if (!GetClientAuthId(target, AuthId_Steam2, auth, sizeof(auth)))
2441 return false;
2442
2443 int userid = admin ? GetClientUserId(admin) : 0;
2444
2445 // Pack everything into a data pack so we can retain it
2446 DataPack dataPack = new DataPack();
2447 DataPack reasonPack = new DataPack();
2448
2449 WritePackString(reasonPack, reason);
2450
2451 dataPack.WriteCell(admin);
2452 dataPack.WriteCell(target);
2453 dataPack.WriteCell(userid);
2454 dataPack.WriteCell(GetClientUserId(target));
2455 dataPack.WriteCell(time);
2456 dataPack.WriteCell(reasonPack);
2457 dataPack.WriteString(name);
2458 dataPack.WriteString(auth);
2459 dataPack.WriteString(ip);
2460 dataPack.WriteString(adminAuth);
2461 dataPack.WriteString(adminIp);
2462
2463 dataPack.Reset();
2464 reasonPack.Reset();
2465
2466 if (reason[0] != '\0')
2467 {
2468 // if we have a valid reason pass move forward with the ban
2469 if (DB != INVALID_HANDLE)
2470 {
2471 UTIL_InsertBan(time, name, auth, ip, reason, adminAuth, adminIp, dataPack);
2472 } else {
2473 UTIL_InsertTempBan(time, name, auth, ip, reason, adminAuth, adminIp, dataPack);
2474 }
2475 } else {
2476 // We need a reason so offer the administrator a menu of reasons
2477 PlayerDataPack[admin] = dataPack;
2478 DisplayMenu(ReasonMenuHandle, admin, MENU_TIME_FOREVER);
2479 ReplyToCommand(admin, "%c[%cSourceBans%c]%c %t", GREEN, NAMECOLOR, GREEN, NAMECOLOR, "Check Menu");
2480 }
2481
2482 Call_StartForward(g_hFwd_OnBanAdded);
2483 Call_PushCell(client);
2484 Call_PushCell(target);
2485 Call_PushCell(time);
2486 Call_PushString(reason);
2487 Call_Finish();
2488
2489 return true;
2490}
2491
2492stock void UTIL_InsertBan(int time, const char[] Name, const char[] Authid, const char[] Ip, const char[] Reason, const char[] AdminAuthid, const char[] AdminIp, DataPack dataPack)
2493{
2494 //new Handle:dummy;
2495 //PruneBans(dummy);
2496 char banName[128];
2497 char banReason[256];
2498 char Query[1024];
2499 DB.Escape(Name, banName, sizeof(banName));
2500 DB.Escape(Reason, banReason, sizeof(banReason));
2501 if (serverID == -1)
2502 {
2503 FormatEx(Query, sizeof(Query), "INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
2504 ('%s', '%s', '%s', UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + %d, %d, '%s', IFNULL((SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'),'0'), '%s', \
2505 (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1), ' ')",
2506 DatabasePrefix, Ip, Authid, banName, (time * 60), (time * 60), banReason, DatabasePrefix, AdminAuthid, AdminAuthid[8], AdminIp, DatabasePrefix, ServerIp, ServerPort);
2507 } else {
2508 FormatEx(Query, sizeof(Query), "INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
2509 ('%s', '%s', '%s', UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + %d, %d, '%s', IFNULL((SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'),'0'), '%s', \
2510 %d, ' ')",
2511 DatabasePrefix, Ip, Authid, banName, (time * 60), (time * 60), banReason, DatabasePrefix, AdminAuthid, AdminAuthid[8], AdminIp, serverID);
2512 }
2513 DB.Query(VerifyInsert, Query, dataPack, DBPrio_High);
2514}
2515
2516stock void UTIL_InsertTempBan(int time, const char[] name, const char[] auth, const char[] ip, const char[] reason, const char[] adminAuth, const char[] adminIp, DataPack dataPack)
2517{
2518 int admin = dataPack.ReadCell(); // admin index
2519
2520 int client = dataPack.ReadCell();
2521
2522 dataPack.ReadCell(); // admin userid
2523 dataPack.ReadCell(); // target userid
2524 dataPack.ReadCell(); // time
2525
2526 DataPack reasonPack = view_as<DataPack>(dataPack.ReadCell());
2527
2528 if (reasonPack != null)
2529 delete reasonPack;
2530 delete dataPack;
2531
2532 // we add a temporary ban and then add the record into the queue to be processed when the database is available
2533 char buffer[50];
2534
2535 Format(buffer, sizeof(buffer), "banid %d %s", ProcessQueueTime, auth);
2536
2537 ServerCommand(buffer);
2538
2539 if (IsClientInGame(client))
2540 {
2541 char length[32];
2542 if(time == 0)
2543 FormatEx(length, sizeof(length), "permament");
2544 else
2545 FormatEx(length, sizeof(length), "%d %s", time, time == 1 ? "minute" : "minutes");
2546 KickClient(client, "%t\n\n%t", "Banned Check Site", WebsiteAddress, "Kick Reason", admin, reason, length);
2547 }
2548
2549 char banName[128], banReason[256], query[512];
2550
2551 SQLiteDB.Escape(name, banName, sizeof(banName));
2552 SQLiteDB.Escape(reason, banReason, sizeof(banReason));
2553
2554 FormatEx(query, sizeof(query), "INSERT INTO queue VALUES ('%s', %i, %i, '%s', '%s', '%s', '%s', '%s')",
2555 auth, time, GetTime(), banReason, banName, ip, adminAuth, adminIp);
2556
2557 SQLiteDB.Query(ErrorCheckCallback, query);
2558}
2559
2560stock void CheckLoadAdmins()
2561{
2562 for (int i = 1; i <= MaxClients; i++)
2563 {
2564 if (IsClientInGame(i) && IsClientAuthorized(i))
2565 {
2566 RunAdminCacheChecks(i);
2567 NotifyPostAdminCheck(i);
2568 }
2569 }
2570}
2571
2572stock void InsertServerInfo()
2573{
2574 if (DB == INVALID_HANDLE) {
2575 return;
2576 }
2577
2578 char query[100];
2579 int pieces[4];
2580 int longip = CvarHostIp.IntValue;
2581
2582 pieces[0] = (longip >> 24) & 0x000000FF;
2583 pieces[1] = (longip >> 16) & 0x000000FF;
2584 pieces[2] = (longip >> 8) & 0x000000FF;
2585 pieces[3] = longip & 0x000000FF;
2586
2587 FormatEx(ServerIp, sizeof(ServerIp), "%d.%d.%d.%d", pieces[0], pieces[1], pieces[2], pieces[3]);
2588 CvarPort.GetString(ServerPort, sizeof(ServerPort));
2589
2590 if (AutoAdd != false) {
2591 FormatEx(query, sizeof(query), "SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s'", DatabasePrefix, ServerIp, ServerPort);
2592 DB.Query(ServerInfoCallback, query);
2593 }
2594}
2595
2596stock void PrepareBan(int client, int target, int time, char[] reason, int size)
2597{
2598 #if defined DEBUG
2599 LogToFile(logFile, "PrepareBan()");
2600 #endif
2601 if (!target || !IsClientInGame(target))
2602 return;
2603 char authid[64], name[32], bannedSite[512];
2604 if (!GetClientAuthId(target, AuthId_Steam2, authid, sizeof(authid)))
2605 return;
2606 GetClientName(target, name, sizeof(name));
2607
2608
2609 if (CreateBan(client, target, time, reason))
2610 {
2611 if (!time)
2612 {
2613 if (reason[0] == '\0')
2614 {
2615 ShowActivity(client, "%t", "Permabanned player", name);
2616 } else {
2617 ShowActivity(client, "%t", "Permabanned player reason", name, reason);
2618 }
2619 } else {
2620 if (reason[0] == '\0')
2621 {
2622 ShowActivity(client, "%t", "Banned player", name, time);
2623 } else {
2624 ShowActivity(client, "%t", "Banned player reason", name, time, reason);
2625 }
2626 }
2627 LogAction(client, target, "\"%L\" banned \"%L\" (minutes \"%d\") (reason \"%s\")", client, target, time, reason);
2628 char length[32];
2629 if(time == 0)
2630 FormatEx(length, sizeof(length), "permament");
2631 else
2632 FormatEx(length, sizeof(length), "%d %s", time, time == 1 ? "minute" : "minutes");
2633 if (time > 5 || time == 0)
2634 time = 5;
2635 Format(bannedSite, sizeof(bannedSite), "%t\n\n%t", "Banned Check Site", WebsiteAddress, "Kick Reason", client, reason, length);//temp
2636 BanClient(target, time, BANFLAG_AUTO, bannedSite, bannedSite, "sm_ban", client);
2637 }
2638
2639 g_BanTarget[client] = -1;
2640 g_BanTime[client] = -1;
2641}
2642
2643stock void ReadConfig()
2644{
2645 InitializeConfigParser();
2646
2647 if (ConfigParser == null)
2648 {
2649 return;
2650 }
2651
2652 char ConfigFile[PLATFORM_MAX_PATH];
2653 BuildPath(Path_SM, ConfigFile, sizeof(ConfigFile), "configs/sourcebans/sourcebans.cfg");
2654
2655 if (FileExists(ConfigFile))
2656 {
2657 InternalReadConfig(ConfigFile);
2658 PrintToServer("%sLoading configs/sourcebans.cfg config file", Prefix);
2659 } else {
2660 char Error[PLATFORM_MAX_PATH + 64];
2661 FormatEx(Error, sizeof(Error), "%sFATAL *** ERROR *** can not find %s", Prefix, ConfigFile);
2662 LogToFile(logFile, "FATAL *** ERROR *** can not find %s", ConfigFile);
2663 SetFailState(Error);
2664 }
2665}
2666
2667stock void ResetSettings()
2668{
2669 CommandDisable = 0;
2670
2671 ResetMenu();
2672 ReadConfig();
2673}
2674
2675stock void ParseBackupConfig_Overrides()
2676{
2677 KeyValues hKV = new KeyValues("SB_Overrides");
2678
2679 if (!hKV.ImportFromFile(overridesLoc))
2680 return;
2681
2682 if (!hKV.GotoFirstSubKey())
2683 return;
2684
2685 char sSection[16], sFlags[32], sName[64];
2686 OverrideType type;
2687
2688 do
2689 {
2690 hKV.GetSectionName(sSection, sizeof(sSection));
2691 if (StrEqual(sSection, "override_commands"))
2692 type = Override_Command;
2693 else if (StrEqual(sSection, "override_groups"))
2694 type = Override_CommandGroup;
2695 else
2696 continue;
2697
2698 if (hKV.GotoFirstSubKey(false))
2699 {
2700 do
2701 {
2702 hKV.GetSectionName(sName, sizeof(sName));
2703 hKV.GetString(NULL_STRING, sFlags, sizeof(sFlags));
2704 AddCommandOverride(sName, type, ReadFlagString(sFlags));
2705 #if defined _DEBUG
2706 PrintToServer("Adding override (%s, %s, %s)", sSection, sName, sFlags);
2707 #endif
2708 } while (hKV.GotoNextKey(false));
2709 hKV.GoBack();
2710 }
2711 }
2712 while (hKV.GotoNextKey());
2713 delete hKV;
2714}
2715
2716stock AdminFlag CreateFlagLetters()
2717{
2718 AdminFlag FlagLetters[FLAG_LETTERS_SIZE];
2719
2720 FlagLetters['a'-'a'] = Admin_Reservation;
2721 FlagLetters['b'-'a'] = Admin_Generic;
2722 FlagLetters['c'-'a'] = Admin_Kick;
2723 FlagLetters['d'-'a'] = Admin_Ban;
2724 FlagLetters['e'-'a'] = Admin_Unban;
2725 FlagLetters['f'-'a'] = Admin_Slay;
2726 FlagLetters['g'-'a'] = Admin_Changemap;
2727 FlagLetters['h'-'a'] = Admin_Convars;
2728 FlagLetters['i'-'a'] = Admin_Config;
2729 FlagLetters['j'-'a'] = Admin_Chat;
2730 FlagLetters['k'-'a'] = Admin_Vote;
2731 FlagLetters['l'-'a'] = Admin_Password;
2732 FlagLetters['m'-'a'] = Admin_RCON;
2733 FlagLetters['n'-'a'] = Admin_Cheats;
2734 FlagLetters['o'-'a'] = Admin_Custom1;
2735 FlagLetters['p'-'a'] = Admin_Custom2;
2736 FlagLetters['q'-'a'] = Admin_Custom3;
2737 FlagLetters['r'-'a'] = Admin_Custom4;
2738 FlagLetters['s'-'a'] = Admin_Custom5;
2739 FlagLetters['t'-'a'] = Admin_Custom6;
2740 FlagLetters['z'-'a'] = Admin_Root;
2741
2742 return FlagLetters;
2743}
2744
2745stock void AccountForLateLoading()
2746{
2747 char auth[30];
2748
2749 for (int i = 1; i <= MaxClients; i++)
2750 {
2751 if (IsClientConnected(i) && !IsFakeClient(i))
2752 {
2753 PlayerStatus[i] = false;
2754 }
2755 if (IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i) && GetClientAuthId(i, AuthId_Steam2, auth, sizeof(auth)))
2756 {
2757 OnClientAuthorized(i, auth);
2758 }
2759 }
2760}