Advertisement
Guest User

Untitled

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