core/AdminCache.cpp
changeset 1965 63d5a5f6935f
parent 1952 b7aa2b626807
child 2000 38c6fa875d9b
     1.1 --- a/core/AdminCache.cpp	Sat Apr 05 00:06:27 2008 +0000
     1.2 +++ b/core/AdminCache.cpp	Sun Apr 06 06:56:45 2008 +0000
     1.3 @@ -41,12 +41,14 @@
     1.4  #include "sourcemod.h"
     1.5  #include "sm_stringutil.h"
     1.6  #include "sourcemm_api.h"
     1.7 +#include "sm_srvcmds.h"
     1.8  
     1.9  #define LEVEL_STATE_NONE		0
    1.10  #define LEVEL_STATE_LEVELS		1
    1.11  #define LEVEL_STATE_FLAGS		2
    1.12  
    1.13  AdminCache g_Admins;
    1.14 +char g_ReverseFlags[26];
    1.15  AdminFlag g_FlagLetters[26];
    1.16  bool g_FlagSet[26];
    1.17  
    1.18 @@ -299,8 +301,23 @@
    1.19  
    1.20  void AdminCache::OnSourceModLevelChange(const char *mapName)
    1.21  {
    1.22 +	int i;
    1.23 +	AdminFlag flag;
    1.24 +
    1.25  	/* For now, we only read these once per level. */
    1.26  	s_FlagReader.LoadLevels();
    1.27 +
    1.28 +	for (i = 0; i < 26; i++)
    1.29 +	{
    1.30 +		if (FindFlag('a' + i, &flag))
    1.31 +		{
    1.32 +			g_ReverseFlags[flag] = 'a' + i;
    1.33 +		}
    1.34 +		else
    1.35 +		{
    1.36 +			g_ReverseFlags[flag] = '?';
    1.37 +		}
    1.38 +	}
    1.39  }
    1.40  
    1.41  void AdminCache::OnSourceModShutdown()
    1.42 @@ -434,7 +451,9 @@
    1.43  		assert(pUser->magic == USR_MAGIC_UNSET);
    1.44  		id = m_FreeUserList;
    1.45  		m_FreeUserList = pUser->next_user;
    1.46 -	} else {
    1.47 +	}
    1.48 +	else
    1.49 +	{
    1.50  		id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser);
    1.51  		pUser->grp_size = 0;
    1.52  		pUser->grp_table = -1;
    1.53 @@ -454,19 +473,28 @@
    1.54  	{
    1.55  		m_FirstUser = id;
    1.56  		m_LastUser = id;
    1.57 -	} else {
    1.58 +	}
    1.59 +	else
    1.60 +	{
    1.61  		AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
    1.62  		pPrev->next_user = id;
    1.63  		pUser->prev_user = m_LastUser;
    1.64  		m_LastUser = id;
    1.65  	}
    1.66  
    1.67 +	/* Since we always append to the tail, we should invalidate their next */
    1.68 +	pUser->next_user = -1;
    1.69 +
    1.70  	if (name && name[0] != '\0')
    1.71  	{
    1.72  		int nameidx = m_pStrings->AddString(name);
    1.73  		pUser = (AdminUser *)m_pMemory->GetAddress(id);
    1.74  		pUser->nameidx = nameidx;
    1.75  	}
    1.76 +	else
    1.77 +	{
    1.78 +		pUser->nameidx = -1;
    1.79 +	}
    1.80  
    1.81  	return id;
    1.82  }
    1.83 @@ -1587,7 +1615,9 @@
    1.84  
    1.85  bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
    1.86  {
    1.87 -	if (c < 'a' || c > 'z')
    1.88 +	if (c < 'a' 
    1.89 +		|| c > 'z'
    1.90 +		|| !g_FlagSet[(unsigned)c - (unsigned)'a'])
    1.91  	{
    1.92  		return false;
    1.93  	}
    1.94 @@ -1600,6 +1630,21 @@
    1.95  	return true;
    1.96  }
    1.97  
    1.98 +bool AdminCache::FindFlagChar(AdminFlag flag, char *c)
    1.99 +{
   1.100 +	if (!g_FlagSet[flag])
   1.101 +	{
   1.102 +		return false;
   1.103 +	}
   1.104 +
   1.105 +	if (c)
   1.106 +	{
   1.107 +		*c = g_ReverseFlags[flag];
   1.108 +	}
   1.109 +
   1.110 +	return true;
   1.111 +}
   1.112 +
   1.113  FlagBits AdminCache::ReadFlagString(const char *flags, const char **end)
   1.114  {
   1.115  	FlagBits bits = 0;
   1.116 @@ -1730,3 +1775,303 @@
   1.117  
   1.118  	return g_ConCmds.CheckCommandAccess(client, cmd, bits) ? 1 : 0;
   1.119  }
   1.120 +
   1.121 +void iterator_glob_basic_override(Trie *pTrie, const char *key, void **value, void *data)
   1.122 +{
   1.123 +	FILE *fp;
   1.124 +	int flags;
   1.125 +	char flagstr[64];
   1.126 +
   1.127 +	fp = (FILE *)data;
   1.128 +	flags = (int)*value;
   1.129 +	g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr));
   1.130 +
   1.131 +	fprintf(fp, "\t\"%s\"\t\t\"%s\"\n", key, flagstr);
   1.132 +}
   1.133 +
   1.134 +void iterator_glob_grp_override(Trie *pTrie, const char *key, void **value, void *data)
   1.135 +{
   1.136 +	FILE *fp;
   1.137 +	int flags;
   1.138 +	char flagstr[64];
   1.139 +
   1.140 +	fp = (FILE *)data;
   1.141 +	flags = (int)*value;
   1.142 +	g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr));
   1.143 +
   1.144 +	fprintf(fp, "\t\"@%s\"\t\t\"%s\"\n", key, flagstr);
   1.145 +}
   1.146 +
   1.147 +void iterator_group_basic_override(Trie *pTrie, const char *key, void **value, void *data)
   1.148 +{
   1.149 +	FILE *fp;
   1.150 +	int flags;
   1.151 +	char flagstr[64];
   1.152 +
   1.153 +	fp = (FILE *)data;
   1.154 +	flags = (int)*value;
   1.155 +	g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr));
   1.156 +
   1.157 +	fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n", key, flagstr);
   1.158 +}
   1.159 +
   1.160 +void iterator_group_grp_override(Trie *pTrie, const char *key, void **value, void *data)
   1.161 +{
   1.162 +	FILE *fp;
   1.163 +	int flags;
   1.164 +	char flagstr[64];
   1.165 +
   1.166 +	fp = (FILE *)data;
   1.167 +	flags = (int)*value;
   1.168 +	g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr));
   1.169 +
   1.170 +	fprintf(fp, "\t\t\t\"@%s\"\t\t\"%s\"\n", key, flagstr);
   1.171 +}
   1.172 +
   1.173 +void AdminCache::DumpCache(FILE *fp)
   1.174 +{
   1.175 +	int *itable;
   1.176 +	AdminId aid;
   1.177 +	GroupId gid;
   1.178 +	char flagstr[64];
   1.179 +	unsigned int num;
   1.180 +	AdminUser *pAdmin;
   1.181 +	AdminGroup *pGroup;
   1.182 +	char name_buffer[512];
   1.183 +
   1.184 +	fprintf(fp, "\"Groups\"\n{\n");
   1.185 +	
   1.186 +	num = 0;
   1.187 +	gid = m_FirstGroup;
   1.188 +	while (gid != INVALID_GROUP_ID
   1.189 +			&& (pGroup = GetGroup(gid)) != NULL)
   1.190 +	{
   1.191 +		num++;
   1.192 +		FillFlagString(pGroup->addflags, flagstr, sizeof(flagstr));
   1.193 +
   1.194 +		fprintf(fp, "\t/* num = %d, gid = 0x%X */\n", num, gid);
   1.195 +		fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pGroup->nameidx));
   1.196 +		fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr);
   1.197 +		fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pGroup->immunity_level);
   1.198 +		
   1.199 +		if (pGroup->immune_table != -1
   1.200 +			&& (itable = (int *)m_pMemory->GetAddress(pGroup->immune_table)) != NULL)
   1.201 +		{
   1.202 +			AdminGroup *pAltGroup;
   1.203 +			const char *gname, *mod;
   1.204 +
   1.205 +			for (int i = 1; i <= itable[0]; i++)
   1.206 +			{
   1.207 +				if ((pAltGroup = GetGroup(itable[i])) == NULL)
   1.208 +				{
   1.209 +					/* Assume the rest of the table is corrupt */
   1.210 +					break;
   1.211 +				}
   1.212 +				gname = GetString(pAltGroup->nameidx);
   1.213 +				if (atoi(gname) != 0)
   1.214 +				{
   1.215 +					mod = "@";
   1.216 +				}
   1.217 +				else
   1.218 +				{
   1.219 +					mod = "";
   1.220 +				}
   1.221 +				fprintf(fp, "\t\t\"immunity\"\t\t\"%s%s\"\n", mod, gname);
   1.222 +			}
   1.223 +		}
   1.224 +
   1.225 +		fprintf(fp, "\n\t\t\"Overrides\"\n\t\t{\n");
   1.226 +		if (pGroup->pCmdGrpTable != NULL)
   1.227 +		{
   1.228 +			sm_trie_bad_iterator(pGroup->pCmdGrpTable, 
   1.229 +				name_buffer,
   1.230 +				sizeof(name_buffer),
   1.231 +				iterator_group_grp_override,
   1.232 +				fp);
   1.233 +		}
   1.234 +		if (pGroup->pCmdTable != NULL)
   1.235 +		{
   1.236 +			sm_trie_bad_iterator(pGroup->pCmdTable, 
   1.237 +				name_buffer,
   1.238 +				sizeof(name_buffer),
   1.239 +				iterator_group_basic_override,
   1.240 +				fp);
   1.241 +		}
   1.242 +		fprintf(fp, "\t\t}\n");
   1.243 +
   1.244 +		fprintf(fp, "\t}\n");
   1.245 +
   1.246 +		if ((gid = pGroup->next_grp) != INVALID_GROUP_ID)
   1.247 +		{
   1.248 +			fprintf(fp, "\n");
   1.249 +		}
   1.250 +	}
   1.251 +
   1.252 +	fprintf(fp, "}\n\n");
   1.253 +	fprintf(fp, "\"Admins\"\n{\n");
   1.254 +
   1.255 +	num = 0;
   1.256 +	aid = m_FirstUser;
   1.257 +	while (aid != INVALID_ADMIN_ID
   1.258 +			&& (pAdmin = GetUser(aid)) != NULL)
   1.259 +	{
   1.260 +		num++;
   1.261 +		FillFlagString(pAdmin->flags, flagstr, sizeof(flagstr));
   1.262 +
   1.263 +		fprintf(fp, "\t/* num = %d, aid = 0x%X, serialno = 0x%X*/\n", num, aid, pAdmin->serialchange);
   1.264 +
   1.265 +		if (pAdmin->nameidx != -1)
   1.266 +		{
   1.267 +			fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pAdmin->nameidx));
   1.268 +		}
   1.269 +		else
   1.270 +		{
   1.271 +			fprintf(fp, "\t\"\"\n\t{\n");
   1.272 +		}
   1.273 +
   1.274 +		if (pAdmin->auth.identidx != -1)
   1.275 +		{
   1.276 +			fprintf(fp, "\t\t\"auth\"\t\t\t\"%s\"\n", GetMethodName(pAdmin->auth.index));
   1.277 +			fprintf(fp, "\t\t\"identity\"\t\t\"%s\"\n", GetString(pAdmin->auth.identidx));
   1.278 +		}
   1.279 +		if (pAdmin->password != -1)
   1.280 +		{
   1.281 +			fprintf(fp, "\t\t\"password\"\t\t\"%s\"\n", GetString(pAdmin->password));
   1.282 +		}
   1.283 +		fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr);
   1.284 +		fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pAdmin->immunity_level);
   1.285 +
   1.286 +		if (pAdmin->grp_count != 0 
   1.287 +			&& pAdmin->grp_table != -1 
   1.288 +			&& (itable = (int *)m_pMemory->GetAddress(pAdmin->grp_table)) != NULL)
   1.289 +		{
   1.290 +			unsigned int i;
   1.291 +
   1.292 +			for (i = 0; i < pAdmin->grp_count; i++)
   1.293 +			{
   1.294 +				if ((pGroup = GetGroup(itable[i])) == NULL)
   1.295 +				{
   1.296 +					/* Assume the rest of the table is corrupt */
   1.297 +					break;
   1.298 +				}
   1.299 +				fprintf(fp, "\t\t\"group\"\t\t\t\"%s\"\n", GetString(pGroup->nameidx));
   1.300 +			}
   1.301 +		}
   1.302 +
   1.303 +		fprintf(fp, "\t}\n");
   1.304 +
   1.305 +		if ((aid = pAdmin->next_user) != INVALID_ADMIN_ID)
   1.306 +		{
   1.307 +			fprintf(fp, "\n");
   1.308 +		}
   1.309 +	}
   1.310 +
   1.311 +	fprintf(fp, "}\n\n");
   1.312 +
   1.313 +	fprintf(fp, "\"Overrides\"\n{\n");
   1.314 +	if (m_pCmdGrpOverrides != NULL)
   1.315 +	{
   1.316 +		sm_trie_bad_iterator(m_pCmdGrpOverrides,
   1.317 +			name_buffer,
   1.318 +			sizeof(name_buffer),
   1.319 +			iterator_glob_grp_override,
   1.320 +			fp);
   1.321 +	}
   1.322 +	if (m_pCmdOverrides != NULL)
   1.323 +	{
   1.324 +		sm_trie_bad_iterator(m_pCmdOverrides,
   1.325 +			name_buffer, 
   1.326 +			sizeof(name_buffer), 
   1.327 +			iterator_glob_basic_override, 
   1.328 +			fp);
   1.329 +	}
   1.330 +	fprintf(fp, "}\n");
   1.331 +}
   1.332 +
   1.333 +AdminGroup *AdminCache::GetGroup(GroupId gid)
   1.334 +{
   1.335 +	AdminGroup *pGroup;
   1.336 +	
   1.337 +	pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
   1.338 +	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   1.339 +	{
   1.340 +		return NULL;
   1.341 +	}
   1.342 +
   1.343 +	return pGroup;
   1.344 +}
   1.345 +
   1.346 +AdminUser *AdminCache::GetUser(AdminId aid)
   1.347 +{
   1.348 +	AdminUser *pAdmin;
   1.349 +
   1.350 +	pAdmin = (AdminUser *)m_pMemory->GetAddress(aid);
   1.351 +	if (!pAdmin || pAdmin->magic != USR_MAGIC_SET)
   1.352 +	{
   1.353 +		return NULL;
   1.354 +	}
   1.355 +
   1.356 +	return pAdmin;
   1.357 +}
   1.358 +
   1.359 +const char *AdminCache::GetMethodName(unsigned int index)
   1.360 +{
   1.361 +	List<AuthMethod>::iterator iter;
   1.362 +	for (iter=m_AuthMethods.begin();
   1.363 +		iter!=m_AuthMethods.end();
   1.364 +		iter++)
   1.365 +	{
   1.366 +		if (index-- == 0)
   1.367 +		{
   1.368 +			return (*iter).name.c_str();
   1.369 +		}
   1.370 +	}
   1.371 +
   1.372 +	return NULL;
   1.373 +}
   1.374 +
   1.375 +const char *AdminCache::GetString(int idx)
   1.376 +{
   1.377 +	return m_pStrings->GetString(idx);
   1.378 +}
   1.379 +
   1.380 +size_t AdminCache::FillFlagString(FlagBits bits, char *buffer, size_t maxlen)
   1.381 +{
   1.382 +	size_t pos;
   1.383 +	unsigned int i, num_flags;
   1.384 +	AdminFlag flags[AdminFlags_TOTAL];
   1.385 +
   1.386 +	num_flags = FlagBitsToArray(bits, flags, AdminFlags_TOTAL);
   1.387 +
   1.388 +	pos = 0;
   1.389 +	for (i = 0; pos < maxlen && i < num_flags; i++)
   1.390 +	{
   1.391 +		if (FindFlagChar(flags[i], &buffer[pos]))
   1.392 +		{
   1.393 +			pos++;
   1.394 +		}
   1.395 +	}
   1.396 +	buffer[pos] = '\0';
   1.397 +
   1.398 +	return pos;
   1.399 +}
   1.400 +
   1.401 +CON_COMMAND(sm_dump_admcache, "Dumps the admin cache for debugging")
   1.402 +{
   1.403 +	FILE *fp;
   1.404 +	char buffer[PLATFORM_MAX_PATH];
   1.405 +
   1.406 +	g_SourceMod.BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt");
   1.407 +
   1.408 +	if ((fp = fopen(buffer, "wt")) == NULL)
   1.409 +	{
   1.410 +		g_RootMenu.ConsolePrint("Could not open file for writing: %s", buffer);
   1.411 +		return;
   1.412 +	}
   1.413 +
   1.414 +	g_Admins.DumpCache(fp);
   1.415 +
   1.416 +	g_RootMenu.ConsolePrint("Admin cache dumped to: %s", buffer);
   1.417 +
   1.418 +	fclose(fp);
   1.419 +}