Added HOOK_EXECUTE_COMMAND for intercepting executed commands and console commands.

Note that built-in console commands are exempt to this hook - they are always performed and the hook is not called. Also note that, for reasons unknown, the HookNotify plugin doesn't list the callback arguments.

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1221 0a769ca7-a7f5-676a-18bf-c427514a06d6
master
madmaxoft@gmail.com 2013-02-21 13:47:01 +00:00
parent 8e64ad0848
commit 99876ea4ba
9 changed files with 114 additions and 14 deletions

View File

@ -23,6 +23,7 @@ function Initialize(Plugin)
PluginManager:AddHook(Plugin, cPluginManager.HOOK_COLLECTING_PICKUP); PluginManager:AddHook(Plugin, cPluginManager.HOOK_COLLECTING_PICKUP);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_CRAFTING_NO_RECIPE); PluginManager:AddHook(Plugin, cPluginManager.HOOK_CRAFTING_NO_RECIPE);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_DISCONNECT); PluginManager:AddHook(Plugin, cPluginManager.HOOK_DISCONNECT);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_EXECUTE_COMMAND);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_HANDSHAKE); PluginManager:AddHook(Plugin, cPluginManager.HOOK_HANDSHAKE);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_KILLING); PluginManager:AddHook(Plugin, cPluginManager.HOOK_KILLING);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_LOGIN); PluginManager:AddHook(Plugin, cPluginManager.HOOK_LOGIN);
@ -174,6 +175,21 @@ end
function OnExecuteCommand(...)
LogHook("OnExecuteCommand", unpack(arg));
-- For some reason logging doesn't work for this callback, so list some stuff manually to verify:
LOG("arg1 type: " .. type(arg[1]));
if (arg[1] ~= nil) then
LOG("Player name: " .. arg[1]:GetName());
end
LOG("Command: " .. arg[2][1]);
end
function OnHandshake(...) function OnHandshake(...)
LogHook("OnHandshake", unpack(arg)); LogHook("OnHandshake", unpack(arg));
end end

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 02/16/13 12:08:29. ** Generated automatically by tolua++-1.0.92 on 02/21/13 14:08:40.
*/ */
#ifndef __cplusplus #ifndef __cplusplus
@ -21948,6 +21948,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"etPickup",cEntity::etPickup); tolua_constant(tolua_S,"etPickup",cEntity::etPickup);
tolua_constant(tolua_S,"etMob",cEntity::etMob); tolua_constant(tolua_S,"etMob",cEntity::etMob);
tolua_constant(tolua_S,"etFallingBlock",cEntity::etFallingBlock); tolua_constant(tolua_S,"etFallingBlock",cEntity::etFallingBlock);
tolua_constant(tolua_S,"etMinecart",cEntity::etMinecart);
tolua_constant(tolua_S,"eEntityType_Entity",cEntity::eEntityType_Entity); tolua_constant(tolua_S,"eEntityType_Entity",cEntity::eEntityType_Entity);
tolua_constant(tolua_S,"eEntityType_Player",cEntity::eEntityType_Player); tolua_constant(tolua_S,"eEntityType_Player",cEntity::eEntityType_Player);
tolua_constant(tolua_S,"eEntityType_Pickup",cEntity::eEntityType_Pickup); tolua_constant(tolua_S,"eEntityType_Pickup",cEntity::eEntityType_Pickup);
@ -22146,6 +22147,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"HOOK_COLLECTING_PICKUP",cPluginManager::HOOK_COLLECTING_PICKUP); tolua_constant(tolua_S,"HOOK_COLLECTING_PICKUP",cPluginManager::HOOK_COLLECTING_PICKUP);
tolua_constant(tolua_S,"HOOK_CRAFTING_NO_RECIPE",cPluginManager::HOOK_CRAFTING_NO_RECIPE); tolua_constant(tolua_S,"HOOK_CRAFTING_NO_RECIPE",cPluginManager::HOOK_CRAFTING_NO_RECIPE);
tolua_constant(tolua_S,"HOOK_DISCONNECT",cPluginManager::HOOK_DISCONNECT); tolua_constant(tolua_S,"HOOK_DISCONNECT",cPluginManager::HOOK_DISCONNECT);
tolua_constant(tolua_S,"HOOK_EXECUTE_COMMAND",cPluginManager::HOOK_EXECUTE_COMMAND);
tolua_constant(tolua_S,"HOOK_HANDSHAKE",cPluginManager::HOOK_HANDSHAKE); tolua_constant(tolua_S,"HOOK_HANDSHAKE",cPluginManager::HOOK_HANDSHAKE);
tolua_constant(tolua_S,"HOOK_KILLING",cPluginManager::HOOK_KILLING); tolua_constant(tolua_S,"HOOK_KILLING",cPluginManager::HOOK_KILLING);
tolua_constant(tolua_S,"HOOK_LOGIN",cPluginManager::HOOK_LOGIN); tolua_constant(tolua_S,"HOOK_LOGIN",cPluginManager::HOOK_LOGIN);

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 02/16/13 12:08:29. ** Generated automatically by tolua++-1.0.92 on 02/21/13 14:08:41.
*/ */
/* Exported function */ /* Exported function */

View File

@ -164,6 +164,17 @@ bool cPlugin::OnDisconnect(cPlayer * a_Player, const AString & a_Reason)
bool cPlugin::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split)
{
UNUSED(a_Player);
UNUSED(a_Split);
return false;
}
bool cPlugin::OnHandshake(cClientHandle * a_Client, const AString & a_Username) bool cPlugin::OnHandshake(cClientHandle * a_Client, const AString & a_Username)
{ {
UNUSED(a_Client); UNUSED(a_Client);

View File

@ -58,6 +58,7 @@ public:
virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup); virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup);
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason); virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason);
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split);
virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username); virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username);
virtual bool OnKilling (cPawn & a_Victim, cEntity * a_Killer); virtual bool OnKilling (cPawn & a_Victim, cEntity * a_Killer);
virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username); virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username);

View File

@ -403,6 +403,27 @@ bool cPluginManager::CallHookDisconnect(cPlayer * a_Player, const AString & a_Re
bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_EXECUTE_COMMAND);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnExecuteCommand(a_Player, a_Split))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookHandshake(cClientHandle * a_ClientHandle, const AString & a_Username) bool cPluginManager::CallHookHandshake(cClientHandle * a_ClientHandle, const AString & a_Username)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_HANDSHAKE); HookMap::iterator Plugins = m_Hooks.find(HOOK_HANDSHAKE);
@ -966,6 +987,13 @@ bool cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command
return false; return false;
} }
// Ask plugins first if a command is okay to execute the command:
if (CallHookExecuteCommand(a_Player, Split))
{
LOGINFO("Player \"%s\" tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player->GetName().c_str(), Split[0].c_str());
return false;
}
if ( if (
a_ShouldCheckPermissions && a_ShouldCheckPermissions &&
!cmd->second.m_Permission.empty() && !cmd->second.m_Permission.empty() &&
@ -1282,6 +1310,13 @@ bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split)
return false; return false;
} }
// Ask plugins first if a command is okay to execute the console command:
if (CallHookExecuteCommand(NULL, a_Split))
{
LOGINFO("Command \"%s\" was stopped by the HOOK_EXECUTE_COMMAND hook", a_Split[0].c_str());
return false;
}
return cmd->second.m_Plugin->HandleConsoleCommand(a_Split); return cmd->second.m_Plugin->HandleConsoleCommand(a_Split);
} }

View File

@ -49,6 +49,7 @@ public: // tolua_export
HOOK_COLLECTING_PICKUP, HOOK_COLLECTING_PICKUP,
HOOK_CRAFTING_NO_RECIPE, HOOK_CRAFTING_NO_RECIPE,
HOOK_DISCONNECT, HOOK_DISCONNECT,
HOOK_EXECUTE_COMMAND,
HOOK_HANDSHAKE, HOOK_HANDSHAKE,
HOOK_KILLING, HOOK_KILLING,
HOOK_LOGIN, HOOK_LOGIN,
@ -116,6 +117,7 @@ public: // tolua_export
bool CallHookCollectingPickup (cPlayer * a_Player, cPickup & a_Pickup); bool CallHookCollectingPickup (cPlayer * a_Player, cPickup & a_Pickup);
bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookDisconnect (cPlayer * a_Player, const AString & a_Reason); bool CallHookDisconnect (cPlayer * a_Player, const AString & a_Reason);
bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split); // If a_Player == NULL, it is a console cmd
bool CallHookHandshake (cClientHandle * a_ClientHandle, const AString & a_Username); bool CallHookHandshake (cClientHandle * a_ClientHandle, const AString & a_Username);
bool CallHookKilling (cPawn & a_Victim, cEntity * a_Killer); bool CallHookKilling (cPawn & a_Victim, cEntity * a_Killer);
bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username); bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username);

View File

@ -461,6 +461,45 @@ bool cPlugin_NewLua::OnDisconnect(cPlayer * a_Player, const AString & a_Reason)
bool cPlugin_NewLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split)
{
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_EXECUTE_COMMAND);
ASSERT(FnName != NULL);
if (!PushFunction(FnName))
{
return false;
}
tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
// Push the split:
lua_createtable(m_LuaState, a_Split.size(), 0);
int newTable = lua_gettop(m_LuaState);
int index = 1;
std::vector<std::string>::const_iterator iter = a_Split.begin(), end = a_Split.end();
while(iter != end)
{
tolua_pushstring(m_LuaState, (*iter).c_str());
lua_rawseti(m_LuaState, newTable, index);
++iter;
++index;
}
if (!CallFunction(2, 1, FnName))
{
return false;
}
bool bRetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
lua_pop(m_LuaState, 1);
return bRetVal;
}
bool cPlugin_NewLua::OnHandshake(cClientHandle * a_Client, const AString & a_Username) bool cPlugin_NewLua::OnHandshake(cClientHandle * a_Client, const AString & a_Username)
{ {
cCSLock Lock(m_CriticalSection); cCSLock Lock(m_CriticalSection);
@ -1280,11 +1319,9 @@ bool cPlugin_NewLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Pl
cCSLock Lock(m_CriticalSection); cCSLock Lock(m_CriticalSection);
// Push the function to be called: // Push the function to be called:
LOGD("1. Stack size: %i", lua_gettop(m_LuaState));
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref() lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref()
// Push the split: // Push the split:
LOGD("2. Stack size: %i", lua_gettop(m_LuaState));
lua_createtable(m_LuaState, a_Split.size(), 0); lua_createtable(m_LuaState, a_Split.size(), 0);
int newTable = lua_gettop(m_LuaState); int newTable = lua_gettop(m_LuaState);
int index = 1; int index = 1;
@ -1296,24 +1333,21 @@ bool cPlugin_NewLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Pl
++iter; ++iter;
++index; ++index;
} }
LOGD("3. Stack size: %i", lua_gettop(m_LuaState));
// Push player: // Push player:
tolua_pushusertype(m_LuaState, a_Player, "cPlayer"); tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
// Call function: // Call function:
LOGD("Calling bound function! :D");
int s = lua_pcall(m_LuaState, 2, 1, 0); int s = lua_pcall(m_LuaState, 2, 1, 0);
if (report_errors(m_LuaState, s)) if (report_errors(m_LuaState, s))
{ {
LOGERROR("error. Stack size: %i", lua_gettop(m_LuaState)); LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
return false; return false;
} }
// Handle return value: // Handle return value:
bool RetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0); bool RetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
lua_pop(m_LuaState, 1); // Pop return value lua_pop(m_LuaState, 1); // Pop return value
LOGD("ok. Stack size: %i", lua_gettop(m_LuaState));
return RetVal; return RetVal;
} }
@ -1335,11 +1369,9 @@ bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split)
cCSLock Lock(m_CriticalSection); cCSLock Lock(m_CriticalSection);
// Push the function to be called: // Push the function to be called:
LOGD("1. Stack size: %i", lua_gettop(m_LuaState));
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref() lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref()
// Push the split: // Push the split:
LOGD("2. Stack size: %i", lua_gettop(m_LuaState));
lua_createtable(m_LuaState, a_Split.size(), 0); lua_createtable(m_LuaState, a_Split.size(), 0);
int newTable = lua_gettop(m_LuaState); int newTable = lua_gettop(m_LuaState);
int index = 1; int index = 1;
@ -1351,10 +1383,8 @@ bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split)
++iter; ++iter;
++index; ++index;
} }
LOGD("3. Stack size: %i", lua_gettop(m_LuaState));
// Call function: // Call function:
LOGD("Calling bound function! :D");
int s = lua_pcall(m_LuaState, 1, 1, 0); int s = lua_pcall(m_LuaState, 1, 1, 0);
if (report_errors(m_LuaState, s)) if (report_errors(m_LuaState, s))
{ {
@ -1365,7 +1395,6 @@ bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split)
// Handle return value: // Handle return value:
bool RetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0); bool RetVal = (tolua_toboolean(m_LuaState, -1, 0) > 0);
lua_pop(m_LuaState, 1); // Pop return value lua_pop(m_LuaState, 1); // Pop return value
LOGD("ok. Stack size: %i", lua_gettop(m_LuaState));
return RetVal; return RetVal;
} }
@ -1471,6 +1500,7 @@ const char * cPlugin_NewLua::GetHookFnName(cPluginManager::PluginHook a_Hook)
case cPluginManager::HOOK_COLLECTING_PICKUP: return "OnCollectingPickup"; case cPluginManager::HOOK_COLLECTING_PICKUP: return "OnCollectingPickup";
case cPluginManager::HOOK_CRAFTING_NO_RECIPE: return "OnCraftingNoRecipe"; case cPluginManager::HOOK_CRAFTING_NO_RECIPE: return "OnCraftingNoRecipe";
case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect"; case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect";
case cPluginManager::HOOK_EXECUTE_COMMAND: return "OnExecuteCommand";
case cPluginManager::HOOK_HANDSHAKE: return "OnHandshake"; case cPluginManager::HOOK_HANDSHAKE: return "OnHandshake";
case cPluginManager::HOOK_KILLING: return "OnKilling"; case cPluginManager::HOOK_KILLING: return "OnKilling";
case cPluginManager::HOOK_LOGIN: return "OnLogin"; case cPluginManager::HOOK_LOGIN: return "OnLogin";
@ -1635,6 +1665,8 @@ bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError
bool cPlugin_NewLua::CallFunction( int a_NumArgs, int a_NumResults, const char * a_FunctionName) bool cPlugin_NewLua::CallFunction( int a_NumArgs, int a_NumResults, const char * a_FunctionName)
{ {
ASSERT(lua_isfunction(m_LuaState, -a_NumArgs - 1));
int s = lua_pcall(m_LuaState, a_NumArgs, a_NumResults, 0); int s = lua_pcall(m_LuaState, a_NumArgs, a_NumResults, 0);
if (report_errors(m_LuaState, s)) if (report_errors(m_LuaState, s))
{ {

View File

@ -43,6 +43,7 @@ public:
virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) override; virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) override;
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) override; virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) override;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) override;
virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) override; virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) override;
virtual bool OnKilling (cPawn & a_Victim, cEntity * a_Killer) override; virtual bool OnKilling (cPawn & a_Victim, cEntity * a_Killer) override;
virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) override; virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) override;