diff --git a/core/AMBuilder b/core/AMBuilder index 63bc18d2..4f0cf3ae 100644 --- a/core/AMBuilder +++ b/core/AMBuilder @@ -52,7 +52,6 @@ for sdk_name in SM.sdks: compiler.linkflags.insert(0, binary.Dep(lib_path)) binary.sources += [ - 'AdminCache.cpp', 'MenuStyle_Valve.cpp', 'logic_bridge.cpp', 'smn_entities.cpp', @@ -60,7 +59,6 @@ for sdk_name in SM.sdks: 'MenuVoting.cpp', 'smn_events.cpp', 'smn_menus.cpp', - 'sm_trie.cpp', 'CDataPack.cpp', 'frame_hooks.cpp', 'smn_nextmap.cpp', diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp index b54bd47a..80d3f703 100644 --- a/core/ConCmdManager.cpp +++ b/core/ConCmdManager.cpp @@ -31,7 +31,6 @@ #include "ConCmdManager.h" #include "sm_srvcmds.h" -#include "AdminCache.h" #include "sm_stringutil.h" #include "PlayerManager.h" #include "HalfLife2.h" @@ -330,85 +329,9 @@ void ConCmdManager::InternalDispatch(const CCommand &command) } } -bool ConCmdManager::CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags) -{ - if (cmdflags == 0 || client == 0) - { - return true; - } - - /* If running listen server, then client 1 is the server host and should have 'root' access */ - if (client == 1 && !engine->IsDedicatedServer()) - { - return true; - } - - CPlayer *player = g_Players.GetPlayerByIndex(client); - if (!player - || player->GetEdict() == NULL - || player->IsFakeClient()) - { - return false; - } - - 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); - - /* root knows all, WHOA */ - if ((bits & ADMFLAG_ROOT) == ADMFLAG_ROOT) - { - return true; - } - - /* Check for overrides - * :TODO: is it worth optimizing this? - */ - unsigned int groups = g_Admins.GetAdminGroupCount(adm); - GroupId gid; - OverrideRule rule; - bool override = false; - for (unsigned int i=0; ieflags)) + if (adminsys->CheckClientCommandAccess(client, cmd, pAdmin->eflags)) { return true; } @@ -468,12 +391,12 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction, pHook->admin = new AdminCmdInfo(cmdgroup, adminflags); /* First get the command group override, if any */ - bool override = g_Admins.GetCommandOverride(group, + bool override = adminsys->GetCommandOverride(group, Override_CommandGroup, &(pHook->admin->eflags)); /* Next get the command override, if any */ - if (g_Admins.GetCommandOverride(name, + if (adminsys->GetCommandOverride(name, Override_Command, &(pHook->admin->eflags))) { diff --git a/core/ConCmdManager.h b/core/ConCmdManager.h index e521dc70..7165336c 100644 --- a/core/ConCmdManager.h +++ b/core/ConCmdManager.h @@ -146,8 +146,6 @@ 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 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/PlayerManager.cpp b/core/PlayerManager.cpp index 8cf53f61..7ccd7a43 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -30,7 +30,7 @@ */ #include "PlayerManager.h" -#include "AdminCache.h" +#include "IAdminSystem.h" #include "ConCmdManager.h" #include "MenuStyle_Valve.h" #include "MenuStyle_Radio.h" @@ -333,7 +333,7 @@ bool PlayerManager::IsServerActivated() bool PlayerManager::CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id) { - const char *password = g_Admins.GetAdminPassword(id); + const char *password = adminsys->GetAdminPassword(id); if (password != NULL) { if (m_PassInfoVar.size() < 1) @@ -356,7 +356,7 @@ bool PlayerManager::CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id) bool PlayerManager::CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id) { - const char *password = g_Admins.GetAdminPassword(id); + const char *password = adminsys->GetAdminPassword(id); if (password == NULL) { return false; @@ -1183,7 +1183,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) if (strcmp(old_name, new_name) != 0) { - AdminId id = g_Admins.FindAdminByIdentity("name", new_name); + AdminId id = adminsys->FindAdminByIdentity("name", new_name); if (id != INVALID_ADMIN_ID && pPlayer->GetAdminId() != id) { if (!CheckSetAdminName(client, pPlayer, id)) @@ -1193,7 +1193,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) pPlayer->Kick(kickMsg); RETURN_META(MRES_IGNORED); } - } else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) { + } else if ((id = adminsys->FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) { if (id == pPlayer->GetAdminId()) { /* This player is changing their name; force them to drop admin privileges! */ @@ -1327,14 +1327,6 @@ void PlayerManager::ClearAdminId(AdminId id) } } -void PlayerManager::ClearAllAdmins() -{ - for (int i=1; i<=m_maxClients; i++) - { - m_Players[i].DumpAdmin(true); - } -} - const char *PlayerManager::GetPassInfoVar() { return m_PassInfoVar.c_str(); @@ -1425,7 +1417,7 @@ int PlayerManager::InternalFilterCommandTarget(CPlayer *pAdmin, CPlayer *pTarget if (pAdmin != NULL) { if ((flags & COMMAND_FILTER_NO_IMMUNITY) != COMMAND_FILTER_NO_IMMUNITY - && !g_Admins.CanAdminTarget(pAdmin->GetAdminId(), pTarget->GetAdminId())) + && !adminsys->CanAdminTarget(pAdmin->GetAdminId(), pTarget->GetAdminId())) { return COMMAND_TARGET_IMMUNE; } @@ -2076,13 +2068,18 @@ AdminId CPlayer::GetAdminId() return m_Admin; } +void CPlayer::ClearAdmin() +{ + DumpAdmin(true); +} + void CPlayer::DumpAdmin(bool deleting) { if (m_Admin != INVALID_ADMIN_ID) { if (m_TempAdmin && !deleting) { - g_Admins.InvalidateAdmin(m_Admin); + adminsys->InvalidateAdmin(m_Admin); } m_Admin = INVALID_ADMIN_ID; m_TempAdmin = false; @@ -2225,7 +2222,7 @@ void CPlayer::DoBasicAdminChecks() AdminId id; int client = IndexOfEdict(m_pEdict); - if ((id = g_Admins.FindAdminByIdentity("name", GetName())) != INVALID_ADMIN_ID) + if ((id = adminsys->FindAdminByIdentity("name", GetName())) != INVALID_ADMIN_ID) { if (!g_Players.CheckSetAdminName(client, this, id)) { @@ -2236,7 +2233,7 @@ void CPlayer::DoBasicAdminChecks() } /* Check IP */ - if ((id = g_Admins.FindAdminByIdentity("ip", m_IpNoPort.c_str())) != INVALID_ADMIN_ID) + if ((id = adminsys->FindAdminByIdentity("ip", m_IpNoPort.c_str())) != INVALID_ADMIN_ID) { if (g_Players.CheckSetAdmin(client, this, id)) { @@ -2245,7 +2242,7 @@ void CPlayer::DoBasicAdminChecks() } /* Check steam id */ - if ((id = g_Admins.FindAdminByIdentity("steam", m_AuthID.c_str())) != INVALID_ADMIN_ID) + if ((id = adminsys->FindAdminByIdentity("steam", m_AuthID.c_str())) != INVALID_ADMIN_ID) { if (g_Players.CheckSetAdmin(client, this, id)) { diff --git a/core/PlayerManager.h b/core/PlayerManager.h index 67850c54..d9f6e553 100644 --- a/core/PlayerManager.h +++ b/core/PlayerManager.h @@ -92,6 +92,7 @@ public: unsigned int GetSerial(); int GetIndex() const; void PrintToConsole(const char *pMsg); + void ClearAdmin(); public: void DoBasicAdminChecks(); void MarkAsBeingKicked(); @@ -149,8 +150,6 @@ public: //SMGlobalClass public: CPlayer *GetPlayerByIndex(int client) const; void RunAuthChecks(); - void ClearAdminId(AdminId id); - void ClearAllAdmins(); public: #if SOURCE_ENGINE == SE_DOTA bool OnClientConnect(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); @@ -190,6 +189,8 @@ public: //IPlayerManager void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler); void ProcessCommandTarget(cmd_target_info_t *info); int GetClientFromSerial(unsigned int serial); + void ClearAdminId(AdminId id); + void RecheckAnyAdmins(); public: inline int MaxClients() { @@ -206,7 +207,6 @@ public: bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id); bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id); const char *GetPassInfoVar(); - void RecheckAnyAdmins(); unsigned int GetReplyTo(); unsigned int SetReplyTo(unsigned int reply); void MaxPlayersChanged(int newvalue = -1); diff --git a/core/logic/AMBuilder b/core/logic/AMBuilder index adbbce2f..09096255 100644 --- a/core/logic/AMBuilder +++ b/core/logic/AMBuilder @@ -63,6 +63,9 @@ binary.sources += [ 'Database.cpp', 'smn_database.cpp', 'ForwardSys.cpp', + 'AdminCache.cpp', + 'sm_trie.cpp', + 'smn_console.cpp', ] if builder.target_platform == 'windows': binary.sources += ['thread/WinThreads.cpp'] diff --git a/core/AdminCache.cpp b/core/logic/AdminCache.cpp similarity index 92% rename from core/AdminCache.cpp rename to core/logic/AdminCache.cpp index 94a71e37..164f2ab4 100644 --- a/core/AdminCache.cpp +++ b/core/logic/AdminCache.cpp @@ -1,1932 +1,1987 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2008 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 -#include -#include -#include "AdminCache.h" -#include "PlayerManager.h" -#include "ConCmdManager.h" -#include "Logger.h" -#include "sourcemod.h" -#include "sm_stringutil.h" -#include "sourcemm_api.h" -#include "sm_srvcmds.h" -#include "logic_bridge.h" - -#define LEVEL_STATE_NONE 0 -#define LEVEL_STATE_LEVELS 1 -#define LEVEL_STATE_FLAGS 2 - -AdminCache g_Admins; -char g_ReverseFlags[26]; -AdminFlag g_FlagLetters[26]; -bool g_FlagSet[26]; - -ConVar sm_immunity_mode("sm_immunity_mode", "1", FCVAR_SPONLY, "Mode for deciding immunity protection"); - -/* Default flags */ -AdminFlag g_DefaultFlags[26] = -{ - Admin_Reservation, Admin_Generic, Admin_Kick, Admin_Ban, Admin_Unban, - Admin_Slay, Admin_Changemap, Admin_Convars, Admin_Config, Admin_Chat, - Admin_Vote, Admin_Password, Admin_RCON, Admin_Cheats, Admin_Custom1, - Admin_Custom2, Admin_Custom3, Admin_Custom4, Admin_Custom5, Admin_Custom6, - Admin_Generic, Admin_Generic, Admin_Generic, Admin_Generic, Admin_Generic, - Admin_Root -}; - - -class FlagReader : public ITextListener_SMC -{ -public: - void LoadLevels() - { - if (!Parse()) - { - memcpy(g_FlagLetters, g_DefaultFlags, sizeof(AdminFlag) * 26); - for (unsigned int i=0; i<20; i++) - { - g_FlagSet[i] = true; - } - g_FlagSet[25] = true; - } - } -private: - bool Parse() - { - SMCStates states; - SMCError error; - - m_bFileNameLogged = false; - g_SourceMod.BuildPath(Path_SM, m_File, sizeof(m_File), "configs/admin_levels.cfg"); - - if ((error = textparsers->ParseFile_SMC(m_File, this, &states)) - != SMCError_Okay) - { - const char *err_string = textparsers->GetSMCErrorString(error); - if (!err_string) - { - err_string = "Unknown error"; - } - ParseError(NULL, "Error %d (%s)", error, err_string); - return false; - } - - return true; - } - void ReadSMC_ParseStart() - { - m_LevelState = LEVEL_STATE_NONE; - m_IgnoreLevel = 0; - memset(g_FlagSet, 0, sizeof(g_FlagSet)); - } - SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name) - { - if (m_IgnoreLevel) - { - m_IgnoreLevel++; - return SMCResult_Continue; - } - - if (m_LevelState == LEVEL_STATE_NONE) - { - if (strcmp(name, "Levels") == 0) - { - m_LevelState = LEVEL_STATE_LEVELS; - } - else - { - m_IgnoreLevel++; - } - } else if (m_LevelState == LEVEL_STATE_LEVELS) { - if (strcmp(name, "Flags") == 0) - { - m_LevelState = LEVEL_STATE_FLAGS; - } - else - { - m_IgnoreLevel++; - } - } - else - { - m_IgnoreLevel++; - } - - return SMCResult_Continue; - } - SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) - { - if (m_LevelState != LEVEL_STATE_FLAGS || m_IgnoreLevel) - { - return SMCResult_Continue; - } - - unsigned char c = (unsigned)value[0]; - - if (c < (unsigned)'a' || c > (unsigned)'z') - { - ParseError(states, "Flag \"%c\" is not a lower-case ASCII letter", c); - return SMCResult_Continue; - } - - c -= (unsigned)'a'; - - if (!g_Admins.FindFlag(key, &g_FlagLetters[c])) - { - ParseError(states, "Unrecognized admin level \"%s\"", key); - return SMCResult_Continue; - } - - g_FlagSet[c] = true; - - return SMCResult_Continue; - } - SMCResult ReadSMC_LeavingSection(const SMCStates *states) - { - if (m_IgnoreLevel) - { - m_IgnoreLevel--; - return SMCResult_Continue; - } - - if (m_LevelState == LEVEL_STATE_FLAGS) - { - m_LevelState = LEVEL_STATE_LEVELS; - return SMCResult_Halt; - } - else if (m_LevelState == LEVEL_STATE_LEVELS) - { - m_LevelState = LEVEL_STATE_NONE; - } - - return SMCResult_Continue; - } - void ParseError(const SMCStates *states, const char *message, ...) - { - va_list ap; - char buffer[256]; - - va_start(ap, message); - UTIL_FormatArgs(buffer, sizeof(buffer), message, ap); - va_end(ap); - - if (!m_bFileNameLogged) - { - g_Logger.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File); - m_bFileNameLogged = true; - } - - g_Logger.LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer); - } -private: - bool m_bFileNameLogged; - char m_File[PLATFORM_MAX_PATH]; - int m_LevelState; - int m_IgnoreLevel; -} s_FlagReader; - -AdminCache::AdminCache() -{ - m_pStrings = new BaseStringTable(1024); - m_pMemory = m_pStrings->GetMemTable(); - m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID; - m_FreeUserList = m_FirstUser = m_LastUser = INVALID_ADMIN_ID; - m_pCacheFwd = NULL; - m_FirstGroup = -1; - m_InvalidatingAdmins = false; - m_destroying = false; -} - -AdminCache::~AdminCache() -{ - m_destroying = true; - DumpAdminCache(AdminCache_Overrides, false); - DumpAdminCache(AdminCache_Groups, false); - - List::iterator iter; - for (iter=m_AuthMethods.begin(); - iter!=m_AuthMethods.end(); - iter++) - { - delete *iter; - } - - delete m_pStrings; -} - -void AdminCache::OnSourceModStartup(bool late) -{ - RegisterAuthIdentType("steam"); - RegisterAuthIdentType("name"); - RegisterAuthIdentType("ip"); - - NameFlag("reservation", Admin_Reservation); - NameFlag("kick", Admin_Kick); - NameFlag("generic", Admin_Generic); - NameFlag("ban", Admin_Ban); - NameFlag("unban", Admin_Unban); - NameFlag("slay", Admin_Slay); - NameFlag("changemap", Admin_Changemap); - NameFlag("cvars", Admin_Convars); - NameFlag("config", Admin_Config); - NameFlag("chat", Admin_Chat); - NameFlag("vote", Admin_Vote); - NameFlag("password", Admin_Password); - NameFlag("rcon", Admin_RCON); - NameFlag("cheats", Admin_Cheats); - NameFlag("root", Admin_Root); - NameFlag("custom1", Admin_Custom1); - NameFlag("custom2", Admin_Custom2); - NameFlag("custom3", Admin_Custom3); - NameFlag("custom4", Admin_Custom4); - NameFlag("custom5", Admin_Custom5); - NameFlag("custom6", Admin_Custom6); -} - -void AdminCache::OnSourceModAllInitialized() -{ - m_pCacheFwd = forwardsys->CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell); - sharesys->AddInterface(NULL, this); -} - -void AdminCache::OnSourceModLevelChange(const char *mapName) -{ - int i; - AdminFlag flag; - - /* For now, we only read these once per level. */ - s_FlagReader.LoadLevels(); - - memset(g_ReverseFlags, '?', sizeof(g_ReverseFlags)); - - for (i = 0; i < 26; i++) - { - if (FindFlag('a' + i, &flag)) - { - g_ReverseFlags[flag] = 'a' + i; - } - } -} - -void AdminCache::OnSourceModShutdown() -{ - forwardsys->ReleaseForward(m_pCacheFwd); - m_pCacheFwd = NULL; -} - -void AdminCache::OnSourceModPluginsLoaded() -{ - DumpAdminCache(AdminCache_Overrides, true); - DumpAdminCache(AdminCache_Groups, true); -} - -void AdminCache::NameFlag(const char *str, AdminFlag flag) -{ - m_LevelNames.insert(str, flag); -} - -bool AdminCache::FindFlag(const char *str, AdminFlag *pFlag) -{ - return m_LevelNames.retrieve(str, pFlag); -} - -void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags) -{ - FlagMap *map; - if (type == Override_Command) - map = &m_CmdOverrides; - else if (type == Override_CommandGroup) - map = &m_CmdGrpOverrides; - else - return; - - map->insert(cmd, flags); - g_ConCmds.UpdateAdminCmdFlags(cmd, type, flags, false); -} - -bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, FlagBits *pFlags) -{ - FlagMap *map; - if (type == Override_Command) - map = &m_CmdOverrides; - else if (type == Override_CommandGroup) - map = &m_CmdGrpOverrides; - else - return false; - - return map->retrieve(cmd, pFlags); -} - -void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type) -{ - if (type == Override_Command) - { - return _UnsetCommandOverride(cmd); - } else if (type == Override_CommandGroup) { - return _UnsetCommandGroupOverride(cmd); - } -} - -void AdminCache::_UnsetCommandGroupOverride(const char *group) -{ - m_CmdGrpOverrides.remove(group); - g_ConCmds.UpdateAdminCmdFlags(group, Override_CommandGroup, 0, true); -} - -void AdminCache::_UnsetCommandOverride(const char *cmd) -{ - m_CmdOverrides.remove(cmd); - g_ConCmds.UpdateAdminCmdFlags(cmd, Override_Command, 0, true); -} - -void AdminCache::DumpCommandOverrideCache(OverrideType type) -{ - if (type == Override_Command) - m_CmdOverrides.clear(); - else if (type == Override_CommandGroup) - m_CmdGrpOverrides.clear(); -} - -AdminId AdminCache::CreateAdmin(const char *name) -{ - AdminId id; - AdminUser *pUser; - - if (m_FreeUserList != INVALID_ADMIN_ID) - { - pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList); - assert(pUser->magic == USR_MAGIC_UNSET); - id = m_FreeUserList; - m_FreeUserList = pUser->next_user; - } - else - { - id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser); - pUser->grp_size = 0; - pUser->grp_table = -1; - } - - pUser->flags = 0; - pUser->eflags = 0; - pUser->grp_count = 0; - pUser->password = -1; - pUser->magic = USR_MAGIC_SET; - pUser->auth.identidx = -1; - pUser->auth.index = 0; - pUser->immunity_level = 0; - pUser->serialchange = 1; - - if (m_FirstUser == INVALID_ADMIN_ID) - { - m_FirstUser = id; - m_LastUser = id; - } - else - { - AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser); - pPrev->next_user = id; - pUser->prev_user = m_LastUser; - m_LastUser = id; - } - - /* Since we always append to the tail, we should invalidate their next */ - pUser->next_user = -1; - - if (name && name[0] != '\0') - { - int nameidx = m_pStrings->AddString(name); - pUser = (AdminUser *)m_pMemory->GetAddress(id); - pUser->nameidx = nameidx; - } - else - { - pUser->nameidx = -1; - } - - return id; -} - -GroupId AdminCache::AddGroup(const char *group_name) -{ - if (m_Groups.contains(group_name)) - return INVALID_GROUP_ID; - - GroupId id; - AdminGroup *pGroup; - if (m_FreeGroupList != INVALID_GROUP_ID) - { - pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList); - assert(pGroup->magic == GRP_MAGIC_UNSET); - id = m_FreeGroupList; - m_FreeGroupList = pGroup->next_grp; - } else { - id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup); - } - - pGroup->immunity_level = 0; - pGroup->immune_table = -1; - pGroup->magic = GRP_MAGIC_SET; - pGroup->next_grp = INVALID_GROUP_ID; - pGroup->pCmdGrpTable = NULL; - pGroup->pCmdTable = NULL; - pGroup->addflags = 0; - - if (m_FirstGroup == INVALID_GROUP_ID) - { - m_FirstGroup = id; - m_LastGroup = id; - pGroup->prev_grp = INVALID_GROUP_ID; - } else { - AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); - assert(pPrev->magic == GRP_MAGIC_SET); - pPrev->next_grp = id; - pGroup->prev_grp = m_LastGroup; - m_LastGroup = id; - } - - int nameidx = m_pStrings->AddString(group_name); - pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - pGroup->nameidx = nameidx; - - m_Groups.insert(group_name, id); - return id; -} - -GroupId AdminCache::FindGroupByName(const char *group_name) -{ - GroupId id; - if (!m_Groups.retrieve(group_name, &id)) - return INVALID_GROUP_ID; - - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - return INVALID_GROUP_ID; - - return id; -} - -void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return; - } - - if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL) - { - return; - } - - FlagBits bits = (1<<(FlagBits)flag); - - if (enabled) - { - pGroup->addflags |= bits; - } else { - pGroup->addflags &= ~bits; - } -} - -bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return false; - } - - if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL) - { - return false; - } - - FlagBits bit = 1<<(FlagBits)flag; - return ((pGroup->addflags & bit) == bit); -} - -FlagBits AdminCache::GetGroupAddFlags(GroupId id) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return 0; - } - - return pGroup->addflags; -} - -const char *AdminCache::GetGroupName(GroupId gid) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return NULL; - } - - return m_pStrings->GetString(pGroup->nameidx); -} - -void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return; - } - - unsigned int level = 0; - - if (enabled) - { - if (type == Immunity_Default) - { - level = 1; - } else if (type == Immunity_Global) { - level = 2; - } - if (level > pGroup->immunity_level) - { - pGroup->immunity_level = level; - } - } else { - pGroup->immunity_level = 0; - } -} - -bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return false; - } - - if (type == Immunity_Default && pGroup->immunity_level >= 1) - { - return true; - } else if (type == Immunity_Global && pGroup->immunity_level >= 2) { - return true; - } - - return false; -} - -void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(other_id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return; - } - - pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return; - } - - /* We always need to resize the immunity table */ - int *table, tblidx; - if (pGroup->immune_table == -1) - { - tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table); - pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - table[0] = 0; - } else { - int *old_table = (int *)m_pMemory->GetAddress(pGroup->immune_table); - /* Break out if this group is already in the list */ - for (int i=0; iCreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table); - /* Get the old address again in case of resize */ - pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - old_table = (int *)m_pMemory->GetAddress(pGroup->immune_table); - table[0] = old_table[0]; - for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++) - { - table[i] = old_table[i]; - } - } - - /* Assign */ - pGroup->immune_table = tblidx; - - /* Add to the array */ - table[0]++; - table[table[0]] = other_id; -} - -unsigned int AdminCache::GetGroupImmunityCount(GroupId id) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return 0; - } - - if (pGroup->immune_table == -1) - { - return 0; - } - - int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); - - return table[0]; -} - -GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return INVALID_GROUP_ID; - } - - if (pGroup->immune_table == -1) - { - return INVALID_GROUP_ID; - } - - int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); - if (number >= (unsigned int)table[0]) - { - return INVALID_GROUP_ID; - } - - return table[1 + number]; -} - -void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return; - } - - OverrideMap *map; - if (type == Override_Command) - { - if (pGroup->pCmdTable == NULL) - pGroup->pCmdTable = new OverrideMap(); - map = pGroup->pCmdTable; - } else if (type == Override_CommandGroup) { - if (pGroup->pCmdGrpTable == NULL) - pGroup->pCmdGrpTable = new OverrideMap(); - map = pGroup->pCmdGrpTable; - } else { - return; - } - - map->insert(name, rule); -} - -bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return false; - } - - OverrideMap *map; - if (type == Override_Command) - { - if (pGroup->pCmdTable == NULL) - return false; - map = pGroup->pCmdTable; - } else if (type == Override_CommandGroup) { - if (pGroup->pCmdGrpTable == NULL) - return false; - map = pGroup->pCmdGrpTable; - } else { - return false; - } - - return map->retrieve(name, pRule); -} - -AuthMethod *AdminCache::GetMethodByIndex(unsigned int index) -{ - List::iterator iter; - for (iter=m_AuthMethods.begin(); - iter!=m_AuthMethods.end(); - iter++) - { - if (index-- == 0) - { - return *iter; - } - } - - return NULL; -} - -bool AdminCache::InvalidateAdmin(AdminId id) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - AdminUser *pOther; - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return false; - } - - if (!m_InvalidatingAdmins && !m_destroying) - { - g_Players.ClearAdminId(id); - } - - /* Unlink from the dbl link list */ - if (id == m_FirstUser && id == m_LastUser) - { - m_FirstUser = INVALID_ADMIN_ID; - m_LastUser = INVALID_ADMIN_ID; - } else if (id == m_FirstUser) { - m_FirstUser = pUser->next_user; - pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser); - pOther->prev_user = INVALID_ADMIN_ID; - } else if (id == m_LastUser) { - m_LastUser = pUser->prev_user; - pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser); - pOther->next_user = INVALID_ADMIN_ID; - } else { - pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user); - pOther->next_user = pUser->next_user; - pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user); - pOther->prev_user = pUser->prev_user; - } - - /* Unlink from auth tables */ - if (pUser->auth.identidx != -1) - { - AuthMethod *method = GetMethodByIndex(pUser->auth.index); - if (method) - method->identities.remove(m_pStrings->GetString(pUser->auth.identidx)); - } - - /* Clear table counts */ - pUser->grp_count = 0; - - /* Link into free list */ - pUser->magic = USR_MAGIC_UNSET; - pUser->next_user = m_FreeUserList; - m_FreeUserList = id; - - /* Unset serial change */ - pUser->serialchange = 0; - - return true; -} - - -void AdminCache::InvalidateGroup(GroupId id) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); - AdminGroup *pOther; - - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return; - } - - const char *str = m_pStrings->GetString(pGroup->nameidx); - m_Groups.remove(str); - - /* Unlink from the live dbllink list */ - if (id == m_FirstGroup && id == m_LastGroup) - { - m_LastGroup = INVALID_GROUP_ID; - m_FirstGroup = INVALID_GROUP_ID; - } else if (id == m_FirstGroup) { - m_FirstGroup = pGroup->next_grp; - pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup); - pOther->prev_grp = INVALID_GROUP_ID; - } else if (id == m_LastGroup) { - m_LastGroup = pGroup->prev_grp; - pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); - pOther->next_grp = INVALID_GROUP_ID; - } else { - pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp); - pOther->next_grp = pGroup->next_grp; - pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp); - pOther->prev_grp = pGroup->prev_grp; - } - - /* Free any used memory */ - delete pGroup->pCmdGrpTable; - pGroup->pCmdGrpTable = NULL; - delete pGroup->pCmdTable; - pGroup->pCmdTable = NULL; - - /* Link into the free list */ - pGroup->magic = GRP_MAGIC_UNSET; - pGroup->next_grp = m_FreeGroupList; - m_FreeGroupList = id; - - int idx = m_FirstUser; - AdminUser *pUser; - int *table; - while (idx != INVALID_ADMIN_ID) - { - pUser = (AdminUser *)m_pMemory->GetAddress(idx); - if (pUser->grp_count > 0) - { - table = (int *)m_pMemory->GetAddress(pUser->grp_table); - for (unsigned int i=0; igrp_count; i++) - { - if (table[i] == id) - { - /* We have to remove this entry */ - for (unsigned int j=i+1; jgrp_count; j++) - { - /* Move everything down by one */ - table[j-1] = table[j]; - } - /* Decrease count */ - pUser->grp_count--; - /* Recalculate effective flags */ - pUser->eflags = pUser->flags; - for (unsigned int j=0; jgrp_count; j++) - { - pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]); - pUser->eflags |= pOther->addflags; - } - /* Mark as changed */ - pUser->serialchange++; - /* Break now, duplicates aren't allowed */ - break; - } - } - } - idx = pUser->next_user; - } -} - -void AdminCache::InvalidateGroupCache() -{ - /* Nuke the free list */ - m_FreeGroupList = -1; - - /* Nuke reverse lookups */ - m_Groups.clear(); - - /* Free memory on groups */ - GroupId cur = m_FirstGroup; - AdminGroup *pGroup; - while (cur != INVALID_GROUP_ID) - { - pGroup = (AdminGroup *)m_pMemory->GetAddress(cur); - assert(pGroup->magic == GRP_MAGIC_SET); - delete pGroup->pCmdGrpTable; - delete pGroup->pCmdTable; - cur = pGroup->next_grp; - } - - m_FirstGroup = INVALID_GROUP_ID; - m_LastGroup = INVALID_GROUP_ID; - - InvalidateAdminCache(false); - - /* Reset the memory table */ - m_pMemory->Reset(); -} - -void AdminCache::AddAdminListener(IAdminListener *pListener) -{ - m_hooks.push_back(pListener); -} - -void AdminCache::RemoveAdminListener(IAdminListener *pListener) -{ - m_hooks.remove(pListener); -} - -void AdminCache::RegisterAuthIdentType(const char *name) -{ - if (m_AuthTables.contains(name)) - return; - - AuthMethod *method = new AuthMethod(name); - m_AuthMethods.push_back(method); - m_AuthTables.insert(name, method); -} - -void AdminCache::InvalidateAdminCache(bool unlink_admins) -{ - m_InvalidatingAdmins = true; - if (!m_destroying) - { - g_Players.ClearAllAdmins(); - } - /* Wipe the identity cache first */ - List::iterator iter; - for (iter=m_AuthMethods.begin(); - iter!=m_AuthMethods.end(); - iter++) - { - (*iter)->identities.clear(); - } - - if (unlink_admins) - { - while (m_FirstUser != INVALID_ADMIN_ID) - { - InvalidateAdmin(m_FirstUser); - } - } else { - m_FirstUser = -1; - m_LastUser = -1; - m_FreeUserList = -1; - } - m_InvalidatingAdmins = false; -} - -void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild) -{ - List::iterator iter; - IAdminListener *pListener; - cell_t result; - - if (part == AdminCache_Overrides) - { - DumpCommandOverrideCache(Override_Command); - DumpCommandOverrideCache(Override_CommandGroup); - if (rebuild && !m_destroying) - { - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) - { - pListener = (*iter); - pListener->OnRebuildOverrideCache(); - } - m_pCacheFwd->PushCell(part); - m_pCacheFwd->Execute(&result); - } - } else if (part == AdminCache_Groups || part == AdminCache_Admins) { - if (part == AdminCache_Groups) - { - InvalidateGroupCache(); - if (rebuild && !m_destroying) - { - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) - { - pListener = (*iter); - pListener->OnRebuildGroupCache(); - } - m_pCacheFwd->PushCell(part); - m_pCacheFwd->Execute(&result); - } - } - InvalidateAdminCache(true); - if (rebuild && !m_destroying) - { - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) - { - pListener = (*iter); - pListener->OnRebuildAdminCache((part == AdminCache_Groups)); - } - m_pCacheFwd->PushCell(AdminCache_Admins); - m_pCacheFwd->Execute(&result); - g_Players.RecheckAnyAdmins(); - } - } -} - -const char *AdminCache::GetAdminName(AdminId id) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return NULL; - } - - return m_pStrings->GetString(pUser->nameidx); -} - -bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index) -{ - List::iterator iter; - unsigned int index = 0; - for (iter=m_AuthMethods.begin(); - iter!=m_AuthMethods.end(); - iter++,index++) - { - if ((*iter)->name.compare(name) == 0) - { - *_index = index; - return true; - } - } - - return false; -} - -bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident) -{ - if (ident[0] == '\0') - { - return false; - } - - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return false; - } - - AuthMethod *method; - if (!m_AuthTables.retrieve(auth, &method)) - return false; - - /* If the id was a steam id strip off the STEAM_*: part */ - if (strcmp(auth, "steam") == 0 && strncmp(ident, "STEAM_", 6) == 0) - { - ident += 8; - } - - if (method->identities.contains(ident)) - return false; - - int i_ident = m_pStrings->AddString(ident); - - pUser = (AdminUser *)m_pMemory->GetAddress(id); - pUser->auth.identidx = i_ident; - GetMethodIndex(auth, &pUser->auth.index); - - return method->identities.insert(ident, id); -} - -AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity) -{ - AuthMethod *method; - if (!m_AuthTables.retrieve(auth, &method)) - return INVALID_ADMIN_ID; - - /* If the id was a steam id strip off the STEAM_*: part */ - if (strcmp(auth, "steam") == 0 && strncmp(identity, "STEAM_", 6) == 0) - { - identity += 8; - } - - AdminId id; - if (!method->identities.retrieve(identity, &id)) - return INVALID_ADMIN_ID; - return id; -} - -void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return; - } - - if (flag < Admin_Reservation - || flag >= AdminFlags_TOTAL) - { - return; - } - - FlagBits bits = (1<<(FlagBits)flag); - - if (enabled) - { - pUser->flags |= bits; - pUser->eflags |= bits; - } else { - pUser->flags &= ~bits; - pUser->eflags &= ~bits; - } - - pUser->serialchange++; -} - -bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return false; - } - - if (flag < Admin_Reservation - || flag >= AdminFlags_TOTAL) - { - return false; - } - - FlagBits bit = (1<<(FlagBits)flag); - - if (mode == Access_Real) - { - return ((pUser->flags & bit) == bit); - } else if (mode == Access_Effective) { - bool has_bit = ((pUser->eflags & bit) == bit); - if (!has_bit && flag != Admin_Root && ((pUser->eflags & ADMFLAG_ROOT) == ADMFLAG_ROOT)) - { - has_bit = true; - } - return has_bit; - } - - return false; -} - -FlagBits AdminCache::GetAdminFlags(AdminId id, AccessMode mode) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return 0; - } - - if (mode == Access_Real) - { - return pUser->flags; - } else if (mode == Access_Effective) { - return pUser->eflags; - } - - return 0; -} - -void AdminCache::SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return; - } - - if (mode == Access_Real) - { - pUser->flags = bits; - pUser->eflags = bits; - } else if (mode == Access_Effective) { - pUser->eflags = bits; - } - - pUser->serialchange++; -} - -bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return false; - } - - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return false; - } - - /* First check for duplicates */ - if (pUser->grp_count != 0) - { - int *temp_table = (int *)m_pMemory->GetAddress(pUser->grp_table); - for (unsigned int i=0; igrp_count; i++) - { - if (temp_table[i] == gid) - { - return false; - } - } - } - - int *table; - if (pUser->grp_count + 1 > pUser->grp_size) - { - int new_size = 0; - int tblidx; - - if (pUser->grp_size == 0) - { - new_size = 2; - } else { - new_size = pUser->grp_size * 2; - } - - /* Create and refresh pointers */ - tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table); - pUser = (AdminUser *)m_pMemory->GetAddress(id); - pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); - - /* Copy old data if necessary */ - if (pUser->grp_table != -1) - { - int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table); - memcpy(table, old_table, sizeof(int) * pUser->grp_count); - } - pUser->grp_table = tblidx; - pUser->grp_size = new_size; - } else { - table = (int *)m_pMemory->GetAddress(pUser->grp_table); - } - - table[pUser->grp_count] = gid; - pUser->grp_count++; - - /* Compute new effective permissions */ - pUser->eflags |= pGroup->addflags; - - if (pGroup->immunity_level > pUser->immunity_level) - { - pUser->immunity_level = pGroup->immunity_level; - } - - pUser->serialchange++; - - return true; -} - -bool AdminCache::IsValidAdmin(AdminId id) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - return (pUser != NULL && pUser->magic == USR_MAGIC_SET); -} - -unsigned int AdminCache::GetAdminGroupCount(AdminId id) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return 0; - } - - return pUser->grp_count; -} - -GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count) - { - return INVALID_GROUP_ID; - } - - int *table = (int *)m_pMemory->GetAddress(pUser->grp_table); - - GroupId gid = table[index]; - - if (name) - { - *name = GetGroupName(gid); - } - - return gid; -} - -const char *AdminCache::GetAdminPassword(AdminId id) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return NULL; - } - - return m_pStrings->GetString(pUser->password); -} - -void AdminCache::SetAdminPassword(AdminId id, const char *password) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return; - } - - if (password[0] == '\0') - { - pUser->password = -1; - return; - } - - int i_password = m_pStrings->AddString(password); - pUser = (AdminUser *)m_pMemory->GetAddress(id); - pUser->password = i_password; -} - -unsigned int AdminCache::FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize) -{ - unsigned int i; - for (i=0; iGetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return false; - } - - return ((pUser->eflags & bits) == bits); -} - -bool AdminCache::CanAdminTarget(AdminId id, AdminId target) -{ - /** - * Zeroth, if the targeting AdminId is INVALID_ADMIN_ID, targeting fails. - * First, if the targeted AdminId is INVALID_ADMIN_ID, targeting succeeds. - */ - - if (id == INVALID_ADMIN_ID) - { - return false; - } - - if (target == INVALID_ADMIN_ID) - { - return true; - } - - if (id == target) - { - return true; - } - - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return false; - } - - AdminUser *pTarget = (AdminUser *)m_pMemory->GetAddress(target); - if (!pTarget || pTarget->magic != USR_MAGIC_SET) - { - return false; - } - - /** - * Second, if the targeting admin is root, targeting succeeds. - */ - if (pUser->eflags & ADMFLAG_ROOT) - { - return true; - } - - /** Fourth, if the targeted admin is immune from targeting admin. */ - int mode = sm_immunity_mode.GetInt(); - switch (mode) - { - case 1: - { - if (pTarget->immunity_level > pUser->immunity_level) - { - return false; - } - break; - } - case 3: - { - /* If neither has any immunity, let this pass. */ - if (!pUser->immunity_level && !pTarget->immunity_level) - { - return true; - } - /* Don't break, go to the next case. */ - } - case 2: - { - if (pTarget->immunity_level >= pUser->immunity_level) - { - return false; - } - break; - } - } - - /** - * Fifth, if the targeted admin has specific immunity from the - * targeting admin via group immunities, targeting fails. - */ - //:TODO: speed this up... maybe with trie hacks. - //idea is to insert %d.%d in the trie after computing this and use it as a cache lookup. - //problem is the trie cannot delete prefixes, so we'd have a problem with invalidations. - if (pTarget->grp_count > 0 && pUser->grp_count > 0) - { - int *grp_table = (int *)m_pMemory->GetAddress(pTarget->grp_table); - int *src_table = (int *)m_pMemory->GetAddress(pUser->grp_table); - GroupId id, other; - unsigned int num; - for (unsigned int i=0; igrp_count; i++) - { - id = grp_table[i]; - num = GetGroupImmunityCount(id); - for (unsigned int j=0; jgrp_count; k++) - { - if (other == src_table[k]) - { - return false; - } - } - } - } - } - - return true; -} - -bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag) -{ - if (c < 'a' - || c > 'z' - || !g_FlagSet[(unsigned)c - (unsigned)'a']) - { - return false; - } - - if (pAdmFlag) - { - *pAdmFlag = g_FlagLetters[(unsigned)c - (unsigned)'a']; - } - - return true; -} - -bool AdminCache::FindFlagChar(AdminFlag flag, char *c) -{ - if (!g_FlagSet[flag]) - { - return false; - } - - if (c) - { - *c = g_ReverseFlags[flag]; - } - - return true; -} - -FlagBits AdminCache::ReadFlagString(const char *flags, const char **end) -{ - FlagBits bits = 0; - - while (flags && (*flags != '\0')) - { - AdminFlag flag; - if (!FindFlag(*flags, &flag)) - { - break; - } - bits |= FlagArrayToBits(&flag, 1); - flags++; - } - - if (end) - { - *end = flags; - } - - return bits; -} - -unsigned int AdminCache::GetAdminSerialChange(AdminId id) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return 0; - } - - return pUser->serialchange; -} - -bool AdminCache::CanAdminUseCommand(int client, const char *cmd) -{ - FlagBits bits; - OverrideType otype = Override_Command; - - if (cmd[0] == '@') - { - otype = Override_CommandGroup; - cmd++; - } - - if (!g_ConCmds.LookForCommandAdminFlags(cmd, &bits)) - { - if (!GetCommandOverride(cmd, otype, &bits)) - { - bits = 0; - } - } - - return g_ConCmds.CheckClientCommandAccess(client, cmd, bits); -} - -unsigned int AdminCache::SetGroupImmunityLevel(GroupId gid, unsigned int level) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return 0; - } - - unsigned int old_level = pGroup->immunity_level; - - pGroup->immunity_level = level; - - return old_level; -} - -unsigned int AdminCache::GetGroupImmunityLevel(GroupId gid) -{ - AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return 0; - } - - return pGroup->immunity_level; -} - -unsigned int AdminCache::SetAdminImmunityLevel(AdminId id, unsigned int level) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return 0; - } - - unsigned int old_level = pUser->immunity_level; - - pUser->immunity_level = level; - - return old_level; -} - -unsigned int AdminCache::GetAdminImmunityLevel(AdminId id) -{ - AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); - if (!pUser || pUser->magic != USR_MAGIC_SET) - { - return 0; - } - - return pUser->immunity_level; -} - -bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool override_only) -{ - if (client == 0) - { - return true; - } - - /* Auto-detect a command if we can */ - FlagBits bits = flags; - bool found_command = false; - if (!override_only) - { - found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits); - } - - if (!found_command) - { - GetCommandOverride(cmd, Override_Command, &bits); - } - - return g_ConCmds.CheckClientCommandAccess(client, cmd, bits) ? 1 : 0; -} - -void iterator_glob_basic_override(FILE *fp, const char *key, FlagBits flags) -{ - char flagstr[64]; - g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr)); - fprintf(fp, "\t\"%s\"\t\t\"%s\"\n", key, flagstr); -} - -void iterator_glob_grp_override(FILE *fp, const char *key, FlagBits flags) -{ - char flagstr[64]; - g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr)); - fprintf(fp, "\t\"@%s\"\t\t\"%s\"\n", key, flagstr); -} - -void iterator_group_basic_override(FILE *fp, const char *key, OverrideRule rule) -{ - const char *str = (rule == Command_Allow) ? "allow" : "deny"; - fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n", key, str); -} - -void iterator_group_grp_override(FILE *fp, const char *key, OverrideRule rule) -{ - const char *str = (rule == Command_Allow) ? "allow" : "deny"; - fprintf(fp, "\t\t\t\"@%s\"\t\t\"%s\"\n", key, str); -} - -void AdminCache::DumpCache(FILE *fp) -{ - int *itable; - AdminId aid; - GroupId gid; - char flagstr[64]; - unsigned int num; - AdminUser *pAdmin; - AdminGroup *pGroup; - - fprintf(fp, "\"Groups\"\n{\n"); - - num = 0; - gid = m_FirstGroup; - while (gid != INVALID_GROUP_ID - && (pGroup = GetGroup(gid)) != NULL) - { - num++; - FillFlagString(pGroup->addflags, flagstr, sizeof(flagstr)); - - fprintf(fp, "\t/* num = %d, gid = 0x%X */\n", num, gid); - fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pGroup->nameidx)); - fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr); - fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pGroup->immunity_level); - - if (pGroup->immune_table != -1 - && (itable = (int *)m_pMemory->GetAddress(pGroup->immune_table)) != NULL) - { - AdminGroup *pAltGroup; - const char *gname, *mod; - - for (int i = 1; i <= itable[0]; i++) - { - if ((pAltGroup = GetGroup(itable[i])) == NULL) - { - /* Assume the rest of the table is corrupt */ - break; - } - gname = GetString(pAltGroup->nameidx); - if (atoi(gname) != 0) - { - mod = "@"; - } - else - { - mod = ""; - } - fprintf(fp, "\t\t\"immunity\"\t\t\"%s%s\"\n", mod, gname); - } - } - - fprintf(fp, "\n\t\t\"Overrides\"\n\t\t{\n"); - if (pGroup->pCmdGrpTable != NULL) - { - for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next()) - iterator_group_grp_override(fp, iter->key.chars(), iter->value); - } - if (pGroup->pCmdTable != NULL) - { - for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next()) - iterator_group_basic_override(fp, iter->key.chars(), iter->value); - } - fprintf(fp, "\t\t}\n"); - - fprintf(fp, "\t}\n"); - - if ((gid = pGroup->next_grp) != INVALID_GROUP_ID) - { - fprintf(fp, "\n"); - } - } - - fprintf(fp, "}\n\n"); - fprintf(fp, "\"Admins\"\n{\n"); - - num = 0; - aid = m_FirstUser; - while (aid != INVALID_ADMIN_ID - && (pAdmin = GetUser(aid)) != NULL) - { - num++; - FillFlagString(pAdmin->flags, flagstr, sizeof(flagstr)); - - fprintf(fp, "\t/* num = %d, aid = 0x%X, serialno = 0x%X*/\n", num, aid, pAdmin->serialchange); - - if (pAdmin->nameidx != -1) - { - fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pAdmin->nameidx)); - } - else - { - fprintf(fp, "\t\"\"\n\t{\n"); - } - - if (pAdmin->auth.identidx != -1) - { - fprintf(fp, "\t\t\"auth\"\t\t\t\"%s\"\n", GetMethodName(pAdmin->auth.index)); - fprintf(fp, "\t\t\"identity\"\t\t\"%s\"\n", GetString(pAdmin->auth.identidx)); - } - if (pAdmin->password != -1) - { - fprintf(fp, "\t\t\"password\"\t\t\"%s\"\n", GetString(pAdmin->password)); - } - fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr); - fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pAdmin->immunity_level); - - if (pAdmin->grp_count != 0 - && pAdmin->grp_table != -1 - && (itable = (int *)m_pMemory->GetAddress(pAdmin->grp_table)) != NULL) - { - unsigned int i; - - for (i = 0; i < pAdmin->grp_count; i++) - { - if ((pGroup = GetGroup(itable[i])) == NULL) - { - /* Assume the rest of the table is corrupt */ - break; - } - fprintf(fp, "\t\t\"group\"\t\t\t\"%s\"\n", GetString(pGroup->nameidx)); - } - } - - fprintf(fp, "\t}\n"); - - if ((aid = pAdmin->next_user) != INVALID_ADMIN_ID) - { - fprintf(fp, "\n"); - } - } - - fprintf(fp, "}\n\n"); - - fprintf(fp, "\"Overrides\"\n{\n"); - for (FlagMap::iterator iter = m_CmdGrpOverrides.iter(); !iter.empty(); iter.next()) - iterator_glob_grp_override(fp, iter->key.chars(), iter->value); - for (FlagMap::iterator iter = m_CmdOverrides.iter(); !iter.empty(); iter.next()) - iterator_glob_basic_override(fp, iter->key.chars(), iter->value); - fprintf(fp, "}\n"); -} - -AdminGroup *AdminCache::GetGroup(GroupId gid) -{ - AdminGroup *pGroup; - - pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); - if (!pGroup || pGroup->magic != GRP_MAGIC_SET) - { - return NULL; - } - - return pGroup; -} - -AdminUser *AdminCache::GetUser(AdminId aid) -{ - AdminUser *pAdmin; - - pAdmin = (AdminUser *)m_pMemory->GetAddress(aid); - if (!pAdmin || pAdmin->magic != USR_MAGIC_SET) - { - return NULL; - } - - return pAdmin; -} - -const char *AdminCache::GetMethodName(unsigned int index) -{ - List::iterator iter; - for (iter=m_AuthMethods.begin(); - iter!=m_AuthMethods.end(); - iter++) - { - if (index-- == 0) - { - return (*iter)->name.c_str(); - } - } - - return NULL; -} - -const char *AdminCache::GetString(int idx) -{ - return m_pStrings->GetString(idx); -} - -size_t AdminCache::FillFlagString(FlagBits bits, char *buffer, size_t maxlen) -{ - size_t pos; - unsigned int i, num_flags; - AdminFlag flags[AdminFlags_TOTAL]; - - num_flags = FlagBitsToArray(bits, flags, AdminFlags_TOTAL); - - pos = 0; - for (i = 0; pos < maxlen && i < num_flags; i++) - { - if (FindFlagChar(flags[i], &buffer[pos])) - { - pos++; - } - } - buffer[pos] = '\0'; - - return pos; -} - -CON_COMMAND(sm_dump_admcache, "Dumps the admin cache for debugging") -{ - FILE *fp; - char buffer[PLATFORM_MAX_PATH]; - - g_SourceMod.BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt"); - - if ((fp = fopen(buffer, "wt")) == NULL) - { - g_RootMenu.ConsolePrint("Could not open file for writing: %s", buffer); - return; - } - - g_Admins.DumpCache(fp); - - g_RootMenu.ConsolePrint("Admin cache dumped to: %s", buffer); - - fclose(fp); -} +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 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 +#include +#include +#include +#include +#include +#include "AdminCache.h" +#include "Translator.h" +#include "common_logic.h" + +#define LEVEL_STATE_NONE 0 +#define LEVEL_STATE_LEVELS 1 +#define LEVEL_STATE_FLAGS 2 + +AdminCache g_Admins; +char g_ReverseFlags[26]; +AdminFlag g_FlagLetters[26]; +bool g_FlagSet[26]; + +/* Default flags */ +AdminFlag g_DefaultFlags[26] = +{ + Admin_Reservation, Admin_Generic, Admin_Kick, Admin_Ban, Admin_Unban, + Admin_Slay, Admin_Changemap, Admin_Convars, Admin_Config, Admin_Chat, + Admin_Vote, Admin_Password, Admin_RCON, Admin_Cheats, Admin_Custom1, + Admin_Custom2, Admin_Custom3, Admin_Custom4, Admin_Custom5, Admin_Custom6, + Admin_Generic, Admin_Generic, Admin_Generic, Admin_Generic, Admin_Generic, + Admin_Root +}; + + +class FlagReader : public ITextListener_SMC +{ +public: + void LoadLevels() + { + if (!Parse()) + { + memcpy(g_FlagLetters, g_DefaultFlags, sizeof(AdminFlag) * 26); + for (unsigned int i=0; i<20; i++) + { + g_FlagSet[i] = true; + } + g_FlagSet[25] = true; + } + } +private: + bool Parse() + { + SMCStates states; + SMCError error; + + m_bFileNameLogged = false; + g_pSM->BuildPath(Path_SM, m_File, sizeof(m_File), "configs/admin_levels.cfg"); + + if ((error = textparsers->ParseFile_SMC(m_File, this, &states)) + != SMCError_Okay) + { + const char *err_string = textparsers->GetSMCErrorString(error); + if (!err_string) + { + err_string = "Unknown error"; + } + ParseError(NULL, "Error %d (%s)", error, err_string); + return false; + } + + return true; + } + void ReadSMC_ParseStart() + { + m_LevelState = LEVEL_STATE_NONE; + m_IgnoreLevel = 0; + memset(g_FlagSet, 0, sizeof(g_FlagSet)); + } + SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name) + { + if (m_IgnoreLevel) + { + m_IgnoreLevel++; + return SMCResult_Continue; + } + + if (m_LevelState == LEVEL_STATE_NONE) + { + if (strcmp(name, "Levels") == 0) + { + m_LevelState = LEVEL_STATE_LEVELS; + } + else + { + m_IgnoreLevel++; + } + } else if (m_LevelState == LEVEL_STATE_LEVELS) { + if (strcmp(name, "Flags") == 0) + { + m_LevelState = LEVEL_STATE_FLAGS; + } + else + { + m_IgnoreLevel++; + } + } + else + { + m_IgnoreLevel++; + } + + return SMCResult_Continue; + } + SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) + { + if (m_LevelState != LEVEL_STATE_FLAGS || m_IgnoreLevel) + { + return SMCResult_Continue; + } + + unsigned char c = (unsigned)value[0]; + + if (c < (unsigned)'a' || c > (unsigned)'z') + { + ParseError(states, "Flag \"%c\" is not a lower-case ASCII letter", c); + return SMCResult_Continue; + } + + c -= (unsigned)'a'; + + if (!g_Admins.FindFlag(key, &g_FlagLetters[c])) + { + ParseError(states, "Unrecognized admin level \"%s\"", key); + return SMCResult_Continue; + } + + g_FlagSet[c] = true; + + return SMCResult_Continue; + } + SMCResult ReadSMC_LeavingSection(const SMCStates *states) + { + if (m_IgnoreLevel) + { + m_IgnoreLevel--; + return SMCResult_Continue; + } + + if (m_LevelState == LEVEL_STATE_FLAGS) + { + m_LevelState = LEVEL_STATE_LEVELS; + return SMCResult_Halt; + } + else if (m_LevelState == LEVEL_STATE_LEVELS) + { + m_LevelState = LEVEL_STATE_NONE; + } + + return SMCResult_Continue; + } + void ParseError(const SMCStates *states, const char *message, ...) + { + va_list ap; + char buffer[256]; + + va_start(ap, message); + g_pSM->FormatArgs(buffer, sizeof(buffer), message, ap); + va_end(ap); + + if (!m_bFileNameLogged) + { + smcore.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File); + m_bFileNameLogged = true; + } + + smcore.LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer); + } +private: + bool m_bFileNameLogged; + char m_File[PLATFORM_MAX_PATH]; + int m_LevelState; + int m_IgnoreLevel; +} s_FlagReader; + +AdminCache::AdminCache() +{ + m_pStrings = new BaseStringTable(1024); + m_pMemory = m_pStrings->GetMemTable(); + m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID; + m_FreeUserList = m_FirstUser = m_LastUser = INVALID_ADMIN_ID; + m_pCacheFwd = NULL; + m_FirstGroup = -1; + m_InvalidatingAdmins = false; + m_destroying = false; +} + +AdminCache::~AdminCache() +{ + m_destroying = true; + DumpAdminCache(AdminCache_Overrides, false); + DumpAdminCache(AdminCache_Groups, false); + + List::iterator iter; + for (iter=m_AuthMethods.begin(); + iter!=m_AuthMethods.end(); + iter++) + { + delete *iter; + } + + delete m_pStrings; +} + +void AdminCache::OnSourceModStartup(bool late) +{ + RegisterAuthIdentType("steam"); + RegisterAuthIdentType("name"); + RegisterAuthIdentType("ip"); + + NameFlag("reservation", Admin_Reservation); + NameFlag("kick", Admin_Kick); + NameFlag("generic", Admin_Generic); + NameFlag("ban", Admin_Ban); + NameFlag("unban", Admin_Unban); + NameFlag("slay", Admin_Slay); + NameFlag("changemap", Admin_Changemap); + NameFlag("cvars", Admin_Convars); + NameFlag("config", Admin_Config); + NameFlag("chat", Admin_Chat); + NameFlag("vote", Admin_Vote); + NameFlag("password", Admin_Password); + NameFlag("rcon", Admin_RCON); + NameFlag("cheats", Admin_Cheats); + NameFlag("root", Admin_Root); + NameFlag("custom1", Admin_Custom1); + NameFlag("custom2", Admin_Custom2); + NameFlag("custom3", Admin_Custom3); + NameFlag("custom4", Admin_Custom4); + NameFlag("custom5", Admin_Custom5); + NameFlag("custom6", Admin_Custom6); +} + +void AdminCache::OnSourceModAllInitialized() +{ + m_pCacheFwd = forwardsys->CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell); + sharesys->AddInterface(NULL, this); +} + +void AdminCache::OnSourceModLevelChange(const char *mapName) +{ + int i; + AdminFlag flag; + + /* For now, we only read these once per level. */ + s_FlagReader.LoadLevels(); + + memset(g_ReverseFlags, '?', sizeof(g_ReverseFlags)); + + for (i = 0; i < 26; i++) + { + if (FindFlag('a' + i, &flag)) + { + g_ReverseFlags[flag] = 'a' + i; + } + } +} + +void AdminCache::OnSourceModShutdown() +{ + forwardsys->ReleaseForward(m_pCacheFwd); + m_pCacheFwd = NULL; +} + +void AdminCache::OnSourceModPluginsLoaded() +{ + DumpAdminCache(AdminCache_Overrides, true); + DumpAdminCache(AdminCache_Groups, true); +} + +void AdminCache::NameFlag(const char *str, AdminFlag flag) +{ + m_LevelNames.insert(str, flag); +} + +bool AdminCache::FindFlag(const char *str, AdminFlag *pFlag) +{ + return m_LevelNames.retrieve(str, pFlag); +} + +void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags) +{ + FlagMap *map; + if (type == Override_Command) + map = &m_CmdOverrides; + else if (type == Override_CommandGroup) + map = &m_CmdGrpOverrides; + else + return; + + map->insert(cmd, flags); + smcore.UpdateAdminCmdFlags(cmd, type, flags, false); +} + +bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, FlagBits *pFlags) +{ + FlagMap *map; + if (type == Override_Command) + map = &m_CmdOverrides; + else if (type == Override_CommandGroup) + map = &m_CmdGrpOverrides; + else + return false; + + return map->retrieve(cmd, pFlags); +} + +void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type) +{ + if (type == Override_Command) + { + return _UnsetCommandOverride(cmd); + } else if (type == Override_CommandGroup) { + return _UnsetCommandGroupOverride(cmd); + } +} + +void AdminCache::_UnsetCommandGroupOverride(const char *group) +{ + m_CmdGrpOverrides.remove(group); + smcore.UpdateAdminCmdFlags(group, Override_CommandGroup, 0, true); +} + +void AdminCache::_UnsetCommandOverride(const char *cmd) +{ + m_CmdOverrides.remove(cmd); + smcore.UpdateAdminCmdFlags(cmd, Override_Command, 0, true); +} + +void AdminCache::DumpCommandOverrideCache(OverrideType type) +{ + if (type == Override_Command) + m_CmdOverrides.clear(); + else if (type == Override_CommandGroup) + m_CmdGrpOverrides.clear(); +} + +AdminId AdminCache::CreateAdmin(const char *name) +{ + AdminId id; + AdminUser *pUser; + + if (m_FreeUserList != INVALID_ADMIN_ID) + { + pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList); + assert(pUser->magic == USR_MAGIC_UNSET); + id = m_FreeUserList; + m_FreeUserList = pUser->next_user; + } + else + { + id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser); + pUser->grp_size = 0; + pUser->grp_table = -1; + } + + pUser->flags = 0; + pUser->eflags = 0; + pUser->grp_count = 0; + pUser->password = -1; + pUser->magic = USR_MAGIC_SET; + pUser->auth.identidx = -1; + pUser->auth.index = 0; + pUser->immunity_level = 0; + pUser->serialchange = 1; + + if (m_FirstUser == INVALID_ADMIN_ID) + { + m_FirstUser = id; + m_LastUser = id; + } + else + { + AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser); + pPrev->next_user = id; + pUser->prev_user = m_LastUser; + m_LastUser = id; + } + + /* Since we always append to the tail, we should invalidate their next */ + pUser->next_user = -1; + + if (name && name[0] != '\0') + { + int nameidx = m_pStrings->AddString(name); + pUser = (AdminUser *)m_pMemory->GetAddress(id); + pUser->nameidx = nameidx; + } + else + { + pUser->nameidx = -1; + } + + return id; +} + +GroupId AdminCache::AddGroup(const char *group_name) +{ + if (m_Groups.contains(group_name)) + return INVALID_GROUP_ID; + + GroupId id; + AdminGroup *pGroup; + if (m_FreeGroupList != INVALID_GROUP_ID) + { + pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList); + assert(pGroup->magic == GRP_MAGIC_UNSET); + id = m_FreeGroupList; + m_FreeGroupList = pGroup->next_grp; + } else { + id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup); + } + + pGroup->immunity_level = 0; + pGroup->immune_table = -1; + pGroup->magic = GRP_MAGIC_SET; + pGroup->next_grp = INVALID_GROUP_ID; + pGroup->pCmdGrpTable = NULL; + pGroup->pCmdTable = NULL; + pGroup->addflags = 0; + + if (m_FirstGroup == INVALID_GROUP_ID) + { + m_FirstGroup = id; + m_LastGroup = id; + pGroup->prev_grp = INVALID_GROUP_ID; + } else { + AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); + assert(pPrev->magic == GRP_MAGIC_SET); + pPrev->next_grp = id; + pGroup->prev_grp = m_LastGroup; + m_LastGroup = id; + } + + int nameidx = m_pStrings->AddString(group_name); + pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + pGroup->nameidx = nameidx; + + m_Groups.insert(group_name, id); + return id; +} + +GroupId AdminCache::FindGroupByName(const char *group_name) +{ + GroupId id; + if (!m_Groups.retrieve(group_name, &id)) + return INVALID_GROUP_ID; + + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + return INVALID_GROUP_ID; + + return id; +} + +void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL) + { + return; + } + + FlagBits bits = (1<<(FlagBits)flag); + + if (enabled) + { + pGroup->addflags |= bits; + } else { + pGroup->addflags &= ~bits; + } +} + +bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL) + { + return false; + } + + FlagBits bit = 1<<(FlagBits)flag; + return ((pGroup->addflags & bit) == bit); +} + +FlagBits AdminCache::GetGroupAddFlags(GroupId id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return 0; + } + + return pGroup->addflags; +} + +const char *AdminCache::GetGroupName(GroupId gid) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return NULL; + } + + return m_pStrings->GetString(pGroup->nameidx); +} + +void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + unsigned int level = 0; + + if (enabled) + { + if (type == Immunity_Default) + { + level = 1; + } else if (type == Immunity_Global) { + level = 2; + } + if (level > pGroup->immunity_level) + { + pGroup->immunity_level = level; + } + } else { + pGroup->immunity_level = 0; + } +} + +bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + if (type == Immunity_Default && pGroup->immunity_level >= 1) + { + return true; + } else if (type == Immunity_Global && pGroup->immunity_level >= 2) { + return true; + } + + return false; +} + +void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(other_id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + /* We always need to resize the immunity table */ + int *table, tblidx; + if (pGroup->immune_table == -1) + { + tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table); + pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + table[0] = 0; + } else { + int *old_table = (int *)m_pMemory->GetAddress(pGroup->immune_table); + /* Break out if this group is already in the list */ + for (int i=0; iCreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table); + /* Get the old address again in case of resize */ + pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + old_table = (int *)m_pMemory->GetAddress(pGroup->immune_table); + table[0] = old_table[0]; + for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++) + { + table[i] = old_table[i]; + } + } + + /* Assign */ + pGroup->immune_table = tblidx; + + /* Add to the array */ + table[0]++; + table[table[0]] = other_id; +} + +unsigned int AdminCache::GetGroupImmunityCount(GroupId id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return 0; + } + + if (pGroup->immune_table == -1) + { + return 0; + } + + int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); + + return table[0]; +} + +GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return INVALID_GROUP_ID; + } + + if (pGroup->immune_table == -1) + { + return INVALID_GROUP_ID; + } + + int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); + if (number >= (unsigned int)table[0]) + { + return INVALID_GROUP_ID; + } + + return table[1 + number]; +} + +void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + OverrideMap *map; + if (type == Override_Command) + { + if (pGroup->pCmdTable == NULL) + pGroup->pCmdTable = new OverrideMap(); + map = pGroup->pCmdTable; + } else if (type == Override_CommandGroup) { + if (pGroup->pCmdGrpTable == NULL) + pGroup->pCmdGrpTable = new OverrideMap(); + map = pGroup->pCmdGrpTable; + } else { + return; + } + + map->insert(name, rule); +} + +bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + OverrideMap *map; + if (type == Override_Command) + { + if (pGroup->pCmdTable == NULL) + return false; + map = pGroup->pCmdTable; + } else if (type == Override_CommandGroup) { + if (pGroup->pCmdGrpTable == NULL) + return false; + map = pGroup->pCmdGrpTable; + } else { + return false; + } + + return map->retrieve(name, pRule); +} + +AuthMethod *AdminCache::GetMethodByIndex(unsigned int index) +{ + List::iterator iter; + for (iter=m_AuthMethods.begin(); + iter!=m_AuthMethods.end(); + iter++) + { + if (index-- == 0) + { + return *iter; + } + } + + return NULL; +} + +bool AdminCache::InvalidateAdmin(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + AdminUser *pOther; + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + if (!m_InvalidatingAdmins && !m_destroying) + { + playerhelpers->ClearAdminId(id); + } + + /* Unlink from the dbl link list */ + if (id == m_FirstUser && id == m_LastUser) + { + m_FirstUser = INVALID_ADMIN_ID; + m_LastUser = INVALID_ADMIN_ID; + } else if (id == m_FirstUser) { + m_FirstUser = pUser->next_user; + pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser); + pOther->prev_user = INVALID_ADMIN_ID; + } else if (id == m_LastUser) { + m_LastUser = pUser->prev_user; + pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser); + pOther->next_user = INVALID_ADMIN_ID; + } else { + pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user); + pOther->next_user = pUser->next_user; + pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user); + pOther->prev_user = pUser->prev_user; + } + + /* Unlink from auth tables */ + if (pUser->auth.identidx != -1) + { + AuthMethod *method = GetMethodByIndex(pUser->auth.index); + if (method) + method->identities.remove(m_pStrings->GetString(pUser->auth.identidx)); + } + + /* Clear table counts */ + pUser->grp_count = 0; + + /* Link into free list */ + pUser->magic = USR_MAGIC_UNSET; + pUser->next_user = m_FreeUserList; + m_FreeUserList = id; + + /* Unset serial change */ + pUser->serialchange = 0; + + return true; +} + + +void AdminCache::InvalidateGroup(GroupId id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + AdminGroup *pOther; + + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + const char *str = m_pStrings->GetString(pGroup->nameidx); + m_Groups.remove(str); + + /* Unlink from the live dbllink list */ + if (id == m_FirstGroup && id == m_LastGroup) + { + m_LastGroup = INVALID_GROUP_ID; + m_FirstGroup = INVALID_GROUP_ID; + } else if (id == m_FirstGroup) { + m_FirstGroup = pGroup->next_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup); + pOther->prev_grp = INVALID_GROUP_ID; + } else if (id == m_LastGroup) { + m_LastGroup = pGroup->prev_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); + pOther->next_grp = INVALID_GROUP_ID; + } else { + pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp); + pOther->next_grp = pGroup->next_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp); + pOther->prev_grp = pGroup->prev_grp; + } + + /* Free any used memory */ + delete pGroup->pCmdGrpTable; + pGroup->pCmdGrpTable = NULL; + delete pGroup->pCmdTable; + pGroup->pCmdTable = NULL; + + /* Link into the free list */ + pGroup->magic = GRP_MAGIC_UNSET; + pGroup->next_grp = m_FreeGroupList; + m_FreeGroupList = id; + + int idx = m_FirstUser; + AdminUser *pUser; + int *table; + while (idx != INVALID_ADMIN_ID) + { + pUser = (AdminUser *)m_pMemory->GetAddress(idx); + if (pUser->grp_count > 0) + { + table = (int *)m_pMemory->GetAddress(pUser->grp_table); + for (unsigned int i=0; igrp_count; i++) + { + if (table[i] == id) + { + /* We have to remove this entry */ + for (unsigned int j=i+1; jgrp_count; j++) + { + /* Move everything down by one */ + table[j-1] = table[j]; + } + /* Decrease count */ + pUser->grp_count--; + /* Recalculate effective flags */ + pUser->eflags = pUser->flags; + for (unsigned int j=0; jgrp_count; j++) + { + pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]); + pUser->eflags |= pOther->addflags; + } + /* Mark as changed */ + pUser->serialchange++; + /* Break now, duplicates aren't allowed */ + break; + } + } + } + idx = pUser->next_user; + } +} + +void AdminCache::InvalidateGroupCache() +{ + /* Nuke the free list */ + m_FreeGroupList = -1; + + /* Nuke reverse lookups */ + m_Groups.clear(); + + /* Free memory on groups */ + GroupId cur = m_FirstGroup; + AdminGroup *pGroup; + while (cur != INVALID_GROUP_ID) + { + pGroup = (AdminGroup *)m_pMemory->GetAddress(cur); + assert(pGroup->magic == GRP_MAGIC_SET); + delete pGroup->pCmdGrpTable; + delete pGroup->pCmdTable; + cur = pGroup->next_grp; + } + + m_FirstGroup = INVALID_GROUP_ID; + m_LastGroup = INVALID_GROUP_ID; + + InvalidateAdminCache(false); + + /* Reset the memory table */ + m_pMemory->Reset(); +} + +void AdminCache::AddAdminListener(IAdminListener *pListener) +{ + m_hooks.push_back(pListener); +} + +void AdminCache::RemoveAdminListener(IAdminListener *pListener) +{ + m_hooks.remove(pListener); +} + +void AdminCache::RegisterAuthIdentType(const char *name) +{ + if (m_AuthTables.contains(name)) + return; + + AuthMethod *method = new AuthMethod(name); + m_AuthMethods.push_back(method); + m_AuthTables.insert(name, method); +} + +void AdminCache::InvalidateAdminCache(bool unlink_admins) +{ + m_InvalidatingAdmins = true; + if (!m_destroying) + { + int maxClients = playerhelpers->GetMaxClients(); + for (int i = 1; i <= maxClients; ++i) + { + playerhelpers->GetGamePlayer(i)->ClearAdmin(); + } + } + /* Wipe the identity cache first */ + List::iterator iter; + for (iter=m_AuthMethods.begin(); + iter!=m_AuthMethods.end(); + iter++) + { + (*iter)->identities.clear(); + } + + if (unlink_admins) + { + while (m_FirstUser != INVALID_ADMIN_ID) + { + InvalidateAdmin(m_FirstUser); + } + } else { + m_FirstUser = -1; + m_LastUser = -1; + m_FreeUserList = -1; + } + m_InvalidatingAdmins = false; +} + +void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild) +{ + List::iterator iter; + IAdminListener *pListener; + cell_t result; + + if (part == AdminCache_Overrides) + { + DumpCommandOverrideCache(Override_Command); + DumpCommandOverrideCache(Override_CommandGroup); + if (rebuild && !m_destroying) + { + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + pListener->OnRebuildOverrideCache(); + } + m_pCacheFwd->PushCell(part); + m_pCacheFwd->Execute(&result); + } + } else if (part == AdminCache_Groups || part == AdminCache_Admins) { + if (part == AdminCache_Groups) + { + InvalidateGroupCache(); + if (rebuild && !m_destroying) + { + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + pListener->OnRebuildGroupCache(); + } + m_pCacheFwd->PushCell(part); + m_pCacheFwd->Execute(&result); + } + } + InvalidateAdminCache(true); + if (rebuild && !m_destroying) + { + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + pListener->OnRebuildAdminCache((part == AdminCache_Groups)); + } + m_pCacheFwd->PushCell(AdminCache_Admins); + m_pCacheFwd->Execute(&result); + playerhelpers->RecheckAnyAdmins(); + } + } +} + +const char *AdminCache::GetAdminName(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return NULL; + } + + return m_pStrings->GetString(pUser->nameidx); +} + +bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index) +{ + List::iterator iter; + unsigned int index = 0; + for (iter=m_AuthMethods.begin(); + iter!=m_AuthMethods.end(); + iter++,index++) + { + if ((*iter)->name.compare(name) == 0) + { + *_index = index; + return true; + } + } + + return false; +} + +bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident) +{ + if (ident[0] == '\0') + { + return false; + } + + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + AuthMethod *method; + if (!m_AuthTables.retrieve(auth, &method)) + return false; + + /* If the id was a steam id strip off the STEAM_*: part */ + if (strcmp(auth, "steam") == 0 && strncmp(ident, "STEAM_", 6) == 0) + { + ident += 8; + } + + if (method->identities.contains(ident)) + return false; + + int i_ident = m_pStrings->AddString(ident); + + pUser = (AdminUser *)m_pMemory->GetAddress(id); + pUser->auth.identidx = i_ident; + GetMethodIndex(auth, &pUser->auth.index); + + return method->identities.insert(ident, id); +} + +AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity) +{ + AuthMethod *method; + if (!m_AuthTables.retrieve(auth, &method)) + return INVALID_ADMIN_ID; + + /* If the id was a steam id strip off the STEAM_*: part */ + if (strcmp(auth, "steam") == 0 && strncmp(identity, "STEAM_", 6) == 0) + { + identity += 8; + } + + AdminId id; + if (!method->identities.retrieve(identity, &id)) + return INVALID_ADMIN_ID; + return id; +} + +void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return; + } + + if (flag < Admin_Reservation + || flag >= AdminFlags_TOTAL) + { + return; + } + + FlagBits bits = (1<<(FlagBits)flag); + + if (enabled) + { + pUser->flags |= bits; + pUser->eflags |= bits; + } else { + pUser->flags &= ~bits; + pUser->eflags &= ~bits; + } + + pUser->serialchange++; +} + +bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + if (flag < Admin_Reservation + || flag >= AdminFlags_TOTAL) + { + return false; + } + + FlagBits bit = (1<<(FlagBits)flag); + + if (mode == Access_Real) + { + return ((pUser->flags & bit) == bit); + } else if (mode == Access_Effective) { + bool has_bit = ((pUser->eflags & bit) == bit); + if (!has_bit && flag != Admin_Root && ((pUser->eflags & ADMFLAG_ROOT) == ADMFLAG_ROOT)) + { + has_bit = true; + } + return has_bit; + } + + return false; +} + +FlagBits AdminCache::GetAdminFlags(AdminId id, AccessMode mode) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return 0; + } + + if (mode == Access_Real) + { + return pUser->flags; + } else if (mode == Access_Effective) { + return pUser->eflags; + } + + return 0; +} + +void AdminCache::SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return; + } + + if (mode == Access_Real) + { + pUser->flags = bits; + pUser->eflags = bits; + } else if (mode == Access_Effective) { + pUser->eflags = bits; + } + + pUser->serialchange++; +} + +bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + /* First check for duplicates */ + if (pUser->grp_count != 0) + { + int *temp_table = (int *)m_pMemory->GetAddress(pUser->grp_table); + for (unsigned int i=0; igrp_count; i++) + { + if (temp_table[i] == gid) + { + return false; + } + } + } + + int *table; + if (pUser->grp_count + 1 > pUser->grp_size) + { + int new_size = 0; + int tblidx; + + if (pUser->grp_size == 0) + { + new_size = 2; + } else { + new_size = pUser->grp_size * 2; + } + + /* Create and refresh pointers */ + tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table); + pUser = (AdminUser *)m_pMemory->GetAddress(id); + pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + + /* Copy old data if necessary */ + if (pUser->grp_table != -1) + { + int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table); + memcpy(table, old_table, sizeof(int) * pUser->grp_count); + } + pUser->grp_table = tblidx; + pUser->grp_size = new_size; + } else { + table = (int *)m_pMemory->GetAddress(pUser->grp_table); + } + + table[pUser->grp_count] = gid; + pUser->grp_count++; + + /* Compute new effective permissions */ + pUser->eflags |= pGroup->addflags; + + if (pGroup->immunity_level > pUser->immunity_level) + { + pUser->immunity_level = pGroup->immunity_level; + } + + pUser->serialchange++; + + return true; +} + +bool AdminCache::IsValidAdmin(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + return (pUser != NULL && pUser->magic == USR_MAGIC_SET); +} + +unsigned int AdminCache::GetAdminGroupCount(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return 0; + } + + return pUser->grp_count; +} + +GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count) + { + return INVALID_GROUP_ID; + } + + int *table = (int *)m_pMemory->GetAddress(pUser->grp_table); + + GroupId gid = table[index]; + + if (name) + { + *name = GetGroupName(gid); + } + + return gid; +} + +const char *AdminCache::GetAdminPassword(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return NULL; + } + + return m_pStrings->GetString(pUser->password); +} + +void AdminCache::SetAdminPassword(AdminId id, const char *password) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return; + } + + if (password[0] == '\0') + { + pUser->password = -1; + return; + } + + int i_password = m_pStrings->AddString(password); + pUser = (AdminUser *)m_pMemory->GetAddress(id); + pUser->password = i_password; +} + +unsigned int AdminCache::FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize) +{ + unsigned int i; + for (i=0; iGetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + return ((pUser->eflags & bits) == bits); +} + +bool AdminCache::CanAdminTarget(AdminId id, AdminId target) +{ + /** + * Zeroth, if the targeting AdminId is INVALID_ADMIN_ID, targeting fails. + * First, if the targeted AdminId is INVALID_ADMIN_ID, targeting succeeds. + */ + + if (id == INVALID_ADMIN_ID) + { + return false; + } + + if (target == INVALID_ADMIN_ID) + { + return true; + } + + if (id == target) + { + return true; + } + + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + AdminUser *pTarget = (AdminUser *)m_pMemory->GetAddress(target); + if (!pTarget || pTarget->magic != USR_MAGIC_SET) + { + return false; + } + + /** + * Second, if the targeting admin is root, targeting succeeds. + */ + if (pUser->eflags & ADMFLAG_ROOT) + { + return true; + } + + /** Fourth, if the targeted admin is immune from targeting admin. */ + int mode = smcore.GetImmunityMode(); + switch (mode) + { + case 1: + { + if (pTarget->immunity_level > pUser->immunity_level) + { + return false; + } + break; + } + case 3: + { + /* If neither has any immunity, let this pass. */ + if (!pUser->immunity_level && !pTarget->immunity_level) + { + return true; + } + /* Don't break, go to the next case. */ + } + case 2: + { + if (pTarget->immunity_level >= pUser->immunity_level) + { + return false; + } + break; + } + } + + /** + * Fifth, if the targeted admin has specific immunity from the + * targeting admin via group immunities, targeting fails. + */ + //:TODO: speed this up... maybe with trie hacks. + //idea is to insert %d.%d in the trie after computing this and use it as a cache lookup. + //problem is the trie cannot delete prefixes, so we'd have a problem with invalidations. + if (pTarget->grp_count > 0 && pUser->grp_count > 0) + { + int *grp_table = (int *)m_pMemory->GetAddress(pTarget->grp_table); + int *src_table = (int *)m_pMemory->GetAddress(pUser->grp_table); + GroupId id, other; + unsigned int num; + for (unsigned int i=0; igrp_count; i++) + { + id = grp_table[i]; + num = GetGroupImmunityCount(id); + for (unsigned int j=0; jgrp_count; k++) + { + if (other == src_table[k]) + { + return false; + } + } + } + } + } + + return true; +} + +bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag) +{ + if (c < 'a' + || c > 'z' + || !g_FlagSet[(unsigned)c - (unsigned)'a']) + { + return false; + } + + if (pAdmFlag) + { + *pAdmFlag = g_FlagLetters[(unsigned)c - (unsigned)'a']; + } + + return true; +} + +bool AdminCache::FindFlagChar(AdminFlag flag, char *c) +{ + if (!g_FlagSet[flag]) + { + return false; + } + + if (c) + { + *c = g_ReverseFlags[flag]; + } + + return true; +} + +FlagBits AdminCache::ReadFlagString(const char *flags, const char **end) +{ + FlagBits bits = 0; + + while (flags && (*flags != '\0')) + { + AdminFlag flag; + if (!FindFlag(*flags, &flag)) + { + break; + } + bits |= FlagArrayToBits(&flag, 1); + flags++; + } + + if (end) + { + *end = flags; + } + + return bits; +} + +unsigned int AdminCache::GetAdminSerialChange(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return 0; + } + + return pUser->serialchange; +} + +bool AdminCache::CanAdminUseCommand(int client, const char *cmd) +{ + FlagBits bits; + OverrideType otype = Override_Command; + + if (cmd[0] == '@') + { + otype = Override_CommandGroup; + cmd++; + } + + if (!smcore.LookForCommandAdminFlags(cmd, &bits)) + { + if (!GetCommandOverride(cmd, otype, &bits)) + { + bits = 0; + } + } + + return CheckClientCommandAccess(client, cmd, bits); +} + +unsigned int AdminCache::SetGroupImmunityLevel(GroupId gid, unsigned int level) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return 0; + } + + unsigned int old_level = pGroup->immunity_level; + + pGroup->immunity_level = level; + + return old_level; +} + +unsigned int AdminCache::GetGroupImmunityLevel(GroupId gid) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return 0; + } + + return pGroup->immunity_level; +} + +unsigned int AdminCache::SetAdminImmunityLevel(AdminId id, unsigned int level) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return 0; + } + + unsigned int old_level = pUser->immunity_level; + + pUser->immunity_level = level; + + return old_level; +} + +unsigned int AdminCache::GetAdminImmunityLevel(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return 0; + } + + return pUser->immunity_level; +} + +bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool override_only) +{ + if (client == 0) + { + return true; + } + + /* Auto-detect a command if we can */ + FlagBits bits = flags; + bool found_command = false; + if (!override_only) + { + found_command = smcore.LookForCommandAdminFlags(cmd, &bits); + } + + if (!found_command) + { + GetCommandOverride(cmd, Override_Command, &bits); + } + + return CheckClientCommandAccess(client, cmd, bits) ? 1 : 0; +} + +void iterator_glob_basic_override(FILE *fp, const char *key, FlagBits flags) +{ + char flagstr[64]; + g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr)); + fprintf(fp, "\t\"%s\"\t\t\"%s\"\n", key, flagstr); +} + +void iterator_glob_grp_override(FILE *fp, const char *key, FlagBits flags) +{ + char flagstr[64]; + g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr)); + fprintf(fp, "\t\"@%s\"\t\t\"%s\"\n", key, flagstr); +} + +void iterator_group_basic_override(FILE *fp, const char *key, OverrideRule rule) +{ + const char *str = (rule == Command_Allow) ? "allow" : "deny"; + fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n", key, str); +} + +void iterator_group_grp_override(FILE *fp, const char *key, OverrideRule rule) +{ + const char *str = (rule == Command_Allow) ? "allow" : "deny"; + fprintf(fp, "\t\t\t\"@%s\"\t\t\"%s\"\n", key, str); +} + +void AdminCache::DumpCache(FILE *fp) +{ + int *itable; + AdminId aid; + GroupId gid; + char flagstr[64]; + unsigned int num; + AdminUser *pAdmin; + AdminGroup *pGroup; + + fprintf(fp, "\"Groups\"\n{\n"); + + num = 0; + gid = m_FirstGroup; + while (gid != INVALID_GROUP_ID + && (pGroup = GetGroup(gid)) != NULL) + { + num++; + FillFlagString(pGroup->addflags, flagstr, sizeof(flagstr)); + + fprintf(fp, "\t/* num = %d, gid = 0x%X */\n", num, gid); + fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pGroup->nameidx)); + fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr); + fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pGroup->immunity_level); + + if (pGroup->immune_table != -1 + && (itable = (int *)m_pMemory->GetAddress(pGroup->immune_table)) != NULL) + { + AdminGroup *pAltGroup; + const char *gname, *mod; + + for (int i = 1; i <= itable[0]; i++) + { + if ((pAltGroup = GetGroup(itable[i])) == NULL) + { + /* Assume the rest of the table is corrupt */ + break; + } + gname = GetString(pAltGroup->nameidx); + if (atoi(gname) != 0) + { + mod = "@"; + } + else + { + mod = ""; + } + fprintf(fp, "\t\t\"immunity\"\t\t\"%s%s\"\n", mod, gname); + } + } + + fprintf(fp, "\n\t\t\"Overrides\"\n\t\t{\n"); + if (pGroup->pCmdGrpTable != NULL) + { + for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next()) + iterator_group_grp_override(fp, iter->key.chars(), iter->value); + } + if (pGroup->pCmdTable != NULL) + { + for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next()) + iterator_group_basic_override(fp, iter->key.chars(), iter->value); + } + fprintf(fp, "\t\t}\n"); + + fprintf(fp, "\t}\n"); + + if ((gid = pGroup->next_grp) != INVALID_GROUP_ID) + { + fprintf(fp, "\n"); + } + } + + fprintf(fp, "}\n\n"); + fprintf(fp, "\"Admins\"\n{\n"); + + num = 0; + aid = m_FirstUser; + while (aid != INVALID_ADMIN_ID + && (pAdmin = GetUser(aid)) != NULL) + { + num++; + FillFlagString(pAdmin->flags, flagstr, sizeof(flagstr)); + + fprintf(fp, "\t/* num = %d, aid = 0x%X, serialno = 0x%X*/\n", num, aid, pAdmin->serialchange); + + if (pAdmin->nameidx != -1) + { + fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pAdmin->nameidx)); + } + else + { + fprintf(fp, "\t\"\"\n\t{\n"); + } + + if (pAdmin->auth.identidx != -1) + { + fprintf(fp, "\t\t\"auth\"\t\t\t\"%s\"\n", GetMethodName(pAdmin->auth.index)); + fprintf(fp, "\t\t\"identity\"\t\t\"%s\"\n", GetString(pAdmin->auth.identidx)); + } + if (pAdmin->password != -1) + { + fprintf(fp, "\t\t\"password\"\t\t\"%s\"\n", GetString(pAdmin->password)); + } + fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr); + fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pAdmin->immunity_level); + + if (pAdmin->grp_count != 0 + && pAdmin->grp_table != -1 + && (itable = (int *)m_pMemory->GetAddress(pAdmin->grp_table)) != NULL) + { + unsigned int i; + + for (i = 0; i < pAdmin->grp_count; i++) + { + if ((pGroup = GetGroup(itable[i])) == NULL) + { + /* Assume the rest of the table is corrupt */ + break; + } + fprintf(fp, "\t\t\"group\"\t\t\t\"%s\"\n", GetString(pGroup->nameidx)); + } + } + + fprintf(fp, "\t}\n"); + + if ((aid = pAdmin->next_user) != INVALID_ADMIN_ID) + { + fprintf(fp, "\n"); + } + } + + fprintf(fp, "}\n\n"); + + fprintf(fp, "\"Overrides\"\n{\n"); + for (FlagMap::iterator iter = m_CmdGrpOverrides.iter(); !iter.empty(); iter.next()) + iterator_glob_grp_override(fp, iter->key.chars(), iter->value); + for (FlagMap::iterator iter = m_CmdOverrides.iter(); !iter.empty(); iter.next()) + iterator_glob_basic_override(fp, iter->key.chars(), iter->value); + fprintf(fp, "}\n"); +} + +AdminGroup *AdminCache::GetGroup(GroupId gid) +{ + AdminGroup *pGroup; + + pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return NULL; + } + + return pGroup; +} + +AdminUser *AdminCache::GetUser(AdminId aid) +{ + AdminUser *pAdmin; + + pAdmin = (AdminUser *)m_pMemory->GetAddress(aid); + if (!pAdmin || pAdmin->magic != USR_MAGIC_SET) + { + return NULL; + } + + return pAdmin; +} + +const char *AdminCache::GetMethodName(unsigned int index) +{ + List::iterator iter; + for (iter=m_AuthMethods.begin(); + iter!=m_AuthMethods.end(); + iter++) + { + if (index-- == 0) + { + return (*iter)->name.c_str(); + } + } + + return NULL; +} + +const char *AdminCache::GetString(int idx) +{ + return m_pStrings->GetString(idx); +} + +size_t AdminCache::FillFlagString(FlagBits bits, char *buffer, size_t maxlen) +{ + size_t pos; + unsigned int i, num_flags; + AdminFlag flags[AdminFlags_TOTAL]; + + num_flags = FlagBitsToArray(bits, flags, AdminFlags_TOTAL); + + pos = 0; + for (i = 0; pos < maxlen && i < num_flags; i++) + { + if (FindFlagChar(flags[i], &buffer[pos])) + { + pos++; + } + } + buffer[pos] = '\0'; + + return pos; +} + +bool AdminCache::CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags) +{ + if (cmdflags == 0 || client == 0) + { + return true; + } + + /* If running listen server, then client 1 is the server host and should have 'root' access */ + if (client == 1 && !engine->IsDedicatedServer()) + { + return true; + } + + IGamePlayer *player = playerhelpers->GetGamePlayer(client); + if (!player + || player->GetEdict() == NULL + || player->IsFakeClient()) + { + return false; + } + + return CheckAdminCommandAccess(player->GetAdminId(), cmd, cmdflags); +} + +bool AdminCache::CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits cmdflags) +{ + if (adm != INVALID_ADMIN_ID) + { + FlagBits bits = GetAdminFlags(adm, Access_Effective); + + /* root knows all, WHOA */ + if ((bits & ADMFLAG_ROOT) == ADMFLAG_ROOT) + { + return true; + } + + /* Check for overrides + * :TODO: is it worth optimizing this? + */ + unsigned int groups = GetAdminGroupCount(adm); + GroupId gid; + OverrideRule rule; + bool override = false; + for (unsigned int i = 0; i. - * - * 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$ - */ - -#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_ -#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_ - -#include "sm_memtable.h" -#include -#include -#include -#include -#include "sm_globals.h" -#include -#include -#include - -using namespace SourceHook; - -#define GRP_MAGIC_SET 0xDEADFADE -#define GRP_MAGIC_UNSET 0xFACEFACE -#define USR_MAGIC_SET 0xDEADFACE -#define USR_MAGIC_UNSET 0xFADEDEAD - -typedef StringHashMap OverrideMap; - -struct AdminGroup -{ - uint32_t magic; /* Magic flag, for memory validation (ugh) */ - unsigned int immunity_level; /* Immunity level */ - /* Immune from target table (-1 = nonexistent) - * [0] = number of entries - * [1...N] = immune targets - */ - int immune_table; - OverrideMap *pCmdTable; /* Command override table (can be NULL) */ - OverrideMap *pCmdGrpTable; /* Command group override table (can be NULL) */ - int next_grp; /* Next group in the chain */ - int prev_grp; /* Previous group in the chain */ - int nameidx; /* Name */ - FlagBits addflags; /* Additive flags */ -}; - -struct AuthMethod -{ - String name; - StringHashMap identities; - - AuthMethod(const char *name) - : name(name) - { - } - - static inline bool matches(const char *name, const AuthMethod *method) - { - return strcmp(name, method->name.c_str()) == 0; - } -}; - -struct UserAuth -{ - unsigned int index; /* Index into auth table */ - int identidx; /* Index into the string table */ -}; - -struct AdminUser -{ - uint32_t magic; /* Magic flag, for memory validation */ - FlagBits flags; /* Flags */ - FlagBits eflags; /* Effective flags */ - int nameidx; /* Name index */ - int password; /* Password index */ - unsigned int grp_count; /* Number of groups */ - unsigned int grp_size; /* Size of groups table */ - int grp_table; /* Group table itself */ - int next_user; /* Next user in the list */ - int prev_user; /* Previous user in the list */ - UserAuth auth; /* Auth method for this user */ - unsigned int immunity_level; /* Immunity level */ - unsigned int serialchange; /* Serial # for changes */ -}; - -class AdminCache : - public IAdminSystem, - public SMGlobalClass -{ -public: - AdminCache(); - ~AdminCache(); -public: //SMGlobalClass - void OnSourceModStartup(bool late); - void OnSourceModAllInitialized(); - void OnSourceModLevelChange(const char *mapName); - void OnSourceModShutdown(); - void OnSourceModPluginsLoaded(); -public: //IAdminSystem - /** Command cache stuff */ - void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags); - bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags); - void UnsetCommandOverride(const char *cmd, OverrideType type); - /** Group cache stuff */ - GroupId AddGroup(const char *group_name); - GroupId FindGroupByName(const char *group_name); - void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled); - bool GetGroupAddFlag(GroupId id, AdminFlag flag); - FlagBits GetGroupAddFlags(GroupId id); - void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled); - bool GetGroupGenericImmunity(GroupId id, ImmunityType type); - void InvalidateGroup(GroupId id); - void AddGroupImmunity(GroupId id, GroupId other_id); - unsigned int GetGroupImmunityCount(GroupId id); - GroupId GetGroupImmunity(GroupId id, unsigned int number); - void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule); - bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule); - void DumpAdminCache(AdminCachePart part, bool rebuild); - void AddAdminListener(IAdminListener *pListener); - void RemoveAdminListener(IAdminListener *pListener); - /** User stuff */ - void RegisterAuthIdentType(const char *name); - AdminId CreateAdmin(const char *name); - const char *GetAdminName(AdminId id); - bool BindAdminIdentity(AdminId id, const char *auth, const char *ident); - virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled); - bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode); - FlagBits GetAdminFlags(AdminId id, AccessMode mode); - bool AdminInheritGroup(AdminId id, GroupId gid); - unsigned int GetAdminGroupCount(AdminId id); - GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name); - void SetAdminPassword(AdminId id, const char *password); - const char *GetAdminPassword(AdminId id); - AdminId FindAdminByIdentity(const char *auth, const char *identity); - bool InvalidateAdmin(AdminId id); - unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize); - FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize); - FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags); - unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize); - bool CheckAdminFlags(AdminId id, FlagBits bits); - bool CanAdminTarget(AdminId id, AdminId target); - void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits); - bool FindFlag(const char *str, AdminFlag *pFlag); - bool FindFlag(char c, AdminFlag *pAdmFlag); - FlagBits ReadFlagString(const char *flags, const char **end); - size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen); - unsigned int GetAdminSerialChange(AdminId id); - bool CanAdminUseCommand(int client, const char *cmd); - const char *GetGroupName(GroupId gid); - unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level); - unsigned int GetGroupImmunityLevel(GroupId gid); - unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level); - unsigned int GetAdminImmunityLevel(AdminId id); - bool CheckAccess(int client, - const char *cmd, - FlagBits flags, - bool override_only); - bool FindFlagChar(AdminFlag flag, char *c); - bool IsValidAdmin(AdminId id); -public: - void DumpCache(FILE *fp); - AdminGroup *GetGroup(GroupId gid); - AdminUser *GetUser(AdminId id); - const char *GetString(int idx); -private: - void _UnsetCommandOverride(const char *cmd); - void _UnsetCommandGroupOverride(const char *group); - void InvalidateGroupCache(); - void InvalidateAdminCache(bool unlink_admins); - void DumpCommandOverrideCache(OverrideType type); - AuthMethod *GetMethodByIndex(unsigned int index); - bool GetMethodIndex(const char *name, unsigned int *_index); - const char *GetMethodName(unsigned int index); - void NameFlag(const char *str, AdminFlag flag); -public: - typedef StringHashMap FlagMap; - - BaseStringTable *m_pStrings; - BaseMemTable *m_pMemory; - FlagMap m_CmdOverrides; - FlagMap m_CmdGrpOverrides; - int m_FirstGroup; - int m_LastGroup; - int m_FreeGroupList; - StringHashMap m_Groups; - List m_hooks; - List m_AuthMethods; - NameHashSet m_AuthTables; - IForward *m_pCacheFwd; - int m_FirstUser; - int m_LastUser; - int m_FreeUserList; - bool m_InvalidatingAdmins; - bool m_destroying; - StringHashMap m_LevelNames; -}; - -extern AdminCache g_Admins; - -#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 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$ + */ + +#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_ +#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_ + +#include "common_logic.h" +#include +#include "sm_memtable.h" +#include +#include +#include +#include +#include +#include + +using namespace SourceHook; + +#define GRP_MAGIC_SET 0xDEADFADE +#define GRP_MAGIC_UNSET 0xFACEFACE +#define USR_MAGIC_SET 0xDEADFACE +#define USR_MAGIC_UNSET 0xFADEDEAD + +typedef StringHashMap OverrideMap; + +struct AdminGroup +{ + uint32_t magic; /* Magic flag, for memory validation (ugh) */ + unsigned int immunity_level; /* Immunity level */ + /* Immune from target table (-1 = nonexistent) + * [0] = number of entries + * [1...N] = immune targets + */ + int immune_table; + OverrideMap *pCmdTable; /* Command override table (can be NULL) */ + OverrideMap *pCmdGrpTable; /* Command group override table (can be NULL) */ + int next_grp; /* Next group in the chain */ + int prev_grp; /* Previous group in the chain */ + int nameidx; /* Name */ + FlagBits addflags; /* Additive flags */ +}; + +struct AuthMethod +{ + String name; + StringHashMap identities; + + AuthMethod(const char *name) + : name(name) + { + } + + static inline bool matches(const char *name, const AuthMethod *method) + { + return strcmp(name, method->name.c_str()) == 0; + } +}; + +struct UserAuth +{ + unsigned int index; /* Index into auth table */ + int identidx; /* Index into the string table */ +}; + +struct AdminUser +{ + uint32_t magic; /* Magic flag, for memory validation */ + FlagBits flags; /* Flags */ + FlagBits eflags; /* Effective flags */ + int nameidx; /* Name index */ + int password; /* Password index */ + unsigned int grp_count; /* Number of groups */ + unsigned int grp_size; /* Size of groups table */ + int grp_table; /* Group table itself */ + int next_user; /* Next user in the list */ + int prev_user; /* Previous user in the list */ + UserAuth auth; /* Auth method for this user */ + unsigned int immunity_level; /* Immunity level */ + unsigned int serialchange; /* Serial # for changes */ +}; + +class AdminCache : + public IAdminSystem, + public SMGlobalClass +{ +public: + AdminCache(); + ~AdminCache(); +public: //SMGlobalClass + void OnSourceModStartup(bool late); + void OnSourceModAllInitialized(); + void OnSourceModLevelChange(const char *mapName); + void OnSourceModShutdown(); + void OnSourceModPluginsLoaded(); +public: //IAdminSystem + /** Command cache stuff */ + void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags); + bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags); + void UnsetCommandOverride(const char *cmd, OverrideType type); + /** Group cache stuff */ + GroupId AddGroup(const char *group_name); + GroupId FindGroupByName(const char *group_name); + void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled); + bool GetGroupAddFlag(GroupId id, AdminFlag flag); + FlagBits GetGroupAddFlags(GroupId id); + void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled); + bool GetGroupGenericImmunity(GroupId id, ImmunityType type); + void InvalidateGroup(GroupId id); + void AddGroupImmunity(GroupId id, GroupId other_id); + unsigned int GetGroupImmunityCount(GroupId id); + GroupId GetGroupImmunity(GroupId id, unsigned int number); + void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule); + bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule); + void DumpAdminCache(AdminCachePart part, bool rebuild); + void AddAdminListener(IAdminListener *pListener); + void RemoveAdminListener(IAdminListener *pListener); + /** User stuff */ + void RegisterAuthIdentType(const char *name); + AdminId CreateAdmin(const char *name); + const char *GetAdminName(AdminId id); + bool BindAdminIdentity(AdminId id, const char *auth, const char *ident); + virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled); + bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode); + FlagBits GetAdminFlags(AdminId id, AccessMode mode); + bool AdminInheritGroup(AdminId id, GroupId gid); + unsigned int GetAdminGroupCount(AdminId id); + GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name); + void SetAdminPassword(AdminId id, const char *password); + const char *GetAdminPassword(AdminId id); + AdminId FindAdminByIdentity(const char *auth, const char *identity); + bool InvalidateAdmin(AdminId id); + unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize); + FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize); + FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags); + unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize); + bool CheckAdminFlags(AdminId id, FlagBits bits); + bool CanAdminTarget(AdminId id, AdminId target); + void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits); + bool FindFlag(const char *str, AdminFlag *pFlag); + bool FindFlag(char c, AdminFlag *pAdmFlag); + FlagBits ReadFlagString(const char *flags, const char **end); + size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen); + unsigned int GetAdminSerialChange(AdminId id); + bool CanAdminUseCommand(int client, const char *cmd); + const char *GetGroupName(GroupId gid); + unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level); + unsigned int GetGroupImmunityLevel(GroupId gid); + unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level); + unsigned int GetAdminImmunityLevel(AdminId id); + bool CheckAccess(int client, + const char *cmd, + FlagBits flags, + bool override_only); + bool FindFlagChar(AdminFlag flag, char *c); + bool IsValidAdmin(AdminId id); + bool CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags); +public: + void DumpCache(FILE *fp); + AdminGroup *GetGroup(GroupId gid); + AdminUser *GetUser(AdminId id); + const char *GetString(int idx); + bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags); +private: + void _UnsetCommandOverride(const char *cmd); + void _UnsetCommandGroupOverride(const char *group); + void InvalidateGroupCache(); + void InvalidateAdminCache(bool unlink_admins); + void DumpCommandOverrideCache(OverrideType type); + AuthMethod *GetMethodByIndex(unsigned int index); + bool GetMethodIndex(const char *name, unsigned int *_index); + const char *GetMethodName(unsigned int index); + void NameFlag(const char *str, AdminFlag flag); +public: + typedef StringHashMap FlagMap; + + BaseStringTable *m_pStrings; + BaseMemTable *m_pMemory; + FlagMap m_CmdOverrides; + FlagMap m_CmdGrpOverrides; + int m_FirstGroup; + int m_LastGroup; + int m_FreeGroupList; + StringHashMap m_Groups; + List m_hooks; + List m_AuthMethods; + NameHashSet m_AuthTables; + IForward *m_pCacheFwd; + int m_FirstUser; + int m_LastUser; + int m_FreeUserList; + bool m_InvalidatingAdmins; + bool m_destroying; + StringHashMap m_LevelNames; +}; + +extern AdminCache g_Admins; + +#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_ diff --git a/core/logic/common_logic.cpp b/core/logic/common_logic.cpp index effed0ed..32816078 100644 --- a/core/logic/common_logic.cpp +++ b/core/logic/common_logic.cpp @@ -49,6 +49,7 @@ #include "HandleSys.h" #include "ExtensionSys.h" #include "ForwardSys.h" +#include "AdminCache.h" sm_core_t smcore; IHandleSys *handlesys = &g_HandleSys; @@ -65,7 +66,7 @@ IForwardManager *forwardsys = &g_Forwards; ITimerSystem *timersys; ServerGlobals serverGlobals; IPlayerManager *playerhelpers; -IAdminSystem *adminsys; +IAdminSystem *adminsys = &g_Admins; IGameHelpers *gamehelpers; ISourcePawnEngine *g_pSourcePawn; ISourcePawnEngine2 *g_pSourcePawn2; @@ -103,6 +104,11 @@ static void DumpHandles(void (*dumpfn)(const char *fmt, ...)) g_HandleSys.Dump(dumpfn); } +static void DumpAdminCache(FILE *f) +{ + g_Admins.DumpCache(f); +} + static sm_logic_t logic = { NULL, @@ -121,11 +127,13 @@ static sm_logic_t logic = GenerateError, AddNatives, DumpHandles, + DumpAdminCache, &g_PluginSys, &g_ShareSys, &g_Extensions, &g_HandleSys, &g_Forwards, + &g_Admins, NULL, -1.0f }; @@ -144,7 +152,6 @@ static void logic_init(const sm_core_t* core, sm_logic_t* _logic) rootmenu = core->rootmenu; timersys = core->timersys; playerhelpers = core->playerhelpers; - adminsys = core->adminsys; gamehelpers = core->gamehelpers; g_pSourcePawn = *core->spe1; g_pSourcePawn2 = *core->spe2; diff --git a/core/logic/intercom.h b/core/logic/intercom.h index e5a10509..9800a3a7 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -42,6 +42,7 @@ #include #include #include +#include using namespace SourceMod; using namespace SourcePawn; @@ -51,7 +52,7 @@ using namespace SourceHook; * Add 1 to the RHS of this expression to bump the intercom file * This is to prevent mismatching core/logic binaries */ -#define SM_LOGIC_MAGIC (0x0F47C0DE - 27) +#define SM_LOGIC_MAGIC (0x0F47C0DE - 28) #if defined SM_LOGIC class IVEngineServer @@ -61,8 +62,13 @@ class IVEngineServer_Logic { public: virtual bool IsMapValid(const char *map) = 0; + virtual bool IsDedicatedServer() = 0; + virtual void InsertServerCommand(const char *cmd) = 0; virtual void ServerCommand(const char *cmd) = 0; + virtual void ServerExecute() = 0; virtual const char *GetClientConVarValue(int clientIndex, const char *name) = 0; + virtual void ClientCommand(edict_t *pEdict, const char *szCommand) = 0; + virtual void FakeClientCommand(edict_t *pEdict, const char *szCommand) = 0; }; typedef void * FileHandle_t; @@ -260,7 +266,6 @@ struct sm_core_t IRootConsole *rootmenu; ITimerSystem *timersys; IPlayerManager *playerhelpers; - IAdminSystem *adminsys; IGameHelpers *gamehelpers; ISourcePawnEngine **spe1; ISourcePawnEngine2 **spe2; @@ -296,6 +301,9 @@ struct sm_core_t void (*ExecuteConfigs)(IPluginContext *ctx); DatabaseInfo (*GetDBInfoFromKeyValues)(KeyValues *); int (*GetActivityFlags)(); + int (*GetImmunityMode)(); + void (*UpdateAdminCmdFlags)(const char *cmd, OverrideType type, FlagBits bits, bool remove); + bool (*LookForCommandAdminFlags)(const char *cmd, FlagBits *pFlags); const char *gamesuffix; /* Data */ ServerGlobals *serverGlobals; @@ -323,11 +331,13 @@ struct sm_logic_t void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...); void (*AddNatives)(sp_nativeinfo_t *natives); void (*DumpHandles)(void (*dumpfn)(const char *fmt, ...)); + void (*DumpAdminCache)(FILE *); IScriptManager *scripts; IShareSys *sharesys; IExtensionSys *extsys; IHandleSys *handlesys; IForwardManager *forwardsys; + IAdminSystem *adminsys; IdentityToken_t *core_ident; float sentinel; }; diff --git a/core/sm_trie.cpp b/core/logic/sm_trie.cpp similarity index 96% rename from core/sm_trie.cpp rename to core/logic/sm_trie.cpp index ac267de7..f0fde2bc 100644 --- a/core/sm_trie.cpp +++ b/core/logic/sm_trie.cpp @@ -1,121 +1,121 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2008 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 -#include -#include -#include "sm_trie.h" - -struct Trie -{ - KTrie k; -}; - -Trie *sm_trie_create() -{ - return new Trie; -} - -void sm_trie_destroy(Trie *trie) -{ - delete trie; -} - -bool sm_trie_insert(Trie *trie, const char *key, void *value) -{ - return trie->k.insert(key, value); -} - -bool sm_trie_replace(Trie *trie, const char *key, void *value) -{ - return trie->k.replace(key, value); -} - -bool sm_trie_retrieve(Trie *trie, const char *key, void **value) -{ - void **pValue = trie->k.retrieve(key); - - if (!pValue) - { - return false; - } - - if (value) - { - *value = *pValue; - } - - return true; -} - -bool sm_trie_delete(Trie *trie, const char *key) -{ - return trie->k.remove(key); -} - -void sm_trie_clear(Trie *trie) -{ - trie->k.clear(); -} - -size_t sm_trie_mem_usage(Trie *trie) -{ - return trie->k.mem_usage(); -} - -struct trie_iter_data -{ - SM_TRIE_BAD_ITERATOR iter; - void *ptr; - Trie *pTrie; -}; - -void our_trie_iterator(KTrie *pTrie, const char *name, void *& obj, void *data) -{ - trie_iter_data *our_iter; - - our_iter = (trie_iter_data *)data; - our_iter->iter(our_iter->pTrie, name, &obj, our_iter->ptr); -} - -void sm_trie_bad_iterator(Trie *trie, - char *buffer, - size_t maxlength, - SM_TRIE_BAD_ITERATOR iter, - void *data) -{ - trie_iter_data our_iter; - - our_iter.iter = iter; - our_iter.ptr = data; - our_iter.pTrie = trie; - trie->k.bad_iterator(buffer, maxlength, &our_iter, our_trie_iterator); -} +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 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 +#include +#include +#include "sm_trie.h" + +struct Trie +{ + KTrie k; +}; + +Trie *sm_trie_create() +{ + return new Trie; +} + +void sm_trie_destroy(Trie *trie) +{ + delete trie; +} + +bool sm_trie_insert(Trie *trie, const char *key, void *value) +{ + return trie->k.insert(key, value); +} + +bool sm_trie_replace(Trie *trie, const char *key, void *value) +{ + return trie->k.replace(key, value); +} + +bool sm_trie_retrieve(Trie *trie, const char *key, void **value) +{ + void **pValue = trie->k.retrieve(key); + + if (!pValue) + { + return false; + } + + if (value) + { + *value = *pValue; + } + + return true; +} + +bool sm_trie_delete(Trie *trie, const char *key) +{ + return trie->k.remove(key); +} + +void sm_trie_clear(Trie *trie) +{ + trie->k.clear(); +} + +size_t sm_trie_mem_usage(Trie *trie) +{ + return trie->k.mem_usage(); +} + +struct trie_iter_data +{ + SM_TRIE_BAD_ITERATOR iter; + void *ptr; + Trie *pTrie; +}; + +void our_trie_iterator(KTrie *pTrie, const char *name, void *& obj, void *data) +{ + trie_iter_data *our_iter; + + our_iter = (trie_iter_data *)data; + our_iter->iter(our_iter->pTrie, name, &obj, our_iter->ptr); +} + +void sm_trie_bad_iterator(Trie *trie, + char *buffer, + size_t maxlength, + SM_TRIE_BAD_ITERATOR iter, + void *data) +{ + trie_iter_data our_iter; + + our_iter.iter = iter; + our_iter.ptr = data; + our_iter.pTrie = trie; + trie->k.bad_iterator(buffer, maxlength, &our_iter, our_trie_iterator); +} diff --git a/core/sm_trie.h b/core/logic/sm_trie.h similarity index 97% rename from core/sm_trie.h rename to core/logic/sm_trie.h index 8306fd55..f88a91fa 100644 --- a/core/sm_trie.h +++ b/core/logic/sm_trie.h @@ -1,53 +1,53 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2008 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$ - */ - -#ifndef _INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_ -#define _INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_ - -struct Trie; - -typedef void (*SM_TRIE_BAD_ITERATOR)(Trie *pTrie, const char *key, void **value, void *data); - -Trie *sm_trie_create(); -void sm_trie_destroy(Trie *trie); -bool sm_trie_insert(Trie *trie, const char *key, void *value); -bool sm_trie_replace(Trie *trie, const char *key, void *value); -bool sm_trie_retrieve(Trie *trie, const char *key, void **value); -bool sm_trie_delete(Trie *trie, const char *key); -void sm_trie_clear(Trie *trie); -size_t sm_trie_mem_usage(Trie *trie); -void sm_trie_bad_iterator(Trie *trie, - char *buffer, - size_t maxlength, - SM_TRIE_BAD_ITERATOR iter, - void *data); - -#endif //_INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 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$ + */ + +#ifndef _INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_ +#define _INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_ + +struct Trie; + +typedef void (*SM_TRIE_BAD_ITERATOR)(Trie *pTrie, const char *key, void **value, void *data); + +Trie *sm_trie_create(); +void sm_trie_destroy(Trie *trie); +bool sm_trie_insert(Trie *trie, const char *key, void *value); +bool sm_trie_replace(Trie *trie, const char *key, void *value); +bool sm_trie_retrieve(Trie *trie, const char *key, void **value); +bool sm_trie_delete(Trie *trie, const char *key); +void sm_trie_clear(Trie *trie); +size_t sm_trie_mem_usage(Trie *trie); +void sm_trie_bad_iterator(Trie *trie, + char *buffer, + size_t maxlength, + SM_TRIE_BAD_ITERATOR iter, + void *data); + +#endif //_INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_ diff --git a/core/logic/smn_console.cpp b/core/logic/smn_console.cpp new file mode 100644 index 00000000..963f4314 --- /dev/null +++ b/core/logic/smn_console.cpp @@ -0,0 +1,347 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2010 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 "common_logic.h" +#include "AdminCache.h" +#include +#include +#include +#include + +static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params) +{ + if (params[1] == 0) + { + return 1; + } + + 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 = smcore.LookForCommandAdminFlags(cmd, &bits); + } + + if (!found_command) + { + adminsys->GetCommandOverride(cmd, Override_Command, &bits); + } + + return adminsys->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 = smcore.LookForCommandAdminFlags(cmd, &bits); + } + + if (!found_command) + { + adminsys->GetCommandOverride(cmd, Override_Command, &bits); + } + + return g_Admins.CheckAdminCommandAccess(params[1], cmd, bits) ? 1 : 0; +} + +static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params) +{ + char buffer[1024]; + char *fmt; + int arg = 2; + + pCtx->LocalToString(params[1], &fmt); + size_t res = smcore.atcprintf(buffer, sizeof(buffer) - 2, fmt, pCtx, params, &arg); + + buffer[res++] = '\n'; + buffer[res] = '\0'; + + smcore.ConPrint(buffer); + + return 1; +} + +static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params) +{ + int index = params[1]; + if ((index < 0) || (index > playerhelpers->GetMaxClients())) + { + return pCtx->ThrowNativeError("Client index %d is invalid", index); + } + + IGamePlayer *pPlayer = NULL; + if (index != 0) + { + pPlayer = playerhelpers->GetGamePlayer(index); + if (!pPlayer->IsInGame()) + { + return pCtx->ThrowNativeError("Client %d is not in game", index); + } + + /* Silent fail on bots, engine will crash */ + if (pPlayer->IsFakeClient()) + { + return 0; + } + } + + char buffer[1024]; + char *fmt; + int arg = 3; + + pCtx->LocalToString(params[2], &fmt); + size_t res = smcore.atcprintf(buffer, sizeof(buffer) - 2, fmt, pCtx, params, &arg); + + buffer[res++] = '\n'; + buffer[res] = '\0'; + + if (index != 0) + { + pPlayer->PrintToConsole(buffer); + } + else { + smcore.ConPrint(buffer); + } + + return 1; +} + +static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params) +{ + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + + char buffer[1024]; + size_t len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 1); + + if (pContext->GetLastNativeError() != SP_ERROR_NONE) + { + return 0; + } + + /* One byte for null terminator, one for newline */ + buffer[len++] = '\n'; + buffer[len] = '\0'; + + engine->ServerCommand(buffer); + + return 1; +} + +static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params) +{ + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + + char buffer[1024]; + size_t len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 1); + + if (pContext->GetLastNativeError() != SP_ERROR_NONE) + { + return 0; + } + + /* One byte for null terminator, one for newline */ + buffer[len++] = '\n'; + buffer[len] = '\0'; + + engine->InsertServerCommand(buffer); + + return 1; +} + +static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params) +{ + engine->ServerExecute(); + + return 1; +} + +static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params) +{ + IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(params[1]); + + if (!pPlayer) + { + return pContext->ThrowNativeError("Client index %d is invalid", params[1]); + } + + if (!pPlayer->IsConnected()) + { + return pContext->ThrowNativeError("Client %d is not connected", params[1]); + } + + g_pSM->SetGlobalTarget(params[1]); + + char buffer[256]; + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2); + + if (pContext->GetLastNativeError() != SP_ERROR_NONE) + { + return 0; + } + + engine->ClientCommand(pPlayer->GetEdict(), buffer); + + return 1; +} + +static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params) +{ + IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(params[1]); + + if (!pPlayer) + { + return pContext->ThrowNativeError("Client index %d is invalid", params[1]); + } + + if (!pPlayer->IsConnected()) + { + return pContext->ThrowNativeError("Client %d is not connected", params[1]); + } + + g_pSM->SetGlobalTarget(params[1]); + + char buffer[256]; + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2); + + if (pContext->GetLastNativeError() != SP_ERROR_NONE) + { + return 0; + } + + engine->FakeClientCommand(pPlayer->GetEdict(), buffer); + + return 1; +} + +static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params) +{ + g_pSM->SetGlobalTarget(params[1]); + + /* Build the format string */ + char buffer[1024]; + size_t len = g_pSM->FormatString(buffer, sizeof(buffer) - 2, pContext, params, 2); + + if (pContext->GetLastNativeError() != SP_ERROR_NONE) + { + return 0; + } + + /* If we're printing to the server, shortcut out */ + if (params[1] == 0) + { + /* Print */ + buffer[len++] = '\n'; + buffer[len] = '\0'; + smcore.ConPrint(buffer); + return 1; + } + + IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(params[1]); + + if (!pPlayer) + { + return pContext->ThrowNativeError("Client index %d is invalid", params[1]); + } + + if (!pPlayer->IsConnected()) + { + return pContext->ThrowNativeError("Client %d is not connected", params[1]); + } + + unsigned int replyto = playerhelpers->GetReplyTo(); + if (replyto == SM_REPLY_CONSOLE) + { + buffer[len++] = '\n'; + buffer[len] = '\0'; + pPlayer->PrintToConsole(buffer); + } + else if (replyto == SM_REPLY_CHAT) { + if (len >= 191) + { + len = 191; + } + buffer[len] = '\0'; + gamehelpers->TextMsg(params[1], TEXTMSG_DEST_CHAT, buffer); + } + + return 1; +} + +static cell_t GetCmdReplyTarget(IPluginContext *pContext, const cell_t *params) +{ + return playerhelpers->GetReplyTo(); +} + +static cell_t SetCmdReplyTarget(IPluginContext *pContext, const cell_t *params) +{ + return playerhelpers->SetReplyTo(params[1]); +} + +static cell_t AddServerTag(IPluginContext *pContext, const cell_t *params) +{ + return 0; +} + +static cell_t RemoveServerTag(IPluginContext *pContext, const cell_t *params) +{ + return 0; +} + + +REGISTER_NATIVES(consoleNatives) +{ + {"CheckCommandAccess", CheckCommandAccess}, + {"CheckAccess", CheckAccess}, + {"PrintToServer", sm_PrintToServer}, + {"PrintToConsole", sm_PrintToConsole}, + {"ServerCommand", sm_ServerCommand}, + {"InsertServerCommand", sm_InsertServerCommand}, + {"ServerExecute", sm_ServerExecute}, + {"ClientCommand", sm_ClientCommand}, + {"FakeClientCommand", FakeClientCommand}, + {"ReplyToCommand", ReplyToCommand}, + {"GetCmdReplySource", GetCmdReplyTarget}, + {"SetCmdReplySource", SetCmdReplyTarget}, + {"AddServerTag", AddServerTag}, + {"RemoveServerTag", RemoveServerTag}, + {NULL, NULL} +}; diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 47c7af4a..abb50685 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -42,9 +42,9 @@ #include "TimerSys.h" #include "logic_bridge.h" #include "PlayerManager.h" -#include "AdminCache.h" #include "HalfLife2.h" #include "CoreConfig.h" +#include "ConCmdManager.h" #include "IDBDriver.h" #if SOURCE_ENGINE == SE_DOTA #include "convar_sm_dota.h" @@ -85,6 +85,7 @@ IShareSys *sharesys; IExtensionSys *extsys; IHandleSys *handlesys; IForwardManager *forwardsys; +IAdminSystem *adminsys; class VEngineServer_Logic : public IVEngineServer_Logic { @@ -93,16 +94,42 @@ public: { return !!engine->IsMapValid(map); } - + virtual bool IsDedicatedServer() + { + return engine->IsDedicatedServer(); + } + virtual void InsertServerCommand(const char *cmd) + { + engine->InsertServerCommand(cmd); + } virtual void ServerCommand(const char *cmd) { engine->ServerCommand(cmd); } - + virtual void ServerExecute() + { + engine->ServerExecute(); + } virtual const char *GetClientConVarValue(int clientIndex, const char *name) { return engine->GetClientConVarValue(clientIndex, name); } + virtual void ClientCommand(edict_t *pEdict, const char *szCommand) + { +#if SOURCE_ENGINE == SE_DOTA + engine->ClientCommand(IndexOfEdict(pEdict), "%s", szCommand); +#else + engine->ClientCommand(pEdict, "%s", szCommand); +#endif + } + virtual void FakeClientCommand(edict_t *pEdict, const char *szCommand) + { +#if SOURCE_ENGINE == SE_DOTA + engine->ClientCommand(IndexOfEdict(pEdict), "%s", szCommand); +#else + serverpluginhelpers->ClientCommand(pEdict, szCommand); +#endif + } }; static VEngineServer_Logic logic_engine; @@ -223,6 +250,7 @@ public: static VPlayerInfo_Logic logic_playerinfo; static ConVar sm_show_activity("sm_show_activity", "13", FCVAR_SPONLY, "Activity display setting (see sourcemod.cfg)"); +static ConVar sm_immunity_mode("sm_immunity_mode", "1", FCVAR_SPONLY, "Mode for deciding immunity protection"); static ConVar *find_convar(const char *name) { @@ -401,6 +429,21 @@ static int get_activity_flags() return sm_show_activity.GetInt(); } +static int get_immunity_mode() +{ + return sm_immunity_mode.GetInt(); +} + +static void update_admin_cmd_flags(const char *cmd, OverrideType type, FlagBits bits, bool remove) +{ + g_ConCmds.UpdateAdminCmdFlags(cmd, type, bits, remove); +} + +static bool look_for_cmd_admin_flags(const char *cmd, FlagBits *pFlags) +{ + return g_ConCmds.LookForCommandAdminFlags(cmd, pFlags); +} + int read_cmd_argc(const CCommand &args) { return args.ArgC(); @@ -511,7 +554,6 @@ static sm_core_t core_bridge = &g_RootMenu, &g_Timers, &g_Players, - &g_Admins, &g_HL2, &g_pSourcePawn, &g_pSourcePawn2, @@ -546,6 +588,9 @@ static sm_core_t core_bridge = SM_ExecuteForPlugin, keyvalues_to_dbinfo, get_activity_flags, + get_immunity_mode, + update_admin_cmd_flags, + look_for_cmd_admin_flags, GAMEFIX, &serverGlobals, }; @@ -591,6 +636,7 @@ void InitLogicBridge() g_pCoreIdent = logicore.core_ident; handlesys = logicore.handlesys; forwardsys = logicore.forwardsys; + adminsys = logicore.adminsys; } bool StartLogicBridge(char *error, size_t maxlength) diff --git a/core/logic_bridge.h b/core/logic_bridge.h index 981d80ee..76372a7c 100644 --- a/core/logic_bridge.h +++ b/core/logic_bridge.h @@ -47,5 +47,6 @@ extern IShareSys *sharesys; extern IExtensionSys *extsys; extern IHandleSys *handlesys; extern IForwardManager *forwardsys; +extern IAdminSystem *adminsys; #endif /* _INCLUDE_SOURCEMOD_LOGIC_BRIDGE_H_ */ diff --git a/core/sm_srvcmds.cpp b/core/sm_srvcmds.cpp index 088c08a5..9ccec0a0 100644 --- a/core/sm_srvcmds.cpp +++ b/core/sm_srvcmds.cpp @@ -422,3 +422,23 @@ CON_COMMAND(sm_reload_translations, "Reparses all loaded translation files") translator->RebuildLanguageDatabase(); } +CON_COMMAND(sm_dump_admcache, "Dumps the admin cache for debugging") +{ + FILE *fp; + char buffer[PLATFORM_MAX_PATH]; + + g_SourceMod.BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt"); + + if ((fp = fopen(buffer, "wt")) == NULL) + { + g_RootMenu.ConsolePrint("Could not open file for writing: %s", buffer); + return; + } + + logicore.DumpAdminCache(fp); + + g_RootMenu.ConsolePrint("Admin cache dumped to: %s", buffer); + + fclose(fp); +} + diff --git a/core/smn_console.cpp b/core/smn_console.cpp index d90a58bf..d92fc492 100644 --- a/core/smn_console.cpp +++ b/core/smn_console.cpp @@ -38,7 +38,6 @@ #include "sm_stringutil.h" #include "PlayerManager.h" #include "ChatTriggers.h" -#include "AdminCache.h" #include #include #include @@ -831,88 +830,6 @@ static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params) return (cell_t)length; } -static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params) -{ - char buffer[1024]; - char *fmt; - int arg = 2; - - pCtx->LocalToString(params[1], &fmt); - size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg); - - buffer[res++] = '\n'; - buffer[res] = '\0'; - - META_CONPRINT(buffer); - - return 1; -} - -static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params) -{ - int index = params[1]; - if ((index < 0) || (index > g_Players.GetMaxClients())) - { - return pCtx->ThrowNativeError("Client index %d is invalid", index); - } - - CPlayer *pPlayer = NULL; - if (index != 0) - { - pPlayer = g_Players.GetPlayerByIndex(index); - if (!pPlayer->IsInGame()) - { - return pCtx->ThrowNativeError("Client %d is not in game", index); - } - - /* Silent fail on bots, engine will crash */ - if (pPlayer->IsFakeClient()) - { - return 0; - } - } - - char buffer[1024]; - char *fmt; - int arg = 3; - - pCtx->LocalToString(params[2], &fmt); - size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg); - - buffer[res++] = '\n'; - buffer[res] = '\0'; - - if (index != 0) - { - pPlayer->PrintToConsole(buffer); - } else { - META_CONPRINT(buffer); - } - - return 1; -} - -static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params) -{ - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - - char buffer[1024]; - size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1); - - if (pContext->GetLastNativeError() != SP_ERROR_NONE) - { - return 0; - } - - /* One byte for null terminator, one for newline */ - buffer[len++] = '\n'; - buffer[len] = '\0'; - - engine->ServerCommand(buffer); - - return 1; -} - char *g_ServerCommandBuffer = NULL; cell_t g_ServerCommandBufferLength; @@ -1031,102 +948,6 @@ static cell_t sm_ServerCommandEx(IPluginContext *pContext, const cell_t *params) return 1; } -static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params) -{ - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - - char buffer[1024]; - size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1); - - if (pContext->GetLastNativeError() != SP_ERROR_NONE) - { - return 0; - } - - /* One byte for null terminator, one for newline */ - buffer[len++] = '\n'; - buffer[len] = '\0'; - - InsertServerCommand(buffer); - - return 1; -} - -static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params) -{ - engine->ServerExecute(); - - return 1; -} - -static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params) -{ - CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]); - - if (!pPlayer) - { - return pContext->ThrowNativeError("Client index %d is invalid", params[1]); - } - - if (!pPlayer->IsConnected()) - { - return pContext->ThrowNativeError("Client %d is not connected", params[1]); - } - - g_SourceMod.SetGlobalTarget(params[1]); - - char buffer[256]; - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); - - if (pContext->GetLastNativeError() != SP_ERROR_NONE) - { - return 0; - } - - engine->ClientCommand( -#if SOURCE_ENGINE == SE_DOTA - pPlayer->GetIndex(), -#else - pPlayer->GetEdict(), -#endif - "%s", buffer); - - return 1; -} - -static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params) -{ - CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]); - - if (!pPlayer) - { - return pContext->ThrowNativeError("Client index %d is invalid", params[1]); - } - - if (!pPlayer->IsConnected()) - { - return pContext->ThrowNativeError("Client %d is not connected", params[1]); - } - - g_SourceMod.SetGlobalTarget(params[1]); - - char buffer[256]; - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); - - if (pContext->GetLastNativeError() != SP_ERROR_NONE) - { - return 0; - } - -#if SOURCE_ENGINE == SE_DOTA - engine->ClientCommand(pPlayer->GetIndex(), "%s", buffer); -#else - serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer); -#endif - - return 1; -} - static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params) { CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]); @@ -1156,69 +977,6 @@ static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params return 1; } -static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params) -{ - g_SourceMod.SetGlobalTarget(params[1]); - - /* Build the format string */ - char buffer[1024]; - size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2); - - if (pContext->GetLastNativeError() != SP_ERROR_NONE) - { - return 0; - } - - /* If we're printing to the server, shortcut out */ - if (params[1] == 0) - { - /* Print */ - buffer[len++] = '\n'; - buffer[len] = '\0'; - META_CONPRINT(buffer); - return 1; - } - - CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]); - - if (!pPlayer) - { - return pContext->ThrowNativeError("Client index %d is invalid", params[1]); - } - - if (!pPlayer->IsConnected()) - { - return pContext->ThrowNativeError("Client %d is not connected", params[1]); - } - - unsigned int replyto = g_ChatTriggers.GetReplyTo(); - if (replyto == SM_REPLY_CONSOLE) - { - buffer[len++] = '\n'; - buffer[len] = '\0'; - pPlayer->PrintToConsole(buffer); - } else if (replyto == SM_REPLY_CHAT) { - if (len >= 191) - { - len = 191; - } - buffer[len] = '\0'; - g_HL2.TextMsg(params[1], HUD_PRINTTALK, buffer); - } - - return 1; -} - -static cell_t GetCmdReplyTarget(IPluginContext *pContext, const cell_t *params) -{ - return g_ChatTriggers.GetReplyTo(); -} - -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; @@ -1278,53 +1036,6 @@ static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params 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); - - /* 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.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) { return g_ChatTriggers.IsChatTrigger() ? 1 : 0; @@ -1496,16 +1207,6 @@ static cell_t SendConVarValue(IPluginContext *pContext, const cell_t *params) return 1; } -static cell_t AddServerTag(IPluginContext *pContext, const cell_t *params) -{ - return 0; -} - -static cell_t RemoveServerTag(IPluginContext *pContext, const cell_t *params) -{ - return 0; -} - static cell_t AddCommandListener(IPluginContext *pContext, const cell_t *params) { char *name; @@ -1573,22 +1274,10 @@ REGISTER_NATIVES(consoleNatives) {"GetCmdArgString", sm_GetCmdArgString}, {"GetCmdArgs", sm_GetCmdArgs}, {"GetCmdArg", sm_GetCmdArg}, - {"PrintToServer", sm_PrintToServer}, - {"PrintToConsole", sm_PrintToConsole}, {"RegAdminCmd", sm_RegAdminCmd}, - {"ServerCommand", sm_ServerCommand}, {"ServerCommandEx", sm_ServerCommandEx}, - {"InsertServerCommand", sm_InsertServerCommand}, - {"ServerExecute", sm_ServerExecute}, - {"ClientCommand", sm_ClientCommand}, - {"FakeClientCommand", FakeClientCommand}, - {"ReplyToCommand", ReplyToCommand}, - {"GetCmdReplySource", GetCmdReplyTarget}, - {"SetCmdReplySource", SetCmdReplyTarget}, {"GetCommandIterator", GetCommandIterator}, {"ReadCommandIterator", ReadCommandIterator}, - {"CheckCommandAccess", CheckCommandAccess}, - {"CheckAccess", CheckAccess}, {"FakeClientCommandEx", FakeClientCommandEx}, {"IsChatTrigger", IsChatTrigger}, {"SetCommandFlags", SetCommandFlags}, @@ -1596,8 +1285,6 @@ REGISTER_NATIVES(consoleNatives) {"FindFirstConCommand", FindFirstConCommand}, {"FindNextConCommand", FindNextConCommand}, {"SendConVarValue", SendConVarValue}, - {"AddServerTag", AddServerTag}, - {"RemoveServerTag", RemoveServerTag}, {"AddCommandListener", AddCommandListener}, {"RemoveCommandListener", RemoveCommandListener}, {NULL, NULL} diff --git a/core/smn_player.cpp b/core/smn_player.cpp index 1e75e69b..95490bc1 100644 --- a/core/smn_player.cpp +++ b/core/smn_player.cpp @@ -30,7 +30,6 @@ */ #include "PlayerManager.h" -#include "AdminCache.h" #include "sm_stringutil.h" #include "HalfLife2.h" #include "sourcemod.h" diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index 6b393dfb..f31b7af6 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -36,7 +36,6 @@ #include #include "CoreConfig.h" #include "Logger.h" -#include "AdminCache.h" #include "sm_stringutil.h" #include "PlayerManager.h" #include "TimerSys.h" diff --git a/public/IAdminSystem.h b/public/IAdminSystem.h index b5a06ae7..465dfb93 100644 --- a/public/IAdminSystem.h +++ b/public/IAdminSystem.h @@ -35,7 +35,7 @@ #include #define SMINTERFACE_ADMINSYS_NAME "IAdminSys" -#define SMINTERFACE_ADMINSYS_VERSION 7 +#define SMINTERFACE_ADMINSYS_VERSION 8 /** * @file IAdminSystem.h @@ -728,12 +728,22 @@ namespace SourceMod virtual bool FindFlagChar(AdminFlag flag, char *c) =0; /** - * brief Returns whether or not an admin id is valid. + * @brief Returns whether or not an admin id is valid. * * @param id Admin id to check. * @return True if valid, otherwise false. */ virtual bool IsValidAdmin(AdminId id) =0; + + /** + * @brief Returns whether or not a client has access to a given command. + * + * @param client Client index. + * @param cmd Command name. + * @param flags Command admin flags. + * @return True if allowed access, otherwise false; + */ + virtual bool CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags) =0; }; } diff --git a/public/IPlayerHelpers.h b/public/IPlayerHelpers.h index 22fe1553..8b1d9cd2 100644 --- a/public/IPlayerHelpers.h +++ b/public/IPlayerHelpers.h @@ -41,7 +41,7 @@ #include #define SMINTERFACE_PLAYERMANAGER_NAME "IPlayerManager" -#define SMINTERFACE_PLAYERMANAGER_VERSION 19 +#define SMINTERFACE_PLAYERMANAGER_VERSION 20 struct edict_t; class IPlayerInfo; @@ -262,6 +262,11 @@ namespace SourceMod * @param pMsg String to print. */ virtual void PrintToConsole(const char *pMsg) =0; + + /** + * @brief Removes admin access from the client. + */ + virtual void ClearAdmin() =0; }; /** @@ -584,6 +589,18 @@ namespace SourceMod * @param info Pointer to the cmd_target_info_t structure to process. */ virtual void ProcessCommandTarget(cmd_target_info_t *info) =0; + + /** + * @brief Removes all access for the given admin id. + * + * @param id Admin id. + */ + virtual void ClearAdminId(AdminId id) =0; + + /** + * @brief Reruns admin checks on all players. + */ + virtual void RecheckAnyAdmins() =0; }; } diff --git a/public/compat_wrappers.h b/public/compat_wrappers.h index e78777c6..abc3b86f 100644 --- a/public/compat_wrappers.h +++ b/public/compat_wrappers.h @@ -41,10 +41,6 @@ { return cmd->IsFlagSet(flag); } - inline void InsertServerCommand(const char *buf) - { - engine->InsertServerCommand(buf); - } inline ConCommandBase *FindCommandBase(const char *name) { return icvar->FindCommandBase(name); @@ -77,10 +73,6 @@ { return cmd->IsBitSet(flag); } - inline void InsertServerCommand(const char *buf) - { - engine->InsertServerCommand(buf); - } inline ConCommandBase *FindCommandBase(const char *name) { ConCommandBase *pBase = icvar->GetCommands();