From f136f2dcaf98d1affd54e12dc43bb27906aab5d2 Mon Sep 17 00:00:00 2001
From: Nicholas Hastings <skamonkey@gmail.com>
Date: Sat, 10 Sep 2011 12:08:38 -0400
Subject: [PATCH] Added CheckAccess native to check cmd/override access of
 AdminId (bug 5083, r=fyren).

---
 core/AdminCache.cpp         |  4 ++--
 core/ConCmdManager.cpp      | 10 +++++++---
 core/ConCmdManager.h        |  3 ++-
 core/smn_console.cpp        | 26 ++++++++++++++++++++++++--
 plugins/include/console.inc | 26 ++++++++++++++++++++++++--
 5 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/core/AdminCache.cpp b/core/AdminCache.cpp
index d93be67f..4b21338a 100644
--- a/core/AdminCache.cpp
+++ b/core/AdminCache.cpp
@@ -1719,7 +1719,7 @@ bool AdminCache::CanAdminUseCommand(int client, const char *cmd)
 		}
 	}
 
-	return g_ConCmds.CheckCommandAccess(client, cmd, bits);
+	return g_ConCmds.CheckClientCommandAccess(client, cmd, bits);
 }
 
 unsigned int AdminCache::SetGroupImmunityLevel(GroupId gid, unsigned int level)
@@ -1794,7 +1794,7 @@ bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool o
 		GetCommandOverride(cmd, Override_Command, &bits);
 	}
 
-	return g_ConCmds.CheckCommandAccess(client, cmd, bits) ? 1 : 0;
+	return g_ConCmds.CheckClientCommandAccess(client, cmd, bits) ? 1 : 0;
 }
 
 void iterator_glob_basic_override(Trie *pTrie, const char *key, void **value, void *data)
diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp
index 9c22cfcd..4493d7ff 100644
--- a/core/ConCmdManager.cpp
+++ b/core/ConCmdManager.cpp
@@ -450,7 +450,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
 	}
 }
 
-bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmdflags)
+bool ConCmdManager::CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags)
 {
 	if (cmdflags == 0 || client == 0)
 	{
@@ -471,7 +471,11 @@ bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmd
 		return false;
 	}
 
-	AdminId adm = player->GetAdminId();
+	return CheckAdminCommandAccess(player->GetAdminId(), cmd, cmdflags);
+}
+
+bool ConCmdManager::CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits cmdflags)
+{
 	if (adm != INVALID_ADMIN_ID)
 	{
 		FlagBits bits = g_Admins.GetAdminFlags(adm, Access_Effective);
@@ -524,7 +528,7 @@ bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmd
 
 bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
 {
-	if (CheckCommandAccess(client, cmd, pAdmin->eflags))
+	if (CheckClientCommandAccess(client, cmd, pAdmin->eflags))
 	{
 		return true;
 	}
diff --git a/core/ConCmdManager.h b/core/ConCmdManager.h
index 448ff953..38ee6b96 100644
--- a/core/ConCmdManager.h
+++ b/core/ConCmdManager.h
@@ -130,7 +130,8 @@ public:
 	void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
 	bool LookForSourceModCommand(const char *cmd);
 	bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
-	bool CheckCommandAccess(int client, const char *cmd, FlagBits flags);
+	bool CheckClientCommandAccess(int client, const char *cmd, FlagBits flags);
+	bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags);
 private:
 	void InternalDispatch(const CCommand &command);
 	ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
diff --git a/core/smn_console.cpp b/core/smn_console.cpp
index 06f29d58..b893e1c0 100644
--- a/core/smn_console.cpp
+++ b/core/smn_console.cpp
@@ -1257,7 +1257,7 @@ static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params)
 	char *cmd;
 	pContext->LocalToString(params[2], &cmd);
 
-	/* Auto-detect a command if we can */
+	/* Match up with an admin command if possible */
 	FlagBits bits = params[3];
 	bool found_command = false;
 	if (params[0] < 4 || !params[4])
@@ -1270,7 +1270,28 @@ static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params)
 		g_Admins.GetCommandOverride(cmd, Override_Command, &bits);
 	}
 
-	return g_ConCmds.CheckCommandAccess(params[1], cmd, bits) ? 1 : 0;
+	return g_ConCmds.CheckClientCommandAccess(params[1], cmd, bits) ? 1 : 0;
+}
+
+static cell_t CheckAccess(IPluginContext *pContext, const cell_t *params)
+{
+	char *cmd;
+	pContext->LocalToString(params[2], &cmd);
+
+	/* Match up with an admin command if possible */
+	FlagBits bits = params[3];
+	bool found_command = false;
+	if (params[0] < 4 || !params[4])
+	{
+		found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits);
+	}
+	
+	if (!found_command)
+	{
+		g_Admins.GetCommandOverride(cmd, Override_Command, &bits);
+	}
+
+	return g_ConCmds.CheckAdminCommandAccess(params[1], cmd, bits) ? 1 : 0;
 }
 
 static cell_t IsChatTrigger(IPluginContext *pContext, const cell_t *params)
@@ -1521,6 +1542,7 @@ REGISTER_NATIVES(consoleNatives)
 	{"GetCommandIterator",	GetCommandIterator},
 	{"ReadCommandIterator",	ReadCommandIterator},
 	{"CheckCommandAccess",	CheckCommandAccess},
+	{"CheckAccess",			CheckAccess},
 	{"FakeClientCommandEx",	FakeClientCommandEx},
 	{"IsChatTrigger",		IsChatTrigger},
 	{"SetCommandFlags",		SetCommandFlags},
diff --git a/plugins/include/console.inc b/plugins/include/console.inc
index 96d64806..84524e57 100644
--- a/plugins/include/console.inc
+++ b/plugins/include/console.inc
@@ -739,8 +739,8 @@ native bool:ReadCommandIterator(Handle:iter,
 
 /**
  * Returns whether a client has access to a given command string.  The string 
- * can also be any override string, as overrides can be independent of 
- * commands.  This important feature essentially allows you to create custom 
+ * can be any override string, as overrides can be independent of 
+ * commands.  This feature essentially allows you to create custom 
  * flags using the override system.
  *
  * @param client		Client index.
@@ -759,6 +759,28 @@ native bool:CheckCommandAccess(client,
 							   flags,
 							   bool:override_only=false);
 
+/**
+ * Returns whether an admin has access to a given command string.  The string 
+ * can be any override string, as overrides can be independent of 
+ * commands.  This feature essentially allows you to create custom flags
+ * using the override system.
+ *
+ * @param id			AdminId of the admin.
+ * @param command		Command name.  If the command is not found, the default 
+ *						flags are used.
+ * @param flags			Flag string to use as a default, if the command or override 
+ *						is not found.
+ * @param override_only	If true, SourceMod will not attempt to find a matching 
+ *						command, and it will only use the default flags specified.
+ *						Otherwise, SourceMod will ignore the default flags if 
+ *						there is a matching admin command.
+ * @return				True if the admin has access, false otherwise.
+ */
+native bool:CheckAccess(AdminId:id, 
+							   const String:command[],
+							   flags,
+							   bool:override_only=false);
+
 /**
  * Returns true if the supplied character is valid in a ConVar name.
  *