AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   [CS:GO] add checker ServerID (https://forums.alliedmods.net/showthread.php?t=305526)

Dr.Mohammad 02-23-2018 12:00

[CS:GO] add checker ServerID
 
hi guys
i used sourcebans++ V1.6.3.
i have 15 server with this.
when player is banned from one server ,has banned from all 15 server
I do not want player is banned from all servers.
I do want player is banned Only the server that is banned from it
How to i add checker ServerID for sb ??

sbpp_main.sp:
PHP Code:

// *************************************************************************
//  This file is part of SourceBans++.
//
//  Copyright (C) 2014-2016 SourceBans++ Dev Team <https://github.com/sbpp>
//
//  SourceBans++ is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, per version 3 of the License.
//
//  SourceBans++ is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with SourceBans++. If not, see <http://www.gnu.org/licenses/>.
//
//  This file is based off work(s) covered by the following copyright(s):
//
//   SourceBans 1.4.11
//   Copyright (C) 2007-2015 SourceBans Team - Part of GameConnect
//   Licensed under GNU GPL version 3, or later.
//   Page: <http://www.sourcebans.net/> - <https://github.com/GameConnect/sourcebansv1>
//
// *************************************************************************

#pragma semicolon 1
#include <sourcemod>
#include <sourcebans>

#undef REQUIRE_PLUGIN
#include <adminmenu>
#tryinclude <updater>

#define SB_VERSION "1.6.3-PRE"
#define SBR_VERSION "1.6.3-PRE"

#if defined _updater_included
#define UPDATE_URL "https://sbpp.github.io/updater/updatefile.txt"
#endif

//GLOBAL DEFINES
#define YELLOW                0x01
#define NAMECOLOR            0x02
#define TEAMCOLOR            0x03
#define GREEN                0x04

#define DISABLE_ADDBAN        1
#define DISABLE_UNBAN        2

#define FLAG_LETTERS_SIZE 26

//#define DEBUG

enum State/* ConfigState */
{
    
ConfigStateNone 0,
    
ConfigStateConfig,
    
ConfigStateReasons,
    
ConfigStateHacking,
    
ConfigStateTime
}

new 
g_BanTarget[MAXPLAYERS 1] =  { -1, ... };
new 
g_BanTime[MAXPLAYERS 1] =  { -1, ... };

new 
State:ConfigState;
new 
Handle:ConfigParser;

new 
Handle:hTopMenu INVALID_HANDLE;

new const 
String:Prefix[] = "[SourceBans++] ";

new 
String:ServerIp[24];
new 
String:ServerPort[7];
new 
String:DatabasePrefix[10] = "sb";
new 
String:WebsiteAddress[128];

/* Admin Stuff*/
new AdminCachePart:loadPart;
new 
bool:loadAdmins;
new 
bool:loadGroups;
new 
bool:loadOverrides;
new 
curLoading 0;
new 
AdminFlag:g_FlagLetters[FLAG_LETTERS_SIZE];

/* Admin KeyValues */
new String:groupsLoc[128];
new 
String:adminsLoc[128];
new 
String:overridesLoc[128];

/* Cvar handle*/
new Handle:CvarHostIp;
new 
Handle:CvarPort;

/* Database handle */
new Handle:DB;
new 
Handle:SQLiteDB;

/* Menu file globals */
new Handle:TimeMenuHandle;
new 
Handle:ReasonMenuHandle;
new 
Handle:HackingMenuHandle;

/* Datapack and Timer handles */
new Handle:PlayerRecheck[MAXPLAYERS 1] =  { INVALID_HANDLE, ... };
new 
Handle:PlayerDataPack[MAXPLAYERS 1] =  { INVALID_HANDLE, ... };

/* Player ban check status */
new bool:PlayerStatus[MAXPLAYERS 1];

/* Disable of addban and unban */
new CommandDisable;
new 
bool:backupConfig true;
new 
bool:enableAdmins true;

/* Require a lastvisited from SB site */
new bool:requireSiteLogin false;

/* Log Stuff */
new String:logFile[256];

/* Own Chat Reason */
new g_ownReasons[MAXPLAYERS 1] =  { false, ... };

new 
Float:RetryTime 15.0;
new 
ProcessQueueTime 5;
new 
bool:LateLoaded;
new 
bool:AutoAdd;
new 
bool:g_bConnecting false;

new 
serverID = -1;

new 
Handle:g_hFwd_OnBanAdded;

public 
Plugin:myinfo =
{
    
name "SourceBans++: Main Plugin",
    
author "SourceBans Development Team, SourceBans++ Dev Team",
    
description "Advanced ban management for the Source engine",
    
version SBR_VERSION,
    
url "https://sbpp.github.io"
};

#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 3
public APLRes:AskPluginLoad2(Handle:myselfbool:lateString:error[], err_max)
#else
public bool:AskPluginLoad(Handle:myselfbool:lateString:error[], err_max)
#endif
{
    
RegPluginLibrary("sourcebans++");
    
CreateNative("SBBanPlayer",            Native_SBBanPlayer);
    
CreateNative("SourceBans_BanPlayer",   Native_SBBanPlayer);

    
g_hFwd_OnBanAdded CreateGlobalForward("SourceBans_OnBanPlayer"ET_IgnoreParam_CellParam_CellParam_CellParam_String);

    
LateLoaded late;

    
#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 3
    
return APLRes_Success;
    
#else
    
return true;
    
#endif
}

public 
OnPluginStart()
{
    
LoadTranslations("common.phrases");
    
LoadTranslations("plugin.basecommands");
    
LoadTranslations("sourcebans.phrases");
    
LoadTranslations("basebans.phrases");
    
loadAdmins loadGroups loadOverrides false;

    
CvarHostIp FindConVar("hostip");
    
CvarPort FindConVar("hostport");
    
CreateConVar("sb_version"SB_VERSION_FCVAR_SPONLY FCVAR_REPLICATED FCVAR_NOTIFY);
    
CreateConVar("sbr_version"SBR_VERSION_FCVAR_SPONLY FCVAR_REPLICATED FCVAR_NOTIFY);
    
RegServerCmd("sm_rehash"sm_rehash"Reload SQL admins");
    
RegAdminCmd("sm_ban"CommandBanADMFLAG_BAN"sm_ban <#userid|name> <minutes|0> [reason]""sourcebans");
    
RegAdminCmd("sm_banip"CommandBanIpADMFLAG_BAN"sm_banip <ip|#userid|name> <time> [reason]""sourcebans");
    
RegAdminCmd("sm_addban"CommandAddBanADMFLAG_RCON"sm_addban <time> <steamid> [reason]""sourcebans");
    
RegAdminCmd("sm_unban"CommandUnbanADMFLAG_UNBAN"sm_unban <steamid|ip> [reason]""sourcebans");
    
RegAdminCmd("sb_reload",
        
_CmdReload,
        
ADMFLAG_RCON,
        
"Reload sourcebans config and ban reason menu options",
        
"sourcebans");

    
RegConsoleCmd("say"ChatHook);
    
RegConsoleCmd("say_team"ChatHook);

    if ((
TimeMenuHandle CreateMenu(MenuHandler_BanTimeListMenuAction_Select|MenuAction_Cancel|MenuAction_DrawItem)) != INVALID_HANDLE)
    {
        
SetMenuPagination(TimeMenuHandle8);
        
SetMenuExitBackButton(TimeMenuHandletrue);
    }

    if ((
ReasonMenuHandle CreateMenu(ReasonSelected)) != INVALID_HANDLE)
    {
        
SetMenuPagination(ReasonMenuHandle8);
        
SetMenuExitBackButton(ReasonMenuHandletrue);
    }

    if ((
HackingMenuHandle CreateMenu(HackingSelected)) != INVALID_HANDLE)
    {
        
SetMenuPagination(HackingMenuHandle8);
        
SetMenuExitBackButton(HackingMenuHandletrue);
    }

    
g_FlagLetters CreateFlagLetters();

    
BuildPath(Path_SMlogFilesizeof(logFile), "logs/sourcebans.log");
    
g_bConnecting true;

    
// Catch config error and show link to FAQ
    
if (!SQL_CheckConfig("sourcebans"))
    {
        if (
ReasonMenuHandle != INVALID_HANDLE)
            
CloseHandle(ReasonMenuHandle);
        if (
HackingMenuHandle != INVALID_HANDLE)
            
CloseHandle(HackingMenuHandle);
        
LogToFile(logFile"Database failure: Could not find Database conf \"sourcebans\". See FAQ: https://sbpp.sarabveer.me/faq/");
        
SetFailState("Database failure: Could not find Database conf \"sourcebans\"");
        return;
    }
    
SQL_TConnect(GotDatabase"sourcebans");

    
BuildPath(Path_SMgroupsLocsizeof(groupsLoc), "configs/sourcebans/sb_admin_groups.cfg");

    
BuildPath(Path_SMadminsLocsizeof(adminsLoc), "configs/sourcebans/sb_admins.cfg");

    
BuildPath(Path_SMoverridesLocsizeof(overridesLoc), "configs/sourcebans/overrides_backup.cfg");

    
InitializeBackupDB();

    
// This timer is what processes the SQLite queue when the database is unavailable
    
CreateTimer(float(ProcessQueueTime 60), ProcessQueue);

    if (
LateLoaded)
    {
        
AccountForLateLoading();
    }

    
#if defined _updater_included
    
if (LibraryExists("updater"))
    {
        
Updater_AddPlugin(UPDATE_URL);
    }
    
#endif
}

#if defined _updater_included
public OnLibraryAdded(const String:name[])
{
    if (
StrEqual(name"updater"))
    {
        
Updater_AddPlugin(UPDATE_URL);
    }
}
#endif

public OnAllPluginsLoaded()
{
    new 
Handle:topmenu;
    
#if defined DEBUG
    
LogToFile(logFile"OnAllPluginsLoaded()");
    
#endif

    
if (LibraryExists("adminmenu") && ((topmenu GetAdminTopMenu()) != INVALID_HANDLE))
    {
        
OnAdminMenuReady(topmenu);
    }
}

public 
OnConfigsExecuted()
{
    
decl String:filename[200];
    
BuildPath(Path_SMfilenamesizeof(filename), "plugins/basebans.smx");
    if (
FileExists(filename))
    {
        
decl String:newfilename[200];
        
BuildPath(Path_SMnewfilenamesizeof(newfilename), "plugins/disabled/basebans.smx");
        
ServerCommand("sm plugins unload basebans");
        if (
FileExists(newfilename))
            
DeleteFile(newfilename);
        
RenameFile(newfilenamefilename);
        
LogToFile(logFile"plugins/basebans.smx was unloaded and moved to plugins/disabled/basebans.smx");
    }
}

public 
OnMapStart()
{
    
ResetSettings();
}

public 
OnMapEnd()
{
    for (new 
0<= MaxClientsi++)
    {
        if (
PlayerDataPack[i] != INVALID_HANDLE)
        {
            
/* Need to close reason pack */
            
CloseHandle(PlayerDataPack[i]);
            
PlayerDataPack[i] = INVALID_HANDLE;
        }
    }
}

// CLIENT CONNECTION FUNCTIONS //

public Action:OnClientPreAdminCheck(client)
{
    if (!
DB || GetUserAdmin(client) != INVALID_ADMIN_ID)
        return 
Plugin_Continue;

    return 
curLoading Plugin_Handled Plugin_Continue;
}

public 
OnClientDisconnect(client)
{
    if (
PlayerRecheck[client] != INVALID_HANDLE)
    {
        
KillTimer(PlayerRecheck[client]);
        
PlayerRecheck[client] = INVALID_HANDLE;
    }
    
g_ownReasons[client] = false;
}

public 
bool:OnClientConnect(clientString:rejectmsg[], maxlen)
{
    
PlayerStatus[client] = false;
    return 
true;
}

public 
OnClientAuthorized(client, const String:auth[])
{
    
/* Do not check bots nor check player with lan steamid. */
    
if (auth[0] == 'B' || auth[9] == 'L' || DB == INVALID_HANDLE)
    {
        
PlayerStatus[client] = true;
        return;
    }

    
decl String:Query[256], String:ip[30];
    
GetClientIP(clientipsizeof(ip));
    
FormatEx(Querysizeof(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"DatabasePrefixauth[8], ip);
    
#if defined DEBUG
    
LogToFile(logFile"Checking ban for: %s"auth);
    
#endif

    
SQL_TQuery(DBVerifyBanQueryGetClientUserId(client), DBPrio_High);
}

public 
OnRebuildAdminCache(AdminCachePart:part)
{
    
loadPart part;
    switch (
loadPart)
    {
        case 
AdminCache_Overrides:
        
loadOverrides true;
        case 
AdminCache_Groups:
        
loadGroups true;
        case 
AdminCache_Admins:
        
loadAdmins true;
    }
    if (
DB == INVALID_HANDLE) {
        if (!
g_bConnecting) {
            
g_bConnecting true;
            
SQL_TConnect(GotDatabase"sourcebans");
        }
    }
    else {
        
GotDatabase(DBDB""0);
    }
}

// COMMAND CODE //

public Action:ChatHook(clientargs)
{
    
// is this player preparing to ban someone
    
if (g_ownReasons[client])
    {
        
// get the reason
        
new String:reason[512];
        
GetCmdArgString(reasonsizeof(reason));
        
StripQuotes(reason);

        
g_ownReasons[client] = false;

        if (
StrEqual(reason[0], "!noreason"))
        {
            
PrintToChat(client"%c[%cSourceBans%c]%c %t"GREENNAMECOLORGREENNAMECOLOR"Chat Reason Aborted");
            return 
Plugin_Handled;
        }

        
// ban him!
        
PrepareBan(clientg_BanTarget[client], g_BanTime[client], reasonsizeof(reason));

        
// block the reason to be sent in chat
        
return Plugin_Handled;
    }
    return 
Plugin_Continue;
}

public 
Action:_CmdReload(clientargs)
{
    
ResetSettings();
    return 
Plugin_Handled;
}

public 
Action:CommandBan(clientargs)
{
    if (
args 2)
    {
        
ReplyToCommand(client"%sUsage: sm_ban <#userid|name> <time|0> [reason]"Prefix);
        return 
Plugin_Handled;
    }

    
// This is mainly for me sanity since client used to be called admin and target used to be called client
    
new admin client;

    
// Get the target, find target returns a message on failure so we do not
    
decl String:buffer[100];
    
GetCmdArg(1buffersizeof(buffer));
    new 
target FindTarget(clientbuffertrue);
    if (
target == -1)
    {
        return 
Plugin_Handled;
    }

    
// Get the ban time
    
GetCmdArg(2buffersizeof(buffer));
    new 
time StringToInt(buffer);
    if (!
time && client && !(CheckCommandAccess(client"sm_unban"ADMFLAG_UNBAN ADMFLAG_ROOT)))
    {
        
ReplyToCommand(client"You do not have Perm Ban Permission");
        return 
Plugin_Handled;
    }

    
// Get the reason
    
new String:reason[128];
    if (
args >= 3)
    {
        
GetCmdArg(3reasonsizeof(reason));
        for (new 
4<= argsi++)
        {
            
GetCmdArg(ibuffersizeof(buffer));
            
Format(reasonsizeof(reason), "%s %s"reasonbuffer);
        }
    }
    else
    {
        
reason[0] = '\0';
    }

    
g_BanTarget[client] = target;
    
g_BanTime[client] = time;

    if (!
PlayerStatus[target])
    {
        
// The target has not been banned verify. It must be completed before you can ban anyone.
        
ReplyToCommand(admin"%c[%cSourceBans%c]%c %t"GREENNAMECOLORGREENNAMECOLOR"Ban Not Verified");
        return 
Plugin_Handled;
    }


    
CreateBan(clienttargettimereason);
    return 
Plugin_Handled;
}

public 
Action:CommandBanIp(clientargs)
{
    if (
args 2)
    {
        
ReplyToCommand(client"%sUsage: sm_banip <ip|#userid|name> <time> [reason]"Prefix);
        return 
Plugin_Handled;
    }

    
decl lennext_len;
    
decl String:Arguments[256];
    
decl String:arg[50], String:time[20];

    
GetCmdArgString(Argumentssizeof(Arguments));
    
len BreakString(Argumentsargsizeof(arg));

    if ((
next_len BreakString(Arguments[len], timesizeof(time))) != -1)
    {
        
len += next_len;
    }
    else
    {
        
len 0;
        
Arguments[0] = '\0';
    }

    
decl String:target_name[MAX_TARGET_LENGTH];
    
decl target_list[1], bool:tn_is_ml;
    new 
target = -1;

    if (
ProcessTargetString(
            
arg,
            
client,
            
target_list,
            
1,
            
COMMAND_FILTER_CONNECTED COMMAND_FILTER_NO_MULTI,
            
target_name,
            
sizeof(target_name),
            
tn_is_ml) > 0)
    {
        
target target_list[0];

        if (!
IsFakeClient(target) && CanUserTarget(clienttarget))
            
GetClientIP(targetargsizeof(arg));
    }

    
decl String:adminIp[24], String:adminAuth[64];
    new 
minutes StringToInt(time);
    if (!
minutes && client && !(CheckCommandAccess(client"sm_unban"ADMFLAG_UNBAN ADMFLAG_ROOT)))
    {
        
ReplyToCommand(client"You do not have Perm Ban Permission");
        return 
Plugin_Handled;
    }
    if (!
client)
    {
        
// setup dummy adminAuth and adminIp for server
        
strcopy(adminAuthsizeof(adminAuth), "STEAM_ID_SERVER");
        
strcopy(adminIpsizeof(adminIp), ServerIp);
    } else {
        
GetClientIP(clientadminIpsizeof(adminIp));
        
GetClientAuthId(clientAuthId_Steam2adminAuthsizeof(adminAuth));
    }

    
// Pack everything into a data pack so we can retain it
    
new Handle:dataPack CreateDataPack();
    
WritePackCell(dataPackclient);
    
WritePackCell(dataPackminutes);
    
WritePackString(dataPackArguments[len]);
    
WritePackString(dataPackarg);
    
WritePackString(dataPackadminAuth);
    
WritePackString(dataPackadminIp);

    
decl String:Query[256];
    
FormatEx(Querysizeof(Query), "SELECT bid FROM %s_bans WHERE type = 1 AND ip     = '%s' AND (length = 0 OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL",
        
DatabasePrefixarg);

    
SQL_TQuery(DBSelectBanIpCallbackQuerydataPackDBPrio_High);
    return 
Plugin_Handled;
}

public 
Action:CommandUnban(clientargs)
{
    if (
args 1)
    {
        
ReplyToCommand(client"%sUsage: sm_unban <steamid|ip> [reason]"Prefix);
        return 
Plugin_Handled;
    }

    if (
CommandDisable DISABLE_UNBAN)
    {
        
// They must go to the website to unban people
        
ReplyToCommand(client"%s%t"Prefix"Can Not Unban"WebsiteAddress);
        return 
Plugin_Handled;
    }

    
decl lenString:Arguments[256], String:arg[50], String:adminAuth[64];
    
GetCmdArgString(Argumentssizeof(Arguments));

    if ((
len BreakString(Argumentsargsizeof(arg))) == -1)
    {
        
len 0;
        
Arguments[0] = '\0';
    }
    if (!
client)
    {
        
// setup dummy adminAuth and adminIp for server
        
strcopy(adminAuthsizeof(adminAuth), "STEAM_ID_SERVER");
    } else {
        
GetClientAuthId(clientAuthId_Steam2adminAuthsizeof(adminAuth));
    }

    
// Pack everything into a data pack so we can retain it
    
new Handle:dataPack CreateDataPack();
    
WritePackCell(dataPackclient);
    
WritePackString(dataPackArguments[len]);
    
WritePackString(dataPackarg);
    
WritePackString(dataPackadminAuth);

    
decl String:query[200];
    if (
strncmp(arg"STEAM_"6) == 0)
    {
        
Format(querysizeof(query), "SELECT bid FROM %s_bans WHERE (type = 0 AND authid = '%s') AND (length = '0' OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL"DatabasePrefixarg);
    } else {
        
Format(querysizeof(query), "SELECT bid FROM %s_bans WHERE (type = 1 AND ip     = '%s') AND (length = '0' OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL"DatabasePrefixarg);
    }
    
SQL_TQuery(DBSelectUnbanCallbackquerydataPack);
    return 
Plugin_Handled;
}

public 
Action:CommandAddBan(clientargs)
{
    if (
args 2)
    {
        
ReplyToCommand(client"%sUsage: sm_addban <time> <steamid> [reason]"Prefix);
        return 
Plugin_Handled;
    }

    if (
CommandDisable DISABLE_ADDBAN)
    {
        
// They must go to the website to add bans
        
ReplyToCommand(client"%s%t"Prefix"Can Not Add Ban"WebsiteAddress);
        return 
Plugin_Handled;
    }

    
decl String:arg_string[256], String:time[50], String:authid[50];
    
GetCmdArgString(arg_stringsizeof(arg_string));

    new 
lentotal_len;

    
/* Get time */
    
if ((len BreakString(arg_stringtimesizeof(time))) == -1)
    {
        
ReplyToCommand(client"%sUsage: sm_addban <time> <steamid> [reason]"Prefix);
        return 
Plugin_Handled;
    }
    
total_len += len;

    
/* Get steamid */
    
if ((len BreakString(arg_string[total_len], authidsizeof(authid))) != -1)
    {
        
total_len += len;
    }
    else
    {
        
total_len 0;
        
arg_string[0] = '\0';
    }

    
decl String:adminIp[24], String:adminAuth[64];
    new 
minutes StringToInt(time);
    if (!
minutes && client && !(CheckCommandAccess(client"sm_unban"ADMFLAG_UNBAN ADMFLAG_ROOT)))
    {
        
ReplyToCommand(client"You do not have Perm Ban Permission");
        return 
Plugin_Handled;
    }
    if (!
client)
    {
        
// setup dummy adminAuth and adminIp for server
        
strcopy(adminAuthsizeof(adminAuth), "STEAM_ID_SERVER");
        
strcopy(adminIpsizeof(adminIp), ServerIp);
    } else {
        
GetClientIP(clientadminIpsizeof(adminIp));
        
GetClientAuthId(clientAuthId_Steam2adminAuthsizeof(adminAuth));
    }

    
// Pack everything into a data pack so we can retain it
    
new Handle:dataPack CreateDataPack();
    
WritePackCell(dataPackclient);
    
WritePackCell(dataPackminutes);
    
WritePackString(dataPackarg_string[total_len]);
    
WritePackString(dataPackauthid);
    
WritePackString(dataPackadminAuth);
    
WritePackString(dataPackadminIp);

    
decl String:Query[256];
    
FormatEx(Querysizeof(Query), "SELECT bid FROM %s_bans WHERE type = 0 AND authid = '%s' AND (length = 0 OR ends > UNIX_TIMESTAMP()) AND RemoveType IS NULL",
        
DatabasePrefixauthid);

    
SQL_TQuery(DBSelectAddbanCallbackQuerydataPackDBPrio_High);
    return 
Plugin_Handled;
}

public 
Action:sm_rehash(args)
{
    if (
enableAdmins)
        
DumpAdminCache(AdminCache_Groupstrue);
    
DumpAdminCache(AdminCache_Overridestrue);
    return 
Plugin_Handled;
}



// MENU CODE //

public OnAdminMenuReady(Handle:topmenu)
{
    
#if defined DEBUG
    
LogToFile(logFile"OnAdminMenuReady()");
    
#endif

    /* Block us from being called twice */
    
if (topmenu == hTopMenu)
    {
        return;
    }

    
/* Save the Handle */
    
hTopMenu topmenu;

    
/* Find the "Player Commands" category */
    
new TopMenuObject:player_commands FindTopMenuCategory(hTopMenuADMINMENU_PLAYERCOMMANDS);

    if (
player_commands != INVALID_TOPMENUOBJECT)
    {
        
// just to avoid "unused variable 'res'" warning
        #if defined DEBUG
        
new TopMenuObject:res AddToTopMenu(hTopMenu,
            
"sm_ban",  // Name
            
TopMenuObject_Item,  // We are a submenu
            
AdminMenu_Ban,  // Handler function
            
player_commands,  // We are a submenu of Player Commands
            
"sm_ban",  // The command to be finally called (Override checks)
            
ADMFLAG_BAN); // What flag do we need to see the menu option
        
decl String:temp[125];
        
Format(temp125"Result of AddToTopMenu: %d"res);
        
LogToFile(logFiletemp);
        
LogToFile(logFile"Added Ban option to admin menu");
        
#else
        
AddToTopMenu(hTopMenu,
            
"sm_ban",  // Name
            
TopMenuObject_Item,  // We are a submenu
            
AdminMenu_Ban,  // Handler function
            
player_commands,  // We are a submenu of Player Commands
            
"sm_ban",  // The command to be finally called (Override checks)
            
ADMFLAG_BAN); // What flag do we need to see the menu option
        #endif
    
}
}

public 
AdminMenu_Ban(Handle:topmenu,
    
TopMenuAction:action,  // Action being performed
    
TopMenuObject:object_id,  // The object ID (if used)
    
param,  // client idx of admin who chose the option (if used)
    
String:buffer[],  // Output buffer (if used)
    
maxlength// Output buffer (if used)
{
    
/* Clear the Ownreason bool, so he is able to chat again;) */
    
g_ownReasons[param] = false;

    
#if defined DEBUG
    
LogToFile(logFile"AdminMenu_Ban()");
    
#endif

    
switch (action)
    {
        
// We are only being displayed, We only need to show the option name
        
case TopMenuAction_DisplayOption:
        {
            
FormatEx(buffermaxlength"%T""Ban player"param);

            
#if defined DEBUG
            
LogToFile(logFile"AdminMenu_Ban() -> Formatted the Ban option text");
            
#endif
        
}

        case 
TopMenuAction_SelectOption:
        {
            
DisplayBanTargetMenu(param); // Someone chose to ban someone, show the list of users menu

            #if defined DEBUG
            
LogToFile(logFile"AdminMenu_Ban() -> DisplayBanTargetMenu()");
            
#endif
        
}
    }
}

public 
ReasonSelected(Handle:menuMenuAction:actionparam1param2)
{
    switch (
action)
    {
        case 
MenuAction_Select:
        {
            
decl String:info[128], String:key[128];
            
GetMenuItem(menuparam2keysizeof(key), _infosizeof(info));

            if (
StrEqual("Hacking"key))
            {
                
DisplayMenu(HackingMenuHandleparam1MENU_TIME_FOREVER);
                return;
            }

            else if (
StrEqual("Own Reason"key)) // admin wants to use his own reason
            
{
                
g_ownReasons[param1] = true;
                
PrintToChat(param1"%c[%cSourceBans%c]%c %t"GREENNAMECOLORGREENNAMECOLOR"Chat Reason");
                return;
            }

            else if (
g_BanTarget[param1] != -&& g_BanTime[param1] != -1)
                
PrepareBan(param1g_BanTarget[param1], g_BanTime[param1], infosizeof(info));
        }

        case 
MenuAction_Cancel:
        {
            if (
param2 == MenuCancel_Disconnected)
            {
                if (
PlayerDataPack[param1] != INVALID_HANDLE)
                {
                    
CloseHandle(PlayerDataPack[param1]);
                    
PlayerDataPack[param1] = INVALID_HANDLE;
                }
            }

            else
            {
                
DisplayBanTimeMenu(param1);
            }
        }
    }
}

public 
HackingSelected(Handle:menuMenuAction:actionparam1param2)
{
    switch (
action)
    {
        case 
MenuAction_Select:
        {
            
decl String:info[128], String:key[128];
            
GetMenuItem(menuparam2keysizeof(key), _infosizeof(info));

            if (
g_BanTarget[param1] != -&& g_BanTime[param1] != -1)
                
PrepareBan(param1g_BanTarget[param1], g_BanTime[param1], infosizeof(info));
        }

        case 
MenuAction_Cancel:
        {
            if (
param2 == MenuCancel_Disconnected)
            {
                new 
Handle:Pack PlayerDataPack[param1];

                if (
Pack != INVALID_HANDLE)
                {
                    
ReadPackCell(Pack); // admin index
                    
ReadPackCell(Pack); // target index
                    
ReadPackCell(Pack); // admin userid
                    
ReadPackCell(Pack); // target userid
                    
ReadPackCell(Pack); // time
                    
new Handle:ReasonPack Handle:ReadPackCell(Pack);

                    if (
ReasonPack != INVALID_HANDLE)
                    {
                        
CloseHandle(ReasonPack);
                    }

                    
CloseHandle(Pack);
                    
PlayerDataPack[param1] = INVALID_HANDLE;
                }
            }

            else
            {
                
DisplayMenu(ReasonMenuHandleparam1MENU_TIME_FOREVER);
            }
        }
    }
}

public 
MenuHandler_BanPlayerList(Handle:menuMenuAction:actionparam1param2)
{
    
#if defined DEBUG
    
LogToFile(logFile"MenuHandler_BanPlayerList()");
    
#endif

    
switch (action)
    {
        case 
MenuAction_End:
        {
            
CloseHandle(menu);
        }

        case 
MenuAction_Cancel:
        {
            if (
param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
            {
                
DisplayTopMenu(hTopMenuparam1TopMenuPosition_LastCategory);
            }
        }

        case 
MenuAction_Select:
        {
            
decl String:info[32], String:name[32];
            new 
useridtarget;

            
GetMenuItem(menuparam2infosizeof(info), _namesizeof(name));
            
userid StringToInt(info);

            if ((
target GetClientOfUserId(userid)) == 0)
            {
                
PrintToChat(param1"%s%t"Prefix"Player no longer available");
            }
            else if (!
CanUserTarget(param1target))
            {
                
PrintToChat(param1"%s%t"Prefix"Unable to target");
            }
            else
            {
                
g_BanTarget[param1] = target;
                
DisplayBanTimeMenu(param1);
            }
        }
    }
}

public 
MenuHandler_BanTimeList(Handle:menuMenuAction:actionparam1param2)
{
    
#if defined DEBUG
    
LogToFile(logFile"MenuHandler_BanTimeList()");
    
#endif

    
switch (action)
    {
        case 
MenuAction_Cancel:
        {
            if (
param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
            {
                
DisplayTopMenu(hTopMenuparam1TopMenuPosition_LastCategory);
            }
        }

        case 
MenuAction_Select:
        {
            
decl String:info[32];

            
GetMenuItem(menuparam2infosizeof(info));
            
g_BanTime[param1] = StringToInt(info);

            
//DisplayBanReasonMenu(param1);
            
DisplayMenu(ReasonMenuHandleparam1MENU_TIME_FOREVER);
        }

        case 
MenuAction_DrawItem:
        {
            
decl String:time[16];
            
GetMenuItem(menuparam2timesizeof(time));

            return (
StringToInt(time) > || CheckCommandAccess(param1"sm_unban"ADMFLAG_UNBAN ADMFLAG_ROOT)) ? ITEMDRAW_DEFAULT ITEMDRAW_DISABLED;
        }
    }

    return 
0;
}

stock DisplayBanTargetMenu(client)
{
    
#if defined DEBUG
    
LogToFile(logFile"DisplayBanTargetMenu()");
    
#endif
    
new Handle:menu CreateMenu(MenuHandler_BanPlayerList); // Create a new menu, pass it the handler.

    
decl String:title[100];
    
FormatEx(titlesizeof(title), "%T:""Ban player"client);

    
SetMenuTitle(menutitle); // Set the title
    
SetMenuExitBackButton(menutrue); // Yes we want back/exit

    
AddTargetsToMenu(menu,  // Add clients to our menu
        
client,  // The client that called the display
        
false,  // We want to see people connecting
        
false); // And dead people

    
DisplayMenu(menuclientMENU_TIME_FOREVER); // Show the menu to the client FOREVER!
}

stock DisplayBanTimeMenu(client)
{
    
#if defined DEBUG
    
LogToFile(logFile"DisplayBanTimeMenu()");
    
#endif

    
decl String:title[100];
    
FormatEx(titlesizeof(title), "%T:""Ban player"client);
    
SetMenuTitle(TimeMenuHandletitle);

    
DisplayMenu(TimeMenuHandleclientMENU_TIME_FOREVER);
}

stock ResetMenu()
{
    if (
TimeMenuHandle != INVALID_HANDLE)
    {
        
RemoveAllMenuItems(TimeMenuHandle);
    }

    if (
ReasonMenuHandle != INVALID_HANDLE)
    {
        
RemoveAllMenuItems(ReasonMenuHandle);
    }

    if (
HackingMenuHandle != INVALID_HANDLE)
    {
        
RemoveAllMenuItems(HackingMenuHandle);
    }
}

// QUERY CALL BACKS //

public GotDatabase(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (
hndl == INVALID_HANDLE)
    {
        
LogToFile(logFile"Database failure: %s. See FAQ: https://sbpp.sarabveer.me/faq/"error);
        
g_bConnecting false;

        
// Parse the overrides backup!
        
ParseBackupConfig_Overrides();
        return;
    }

    
DB hndl;

    
decl String:query[1024];
    
SQL_SetCharset(DB"utf8");

    
InsertServerInfo();

    
//CreateTimer(900.0, PruneBans);

    
if (loadOverrides)
    {
        
Format(query1024"SELECT type, name, flags FROM %s_overrides"DatabasePrefix);
        
SQL_TQuery(DBOverridesDonequery);
        
loadOverrides false;
    }

    if (
loadGroups && enableAdmins)
    {
        
FormatEx(query1024"SELECT name, flags, immunity, groups_immune   \
                    FROM %s_srvgroups ORDER BY id"
DatabasePrefix);
        
curLoading++;
        
SQL_TQuery(DBGroupsDonequery);

        
#if defined DEBUG
        
LogToFile(logFile"Fetching Group List");
        
#endif
        
loadGroups false;
    }

    if (
loadAdmins && enableAdmins)
    {
        new 
String:queryLastLogin[50] = "";

        if (
requireSiteLogin)
            
queryLastLogin "lastvisit IS NOT NULL AND lastvisit != '' AND";

        if (
serverID == -1)
        {
            
FormatEx(query1024"SELECT authid, srv_password, (SELECT name FROM %s_srvgroups WHERE name = srv_group AND flags != '') AS srv_group, srv_flags, user, immunity  \
                        FROM %s_admins_servers_groups AS asg \
                        LEFT JOIN %s_admins AS a ON a.aid = asg.admin_id \
                        WHERE %s (server_id = (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1)  \
                        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))) \
                        GROUP BY aid, authid, srv_password, srv_group, srv_flags, user"
,
                
DatabasePrefixDatabasePrefixDatabasePrefixqueryLastLoginDatabasePrefixServerIpServerPortDatabasePrefixDatabasePrefixServerIpServerPort);
        } else {
            
FormatEx(query1024"SELECT authid, srv_password, (SELECT name FROM %s_srvgroups WHERE name = srv_group AND flags != '') AS srv_group, srv_flags, user, immunity  \
                        FROM %s_admins_servers_groups AS asg \
                        LEFT JOIN %s_admins AS a ON a.aid = asg.admin_id \
                        WHERE %s server_id = %d  \
                        OR srv_group_id = ANY (SELECT group_id FROM %s_servers_groups WHERE server_id = %d) \
                        GROUP BY aid, authid, srv_password, srv_group, srv_flags, user"
,
                
DatabasePrefixDatabasePrefixDatabasePrefixqueryLastLoginserverIDDatabasePrefixserverID);
        }
        
curLoading++;
        
SQL_TQuery(DBAdminsDonequery);

        
#if defined DEBUG
        
LogToFile(logFile"Fetching Admin List");
        
LogToFile(logFilequery);
        
#endif
        
loadAdmins false;
    }
    
g_bConnecting false;
}

public 
VerifyInsert(Handle:ownerHandle:hndl, const String:error[], any:dataPack)
{
    if (
dataPack == INVALID_HANDLE)
    {
        
LogToFile(logFile"Ban Failed: %s"error);
        return;
    }

    if (
hndl == INVALID_HANDLE || error[0])
    {
        
LogToFile(logFile"Verify Insert Query Failed: %s"error);
        new 
admin ReadPackCell(dataPack);
        
ReadPackCell(dataPack); // target
        
ReadPackCell(dataPack); // admin userid
        
ReadPackCell(dataPack); // target userid
        
new time ReadPackCell(dataPack);
        new 
Handle:reasonPack Handle:ReadPackCell(dataPack);
        new 
String:reason[128];
        
ReadPackString(reasonPackreasonsizeof(reason));
        
decl String:name[50];
        
ReadPackString(dataPacknamesizeof(name));
        
decl String:auth[30];
        
ReadPackString(dataPackauthsizeof(auth));
        
decl String:ip[20];
        
ReadPackString(dataPackipsizeof(ip));
        
decl String:adminAuth[30];
        
ReadPackString(dataPackadminAuthsizeof(adminAuth));
        
decl String:adminIp[20];
        
ReadPackString(dataPackadminIpsizeof(adminIp));
        
ResetPack(dataPack);
        
ResetPack(reasonPack);

        
PlayerDataPack[admin] = INVALID_HANDLE;
        
UTIL_InsertTempBan(timenameauthipreasonadminAuthadminIpHandle:dataPack);
        return;
    }

    new 
admin ReadPackCell(dataPack);
    new 
client ReadPackCell(dataPack);

    if (!
IsClientConnected(client) || IsFakeClient(client))
        return;

    
ReadPackCell(dataPack); // admin userid
    
new UserId ReadPackCell(dataPack);
    new 
time ReadPackCell(dataPack);
    new 
Handle:ReasonPack Handle:ReadPackCell(dataPack);

    
decl String:Name[64];
    new 
String:Reason[128];

    
ReadPackString(dataPackNamesizeof(Name));
    
ReadPackString(ReasonPackReasonsizeof(Reason));

    if (!
time)
    {
        if (
Reason[0] == '\0')
        {
            
ShowActivityEx(adminPrefix"%t""Permabanned player"Name);
        } else {
            
ShowActivityEx(adminPrefix"%t""Permabanned player reason"NameReason);
        }
    } else {
        if (
Reason[0] == '\0')
        {
            
ShowActivityEx(adminPrefix"%t""Banned player"Nametime);
        } else {
            
ShowActivityEx(adminPrefix"%t""Banned player reason"NametimeReason);
        }
    }

    
LogAction(adminclient"\"%L\" banned \"%L\" (minutes \"%d\") (reason \"%s\")"adminclienttimeReason);

    if (
PlayerDataPack[admin] != INVALID_HANDLE)
    {
        
CloseHandle(PlayerDataPack[admin]);
        
CloseHandle(ReasonPack);
        
PlayerDataPack[admin] = INVALID_HANDLE;
    }

    
// Kick player
    
if (GetClientUserId(client) == UserId)
        
KickClient(client"%t""Banned Check Site"WebsiteAddress);
}

public 
SelectBanIpCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    
decl adminminutesString:adminAuth[30], String:adminIp[30], String:banReason[256], String:ip[16], String:Query[512];
    new 
String:reason[128];
    
ResetPack(data);
    
admin ReadPackCell(data);
    
minutes ReadPackCell(data);
    
ReadPackString(datareasonsizeof(reason));
    
ReadPackString(dataipsizeof(ip));
    
ReadPackString(dataadminAuthsizeof(adminAuth));
    
ReadPackString(dataadminIpsizeof(adminIp));
    
SQL_EscapeString(DBreasonbanReasonsizeof(banReason));

    if (
error[0])
    {
        
LogToFile(logFile"Ban IP Select Query Failed: %s"error);
        if (
admin && IsClientInGame(admin))
            
PrintToChat(admin"%sFailed to ban %s."Prefixip);
        else
            
PrintToServer("%sFailed to ban %s."Prefixip);
        return;
    }
    if (
SQL_GetRowCount(hndl))
    {
        if (
admin && IsClientInGame(admin))
            
PrintToChat(admin"%s%s is already banned."Prefixip);
        else
            
PrintToServer("%s%s is already banned."Prefixip);
        return;
    }
    if (
serverID == -1)
    {
        
FormatEx(Querysizeof(Query), "INSERT INTO %s_bans (type, ip, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
                        (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', \
                        (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1), ' ')"
,
            
DatabasePrefixip, (minutes 60), (minutes 60), banReasonDatabasePrefixadminAuthadminAuth[8], adminIpDatabasePrefixServerIpServerPort);
    } else {
        
FormatEx(Querysizeof(Query), "INSERT INTO %s_bans (type, ip, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
                        (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', \
                        %d, ' ')"
,
            
DatabasePrefixip, (minutes 60), (minutes 60), banReasonDatabasePrefixadminAuthadminAuth[8], adminIpserverID);
    }

    
SQL_TQuery(DBInsertBanIpCallbackQuerydataDBPrio_High);
}

public 
InsertBanIpCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    
// if the pack is good unpack it and close the handle
    
new adminminutes;
    new 
String:reason[128];
    
decl String:arg[30];
    if (
data != INVALID_HANDLE)
    {
        
ResetPack(data);
        
admin ReadPackCell(data);
        
minutes ReadPackCell(data);
        
ReadPackString(datareasonsizeof(reason));
        
ReadPackString(dataargsizeof(arg));
        
CloseHandle(data);
    } else {
        
// Technically this should not be possible
        
ThrowError("Invalid Handle in InsertBanIpCallback");
    }

    
// If error is not an empty string the query failed
    
if (error[0] != '\0')
    {
        
LogToFile(logFile"Ban IP Insert Query Failed: %s"error);
        if (
admin && IsClientInGame(admin))
            
PrintToChat(admin"%ssm_banip failed"Prefix);
        return;
    }

    
LogAction(admin,
        -
1,
        
"\"%L\" added ban (minutes \"%d\") (ip \"%s\") (reason \"%s\")",
        
admin,
        
minutes,
        
arg,
        
reason);
    if (
admin && IsClientInGame(admin))
        
PrintToChat(admin"%s%s successfully banned"Prefixarg);
    else
        
PrintToServer("%s%s successfully banned"Prefixarg);
}

public 
SelectUnbanCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    
decl adminString:arg[30], String:adminAuth[30], String:unbanReason[256];
    new 
String:reason[128];
    
ResetPack(data);
    
admin ReadPackCell(data);
    
ReadPackString(datareasonsizeof(reason));
    
ReadPackString(dataargsizeof(arg));
    
ReadPackString(dataadminAuthsizeof(adminAuth));
    
SQL_EscapeString(DBreasonunbanReasonsizeof(unbanReason));

    
// If error is not an empty string the query failed
    
if (error[0] != '\0')
    {
        
LogToFile(logFile"Unban Select Query Failed: %s"error);
        if (
admin && IsClientInGame(admin))
        {
            
PrintToChat(admin"%ssm_unban failed"Prefix);
        }
        return;
    }

    
// If there was no results then a ban does not exist for that id
    
if (hndl == INVALID_HANDLE || !SQL_GetRowCount(hndl))
    {
        if (
admin && IsClientInGame(admin))
        {
            
PrintToChat(admin"%sNo active bans found for that filter"Prefix);
        } else {
            
PrintToServer("%sNo active bans found for that filter"Prefix);
        }
        return;
    }

    
// There is ban
    
if (hndl != INVALID_HANDLE && SQL_FetchRow(hndl))
    {
        
// Get the values from the existing ban record
        
new bid SQL_FetchInt(hndl0);

        
decl String:query[1000];
        
Format(querysizeof(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",
            
DatabasePrefixDatabasePrefixadminAuthadminAuth[8], unbanReasonbid);

        
SQL_TQuery(DBInsertUnbanCallbackquerydata);
    }
    return;
}

public 
InsertUnbanCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    
// if the pack is good unpack it and close the handle
    
decl adminString:arg[30];
    new 
String:reason[128];
    if (
data != INVALID_HANDLE)
    {
        
ResetPack(data);
        
admin ReadPackCell(data);
        
ReadPackString(datareasonsizeof(reason));
        
ReadPackString(dataargsizeof(arg));
        
CloseHandle(data);
    } else {
        
// Technically this should not be possible
        
ThrowError("Invalid Handle in InsertUnbanCallback");
    }

    
// If error is not an empty string the query failed
    
if (error[0] != '\0')
    {
        
LogToFile(logFile"Unban Insert Query Failed: %s"error);
        if (
admin && IsClientInGame(admin))
        {
            
PrintToChat(admin"%ssm_unban failed"Prefix);
        }
        return;
    }

    
LogAction(admin, -1"\"%L\" removed ban (filter \"%s\") (reason \"%s\")"adminargreason);
    if (
admin && IsClientInGame(admin))
    {
        
PrintToChat(admin"%s%s successfully unbanned"Prefixarg);
    } else {
        
PrintToServer("%s%s successfully unbanned"Prefixarg);
    }
}

public 
SelectAddbanCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    
decl adminminutesString:adminAuth[30], String:adminIp[30], String:authid[20], String:banReason[256], String:Query[512];
    new 
String:reason[128];
    
ResetPack(data);
    
admin ReadPackCell(data);
    
minutes ReadPackCell(data);
    
ReadPackString(datareasonsizeof(reason));
    
ReadPackString(dataauthidsizeof(authid));
    
ReadPackString(dataadminAuthsizeof(adminAuth));
    
ReadPackString(dataadminIpsizeof(adminIp));
    
SQL_EscapeString(DBreasonbanReasonsizeof(banReason));

    if (
error[0])
    {
        
LogToFile(logFile"Add Ban Select Query Failed: %s"error);
        if (
admin && IsClientInGame(admin))
            
PrintToChat(admin"%sFailed to ban %s."Prefixauthid);
        else
            
PrintToServer("%sFailed to ban %s."Prefixauthid);
        return;
    }
    if (
SQL_GetRowCount(hndl))
    {
        if (
admin && IsClientInGame(admin))
            
PrintToChat(admin"%s%s is already banned."Prefixauthid);
        else
            
PrintToServer("%s%s is already banned."Prefixauthid);
        return;
    }
    if (
serverID == -1)
    {
        
FormatEx(Querysizeof(Query), "INSERT INTO %s_bans (authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
                        ('%s', '', UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
                        (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1), ' ')"
,
            
DatabasePrefixauthid, (minutes 60), (minutes 60), banReasonDatabasePrefixadminAuthadminAuth[8], adminIpDatabasePrefixServerIpServerPort);
    } else {
        
FormatEx(Querysizeof(Query), "INSERT INTO %s_bans (authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
                        ('%s', '', UNIX_TIMESTAMP(), UNIX_TIMESTAMP() + %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
                        %d, ' ')"
,
            
DatabasePrefixauthid, (minutes 60), (minutes 60), banReasonDatabasePrefixadminAuthadminAuth[8], adminIpserverID);
    }

    
SQL_TQuery(DBInsertAddbanCallbackQuerydataDBPrio_High);
}

public 
InsertAddbanCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    
decl adminminutesString:authid[20];
    new 
String:reason[128];
    
ResetPack(data);
    
admin ReadPackCell(data);
    
minutes ReadPackCell(data);
    
ReadPackString(datareasonsizeof(reason));
    
ReadPackString(dataauthidsizeof(authid));

    
// If error is not an empty string the query failed
    
if (error[0] != '\0')
    {
        
LogToFile(logFile"Add Ban Insert Query Failed: %s"error);
        if (
admin && IsClientInGame(admin))
        {
            
PrintToChat(admin"%ssm_addban failed"Prefix);
        }
        return;
    }

    
LogAction(admin,
        -
1,
        
"\"%L\" added ban (minutes \"%i\") (id \"%s\") (reason \"%s\")",
        
admin,
        
minutes,
        
authid,
        
reason);
    if (
admin && IsClientInGame(admin))
    {
        
PrintToChat(admin"%s%s successfully banned"Prefixauthid);
    } else {
        
PrintToServer("%s%s successfully banned"Prefixauthid);
    }
}

// ProcessQueueCallback is called as the result of selecting all the rows from the queue table
public ProcessQueueCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (
hndl == INVALID_HANDLE || strlen(error) > 0)
    {
        
LogToFile(logFile"Failed to retrieve queued bans from sqlite database, %s"error);
        return;
    }

    
decl String:auth[30];
    
decl time;
    
decl startTime;
    new 
String:reason[128];
    
decl String:name[64];
    
decl String:ip[20];
    
decl String:adminAuth[30];
    
decl String:adminIp[20];
    
decl String:query[1024];
    
decl String:banName[128];
    
decl String:banReason[256];
    while (
SQL_MoreRows(hndl))
    {
        
// Oh noes! What happened?!
        
if (!SQL_FetchRow(hndl))
            continue;

        
// if we get to here then there are rows in the queue pending processing
        
SQL_FetchString(hndl0authsizeof(auth));
        
time SQL_FetchInt(hndl1);
        
startTime SQL_FetchInt(hndl2);
        
SQL_FetchString(hndl3reasonsizeof(reason));
        
SQL_FetchString(hndl4namesizeof(name));
        
SQL_FetchString(hndl5ipsizeof(ip));
        
SQL_FetchString(hndl6adminAuthsizeof(adminAuth));
        
SQL_FetchString(hndl7adminIpsizeof(adminIp));
        
SQL_EscapeString(SQLiteDBnamebanNamesizeof(banName));
        
SQL_EscapeString(SQLiteDBreasonbanReasonsizeof(banReason));
        if (
startTime time 60 GetTime() || time == 0)
        {
            
// This ban is still valid and should be entered into the db
            
if (serverID == -1)
            {
                
FormatEx(querysizeof(query),
                    
"INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid) VALUES  \
                        ('%s', '%s', '%s', %d, %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
                        (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1))"
,
                    
DatabasePrefixipauthbanNamestartTimestartTime time 60time 60banReasonDatabasePrefixadminAuthadminAuth[8], adminIpDatabasePrefixServerIpServerPort);
            }
            else
            {
                
FormatEx(querysizeof(query),
                    
"INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid) VALUES  \
                        ('%s', '%s', '%s', %d, %d, %d, '%s', (SELECT aid FROM %s_admins WHERE authid = '%s' OR authid REGEXP '^STEAM_[0-9]:%s$'), '%s', \
                        %d)"
,
                    
DatabasePrefixipauthbanNamestartTimestartTime time 60time 60banReasonDatabasePrefixadminAuthadminAuth[8], adminIpserverID);
            }
            new 
Handle:authPack CreateDataPack();
            
WritePackString(authPackauth);
            
ResetPack(authPack);
            
SQL_TQuery(DBAddedFromSQLiteCallbackqueryauthPack);
        } else {
            
// The ban is no longer valid and should be deleted from the queue
            
FormatEx(querysizeof(query), "DELETE FROM queue WHERE steam_id = '%s'"auth);
            
SQL_TQuery(SQLiteDBErrorCheckCallbackquery);
        }
    }
    
// We have finished processing the queue but should process again in ProcessQueueTime minutes
    
CreateTimer(float(ProcessQueueTime 60), ProcessQueue);
}

public 
AddedFromSQLiteCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    
decl String:buffer[512];
    
decl String:auth[40];
    
ReadPackString(dataauthsizeof(auth));
    if (
error[0] == '\0')
    {
        
// The insert was successful so delete the record from the queue
        
FormatEx(buffersizeof(buffer), "DELETE FROM queue WHERE steam_id = '%s'"auth);
        
SQL_TQuery(SQLiteDBErrorCheckCallbackbuffer);

        
// They are added to main banlist, so remove the temp ban
        
RemoveBan(authBANFLAG_AUTHID);

    } else {
        
// the insert failed so we leave the record in the queue and increase our temporary ban
        
FormatEx(buffersizeof(buffer), "banid %d %s"ProcessQueueTimeauth);
        
ServerCommand(buffer);
    }
    
CloseHandle(data);
}

public 
ServerInfoCallback(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (
error[0])
    {
        
LogToFile(logFile"Server Select Query Failed: %s"error);
        return;
    }

    if (
hndl == INVALID_HANDLE || SQL_GetRowCount(hndl) == 0)
    {
        
// get the game folder name used to determine the mod
        
decl String:desc[64], String:query[200];
        
GetGameFolderName(descsizeof(desc));
        
FormatEx(querysizeof(query), "INSERT INTO %s_servers (ip, port, rcon, modid) VALUES ('%s', '%s', '', (SELECT mid FROM %s_mods WHERE modfolder = '%s'))"DatabasePrefixServerIpServerPortDatabasePrefixdesc);
        
SQL_TQuery(DBErrorCheckCallbackquery);
    }
}

public 
ErrorCheckCallback(Handle:ownerHandle:hndle, const String:error[], any:data)
{
    if (
error[0])
    {
        
LogToFile(logFile"Query Failed: %s"error);
    }
}

public 
VerifyBan(Handle:ownerHandle:hndl, const String:error[], any:userid)
{
    
decl String:clientName[64];
    
decl String:clientAuth[64];
    
decl String:clientIp[64];
    new 
client GetClientOfUserId(userid);

    if (!
client)
        return;

    
/* Failure happen. Do retry with delay */
    
if (hndl == INVALID_HANDLE)
    {
        
LogToFile(logFile"Verify Ban Query Failed: %s"error);
        
PlayerRecheck[client] = CreateTimer(RetryTimeClientRecheckclient);
        return;
    }
    
GetClientIP(clientclientIpsizeof(clientIp));
    
GetClientAuthId(clientAuthId_Steam2clientAuthsizeof(clientAuth));
    
GetClientName(clientclientNamesizeof(clientName));
    if (
SQL_GetRowCount(hndl) > 0)
    {
        
decl String:buffer[40];
        
decl String:Name[128];
        
decl String:Query[512];

        
SQL_EscapeString(DBclientNameNamesizeof(Name));
        if (
serverID == -1)
        {
            
FormatEx(Querysizeof(Query), "INSERT INTO %s_banlog (sid ,time ,name ,bid) VALUES  \
                ((SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1), UNIX_TIMESTAMP(), '%s', \
                (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))"
,
                
DatabasePrefixDatabasePrefixServerIpServerPortNameDatabasePrefixclientAuth[8], clientIp);
        }
        else
        {
            
FormatEx(Querysizeof(Query), "INSERT INTO %s_banlog (sid ,time ,name ,bid) VALUES  \
                (%d, UNIX_TIMESTAMP(), '%s', \
                (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))"
,
                
DatabasePrefixserverIDNameDatabasePrefixclientAuth[8], clientIp);
        }

        
SQL_TQuery(DBErrorCheckCallbackQueryclientDBPrio_High);
        
FormatEx(buffersizeof(buffer), "banid 5 %s"clientAuth);
        
ServerCommand(buffer);
        
KickClient(client"%t""Banned Check Site"WebsiteAddress);
        return;
    }
    
#if defined DEBUG
    
LogToFile(logFile"%s is NOT banned."clientAuth);
    
#endif

    
PlayerStatus[client] = true;
}

public 
AdminsDone(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    
//SELECT authid, srv_password , srv_group, srv_flags, user
    
if (hndl == INVALID_HANDLE || strlen(error) > 0)
    {
        --
curLoading;
        
CheckLoadAdmins();
        
LogToFile(logFile"Failed to retrieve admins from the database, %s"error);
        return;
    }
    
decl String:authType[] = "steam";
    
decl String:identity[66];
    
decl String:password[66];
    
decl String:groups[256];
    
decl String:flags[32];
    
decl String:name[66];
    new 
admCount 0;
    new 
Immunity 0;
    new 
AdminId:curAdm INVALID_ADMIN_ID;
    new 
Handle:adminsKV CreateKeyValues("Admins");

    while (
SQL_MoreRows(hndl))
    {
        
SQL_FetchRow(hndl);
        if (
SQL_IsFieldNull(hndl0))
            continue; 
// Sometimes some rows return NULL due to some setups

        
SQL_FetchString(hndl0identity66);
        
SQL_FetchString(hndl1password66);
        
SQL_FetchString(hndl2groups256);
        
SQL_FetchString(hndl3flags32);
        
SQL_FetchString(hndl4name66);

        
Immunity SQL_FetchInt(hndl5);

        
TrimString(name);
        
TrimString(identity);
        
TrimString(groups);
        
TrimString(flags);

        
// Disable writing to file if they chose to
        
if (backupConfig)
        {
            
KvJumpToKey(adminsKVnametrue);

            
KvSetString(adminsKV"auth"authType);
            
KvSetString(adminsKV"identity"identity);

            if (
strlen(flags) > 0)
                
KvSetString(adminsKV"flags"flags);

            if (
strlen(groups) > 0)
                
KvSetString(adminsKV"group"groups);

            if (
strlen(password) > 0)
                
KvSetString(adminsKV"password"password);

            if (
Immunity 0)
                
KvSetNum(adminsKV"immunity"Immunity);

            
KvRewind(adminsKV);
        }

        
// find or create the admin using that identity
        
if ((curAdm FindAdminByIdentity(authTypeidentity)) == INVALID_ADMIN_ID)
        {
            
curAdm CreateAdmin(name);
            
// That should never happen!
            
if (!BindAdminIdentity(curAdmauthTypeidentity))
            {
                
LogToFile(logFile"Unable to bind admin %s to identity %s"nameidentity);
                
RemoveAdmin(curAdm);
                continue;
            }
        }

        
#if defined DEBUG
        
LogToFile(logFile"Given %s (%s) admin"nameidentity);
        
#endif

        
new curPos 0;
        new 
GroupId:curGrp INVALID_GROUP_ID;
        new 
numGroups;
        
decl String:iterGroupName[64];

        
// Who thought this comma seperated group parsing would be a good idea?!
        /*
        decl String:grp[64];
        new nextPos = 0;
        while ((nextPos = SplitString(groups[curPos],",",grp,64)) != -1)
        {
            curPos += nextPos;
            curGrp = FindAdmGroup(grp);
            if (curGrp == INVALID_GROUP_ID)
            {
                LogToFile(logFile, "Unknown group \"%s\"",grp);
            }
            else
            {
                // Check, if he's not in the group already.
                numGroups = GetAdminGroupCount(curAdm);
                for(new i=0;i<numGroups;i++)
                {
                    GetAdminGroup(curAdm, i, iterGroupName, sizeof(iterGroupName));
                    // Admin is already part of the group, so don't try to inherit its permissions.
                    if(StrEqual(iterGroupName, grp))
                    {
                        numGroups = -2;
                        break;
                    }
                }
                // Only try to inherit the group, if it's a new one.
                if (numGroups != -2 && !AdminInheritGroup(curAdm,curGrp))
                {
                    LogToFile(logFile, "Unable to inherit group \"%s\"",grp);
                }
            }
        }*/

        
if (strcmp(groups[curPos], "") != 0)
        {
            
curGrp FindAdmGroup(groups[curPos]);
            if (
curGrp == INVALID_GROUP_ID)
            {
                
LogToFile(logFile"Unknown group \"%s\""groups[curPos]);
            }
            else
            {
                
// Check, if he's not in the group already.
                
numGroups GetAdminGroupCount(curAdm);
                for (new 
0numGroupsi++)
                {
                    
GetAdminGroup(curAdmiiterGroupNamesizeof(iterGroupName));
                    
// Admin is already part of the group, so don't try to inherit its permissions.
                    
if (StrEqual(iterGroupNamegroups[curPos]))
                    {
                        
numGroups = -2;
                        break;
                    }
                }

                
// Only try to inherit the group, if it's a new one.
                
if (numGroups != -&& !AdminInheritGroup(curAdmcurGrp))
                {
                    
LogToFile(logFile"Unable to inherit group \"%s\""groups[curPos]);
                }

                if (
GetAdminImmunityLevel(curAdm) < Immunity)
                {
                    
SetAdminImmunityLevel(curAdmImmunity);
                }
                
#if defined DEBUG
                
LogToFile(logFile"Admin %s (%s) has %d immunity"nameidentityImmunity);
                
#endif
            
}
        }

        if (
strlen(password) > 0)
            
SetAdminPassword(curAdmpassword);

        for (new 
0strlen(flags); ++i)
        {
            if (
flags[i] < 'a' || flags[i] > 'z')
                continue;

            if (
g_FlagLetters[flags[i]-'a'] < Admin_Reservation)
                continue;

            
SetAdminFlag(curAdmg_FlagLetters[flags[i]-'a'], true);
        }
        ++
admCount;
    }

    if (
backupConfig)
        
KeyValuesToFile(adminsKVadminsLoc);
    
CloseHandle(adminsKV);

    
#if defined DEBUG
    
LogToFile(logFile"Finished loading %i admins."admCount);
    
#endif

    
--curLoading;
    
CheckLoadAdmins();
}

public 
GroupsDone(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (
hndl == INVALID_HANDLE)
    {
        
curLoading--;
        
CheckLoadAdmins();
        
LogToFile(logFile"Failed to retrieve groups from the database, %s"error);
        return;
    }
    
decl String:grpName[128], String:immuneGrpName[128];
    
decl String:grpFlags[32];
    new 
Immunity;
    new 
grpCount 0;
    new 
Handle:groupsKV CreateKeyValues("Groups");

    new 
GroupId:curGrp INVALID_GROUP_ID;
    while (
SQL_MoreRows(hndl))
    {
        
SQL_FetchRow(hndl);
        if (
SQL_IsFieldNull(hndl0))
            continue; 
// Sometimes some rows return NULL due to some setups
        
SQL_FetchString(hndl0grpName128);
        
SQL_FetchString(hndl1grpFlags32);
        
Immunity SQL_FetchInt(hndl2);
        
SQL_FetchString(hndl3immuneGrpName128);

        
TrimString(grpName);
        
TrimString(grpFlags);
        
TrimString(immuneGrpName);

        
// Ignore empty rows..
        
if (!strlen(grpName))
            continue;

        
curGrp CreateAdmGroup(grpName);

        if (
backupConfig)
        {
            
KvJumpToKey(groupsKVgrpNametrue);
            if (
strlen(grpFlags) > 0)
                
KvSetString(groupsKV"flags"grpFlags);
            if (
Immunity 0)
                
KvSetNum(groupsKV"immunity"Immunity);

            
KvRewind(groupsKV);
        }

        if (
curGrp == INVALID_GROUP_ID)
        {  
//This occurs when the group already exists
            
curGrp FindAdmGroup(grpName);
        }

        for (new 
0strlen(grpFlags); ++i)
        {
            if (
grpFlags[i] < 'a' || grpFlags[i] > 'z')
                continue;

            if (
g_FlagLetters[grpFlags[i]-'a'] < Admin_Reservation)
                continue;

            
SetAdmGroupAddFlag(curGrpg_FlagLetters[grpFlags[i]-'a'], true);
        }

        
// Set the group immunity.
        
if (Immunity 0)
        {
            
SetAdmGroupImmunityLevel(curGrpImmunity);
            
#if defined DEBUG
            
LogToFile(logFile"Group %s has %d immunity"grpNameImmunity);
            
#endif
        
}

        
grpCount++;
    }

    if (
backupConfig)
        
KeyValuesToFile(groupsKVgroupsLoc);
    
CloseHandle(groupsKV);

    
#if defined DEBUG
    
LogToFile(logFile"Finished loading %i groups."grpCount);
    
#endif

    // Load the group overrides
    
decl String:query[512];
    
FormatEx(query512"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"DatabasePrefixDatabasePrefix);
    
SQL_TQuery(DBLoadGroupsOverridesquery);

    
/*if (reparse)
    {
        decl String:query[512];
        FormatEx(query,512,"SELECT name, immunity, groups_immune FROM %s_srvgroups ORDER BY id",DatabasePrefix);
        SQL_TQuery(DB,GroupsSecondPass,query);
    }
    else
    {
        curLoading--;
        CheckLoadAdmins();
    }*/
}

// Reparse to apply inherited immunity
public GroupsSecondPass(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (
hndl == INVALID_HANDLE)
    {
        
curLoading--;
        
CheckLoadAdmins();
        
LogToFile(logFile"Failed to retrieve groups from the database, %s"error);
        return;
    }
    
decl String:grpName[128], String:immunityGrpName[128];

    new 
GroupId:curGrp INVALID_GROUP_ID;
    new 
GroupId:immuneGrp INVALID_GROUP_ID;
    while (
SQL_MoreRows(hndl))
    {
        
SQL_FetchRow(hndl);
        if (
SQL_IsFieldNull(hndl0))
            continue; 
// Sometimes some rows return NULL due to some setups

        
SQL_FetchString(hndl0grpName128);
        
TrimString(grpName);
        if (
strlen(grpName) == 0)
            continue;

        
SQL_FetchString(hndl2immunityGrpNamesizeof(immunityGrpName));
        
TrimString(immunityGrpName);

        
curGrp FindAdmGroup(grpName);
        if (
curGrp == INVALID_GROUP_ID)
            continue;

        
immuneGrp FindAdmGroup(immunityGrpName);
        if (
immuneGrp == INVALID_GROUP_ID)
            continue;

        
SetAdmGroupImmuneFrom(curGrpimmuneGrp);

        
#if defined DEBUG
        
LogToFile(logFile"Group %s inhertied immunity from group %s"grpNameimmunityGrpName);
        
#endif
    
}
    --
curLoading;
    
CheckLoadAdmins();
}

public 
LoadGroupsOverrides(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (
hndl == INVALID_HANDLE)
    {
        
curLoading--;
        
CheckLoadAdmins();
        
LogToFile(logFile"Failed to retrieve group overrides from the database, %s"error);
        return;
    }
    
decl String:sGroupName[128], String:sType[16], String:sCommand[64], String:sAllowed[16];
    
decl OverrideRule:iRuleOverrideType:iType;

    new 
Handle:groupsKV CreateKeyValues("Groups");
    
FileToKeyValues(groupsKVgroupsLoc);

    new 
GroupId:curGrp INVALID_GROUP_ID;
    while (
SQL_MoreRows(hndl))
    {
        
SQL_FetchRow(hndl);
        if (
SQL_IsFieldNull(hndl0))
            continue; 
// Sometimes some rows return NULL due to some setups

        
SQL_FetchString(hndl0sGroupNamesizeof(sGroupName));
        
TrimString(sGroupName);
        if (
strlen(sGroupName) == 0)
            continue;

        
SQL_FetchString(hndl1sTypesizeof(sType));
        
SQL_FetchString(hndl2sCommandsizeof(sCommand));
        
SQL_FetchString(hndl3sAllowedsizeof(sAllowed));

        
curGrp FindAdmGroup(sGroupName);
        if (
curGrp == INVALID_GROUP_ID)
            continue;

        
iRule StrEqual(sAllowed"allow") ? Command_Allow Command_Deny;
        
iType StrEqual(sType"group") ? Override_CommandGroup Override_Command;

        
#if defined DEBUG
        
PrintToServer("AddAdmGroupCmdOverride(%i, %s, %i, %i)"curGrpsCommandiTypeiRule);
        
#endif

        // Save overrides into admin_groups.cfg backup
        
if (KvJumpToKey(groupsKVsGroupName))
        {
            
KvJumpToKey(groupsKV"Overrides"true);
            if (
iType == Override_Command)
                
KvSetString(groupsKVsCommandsAllowed);
            else
            {
                
Format(sCommandsizeof(sCommand), "@%s"sCommand);
                
KvSetString(groupsKVsCommandsAllowed);
            }
            
KvRewind(groupsKV);
        }

        
AddAdmGroupCmdOverride(curGrpsCommandiTypeiRule);
    }
    
curLoading--;
    
CheckLoadAdmins();

    if (
backupConfig)
        
KeyValuesToFile(groupsKVgroupsLoc);
    
CloseHandle(groupsKV);
}

public 
OverridesDone(Handle:ownerHandle:hndl, const String:error[], any:data)
{
    if (
hndl == INVALID_HANDLE)
    {
        
LogToFile(logFile"Failed to retrieve overrides from the database, %s"error);
        
ParseBackupConfig_Overrides();
        return;
    }

    new 
Handle:hKV CreateKeyValues("SB_Overrides");

    
decl String:sFlags[32], String:sName[64], String:sType[64];
    while (
SQL_FetchRow(hndl))
    {
        
SQL_FetchString(hndl0sTypesizeof(sType));
        
SQL_FetchString(hndl1sNamesizeof(sName));
        
SQL_FetchString(hndl2sFlagssizeof(sFlags));

        
// KeyValuesToFile won't add that key, if the value is ""..
        
if (sFlags[0] == '\0')
        {
            
sFlags[0] = ' ';
            
sFlags[1] = '\0';
        }

        
#if defined DEBUG
        
LogToFile(logFile"Adding override (%s, %s, %s)"sTypesNamesFlags);
        
#endif

        
if (StrEqual(sType"command"))
        {
            
AddCommandOverride(sNameOverride_CommandReadFlagString(sFlags));
            
KvJumpToKey(hKV"override_commands"true);
            
KvSetString(hKVsNamesFlags);
            
KvGoBack(hKV);
        }
        else if (
StrEqual(sType"group"))
        {
            
AddCommandOverride(sNameOverride_CommandGroupReadFlagString(sFlags));
            
KvJumpToKey(hKV"override_groups"true);
            
KvSetString(hKVsNamesFlags);
            
KvGoBack(hKV);
        }
    }

    
KvRewind(hKV);

    if (
backupConfig)
        
KeyValuesToFile(hKVoverridesLoc);
    
CloseHandle(hKV);
}

// TIMER CALL BACKS //

public Action:ClientRecheck(Handle:timerany:client)
{
    
decl String:Authid[64];
    if (!
PlayerStatus[client] && IsClientConnected(client) && GetClientAuthId(clientAuthId_Steam2Authidsizeof(Authid)))
    {
        
OnClientAuthorized(clientAuthid);
    }

    
PlayerRecheck[client] = INVALID_HANDLE;
    return 
Plugin_Stop;
}

/*
public Action:PruneBans(Handle:timer)
{
    decl String:Query[512];
    FormatEx(Query, sizeof(Query),
            "UPDATE %s_bans SET RemovedBy = 0, RemoveType = 'E', RemovedOn = UNIX_TIMESTAMP() WHERE length != '0' AND ends < UNIX_TIMESTAMP()",
            DatabasePrefix);

    SQL_TQuery(DB, ErrorCheckCallback, Query);
    return Plugin_Continue;
}
*/

public Action:ProcessQueue(Handle:timerany:data)
{
    
decl String:buffer[512];
    
Format(buffersizeof(buffer), "SELECT steam_id, time, start_time, reason, name, ip, admin_id, admin_ip FROM queue");
    
SQL_TQuery(SQLiteDBProcessQueueCallbackbuffer);
}

// PARSER //

static InitializeConfigParser()
{
    if (
ConfigParser == INVALID_HANDLE)
    {
        
ConfigParser SMC_CreateParser();
        
SMC_SetReaders(ConfigParserReadConfig_NewSectionReadConfig_KeyValueReadConfig_EndSection);
    }
}

static 
InternalReadConfig(const String:path[])
{
    
ConfigState ConfigStateNone;

    new 
SMCError:err SMC_ParseFile(ConfigParserpath);

    if (
err != SMCError_Okay)
    {
        
decl String:buffer[64];
        
PrintToServer("%s"SMC_GetErrorString(errbuffersizeof(buffer)) ? buffer "Fatal parse error");
    }
}

public 
SMCResult:ReadConfig_NewSection(Handle:smc, const String:name[], bool:opt_quotes)
{
    if (
name[0])
    {
        if (
strcmp("Config"namefalse) == 0) {
            
ConfigState ConfigStateConfig;
        } else if (
strcmp("BanReasons"namefalse) == 0) {
            
ConfigState ConfigStateReasons;
        } else if (
strcmp("HackingReasons"namefalse) == 0) {
            
ConfigState ConfigStateHacking;
        } else if (
strcmp("BanTime"namefalse) == 0) {
            
ConfigState ConfigStateTime;
        }
    }
    return 
SMCParse_Continue;
}

public 
SMCResult:ReadConfig_KeyValue(Handle:smc, const String:key[], const String:value[], bool:key_quotesbool:value_quotes)
{
    if (!
key[0])
        return 
SMCParse_Continue;

    switch (
ConfigState)
    {
        case 
ConfigStateConfig:
        {
            if (
strcmp("website"keyfalse) == 0)
            {
                
strcopy(WebsiteAddresssizeof(WebsiteAddress), value);
            }
            else if (
strcmp("Addban"keyfalse) == 0)
            {
                if (
StringToInt(value) == 0)
                {
                    
CommandDisable |= DISABLE_ADDBAN;
                }
            }
            else if (
strcmp("AutoAddServer"keyfalse) == 0)
            {
                
AutoAdd StringToInt(value) == 1;
            }
            else if (
strcmp("Unban"keyfalse) == 0)
            {
                if (
StringToInt(value) == 0)
                {
                    
CommandDisable |= DISABLE_UNBAN;
                }
            }
            else if (
strcmp("DatabasePrefix"keyfalse) == 0)
            {
                
strcopy(DatabasePrefixsizeof(DatabasePrefix), value);

                if (
DatabasePrefix[0] == '\0')
                {
                    
DatabasePrefix "sb";
                }
            }
            else if (
strcmp("RetryTime"keyfalse) == 0)
            {
                
RetryTime StringToFloat(value);
                if (
RetryTime 15.0)
                {
                    
RetryTime 15.0;
                } else if (
RetryTime 60.0) {
                    
RetryTime 60.0;
                }
            }
            else if (
strcmp("ProcessQueueTime"keyfalse) == 0)
            {
                
ProcessQueueTime StringToInt(value);
            }
            else if (
strcmp("BackupConfigs"keyfalse) == 0)
            {
                
backupConfig StringToInt(value) == 1;
            }
            else if (
strcmp("EnableAdmins"keyfalse) == 0)
            {
                
enableAdmins StringToInt(value) == 1;
            }
            else if (
strcmp("RequireSiteLogin"keyfalse) == 0)
            {
                
requireSiteLogin StringToInt(value) == 1;
            }
            else if (
strcmp("ServerID"keyfalse) == 0)
            {
                
serverID StringToInt(value);
            }
        }

        case 
ConfigStateReasons:
        {
            if (
ReasonMenuHandle != INVALID_HANDLE)
            {
                
AddMenuItem(ReasonMenuHandlekeyvalue);
            }
        }
        case 
ConfigStateHacking:
        {
            if (
HackingMenuHandle != INVALID_HANDLE)
            {
                
AddMenuItem(HackingMenuHandlekeyvalue);
            }
        }
        case 
ConfigStateTime:
        {
            if (
StringToInt(key) > -&& TimeMenuHandle != INVALID_HANDLE)
            {
                
AddMenuItem(TimeMenuHandlekeyvalue);
            }
        }
    }
    return 
SMCParse_Continue;
}

public 
SMCResult:ReadConfig_EndSection(Handle:smc)
{
    return 
SMCParse_Continue;
}


/*********************************************************
 * Ban Player from server
 *
 * @param client    The client index of the player to ban
 * @param time        The time to ban the player for (in minutes, 0 = permanent)
 * @param reason    The reason to ban the player from the server
 * @noreturn
 *********************************************************/
public Native_SBBanPlayer(Handle:pluginnumParams)
{
    new 
client GetNativeCell(1);
    new 
target GetNativeCell(2);
    new 
time GetNativeCell(3);
    new 
String:reason[128];
    
GetNativeString(4reason128);

    if (
reason[0] == '\0')
        
strcopy(reasonsizeof(reason), "Banned by SourceBans");

    if (
client && IsClientInGame(client))
    {
        new 
AdminId:aid GetUserAdmin(client);
        if (
aid == INVALID_ADMIN_ID)
        {
            
ThrowNativeError(SP_ERROR_NATIVE"Ban Error: Player is not an admin.");
            return 
0;
        }

        if (!
GetAdminFlag(aidAdmin_Ban))
        {
            
ThrowNativeError(SP_ERROR_NATIVE"Ban Error: Player does not have BAN flag.");
            return 
0;
        }
    }

    
PrepareBan(clienttargettimereasonsizeof(reason));
    return 
true;
}


// STOCK FUNCTIONS //

public InitializeBackupDB()
{
    
decl String:error[255];
    
SQLiteDB SQLite_UseDatabase("sourcebans-queue"errorsizeof(error));
    if (
SQLiteDB == INVALID_HANDLE)
        
SetFailState(error);

    
SQL_LockDatabase(SQLiteDB);
    
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);");
    
SQL_UnlockDatabase(SQLiteDB);
}

public 
bool:CreateBan(clienttargettimeString:reason[])
{
    
decl String:adminIp[24], String:adminAuth[64];
    new 
admin client;

    
// The server is the one calling the ban
    
if (!admin)
    {
        if (
reason[0] == '\0')
        {
            
// We cannot pop the reason menu if the command was issued from the server
            
PrintToServer("%s%T"Prefix"Include Reason"LANG_SERVER);
            return 
false;
        }

        
// setup dummy adminAuth and adminIp for server
        
strcopy(adminAuthsizeof(adminAuth), "STEAM_ID_SERVER");
        
strcopy(adminIpsizeof(adminIp), ServerIp);
    } else {
        
GetClientIP(adminadminIpsizeof(adminIp));
        
GetClientAuthId(adminAuthId_Steam2adminAuthsizeof(adminAuth));
    }

    
// target information
    
decl String:ip[24], String:auth[64], String:name[64];

    
GetClientName(targetnamesizeof(name));
    
GetClientIP(targetipsizeof(ip));
    if (!
GetClientAuthId(targetAuthId_Steam2authsizeof(auth)))
        return 
false;

    new 
userid admin GetClientUserId(admin) : 0;

    
// Pack everything into a data pack so we can retain it
    
new Handle:dataPack CreateDataPack();
    new 
Handle:reasonPack CreateDataPack();
    
WritePackString(reasonPackreason);

    
WritePackCell(dataPackadmin);
    
WritePackCell(dataPacktarget);
    
WritePackCell(dataPackuserid);
    
WritePackCell(dataPackGetClientUserId(target));
    
WritePackCell(dataPacktime);
    
WritePackCell(dataPack_:reasonPack);
    
WritePackString(dataPackname);
    
WritePackString(dataPackauth);
    
WritePackString(dataPackip);
    
WritePackString(dataPackadminAuth);
    
WritePackString(dataPackadminIp);

    
ResetPack(dataPack);
    
ResetPack(reasonPack);

    if (
reason[0] != '\0')
    {
        
// if we have a valid reason pass move forward with the ban
        
if (DB != INVALID_HANDLE)
        {
            
UTIL_InsertBan(timenameauthipreasonadminAuthadminIpdataPack);
        } else {
            
UTIL_InsertTempBan(timenameauthipreasonadminAuthadminIpdataPack);
        }
    } else {
        
// We need a reason so offer the administrator a menu of reasons
        
PlayerDataPack[admin] = dataPack;
        
DisplayMenu(ReasonMenuHandleadminMENU_TIME_FOREVER);
        
ReplyToCommand(admin"%c[%cSourceBans%c]%c %t"GREENNAMECOLORGREENNAMECOLOR"Check Menu");
    }

    
Call_StartForward(g_hFwd_OnBanAdded);
    
Call_PushCell(client);
    
Call_PushCell(target);
    
Call_PushCell(time);
    
Call_PushString(reason);
    
Call_Finish();

    return 
true;
}

stock UTIL_InsertBan(time, const String:Name[], const String:Authid[], const String:Ip[], const String:Reason[], const String:AdminAuthid[], const String:AdminIp[], Handle:Pack)
{
    
//new Handle:dummy;
    //PruneBans(dummy);
    
decl String:banName[128];
    
decl String:banReason[256];
    
decl String:Query[1024];
    
SQL_EscapeString(DBNamebanNamesizeof(banName));
    
SQL_EscapeString(DBReasonbanReasonsizeof(banReason));
    if (
serverID == -1)
    {
        
FormatEx(Querysizeof(Query), "INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
                        ('%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', \
                        (SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s' LIMIT 0,1), ' ')"
,
            
DatabasePrefixIpAuthidbanName, (time 60), (time 60), banReasonDatabasePrefixAdminAuthidAdminAuthid[8], AdminIpDatabasePrefixServerIpServerPort);
    } else {
        
FormatEx(Querysizeof(Query), "INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES \
                        ('%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', \
                        %d, ' ')"
,
            
DatabasePrefixIpAuthidbanName, (time 60), (time 60), banReasonDatabasePrefixAdminAuthidAdminAuthid[8], AdminIpserverID);
    }

    
SQL_TQuery(DBVerifyInsertQueryPackDBPrio_High);
}

stock UTIL_InsertTempBan(time, const String:name[], const String:auth[], const String:ip[], const String:reason[], const String:adminAuth[], const String:adminIp[], Handle:dataPack)
{
    
ReadPackCell(dataPack); // admin index
    
new client ReadPackCell(dataPack);
    
ReadPackCell(dataPack); // admin userid
    
ReadPackCell(dataPack); // target userid
    
ReadPackCell(dataPack); // time
    
new Handle:reasonPack Handle:ReadPackCell(dataPack);
    if (
reasonPack != INVALID_HANDLE)
    {
        
CloseHandle(reasonPack);
    }
    
CloseHandle(dataPack);

    
// we add a temporary ban and then add the record into the queue to be processed when the database is available
    
decl String:buffer[50];
    
Format(buffersizeof(buffer), "banid %d %s"ProcessQueueTimeauth);
    
ServerCommand(buffer);
    if (
IsClientInGame(client))
        
KickClient(client"%t""Banned Check Site"WebsiteAddress);

    
decl String:banName[128];
    
decl String:banReason[256];
    
decl String:query[512];
    
SQL_EscapeString(SQLiteDBnamebanNamesizeof(banName));
    
SQL_EscapeString(SQLiteDBreasonbanReasonsizeof(banReason));
    
FormatEx(querysizeof(query), "INSERT INTO queue VALUES ('%s', %i, %i, '%s', '%s', '%s', '%s', '%s')",
        
authtimeGetTime(), banReasonbanNameipadminAuthadminIp);
    
SQL_TQuery(SQLiteDBErrorCheckCallbackquery);
}

stock CheckLoadAdmins()
{
    for (new 
1<= MaxClientsi++)
    {
        if (
IsClientInGame(i) && IsClientAuthorized(i))
        {
            
RunAdminCacheChecks(i);
            
NotifyPostAdminCheck(i);
        }
    }
}

stock InsertServerInfo()
{
    if (
DB == INVALID_HANDLE)
    {
        return;
    }

    
decl String:query[100], pieces[4];
    new 
longip GetConVarInt(CvarHostIp);
    
pieces[0] = (longip >> 24) & 0x000000FF;
    
pieces[1] = (longip >> 16) & 0x000000FF;
    
pieces[2] = (longip >> 8) & 0x000000FF;
    
pieces[3] = longip 0x000000FF;
    
FormatEx(ServerIpsizeof(ServerIp), "%d.%d.%d.%d"pieces[0], pieces[1], pieces[2], pieces[3]);
    
GetConVarString(CvarPortServerPortsizeof(ServerPort));

    if (
AutoAdd != false)
    {
        
FormatEx(querysizeof(query), "SELECT sid FROM %s_servers WHERE ip = '%s' AND port = '%s'"DatabasePrefixServerIpServerPort);
        
SQL_TQuery(DBServerInfoCallbackquery);
    }
}

stock PrepareBan(clienttargettimeString:reason[], size)
{
    
#if defined DEBUG
    
LogToFile(logFile"PrepareBan()");
    
#endif
    
if (!target || !IsClientInGame(target))
        return;
    
decl String:authid[64], String:name[32], String:bannedSite[512];
    if (!
GetClientAuthId(targetAuthId_Steam2authidsizeof(authid)))
        return;
    
GetClientName(targetnamesizeof(name));


    if (
CreateBan(clienttargettimereason))
    {
        if (!
time)
        {
            if (
reason[0] == '\0')
            {
                
ShowActivity(client"%t""Permabanned player"name);
            } else {
                
ShowActivity(client"%t""Permabanned player reason"namereason);
            }
        } else {
            if (
reason[0] == '\0')
            {
                
ShowActivity(client"%t""Banned player"nametime);
            } else {
                
ShowActivity(client"%t""Banned player reason"nametimereason);
            }
        }
        
LogAction(clienttarget"\"%L\" banned \"%L\" (minutes \"%d\") (reason \"%s\")"clienttargettimereason);

        if (
time || time == 0)
            
time 5;
        
Format(bannedSitesizeof(bannedSite), "%T""Banned Check Site"targetWebsiteAddress);
        
BanClient(targettimeBANFLAG_AUTObannedSitebannedSite"sm_ban"client);
    }

    
g_BanTarget[client] = -1;
    
g_BanTime[client] = -1;
}

stock ReadConfig()
{
    
InitializeConfigParser();

    if (
ConfigParser == INVALID_HANDLE)
    {
        return;
    }

    
decl String:ConfigFile[PLATFORM_MAX_PATH];
    
BuildPath(Path_SMConfigFilesizeof(ConfigFile), "configs/sourcebans/sourcebans.cfg");

    if (
FileExists(ConfigFile))
    {
        
InternalReadConfig(ConfigFile);
        
PrintToServer("%sLoading configs/sourcebans.cfg config file"Prefix);
    } else {
        
decl String:Error[PLATFORM_MAX_PATH 64];
        
FormatEx(Errorsizeof(Error), "%sFATAL *** ERROR *** can not find %s"PrefixConfigFile);
        
LogToFile(logFile"FATAL *** ERROR *** can not find %s"ConfigFile);
        
SetFailState(Error);
    }
}

stock ResetSettings()
{
    
CommandDisable 0;

    
ResetMenu();
    
ReadConfig();
}

stock ParseBackupConfig_Overrides()
{
    new 
Handle:hKV CreateKeyValues("SB_Overrides");
    if (!
FileToKeyValues(hKVoverridesLoc))
        return;

    if (!
KvGotoFirstSubKey(hKV))
        return;

    
decl String:sSection[16], String:sFlags[32], String:sName[64];
    
decl OverrideType:type;
    do
    {
        
KvGetSectionName(hKVsSectionsizeof(sSection));
        if (
StrEqual(sSection"override_commands"))
            
type Override_Command;
        else if (
StrEqual(sSection"override_groups"))
            
type Override_CommandGroup;
        else
            continue;

        if (
KvGotoFirstSubKey(hKVfalse))
        {
            do
            {
                
KvGetSectionName(hKVsNamesizeof(sName));
                
KvGetString(hKVNULL_STRINGsFlagssizeof(sFlags));
                
AddCommandOverride(sNametypeReadFlagString(sFlags));
                
#if defined _DEBUG
                
PrintToServer("Adding override (%s, %s, %s)"sSectionsNamesFlags);
                
#endif
            
} while (KvGotoNextKey(hKVfalse));
            
KvGoBack(hKV);
        }
    }
    while (
KvGotoNextKey(hKV));
    
CloseHandle(hKV);
}

stock AdminFlag:CreateFlagLetters()
{
    new 
AdminFlag:FlagLetters[FLAG_LETTERS_SIZE];

    
FlagLetters['a'-'a'] = Admin_Reservation;
    
FlagLetters['b'-'a'] = Admin_Generic;
    
FlagLetters['c'-'a'] = Admin_Kick;
    
FlagLetters['d'-'a'] = Admin_Ban;
    
FlagLetters['e'-'a'] = Admin_Unban;
    
FlagLetters['f'-'a'] = Admin_Slay;
    
FlagLetters['g'-'a'] = Admin_Changemap;
    
FlagLetters['h'-'a'] = Admin_Convars;
    
FlagLetters['i'-'a'] = Admin_Config;
    
FlagLetters['j'-'a'] = Admin_Chat;
    
FlagLetters['k'-'a'] = Admin_Vote;
    
FlagLetters['l'-'a'] = Admin_Password;
    
FlagLetters['m'-'a'] = Admin_RCON;
    
FlagLetters['n'-'a'] = Admin_Cheats;
    
FlagLetters['o'-'a'] = Admin_Custom1;
    
FlagLetters['p'-'a'] = Admin_Custom2;
    
FlagLetters['q'-'a'] = Admin_Custom3;
    
FlagLetters['r'-'a'] = Admin_Custom4;
    
FlagLetters['s'-'a'] = Admin_Custom5;
    
FlagLetters['t'-'a'] = Admin_Custom6;
    
FlagLetters['z'-'a'] = Admin_Root;

    return 
FlagLetters;
}

stock AccountForLateLoading()
{
    
decl String:auth[30];
    for (new 
1<= GetMaxClients(); i++)
    {
        if (
IsClientConnected(i) && !IsFakeClient(i))
        {
            
PlayerStatus[i] = false;
        }
        if (
IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i) && GetClientAuthId(iAuthId_Steam2authsizeof(auth)))
        {
            
OnClientAuthorized(iauth);
        }
    }
}

//Yarr! 

DataBase:
http://uupload.ir/files/mjed_untitlwwwwwed.png

web:
http://uupload.ir/files/ck3_untit1111ed.png

Neuro Toxin 02-23-2018 20:11

Re: [CS:GO] add checker ServerID
 
Ask in the plugins thread.

Dr.Mohammad 02-24-2018 07:03

Re: [CS:GO] add checker ServerID
 
Quote:

Originally Posted by Neuro Toxin (Post 2579775)
Ask in the plugins thread.

i asked in the plugins thread:
https://forums.alliedmods.net/showth...63735&page=122
and
i searched on this forum but no find anything :(

please help me

DarkDeviL 02-24-2018 09:50

Re: [CS:GO] add checker ServerID
 
SourceBans is a GLOBAL ban database, built to work across all your servers, and not built as a "per server" ban system.

Remove SourceBans and use the game engine's own ban system if you want things on a "per server" basis.

backwards 02-24-2018 12:39

Re: [CS:GO] add checker ServerID
 
Quote:

Originally Posted by arne1288 (Post 2579857)
SourceBans is a GLOBAL ban database, built to work across all your servers, and not built as a "per server" ban system.

Remove SourceBans and use the game engine's own ban system if you want things on a "per server" basis.

OR just add:
PHP Code:

while(SQL_FetchRow(hndl))
{
    new 
sid SQL_FetchInt(hndl1);
    if(
serverID != sid)
    {
        
PlayerStatus[client] = true;
        return;
    }


inside the function
PHP Code:

public VerifyBan(Handle:ownerHandle:hndl, const String:error[], any:userid

between functions:
PHP Code:

SQL_TQuery(DBErrorCheckCallbackQueryclientDBPrio_High); 

and:
PHP Code:

FormatEx(buffersizeof(buffer), "banid 5 %s"clientAuth); 

Then in function:
PHP Code:

public OnClientAuthorized(client, const String:auth[]) 

modify the FormatEx string from:
PHP Code:

"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" 

to:
PHP Code:

"SELECT bid, sid 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" 


Dr.Mohammad 02-24-2018 21:17

Re: [CS:GO] add checker ServerID
 
Quote:

Originally Posted by 1337norway (Post 2579903)
OR just add:
PHP Code:

while(SQL_FetchRow(hndl))
{
    new 
sid SQL_FetchInt(hndl1);
    if(
serverID != sid)
    {
        
PlayerStatus[client] = true;
        return;
    }


inside the function
PHP Code:

public VerifyBan(Handle:ownerHandle:hndl, const String:error[], any:userid

between functions:
PHP Code:

SQL_TQuery(DBErrorCheckCallbackQueryclientDBPrio_High); 

and:
PHP Code:

FormatEx(buffersizeof(buffer), "banid 5 %s"clientAuth); 

Then in function:
PHP Code:

public OnClientAuthorized(client, const String:auth[]) 

modify the FormatEx string from:
PHP Code:

"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" 

to:
PHP Code:

"SELECT bid, sid 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" 


:bacon!::bacon!::bacon!::bacon!::bacon!:

Nice Work

Thank You For Help

:bacon!::bacon!::bacon!::bacon!::bacon!:


All times are GMT -4. The time now is 07:46.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.