core/AdminCache.cpp
changeset 1298 9cddbed74581
parent 1231 17badaf66ce4
child 1299 10f58032bc78
     1.1 --- a/core/AdminCache.cpp	Fri Aug 10 01:07:07 2007 +0000
     1.2 +++ b/core/AdminCache.cpp	Fri Aug 10 04:53:30 2007 +0000
     1.3 @@ -37,8 +37,181 @@
     1.4  #include "ForwardSys.h"
     1.5  #include "PlayerManager.h"
     1.6  #include "ConCmdManager.h"
     1.7 +#include "TextParsers.h"
     1.8 +#include "Logger.h"
     1.9 +#include "sourcemod.h"
    1.10 +#include "sm_stringutil.h"
    1.11 +
    1.12 +#define LEVEL_STATE_NONE		0
    1.13 +#define LEVEL_STATE_LEVELS		1
    1.14 +#define LEVEL_STATE_FLAGS		2
    1.15  
    1.16  AdminCache g_Admins;
    1.17 +AdminFlag g_FlagLetters[26];
    1.18 +bool g_FlagSet[26];
    1.19 +
    1.20 +/* Default flags */
    1.21 +AdminFlag g_DefaultFlags[26] = 
    1.22 +{
    1.23 +	Admin_Reservation, Admin_Generic, Admin_Kick, Admin_Ban, Admin_Unban,
    1.24 +	Admin_Slay, Admin_Changemap, Admin_Convars, Admin_Config, Admin_Chat,
    1.25 +	Admin_Vote, Admin_Password, Admin_RCON, Admin_Cheats, Admin_Custom1, 
    1.26 +	Admin_Custom2, Admin_Custom3, Admin_Custom4, Admin_Custom5, Admin_Custom6,
    1.27 +	Admin_Generic, Admin_Generic, Admin_Generic, Admin_Generic, Admin_Generic,
    1.28 +	Admin_Root
    1.29 +};
    1.30 +
    1.31 +
    1.32 +class FlagReader : public ITextListener_SMC
    1.33 +{
    1.34 +public:
    1.35 +	void LoadLevels()
    1.36 +	{
    1.37 +		if (!Parse())
    1.38 +		{
    1.39 +			memcpy(g_FlagLetters, g_DefaultFlags, sizeof(AdminFlag) * 26);
    1.40 +			for (unsigned int i=0; i<20; i++)
    1.41 +			{
    1.42 +				g_FlagSet[i] = true;
    1.43 +			}
    1.44 +			g_FlagSet[25] = true;
    1.45 +		}
    1.46 +	}
    1.47 +private:
    1.48 +	bool Parse()
    1.49 +	{
    1.50 +		unsigned int line = 0;
    1.51 +		SMCParseError error;
    1.52 +
    1.53 +		m_Line = 0;
    1.54 +		m_bFileNameLogged = false;
    1.55 +		g_SourceMod.BuildPath(Path_SM, m_File, sizeof(m_File), "configs/admin_levels.cfg");
    1.56 +
    1.57 +		if ((error = g_TextParser.ParseFile_SMC(m_File, this, &line, NULL))
    1.58 +			!= SMCParse_Okay)
    1.59 +		{
    1.60 +			const char *err_string = g_TextParser.GetSMCErrorString(error);
    1.61 +			if (!err_string)
    1.62 +			{
    1.63 +				err_string = "Unknown error";
    1.64 +			}
    1.65 +			ParseError("Error %d (%s)", error, err_string);
    1.66 +			return false;
    1.67 +		}
    1.68 +
    1.69 +		return true;
    1.70 +	}
    1.71 +	void ReadSMC_ParseStart()
    1.72 +	{
    1.73 +		m_LevelState = LEVEL_STATE_NONE;
    1.74 +		m_IgnoreLevel = 0;
    1.75 +		memset(g_FlagSet, 0, sizeof(g_FlagSet));
    1.76 +	}
    1.77 +	SMCParseResult ReadSMC_NewSection(const char *name, bool opt_quotes)
    1.78 +	{
    1.79 +		if (m_IgnoreLevel)
    1.80 +		{
    1.81 +			m_IgnoreLevel++;
    1.82 +			return SMCParse_Continue;
    1.83 +		}
    1.84 +
    1.85 +		if (m_LevelState == LEVEL_STATE_NONE)
    1.86 +		{
    1.87 +			if (strcmp(name, "Levels") == 0)
    1.88 +			{
    1.89 +				m_IgnoreLevel = LEVEL_STATE_LEVELS;
    1.90 +			} else {
    1.91 +				m_IgnoreLevel++;
    1.92 +			}
    1.93 +		} else if (m_IgnoreLevel == LEVEL_STATE_LEVELS) {
    1.94 +			if (strcmp(name, "Flags") == 0)
    1.95 +			{
    1.96 +				m_IgnoreLevel = LEVEL_STATE_FLAGS;
    1.97 +			} else {
    1.98 +				m_IgnoreLevel++;
    1.99 +			}
   1.100 +		} else {
   1.101 +			m_IgnoreLevel++;
   1.102 +		}
   1.103 +
   1.104 +		return SMCParse_Continue;
   1.105 +	}
   1.106 +	SMCParseResult ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes)
   1.107 +	{
   1.108 +		if (m_IgnoreLevel != LEVEL_STATE_FLAGS || m_IgnoreLevel)
   1.109 +		{
   1.110 +			return SMCParse_Continue;
   1.111 +		}
   1.112 +
   1.113 +		unsigned char c = (unsigned)value[0];
   1.114 +
   1.115 +		if (c < (unsigned)'a' || c > (unsigned)'z')
   1.116 +		{
   1.117 +			ParseError("Flag \"%c\" is not a lower-case ASCII letter", c);
   1.118 +			return SMCParse_Continue;
   1.119 +		}
   1.120 +
   1.121 +		c -= (unsigned)'a';
   1.122 +
   1.123 +		assert(c >= 0 && c < 26);
   1.124 +
   1.125 +		if (!g_Admins.FindFlag(key, &g_FlagLetters[c]))
   1.126 +		{
   1.127 +			ParseError("Unrecognized admin level \"%s\"", key);
   1.128 +			return SMCParse_Continue;
   1.129 +		}
   1.130 +
   1.131 +		g_FlagSet[c] = true;
   1.132 +
   1.133 +		return SMCParse_Continue;
   1.134 +	}
   1.135 +	SMCParseResult ReadSMC_LeavingSection()
   1.136 +	{
   1.137 +		if (m_IgnoreLevel)
   1.138 +		{
   1.139 +			m_IgnoreLevel--;
   1.140 +			return SMCParse_Continue;
   1.141 +		}
   1.142 +
   1.143 +		if (m_LevelState == LEVEL_STATE_FLAGS)
   1.144 +		{
   1.145 +			m_LevelState = LEVEL_STATE_LEVELS;
   1.146 +			return SMCParse_Halt;
   1.147 +		} else if (m_LevelState == LEVEL_STATE_LEVELS) {
   1.148 +			m_LevelState = LEVEL_STATE_NONE;
   1.149 +		}
   1.150 +
   1.151 +		return SMCParse_Continue;
   1.152 +	}
   1.153 +	SMCParseResult ReadSMC_RawLine(const char *line, unsigned int curline)
   1.154 +	{
   1.155 +		m_Line = curline;
   1.156 +		return SMCParse_Continue;
   1.157 +	}
   1.158 +	void ParseError(const char *message, ...)
   1.159 +	{
   1.160 +		va_list ap;
   1.161 +		char buffer[256];
   1.162 +
   1.163 +		va_start(ap, message);
   1.164 +		UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
   1.165 +		va_end(ap);
   1.166 +
   1.167 +		if (!m_bFileNameLogged)
   1.168 +		{
   1.169 +			g_Logger.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File);
   1.170 +			m_bFileNameLogged = true;
   1.171 +		}
   1.172 +
   1.173 +		g_Logger.LogError("[SM] (Line %d): %s", m_Line, buffer);
   1.174 +	}
   1.175 +private:
   1.176 +	bool m_bFileNameLogged;
   1.177 +	char m_File[PLATFORM_MAX_PATH];
   1.178 +	int m_LevelState;
   1.179 +	int m_IgnoreLevel;
   1.180 +	unsigned int m_Line;
   1.181 +} s_FlagReader;
   1.182  
   1.183  AdminCache::AdminCache()
   1.184  {
   1.185 @@ -54,6 +227,7 @@
   1.186  	m_pAuthTables = sm_trie_create();
   1.187  	m_InvalidatingAdmins = false;
   1.188  	m_destroying = false;
   1.189 +	m_pLevelNames = sm_trie_create();
   1.190  }
   1.191  
   1.192  AdminCache::~AdminCache()
   1.193 @@ -81,6 +255,8 @@
   1.194  	sm_trie_destroy(m_pAuthTables);
   1.195  
   1.196  	delete m_pStrings;
   1.197 +
   1.198 +	sm_trie_destroy(m_pLevelNames);
   1.199  }
   1.200  
   1.201  void AdminCache::OnSourceModStartup(bool late)
   1.202 @@ -88,6 +264,28 @@
   1.203  	RegisterAuthIdentType("steam");
   1.204  	RegisterAuthIdentType("name");
   1.205  	RegisterAuthIdentType("ip");
   1.206 +
   1.207 +	NameFlag("reservation", Admin_Reservation);
   1.208 +	NameFlag("kick", Admin_Kick);
   1.209 +	NameFlag("generic", Admin_Generic);
   1.210 +	NameFlag("ban", Admin_Ban);
   1.211 +	NameFlag("unban", Admin_Unban);
   1.212 +	NameFlag("slay", Admin_Slay);
   1.213 +	NameFlag("changemap", Admin_Changemap);
   1.214 +	NameFlag("cvars", Admin_Convars);
   1.215 +	NameFlag("config", Admin_Config);
   1.216 +	NameFlag("chat", Admin_Chat);
   1.217 +	NameFlag("vote", Admin_Vote);
   1.218 +	NameFlag("password", Admin_Password);
   1.219 +	NameFlag("rcon", Admin_RCON);
   1.220 +	NameFlag("cheats", Admin_Cheats);
   1.221 +	NameFlag("root", Admin_Root);
   1.222 +	NameFlag("custom1", Admin_Custom1);
   1.223 +	NameFlag("custom2", Admin_Custom2);
   1.224 +	NameFlag("custom3", Admin_Custom3);
   1.225 +	NameFlag("custom4", Admin_Custom4);
   1.226 +	NameFlag("custom5", Admin_Custom5);
   1.227 +	NameFlag("custom6", Admin_Custom6);
   1.228  }
   1.229  
   1.230  void AdminCache::OnSourceModAllInitialized()
   1.231 @@ -96,6 +294,12 @@
   1.232  	g_ShareSys.AddInterface(NULL, this);
   1.233  }
   1.234  
   1.235 +void AdminCache::OnSourceModLevelChange(const char *mapName)
   1.236 +{
   1.237 +	/* For now, we only read these once per level. */
   1.238 +	s_FlagReader.LoadLevels();
   1.239 +}
   1.240 +
   1.241  void AdminCache::OnSourceModShutdown()
   1.242  {
   1.243  	g_Forwards.ReleaseForward(m_pCacheFwd);
   1.244 @@ -108,6 +312,27 @@
   1.245  	DumpAdminCache(AdminCache_Groups, true);
   1.246  }
   1.247  
   1.248 +void AdminCache::NameFlag(const char *str, AdminFlag flag)
   1.249 +{
   1.250 +	sm_trie_insert(m_pLevelNames, str, (void *)flag);
   1.251 +}
   1.252 +
   1.253 +bool AdminCache::FindFlag(const char *str, AdminFlag *pFlag)
   1.254 +{
   1.255 +	void *obj;
   1.256 +	if (!sm_trie_retrieve(m_pLevelNames, str, &obj))
   1.257 +	{
   1.258 +		return false;
   1.259 +	}
   1.260 +
   1.261 +	if (pFlag)
   1.262 +	{
   1.263 +		*pFlag = (AdminFlag)(int)obj;
   1.264 +	}
   1.265 +
   1.266 +	return true;
   1.267 +}
   1.268 +
   1.269  void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags)
   1.270  {
   1.271  	Trie *pTrie = NULL;
   1.272 @@ -1289,3 +1514,41 @@
   1.273  	
   1.274  	return true;
   1.275  }
   1.276 +
   1.277 +bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
   1.278 +{
   1.279 +	if (c < 'a' || c > 'z')
   1.280 +	{
   1.281 +		return false;
   1.282 +	}
   1.283 +
   1.284 +	if (*pAdmFlag)
   1.285 +	{
   1.286 +		*pAdmFlag = g_FlagLetters[(unsigned)c - (unsigned)'a'];
   1.287 +	}
   1.288 +
   1.289 +	return true;
   1.290 +}
   1.291 +
   1.292 +FlagBits AdminCache::ReadFlagString(const char *flags, const char **end)
   1.293 +{
   1.294 +	FlagBits bits = 0;
   1.295 +
   1.296 +	while (flags && (*flags != '\0'))
   1.297 +	{
   1.298 +		AdminFlag flag;
   1.299 +		if (!FindFlag(*flags, &flag))
   1.300 +		{
   1.301 +			break;
   1.302 +		}
   1.303 +		bits |= FlagArrayToBits(&flag, 1);
   1.304 +		flags++;
   1.305 +	}
   1.306 +
   1.307 +	if (end)
   1.308 +	{
   1.309 +		*end = flags;
   1.310 +	}
   1.311 +
   1.312 +	return bits;
   1.313 +}