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