diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp
index 3265756d..c1f7cf46 100644
--- a/core/HalfLife2.cpp
+++ b/core/HalfLife2.cpp
@@ -37,6 +37,7 @@
CHalfLife2 g_HL2;
bool g_IsOriginalEngine = false;
+ConVar *sv_lan = NULL;
namespace SourceHook
{
@@ -369,3 +370,16 @@ void CHalfLife2::ProcessFakeCliCmdQueue()
m_CmdQueue.pop();
}
}
+
+bool CHalfLife2::IsLANServer()
+{
+ sv_lan = icvar->FindVar("sv_lan");
+
+ if (!sv_lan)
+ {
+ return false;
+ }
+
+ return (sv_lan->GetInt() != 0);
+}
+
diff --git a/core/HalfLife2.h b/core/HalfLife2.h
index a617fcf4..23664fc3 100644
--- a/core/HalfLife2.h
+++ b/core/HalfLife2.h
@@ -86,6 +86,7 @@ public: //IGameHelpers
bool TextMsg(int client, int dest, const char *msg);
bool HintTextMsg(int client, const char *msg);
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
+ bool IsLANServer();
public:
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
void ProcessFakeCliCmdQueue();
diff --git a/core/Makefile b/core/Makefile
index c9022815..8af985e1 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -27,7 +27,8 @@ OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreC
frame_hooks.cpp
OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
- smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp smn_handles.cpp smn_keyvalues.cpp \
+ smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
+ smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp \
smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp
OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
diff --git a/core/smn_banning.cpp b/core/smn_banning.cpp
new file mode 100644
index 00000000..6984e71e
--- /dev/null
+++ b/core/smn_banning.cpp
@@ -0,0 +1,378 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod
+ * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program 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
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#include "sm_globals.h"
+#include "sm_stringutil.h"
+#include "HalfLife2.h"
+#include "PlayerManager.h"
+#include "ForwardSys.h"
+#include
+#include
+
+#define BANFLAG_AUTO (1<<0) /**< Auto-detects whether to ban by steamid or IP */
+#define BANFLAG_IP (1<<1) /**< Always ban by IP address */
+#define BANFLAG_AUTHID (1<<2) /**< Ban by SteamID */
+#define BANFLAG_NOKICK (1<<3) /**< Does not kick the client */
+#define BANFLAG_NOWRITE (1<<4) /**< Ban is not written to SourceDS's files if permanent */
+
+IForward *g_pOnBanClient = NULL;
+IForward *g_pOnBanIdentity = NULL;
+IForward *g_pOnRemoveBan = NULL;
+
+class BanNativeHelpers : public SMGlobalClass
+{
+public:
+ void OnSourceModAllInitialized()
+ {
+ g_pOnBanClient = g_Forwards.CreateForward(
+ "OnBanClient",
+ ET_Ignore,
+ 7,
+ NULL,
+ Param_Cell,
+ Param_Cell,
+ Param_Cell,
+ Param_String,
+ Param_String,
+ Param_String,
+ Param_Cell);
+ g_pOnBanIdentity = g_Forwards.CreateForward(
+ "OnBanIdentity",
+ ET_Ignore,
+ 6,
+ NULL,
+ Param_String,
+ Param_Cell,
+ Param_Cell,
+ Param_String,
+ Param_String,
+ Param_Cell);
+ g_pOnRemoveBan = g_Forwards.CreateForward(
+ "OnRemoveBan",
+ ET_Ignore,
+ 4,
+ NULL,
+ Param_String,
+ Param_Cell,
+ Param_String,
+ Param_Cell);
+ }
+ void OnSourceModShutdown()
+ {
+ g_Forwards.ReleaseForward(g_pOnBanClient);
+ g_Forwards.ReleaseForward(g_pOnBanIdentity);
+ g_Forwards.ReleaseForward(g_pOnRemoveBan);
+
+ g_pOnBanClient = NULL;
+ g_pOnBanIdentity = NULL;
+ g_pOnRemoveBan = NULL;
+ }
+} s_BanNativeHelpers;
+
+
+static cell_t BanIdentity(IPluginContext *pContext, const cell_t *params)
+{
+ char *r_identity, *ban_reason, *ban_cmd;
+ int ban_time, ban_flags, ban_source;
+
+ pContext->LocalToString(params[1], &r_identity);
+ pContext->LocalToString(params[4], &ban_reason);
+ pContext->LocalToString(params[5], &ban_cmd);
+ ban_time = params[2];
+ ban_flags = params[3];
+ ban_source = params[6];
+
+ /* Make sure we can ban by one of the two methods! */
+ bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
+ if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
+ {
+ return pContext->ThrowNativeError("No valid ban flags specified");
+ }
+
+ /* Sanitize the input */
+ char identity[64];
+ strncopy(identity, r_identity, sizeof(identity));
+ UTIL_ReplaceAll(identity, sizeof(identity), ";", "");
+
+ if (ban_cmd[0] != '\0' && g_pOnBanIdentity->GetFunctionCount() > 0)
+ {
+ g_pOnBanIdentity->PushString(identity);
+ g_pOnBanIdentity->PushCell(ban_time);
+ g_pOnBanIdentity->PushCell(ban_flags);
+ g_pOnBanIdentity->PushString(ban_reason);
+ g_pOnBanIdentity->PushString(ban_cmd);
+ g_pOnBanIdentity->PushCell(ban_source);
+ g_pOnBanIdentity->Execute(NULL);
+ }
+
+ bool write_ban = ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE);
+
+ char command[256];
+ if (ban_by_ip)
+ {
+ UTIL_Format(
+ command,
+ sizeof(command),
+ "addip %d %s\n",
+ ban_time,
+ identity);
+ engine->ServerCommand(command);
+
+ if (write_ban && ban_time == 0)
+ {
+ engine->ServerCommand("writeip\n");
+ }
+ }
+ else if (!g_HL2.IsLANServer())
+ {
+ UTIL_Format(
+ command,
+ sizeof(command),
+ "banid %d %s\n",
+ ban_time,
+ identity);
+ engine->ServerCommand(command);
+
+ if (write_ban && ban_time == 0)
+ {
+ engine->ServerCommand("writeid\n");
+ }
+ }
+ else
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static cell_t RemoveBan(IPluginContext *pContext, const cell_t *params)
+{
+ char *r_identity, *ban_cmd;
+ int ban_flags, ban_source;
+
+ pContext->LocalToString(params[1], &r_identity);
+ pContext->LocalToString(params[3], &ban_cmd);
+ ban_flags = params[2];
+ ban_source = params[4];
+
+ /* Make sure we can ban by one of the two methods! */
+ bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
+ if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
+ {
+ return pContext->ThrowNativeError("No valid ban flags specified");
+ }
+
+ char identity[64];
+ strncopy(identity, r_identity, sizeof(identity));
+ UTIL_ReplaceAll(identity, sizeof(identity), ";", "");
+
+ if (ban_cmd[0] != '\0' && g_pOnRemoveBan->GetFunctionCount() > 0)
+ {
+ g_pOnRemoveBan->PushString(identity);
+ g_pOnRemoveBan->PushCell(ban_flags);
+ g_pOnRemoveBan->PushString(ban_cmd);
+ g_pOnRemoveBan->PushCell(ban_source);
+ g_pOnRemoveBan->Execute(NULL);
+ }
+
+ char command[256];
+ if (ban_by_ip)
+ {
+ UTIL_Format(
+ command,
+ sizeof(command),
+ "removeip %s\n",
+ identity);
+ engine->ServerCommand(command);
+ engine->ServerCommand("writeip\n");
+ }
+ else if (!g_HL2.IsLANServer())
+ {
+ UTIL_Format(
+ command,
+ sizeof(command),
+ "removeid %s\n",
+ identity);
+ engine->ServerCommand(command);
+ engine->ServerCommand("writeid\n");
+ }
+ else
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+static cell_t BanClient(IPluginContext *pContext, const cell_t *params)
+{
+ const char *kick_message;
+ char *ban_reason, *ban_cmd;
+ int client, ban_flags, ban_source, ban_time;
+
+ client = params[1];
+
+ CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
+ if (!pPlayer || !pPlayer->IsConnected())
+ {
+ return pContext->ThrowNativeError("Client index %d is invalid", client);
+ }
+
+ pContext->LocalToString(params[4], &ban_reason);
+ pContext->LocalToString(params[5], (char **)&kick_message);
+ pContext->LocalToString(params[6], &ban_cmd);
+ ban_time = params[2];
+ ban_flags = params[3];
+ ban_source = params[7];
+
+ INetChannel *pNetChan = static_cast(engine->GetPlayerNetInfo(params[1]));
+ IClient *pClient = static_cast(pNetChan->GetMsgHandler());
+
+ /* Check how we should ban the player */
+ if ((ban_flags & BANFLAG_AUTO) == BANFLAG_AUTO)
+ {
+ if (g_HL2.IsLANServer() || !pPlayer->IsAuthorized())
+ {
+ ban_flags |= BANFLAG_IP;
+ ban_flags &= BANFLAG_AUTHID;
+ }
+ else
+ {
+ ban_flags |= BANFLAG_AUTHID;
+ ban_flags &= BANFLAG_IP;
+ }
+ }
+ else if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
+ {
+ ban_flags |= BANFLAG_IP;
+ ban_flags &= BANFLAG_AUTHID;
+ }
+ else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
+ {
+ if (pPlayer->IsAuthorized())
+ {
+ ban_flags |= BANFLAG_AUTHID;
+ ban_flags &= BANFLAG_IP;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ return pContext->ThrowNativeError("No valid ban method flags specified");
+ }
+
+ if (ban_cmd[0] != '\0' && g_pOnBanClient->GetFunctionCount() > 0)
+ {
+ g_pOnBanClient->PushCell(client);
+ g_pOnBanClient->PushCell(ban_time);
+ g_pOnBanClient->PushCell(ban_flags);
+ g_pOnBanClient->PushString(ban_reason);
+ g_pOnBanClient->PushString(kick_message);
+ g_pOnBanClient->PushString(ban_cmd);
+ g_pOnBanClient->PushCell(ban_source);
+ g_pOnBanClient->Execute(NULL);
+ }
+
+ if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
+ {
+ /* Build a kick message */
+ const char *kick_message = "";
+ pContext->LocalToString(params[5], (char **)&kick_message);
+ if (kick_message[0] == '\0')
+ {
+ kick_message = "Kicked";
+ }
+
+ /* Disconnect the client now */
+ pClient->Disconnect("%s", kick_message);
+ }
+
+ if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
+ {
+ /* Get the IP address and strip the port */
+ char ip[24], *ptr;
+ strncopy(ip, pPlayer->GetIPAddress(), sizeof(ip));
+ if ((ptr = strchr(ip, ':')) != NULL)
+ {
+ *ptr = '\0';
+ }
+
+ /* Tell the server to ban the ip */
+ char command[256];
+ UTIL_Format(
+ command,
+ sizeof(command),
+ "addip %d %s\n",
+ ban_time,
+ ip);
+ engine->ServerCommand(command);
+
+ /* Physically write the ban */
+ if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
+ {
+ engine->ServerCommand("writeip\n");
+ }
+ }
+ else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
+ {
+ /* Tell the server to ban the auth string */
+ char command[256];
+ UTIL_Format(
+ command,
+ sizeof(command),
+ "banid %d %s\n",
+ ban_time,
+ pPlayer->GetAuthString());
+ engine->ServerCommand(command);
+
+ /* Physically write the ban if it's permanent */
+ if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
+ {
+ engine->ServerCommand("writeid\n");
+ }
+ }
+
+
+ return 1;
+}
+
+REGISTER_NATIVES(banNatives)
+{
+ {"BanClient", BanClient},
+ {"BanIdentity", BanIdentity},
+ {"RemoveBan", RemoveBan},
+ {NULL, NULL}
+};
+
diff --git a/core/smn_player.cpp b/core/smn_player.cpp
index d7d686e6..a82f71db 100644
--- a/core/smn_player.cpp
+++ b/core/smn_player.cpp
@@ -1142,3 +1142,4 @@ REGISTER_NATIVES(playernatives)
{"NotifyPostAdminCheck", NotifyPostAdminCheck},
{NULL, NULL}
};
+
diff --git a/plugins/basebans.sp b/plugins/basebans.sp
new file mode 100644
index 00000000..90ec2d24
--- /dev/null
+++ b/plugins/basebans.sp
@@ -0,0 +1,284 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod Basic Commands Plugin
+ * Implements basic admin commands.
+ *
+ * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program 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
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#pragma semicolon 1
+
+#include
+
+public Plugin:myinfo =
+{
+ name = "Basic Ban Commands",
+ author = "AlliedModders LLC",
+ description = "Basic Banning Commands",
+ version = SOURCEMOD_VERSION,
+ url = "http://www.sourcemod.net/"
+};
+
+public OnPluginStart()
+{
+ LoadTranslations("common.phrases");
+
+ RegAdminCmd("sm_ban", Command_Ban, ADMFLAG_BAN, "sm_ban <#userid|name> [reason]");
+ RegAdminCmd("sm_unban", Command_Unban, ADMFLAG_UNBAN, "sm_unban ");
+ RegAdminCmd("sm_addban", Command_AddBan, ADMFLAG_RCON, "sm_addban