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