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