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