From d218f638b15f832ccb858d310fa71add7afef530 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 15 Jul 2007 18:51:25 +0000 Subject: [PATCH] added api to walk cmd list --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401125 --- core/ConCmdManager.cpp | 24 ++++++--- core/ConCmdManager.h | 6 +++ core/smn_console.cpp | 103 ++++++++++++++++++++++++++++++++++++ core/vm/sp_vm_engine.cpp | 2 +- plugins/include/console.inc | 37 +++++++++++++ 5 files changed, 164 insertions(+), 8 deletions(-) diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp index fd53dfa3..d14f702e 100644 --- a/core/ConCmdManager.cpp +++ b/core/ConCmdManager.cpp @@ -306,9 +306,8 @@ void ConCmdManager::InternalDispatch() } } -bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin) +bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmdflags) { - FlagBits cmdflags = pAdmin->eflags; if (cmdflags == 0) { return true; @@ -321,7 +320,9 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi } CPlayer *player = g_Players.GetPlayerByIndex(client); - if (!player) + if (!player + || player->GetEdict() == NULL + || player->IsFakeClient()) { return false; } @@ -370,11 +371,17 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi } } - if (player->IsFakeClient() - || player->GetEdict() == NULL) + return false; +} + +bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin) +{ + if (CheckCommandAccess(client, cmd, pAdmin->eflags)) { - return false; + return true; } + + edict_t *pEdict = engine->PEntityOfEntIndex(client); /* If we got here, the command failed... */ char buffer[128]; @@ -389,7 +396,7 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi { char fullbuffer[192]; snprintf(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer); - engine->ClientPrintf(player->GetEdict(), fullbuffer); + engine->ClientPrintf(pEdict, fullbuffer); } else if (replyto == SM_REPLY_CHAT) { char fullbuffer[192]; snprintf(fullbuffer, sizeof(fullbuffer), "[SM] %s.", buffer); @@ -495,6 +502,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction, /* Finally, add the hook */ pInfo->conhooks.push_back(pHook); + pInfo->admin = *(pHook->pAdmin); /* Now add to the plugin */ CmdList *pList; @@ -636,6 +644,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag } else { pHook->pAdmin->eflags = pHook->pAdmin->flags; } + pInfo->admin = *(pHook->pAdmin); } } } else if (type == Override_CommandGroup) { @@ -665,6 +674,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag } else { pHook->pAdmin->eflags = pHook->pAdmin->flags; } + pInfo->admin = *(pHook->pAdmin); } } } diff --git a/core/ConCmdManager.h b/core/ConCmdManager.h index bf363d64..3453bae7 100644 --- a/core/ConCmdManager.h +++ b/core/ConCmdManager.h @@ -70,6 +70,7 @@ struct ConCmdInfo ConCommand *pCmd; /**< Pointer to the command itself */ List srvhooks; /**< Hooks as a server command */ List conhooks; /**< Hooks as a console command */ + AdminCmdInfo admin; /**< Admin info, if any */ }; class ConCmdManager : @@ -100,6 +101,7 @@ public: ResultType DispatchClientCommand(int client, ResultType type); void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits); bool LookForSourceModCommand(const char *cmd); + bool CheckCommandAccess(int client, const char *cmd, FlagBits flags); private: void InternalDispatch(); ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args); @@ -114,6 +116,10 @@ public: { return m_CmdClient; } + inline const List & GetCommandList() + { + return m_CmdList; + } private: Trie *m_pCmds; /* command lookup */ Trie *m_pCmdGrps; /* command group lookup */ diff --git a/core/smn_console.cpp b/core/smn_console.cpp index 9b7490d3..933bef08 100644 --- a/core/smn_console.cpp +++ b/core/smn_console.cpp @@ -33,6 +33,34 @@ enum ConVarBounds ConVarBound_Lower }; +HandleType_t hCmdIterType = 0; + +struct GlobCmdIter +{ + bool started; + List::iterator iter; +}; + +class ConsoleHelpers : + public SMGlobalClass, + public IHandleTypeDispatch +{ +public: + virtual void OnSourceModAllInitialized() + { + HandleAccess access; + g_HandleSys.InitAccessDefaults(NULL, &access); + access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER | HANDLE_RESTRICT_IDENTITY; + + hCmdIterType = g_HandleSys.CreateType(NULL, this, 0, NULL, &access, g_pCoreIdent, NULL); + } + virtual void OnHandleDestroy(HandleType_t type, void *object) + { + GlobCmdIter *iter = (GlobCmdIter *)object; + delete iter; + } +} s_ConsoleHelpers; + static void ReplicateConVar(ConVar *pConVar) { int maxClients = g_Players.GetMaxClients(); @@ -802,6 +830,78 @@ static cell_t SetCmdReplyTarget(IPluginContext *pContext, const cell_t *params) return g_ChatTriggers.SetReplyTo(params[1]); } +static cell_t GetCommandIterator(IPluginContext *pContext, const cell_t *params) +{ + GlobCmdIter *iter = new GlobCmdIter; + iter->started = false; + + Handle_t hndl = g_HandleSys.CreateHandle(hCmdIterType, iter, pContext->GetIdentity(), g_pCoreIdent, NULL); + if (hndl == BAD_HANDLE) + { + delete iter; + } + + return hndl; +} + +static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params) +{ + GlobCmdIter *iter; + HandleError err; + HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); + + if ((err = g_HandleSys.ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid GlobCmdIter Handle %x", params[1]); + } + + const List &cmds = g_ConCmds.GetCommandList(); + + if (!iter->started) + { + iter->iter = cmds.begin(); + iter->started = true; + } + + while (iter->iter != cmds.end() + && !(*(iter->iter))->sourceMod) + { + iter->iter++; + } + + if (iter->iter == cmds.end()) + { + return 0; + } + + ConCmdInfo *pInfo = (*(iter->iter)); + + pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetName(), NULL); + pContext->StringToLocalUTF8(params[5], params[6], pInfo->pCmd->GetHelpText(), NULL); + + cell_t *addr; + pContext->LocalToPhysAddr(params[4], &addr); + *addr = pInfo->admin.eflags; + + iter->iter++; + + return 1; +} + +static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params) +{ + if (params[1] == 0) + { + return 1; + } + + char *cmd; + pContext->LocalToString(params[2], &cmd); + + return g_ConCmds.CheckCommandAccess(params[1], cmd, params[3]) ? 1 : 0; +} + REGISTER_NATIVES(consoleNatives) { {"CreateConVar", sm_CreateConVar}, @@ -839,5 +939,8 @@ REGISTER_NATIVES(consoleNatives) {"ReplyToCommand", ReplyToCommand}, {"GetCmdReplySource", GetCmdReplyTarget}, {"SetCmdReplySource", SetCmdReplyTarget}, + {"GetCommandIterator", GetCommandIterator}, + {"ReadCommandIterator", ReadCommandIterator}, + {"CheckCommandAccess", CheckCommandAccess}, {NULL, NULL} }; diff --git a/core/vm/sp_vm_engine.cpp b/core/vm/sp_vm_engine.cpp index fb56e4df..80219053 100644 --- a/core/vm/sp_vm_engine.cpp +++ b/core/vm/sp_vm_engine.cpp @@ -56,7 +56,7 @@ static const char *g_ErrorMsgTable[] = "Heap memory leaked by native", "Dynamic array is too big", "Tracker stack is out of bounds", - "Native was never bound", + "Native is not bound", "Maximum number of parameters reached", "Native detected error", "Plugin not runnable", diff --git a/plugins/include/console.inc b/plugins/include/console.inc index 39a71041..daef8dc7 100644 --- a/plugins/include/console.inc +++ b/plugins/include/console.inc @@ -571,3 +571,40 @@ funcenum ConVarQueryFinished * Returns QUERYCOOKIE_FAILED on failure, such as when used on a bot. */ native QueryCookie:QueryClientConVar(client, const String:cvarName[], ConVarQueryFinished:callback, any:value=0); + +/** + * Gets a command iterator. Must be freed with CloseHandle(). + * + * @return A new command iterator. + */ +native Handle:GetCommandIterator(); + +/** + * Reads a command iterator, then advances to the next command if any. + * Only SourceMod specific commands are returned. + * + * @param iter Command iterator Handle. + * @param name Name buffer. + * @param nameLen Name buffer size. + * @param eflags Effective default flags of a command. + * @param desc Command description buffer. + * @param descLen Command description buffer size. + * @return True on success, false if there are no more commands. + */ +native bool:ReadCommandIterator(Handle:iter, + String:name[], + nameLen, + &eflags=0, + String:desc[]="", + descLen=0); + +/** + * Returns whether a user has access to a command. This takes into account + * the override system built into SourceMod. + * + * @param client Client index. + * @param command Command name. + * @param flags Default command flags. + * @return True if the user has access, false otherwise. + */ +native bool:CheckCommandAccess(client, const String:command[], flags);