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