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