core/AdminCache.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Thu Feb 13 12:12:36 2014 -0500 (2014-02-13)
changeset 4251 9290c598d3cb
parent 4139 de7d1cd00703
child 4266 b6060fd93236
permissions -rw-r--r--
Update CSSDM gdc patch bytes (NPOTB)
dvander@370
     1
/**
dvander@4077
     2
 * vim: set ts=4 sw=4 tw=99 noet :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@370
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@370
    28
 *
dvander@370
    29
 * Version: $Id$
dvander@370
    30
 */
dvander@370
    31
dvander@335
    32
#include <string.h>
dvander@335
    33
#include <assert.h>
dvander@1406
    34
#include <ITextParsers.h>
dvander@335
    35
#include "AdminCache.h"
dvander@591
    36
#include "PlayerManager.h"
dvander@583
    37
#include "ConCmdManager.h"
dvander@1298
    38
#include "Logger.h"
dvander@1298
    39
#include "sourcemod.h"
dvander@1298
    40
#include "sm_stringutil.h"
dvander@1403
    41
#include "sourcemm_api.h"
dvander@1965
    42
#include "sm_srvcmds.h"
dvander@3872
    43
#include "logic_bridge.h"
dvander@1298
    44
dvander@1298
    45
#define LEVEL_STATE_NONE		0
dvander@1298
    46
#define LEVEL_STATE_LEVELS		1
dvander@1298
    47
#define LEVEL_STATE_FLAGS		2
dvander@335
    48
dvander@335
    49
AdminCache g_Admins;
dvander@1965
    50
char g_ReverseFlags[26];
dvander@1298
    51
AdminFlag g_FlagLetters[26];
dvander@1298
    52
bool g_FlagSet[26];
dvander@1298
    53
dvander@1839
    54
ConVar sm_immunity_mode("sm_immunity_mode", "1", FCVAR_SPONLY, "Mode for deciding immunity protection");
dvander@1403
    55
dvander@1298
    56
/* Default flags */
dvander@1298
    57
AdminFlag g_DefaultFlags[26] = 
dvander@1298
    58
{
dvander@1298
    59
	Admin_Reservation, Admin_Generic, Admin_Kick, Admin_Ban, Admin_Unban,
dvander@1298
    60
	Admin_Slay, Admin_Changemap, Admin_Convars, Admin_Config, Admin_Chat,
dvander@1298
    61
	Admin_Vote, Admin_Password, Admin_RCON, Admin_Cheats, Admin_Custom1, 
dvander@1298
    62
	Admin_Custom2, Admin_Custom3, Admin_Custom4, Admin_Custom5, Admin_Custom6,
dvander@1298
    63
	Admin_Generic, Admin_Generic, Admin_Generic, Admin_Generic, Admin_Generic,
dvander@1298
    64
	Admin_Root
dvander@1298
    65
};
dvander@1298
    66
dvander@1298
    67
dvander@1298
    68
class FlagReader : public ITextListener_SMC
dvander@1298
    69
{
dvander@1298
    70
public:
dvander@1298
    71
	void LoadLevels()
dvander@1298
    72
	{
dvander@1298
    73
		if (!Parse())
dvander@1298
    74
		{
dvander@1298
    75
			memcpy(g_FlagLetters, g_DefaultFlags, sizeof(AdminFlag) * 26);
dvander@1298
    76
			for (unsigned int i=0; i<20; i++)
dvander@1298
    77
			{
dvander@1298
    78
				g_FlagSet[i] = true;
dvander@1298
    79
			}
dvander@1298
    80
			g_FlagSet[25] = true;
dvander@1298
    81
		}
dvander@1298
    82
	}
dvander@1298
    83
private:
dvander@1298
    84
	bool Parse()
dvander@1298
    85
	{
dvander@1656
    86
		SMCStates states;
dvander@1656
    87
		SMCError error;
dvander@1298
    88
dvander@1298
    89
		m_bFileNameLogged = false;
dvander@1298
    90
		g_SourceMod.BuildPath(Path_SM, m_File, sizeof(m_File), "configs/admin_levels.cfg");
dvander@1298
    91
dvander@1656
    92
		if ((error = textparsers->ParseFile_SMC(m_File, this, &states))
dvander@1656
    93
			!= SMCError_Okay)
dvander@1298
    94
		{
dvander@1406
    95
			const char *err_string = textparsers->GetSMCErrorString(error);
dvander@1298
    96
			if (!err_string)
dvander@1298
    97
			{
dvander@1298
    98
				err_string = "Unknown error";
dvander@1298
    99
			}
dvander@1656
   100
			ParseError(NULL, "Error %d (%s)", error, err_string);
dvander@1298
   101
			return false;
dvander@1298
   102
		}
dvander@1298
   103
dvander@1298
   104
		return true;
dvander@1298
   105
	}
dvander@1298
   106
	void ReadSMC_ParseStart()
dvander@1298
   107
	{
dvander@1298
   108
		m_LevelState = LEVEL_STATE_NONE;
dvander@1298
   109
		m_IgnoreLevel = 0;
dvander@1298
   110
		memset(g_FlagSet, 0, sizeof(g_FlagSet));
dvander@1298
   111
	}
dvander@1656
   112
	SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
dvander@1298
   113
	{
dvander@1298
   114
		if (m_IgnoreLevel)
dvander@1298
   115
		{
dvander@1298
   116
			m_IgnoreLevel++;
dvander@1656
   117
			return SMCResult_Continue;
dvander@1298
   118
		}
dvander@1298
   119
dvander@1298
   120
		if (m_LevelState == LEVEL_STATE_NONE)
dvander@1298
   121
		{
dvander@1298
   122
			if (strcmp(name, "Levels") == 0)
dvander@1298
   123
			{
dvander@1299
   124
				m_LevelState = LEVEL_STATE_LEVELS;
dvander@1656
   125
			} 
dvander@1656
   126
			else 
dvander@1656
   127
			{
dvander@1298
   128
				m_IgnoreLevel++;
dvander@1298
   129
			}
dvander@1299
   130
		} else if (m_LevelState == LEVEL_STATE_LEVELS) {
dvander@1298
   131
			if (strcmp(name, "Flags") == 0)
dvander@1298
   132
			{
dvander@1299
   133
				m_LevelState = LEVEL_STATE_FLAGS;
dvander@1656
   134
			} 
dvander@1656
   135
			else 
dvander@1656
   136
			{
dvander@1298
   137
				m_IgnoreLevel++;
dvander@1298
   138
			}
dvander@1656
   139
		} 
dvander@1656
   140
		else 
dvander@1656
   141
		{
dvander@1298
   142
			m_IgnoreLevel++;
dvander@1298
   143
		}
dvander@1298
   144
dvander@1656
   145
		return SMCResult_Continue;
dvander@1298
   146
	}
dvander@1656
   147
	SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
dvander@1298
   148
	{
dvander@1299
   149
		if (m_LevelState != LEVEL_STATE_FLAGS || m_IgnoreLevel)
dvander@1298
   150
		{
dvander@1656
   151
			return SMCResult_Continue;
dvander@1298
   152
		}
dvander@1298
   153
dvander@1298
   154
		unsigned char c = (unsigned)value[0];
dvander@1298
   155
dvander@1298
   156
		if (c < (unsigned)'a' || c > (unsigned)'z')
dvander@1298
   157
		{
dvander@1656
   158
			ParseError(states, "Flag \"%c\" is not a lower-case ASCII letter", c);
dvander@1656
   159
			return SMCResult_Continue;
dvander@1298
   160
		}
dvander@1298
   161
dvander@1298
   162
		c -= (unsigned)'a';
dvander@1298
   163
dvander@1298
   164
		if (!g_Admins.FindFlag(key, &g_FlagLetters[c]))
dvander@1298
   165
		{
dvander@1656
   166
			ParseError(states, "Unrecognized admin level \"%s\"", key);
dvander@1656
   167
			return SMCResult_Continue;
dvander@1298
   168
		}
dvander@1298
   169
dvander@1298
   170
		g_FlagSet[c] = true;
dvander@1298
   171
dvander@1656
   172
		return SMCResult_Continue;
dvander@1298
   173
	}
dvander@1656
   174
	SMCResult ReadSMC_LeavingSection(const SMCStates *states)
dvander@1298
   175
	{
dvander@1298
   176
		if (m_IgnoreLevel)
dvander@1298
   177
		{
dvander@1298
   178
			m_IgnoreLevel--;
dvander@1656
   179
			return SMCResult_Continue;
dvander@1298
   180
		}
dvander@1298
   181
dvander@1298
   182
		if (m_LevelState == LEVEL_STATE_FLAGS)
dvander@1298
   183
		{
dvander@1298
   184
			m_LevelState = LEVEL_STATE_LEVELS;
dvander@1656
   185
			return SMCResult_Halt;
dvander@1656
   186
		} 
dvander@1656
   187
		else if (m_LevelState == LEVEL_STATE_LEVELS) 
dvander@1656
   188
		{
dvander@1298
   189
			m_LevelState = LEVEL_STATE_NONE;
dvander@1298
   190
		}
dvander@1298
   191
dvander@1656
   192
		return SMCResult_Continue;
dvander@1298
   193
	}
dvander@1656
   194
	void ParseError(const SMCStates *states, const char *message, ...)
dvander@1298
   195
	{
dvander@1298
   196
		va_list ap;
dvander@1298
   197
		char buffer[256];
dvander@1298
   198
dvander@1298
   199
		va_start(ap, message);
dvander@1298
   200
		UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
dvander@1298
   201
		va_end(ap);
dvander@1298
   202
dvander@1298
   203
		if (!m_bFileNameLogged)
dvander@1298
   204
		{
dvander@1298
   205
			g_Logger.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File);
dvander@1298
   206
			m_bFileNameLogged = true;
dvander@1298
   207
		}
dvander@1298
   208
dvander@1656
   209
		g_Logger.LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer);
dvander@1298
   210
	}
dvander@1298
   211
private:
dvander@1298
   212
	bool m_bFileNameLogged;
dvander@1298
   213
	char m_File[PLATFORM_MAX_PATH];
dvander@1298
   214
	int m_LevelState;
dvander@1298
   215
	int m_IgnoreLevel;
dvander@1298
   216
} s_FlagReader;
dvander@335
   217
dvander@335
   218
AdminCache::AdminCache()
dvander@335
   219
{
dvander@335
   220
	m_pStrings = new BaseStringTable(1024);
dvander@335
   221
	m_pMemory = m_pStrings->GetMemTable();
dvander@335
   222
	m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
dvander@404
   223
	m_FreeUserList = m_FirstUser = m_LastUser = INVALID_ADMIN_ID;
dvander@336
   224
	m_pCacheFwd = NULL;
dvander@404
   225
	m_FirstGroup = -1;
dvander@458
   226
	m_InvalidatingAdmins = false;
dvander@520
   227
	m_destroying = false;
dvander@335
   228
}
dvander@335
   229
dvander@335
   230
AdminCache::~AdminCache()
dvander@335
   231
{
dvander@520
   232
	m_destroying = true;
dvander@438
   233
	DumpAdminCache(AdminCache_Overrides, false);
dvander@438
   234
	DumpAdminCache(AdminCache_Groups, false);
dvander@438
   235
dvander@4081
   236
	List<AuthMethod *>::iterator iter;
dvander@405
   237
	for (iter=m_AuthMethods.begin();
dvander@405
   238
		 iter!=m_AuthMethods.end();
dvander@405
   239
		 iter++)
dvander@405
   240
	{
dvander@4081
   241
		delete *iter;
dvander@405
   242
	}
dvander@405
   243
dvander@335
   244
	delete m_pStrings;
dvander@335
   245
}
dvander@335
   246
dvander@404
   247
void AdminCache::OnSourceModStartup(bool late)
dvander@404
   248
{
dvander@404
   249
	RegisterAuthIdentType("steam");
dvander@404
   250
	RegisterAuthIdentType("name");
dvander@404
   251
	RegisterAuthIdentType("ip");
dvander@1298
   252
dvander@1298
   253
	NameFlag("reservation", Admin_Reservation);
dvander@1298
   254
	NameFlag("kick", Admin_Kick);
dvander@1298
   255
	NameFlag("generic", Admin_Generic);
dvander@1298
   256
	NameFlag("ban", Admin_Ban);
dvander@1298
   257
	NameFlag("unban", Admin_Unban);
dvander@1298
   258
	NameFlag("slay", Admin_Slay);
dvander@1298
   259
	NameFlag("changemap", Admin_Changemap);
dvander@1298
   260
	NameFlag("cvars", Admin_Convars);
dvander@1298
   261
	NameFlag("config", Admin_Config);
dvander@1298
   262
	NameFlag("chat", Admin_Chat);
dvander@1298
   263
	NameFlag("vote", Admin_Vote);
dvander@1298
   264
	NameFlag("password", Admin_Password);
dvander@1298
   265
	NameFlag("rcon", Admin_RCON);
dvander@1298
   266
	NameFlag("cheats", Admin_Cheats);
dvander@1298
   267
	NameFlag("root", Admin_Root);
dvander@1298
   268
	NameFlag("custom1", Admin_Custom1);
dvander@1298
   269
	NameFlag("custom2", Admin_Custom2);
dvander@1298
   270
	NameFlag("custom3", Admin_Custom3);
dvander@1298
   271
	NameFlag("custom4", Admin_Custom4);
dvander@1298
   272
	NameFlag("custom5", Admin_Custom5);
dvander@1298
   273
	NameFlag("custom6", Admin_Custom6);
dvander@404
   274
}
dvander@404
   275
dvander@335
   276
void AdminCache::OnSourceModAllInitialized()
dvander@335
   277
{
skamonkey@4139
   278
	m_pCacheFwd = forwardsys->CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell);
dvander@3872
   279
	sharesys->AddInterface(NULL, this);
dvander@335
   280
}
dvander@335
   281
dvander@1298
   282
void AdminCache::OnSourceModLevelChange(const char *mapName)
dvander@1298
   283
{
dvander@1965
   284
	int i;
dvander@1965
   285
	AdminFlag flag;
dvander@1965
   286
dvander@1298
   287
	/* For now, we only read these once per level. */
dvander@1298
   288
	s_FlagReader.LoadLevels();
dvander@1965
   289
dvander@1965
   290
	for (i = 0; i < 26; i++)
dvander@1965
   291
	{
dvander@1965
   292
		if (FindFlag('a' + i, &flag))
dvander@1965
   293
		{
dvander@1965
   294
			g_ReverseFlags[flag] = 'a' + i;
dvander@1965
   295
		}
dvander@1965
   296
		else
dvander@1965
   297
		{
dvander@1965
   298
			g_ReverseFlags[flag] = '?';
dvander@1965
   299
		}
dvander@1965
   300
	}
dvander@1298
   301
}
dvander@1298
   302
dvander@336
   303
void AdminCache::OnSourceModShutdown()
dvander@336
   304
{
skamonkey@4139
   305
	forwardsys->ReleaseForward(m_pCacheFwd);
dvander@336
   306
	m_pCacheFwd = NULL;
dvander@336
   307
}
dvander@336
   308
dvander@673
   309
void AdminCache::OnSourceModPluginsLoaded()
dvander@673
   310
{
dvander@673
   311
	DumpAdminCache(AdminCache_Overrides, true);
dvander@673
   312
	DumpAdminCache(AdminCache_Groups, true);
dvander@673
   313
}
dvander@673
   314
dvander@1298
   315
void AdminCache::NameFlag(const char *str, AdminFlag flag)
dvander@1298
   316
{
dvander@4081
   317
	m_LevelNames.insert(str, flag);
dvander@1298
   318
}
dvander@1298
   319
dvander@1298
   320
bool AdminCache::FindFlag(const char *str, AdminFlag *pFlag)
dvander@1298
   321
{
dvander@4081
   322
	return m_LevelNames.retrieve(str, pFlag);
dvander@1298
   323
}
dvander@1298
   324
dvander@433
   325
void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags)
dvander@335
   326
{
dvander@4081
   327
	FlagMap *map;
dvander@335
   328
	if (type == Override_Command)
dvander@4081
   329
		map = &m_CmdOverrides;
dvander@4081
   330
	else if (type == Override_CommandGroup)
dvander@4081
   331
		map = &m_CmdGrpOverrides;
dvander@4081
   332
	else
dvander@433
   333
		return;
dvander@433
   334
dvander@4081
   335
	map->insert(cmd, flags);
dvander@1435
   336
	g_ConCmds.UpdateAdminCmdFlags(cmd, type, flags, false);
dvander@335
   337
}
dvander@335
   338
dvander@433
   339
bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, FlagBits *pFlags)
dvander@335
   340
{
dvander@4081
   341
	FlagMap *map;
dvander@335
   342
	if (type == Override_Command)
dvander@4081
   343
		map = &m_CmdOverrides;
dvander@4081
   344
	else if (type == Override_CommandGroup)
dvander@4081
   345
		map = &m_CmdGrpOverrides;
dvander@4081
   346
	else
dvander@433
   347
		return false;
dvander@433
   348
dvander@4081
   349
	return map->retrieve(cmd, pFlags);
dvander@335
   350
}
dvander@335
   351
dvander@335
   352
void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
dvander@335
   353
{
dvander@335
   354
	if (type == Override_Command)
dvander@335
   355
	{
dvander@335
   356
		return _UnsetCommandOverride(cmd);
dvander@335
   357
	} else if (type == Override_CommandGroup) {
dvander@335
   358
		return _UnsetCommandGroupOverride(cmd);
dvander@335
   359
	}
dvander@335
   360
}
dvander@335
   361
dvander@335
   362
void AdminCache::_UnsetCommandGroupOverride(const char *group)
dvander@335
   363
{
dvander@4081
   364
	m_CmdGrpOverrides.remove(group);
dvander@1435
   365
	g_ConCmds.UpdateAdminCmdFlags(group, Override_CommandGroup, 0, true);
dvander@335
   366
}
dvander@335
   367
dvander@335
   368
void AdminCache::_UnsetCommandOverride(const char *cmd)
dvander@335
   369
{
dvander@4081
   370
	m_CmdOverrides.remove(cmd);
dvander@1435
   371
	g_ConCmds.UpdateAdminCmdFlags(cmd, Override_Command, 0, true);
dvander@335
   372
}
dvander@335
   373
dvander@335
   374
void AdminCache::DumpCommandOverrideCache(OverrideType type)
dvander@335
   375
{
dvander@4081
   376
	if (type == Override_Command)
dvander@4081
   377
		m_CmdOverrides.clear();
dvander@4081
   378
	else if (type == Override_CommandGroup)
dvander@4081
   379
		m_CmdGrpOverrides.clear();
dvander@335
   380
}
dvander@335
   381
dvander@404
   382
AdminId AdminCache::CreateAdmin(const char *name)
dvander@404
   383
{
dvander@404
   384
	AdminId id;
dvander@404
   385
	AdminUser *pUser;
dvander@404
   386
dvander@404
   387
	if (m_FreeUserList != INVALID_ADMIN_ID)
dvander@404
   388
	{
dvander@404
   389
		pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList);
dvander@404
   390
		assert(pUser->magic == USR_MAGIC_UNSET);
dvander@404
   391
		id = m_FreeUserList;
dvander@404
   392
		m_FreeUserList = pUser->next_user;
dvander@1965
   393
	}
dvander@1965
   394
	else
dvander@1965
   395
	{
dvander@404
   396
		id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser);
dvander@404
   397
		pUser->grp_size = 0;
dvander@404
   398
		pUser->grp_table = -1;
dvander@404
   399
	}
dvander@404
   400
dvander@433
   401
	pUser->flags = 0;
dvander@433
   402
	pUser->eflags = 0;
dvander@404
   403
	pUser->grp_count = 0;
dvander@404
   404
	pUser->password = -1;
dvander@404
   405
	pUser->magic = USR_MAGIC_SET;
dvander@405
   406
	pUser->auth.identidx = -1;
dvander@405
   407
	pUser->auth.index = 0;
dvander@1403
   408
	pUser->immunity_level = 0;
dvander@1349
   409
	pUser->serialchange = 1;
dvander@404
   410
dvander@404
   411
	if (m_FirstUser == INVALID_ADMIN_ID)
dvander@404
   412
	{
dvander@404
   413
		m_FirstUser = id;
dvander@404
   414
		m_LastUser = id;
dvander@1965
   415
	}
dvander@1965
   416
	else
dvander@1965
   417
	{
dvander@404
   418
		AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
dvander@404
   419
		pPrev->next_user = id;
dvander@404
   420
		pUser->prev_user = m_LastUser;
dvander@404
   421
		m_LastUser = id;
dvander@404
   422
	}
dvander@404
   423
dvander@1965
   424
	/* Since we always append to the tail, we should invalidate their next */
dvander@1965
   425
	pUser->next_user = -1;
dvander@1965
   426
dvander@404
   427
	if (name && name[0] != '\0')
dvander@404
   428
	{
dvander@1356
   429
		int nameidx = m_pStrings->AddString(name);
dvander@1356
   430
		pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1356
   431
		pUser->nameidx = nameidx;
dvander@404
   432
	}
dvander@1965
   433
	else
dvander@1965
   434
	{
dvander@1965
   435
		pUser->nameidx = -1;
dvander@1965
   436
	}
dvander@404
   437
dvander@404
   438
	return id;
dvander@404
   439
}
dvander@404
   440
dvander@335
   441
GroupId AdminCache::AddGroup(const char *group_name)
dvander@335
   442
{
dvander@4081
   443
	if (m_Groups.contains(group_name))
dvander@335
   444
		return INVALID_GROUP_ID;
dvander@335
   445
dvander@335
   446
	GroupId id;
dvander@335
   447
	AdminGroup *pGroup;
dvander@335
   448
	if (m_FreeGroupList != INVALID_GROUP_ID)
dvander@335
   449
	{
dvander@335
   450
		pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList);
dvander@335
   451
		assert(pGroup->magic == GRP_MAGIC_UNSET);
dvander@335
   452
		id = m_FreeGroupList;
dvander@335
   453
		m_FreeGroupList = pGroup->next_grp;
dvander@335
   454
	} else {
dvander@335
   455
		id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup);
dvander@335
   456
	}
dvander@335
   457
dvander@1403
   458
	pGroup->immunity_level = 0;
dvander@335
   459
	pGroup->immune_table = -1;
dvander@335
   460
	pGroup->magic = GRP_MAGIC_SET;
dvander@335
   461
	pGroup->next_grp = INVALID_GROUP_ID;
dvander@335
   462
	pGroup->pCmdGrpTable = NULL;
dvander@335
   463
	pGroup->pCmdTable = NULL;
dvander@433
   464
	pGroup->addflags = 0;
dvander@335
   465
dvander@335
   466
	if (m_FirstGroup == INVALID_GROUP_ID)
dvander@335
   467
	{
dvander@335
   468
		m_FirstGroup = id;
dvander@335
   469
		m_LastGroup = id;
dvander@335
   470
		pGroup->prev_grp = INVALID_GROUP_ID;
dvander@335
   471
	} else {
dvander@335
   472
		AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
dvander@335
   473
		assert(pPrev->magic == GRP_MAGIC_SET);
dvander@335
   474
		pPrev->next_grp = id;
dvander@335
   475
		pGroup->prev_grp = m_LastGroup;
dvander@335
   476
		m_LastGroup = id;
dvander@335
   477
	}
dvander@335
   478
dvander@1356
   479
	int nameidx = m_pStrings->AddString(group_name);
dvander@1356
   480
	pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@1356
   481
	pGroup->nameidx = nameidx;
dvander@404
   482
dvander@4081
   483
	m_Groups.insert(group_name, id);
dvander@335
   484
	return id;
dvander@335
   485
}
dvander@335
   486
dvander@335
   487
GroupId AdminCache::FindGroupByName(const char *group_name)
dvander@335
   488
{
dvander@4081
   489
	GroupId id;
dvander@4081
   490
	if (!m_Groups.retrieve(group_name, &id))
dvander@335
   491
		return INVALID_GROUP_ID;
dvander@335
   492
dvander@335
   493
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   494
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   495
		return INVALID_GROUP_ID;
dvander@335
   496
dvander@335
   497
	return id;
dvander@335
   498
}
dvander@335
   499
dvander@335
   500
void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled)
dvander@335
   501
{
dvander@335
   502
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   503
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   504
	{
dvander@335
   505
		return;
dvander@335
   506
	}
dvander@335
   507
dvander@433
   508
	if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL)
dvander@335
   509
	{
dvander@335
   510
		return;
dvander@335
   511
	}
dvander@335
   512
dvander@436
   513
	FlagBits bits = (1<<(FlagBits)flag);
dvander@436
   514
dvander@436
   515
	if (enabled)
dvander@436
   516
	{
dvander@436
   517
		pGroup->addflags |= bits;
dvander@436
   518
	} else {
dvander@436
   519
		pGroup->addflags &= ~bits;
dvander@436
   520
	}
dvander@335
   521
}
dvander@335
   522
dvander@335
   523
bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag)
dvander@335
   524
{
dvander@335
   525
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   526
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   527
	{
dvander@335
   528
		return false;
dvander@335
   529
	}
dvander@335
   530
dvander@433
   531
	if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL)
dvander@335
   532
	{
dvander@335
   533
		return false;
dvander@335
   534
	}
dvander@335
   535
dvander@433
   536
	FlagBits bit = 1<<(FlagBits)flag;
dvander@433
   537
	return ((pGroup->addflags & bit) == bit);
dvander@335
   538
}
dvander@335
   539
dvander@433
   540
FlagBits AdminCache::GetGroupAddFlags(GroupId id)
dvander@335
   541
{
dvander@335
   542
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   543
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   544
	{
dvander@335
   545
		return 0;
dvander@335
   546
	}
dvander@335
   547
dvander@433
   548
	return pGroup->addflags;
dvander@335
   549
}
dvander@335
   550
dvander@1356
   551
const char *AdminCache::GetGroupName(GroupId gid)
dvander@1356
   552
{
dvander@1356
   553
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@1356
   554
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@1356
   555
	{
dvander@1403
   556
		return NULL;
dvander@1356
   557
	}
dvander@1356
   558
dvander@1356
   559
	return m_pStrings->GetString(pGroup->nameidx);
dvander@1356
   560
}
dvander@1356
   561
dvander@335
   562
void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled)
dvander@335
   563
{
dvander@335
   564
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   565
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   566
	{
dvander@335
   567
		return;
dvander@335
   568
	}
dvander@335
   569
dvander@1403
   570
	unsigned int level = 0;
dvander@1403
   571
dvander@1403
   572
	if (enabled)
dvander@335
   573
	{
dvander@1403
   574
		if (type == Immunity_Default)
dvander@1403
   575
		{
dvander@1403
   576
			level = 1;
dvander@1403
   577
		} else if (type == Immunity_Global) {
dvander@1403
   578
			level = 2;
dvander@1403
   579
		}
dvander@1403
   580
		if (level > pGroup->immunity_level)
dvander@1403
   581
		{
dvander@1403
   582
			pGroup->immunity_level = level;
dvander@1403
   583
		}
dvander@1403
   584
	} else {
dvander@1403
   585
		pGroup->immunity_level = 0;
dvander@1403
   586
	}
dvander@335
   587
}
dvander@335
   588
dvander@335
   589
bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type)
dvander@335
   590
{
dvander@335
   591
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   592
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   593
	{
dvander@335
   594
		return false;
dvander@335
   595
	}
dvander@335
   596
dvander@1403
   597
	if (type == Immunity_Default && pGroup->immunity_level >= 1)
dvander@335
   598
	{
dvander@1403
   599
		return true;
dvander@1403
   600
	} else if (type == Immunity_Global && pGroup->immunity_level >= 2) {
dvander@1403
   601
		return true;
dvander@335
   602
	}
dvander@335
   603
dvander@335
   604
	return false;
dvander@335
   605
}
dvander@335
   606
dvander@335
   607
void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id)
dvander@335
   608
{
dvander@1356
   609
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(other_id);
dvander@335
   610
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   611
	{
dvander@335
   612
		return;
dvander@335
   613
	}
dvander@335
   614
dvander@1356
   615
	pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@1356
   616
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   617
	{
dvander@335
   618
		return;
dvander@335
   619
	}
dvander@335
   620
dvander@335
   621
	/* We always need to resize the immunity table */
dvander@335
   622
	int *table, tblidx;
dvander@1356
   623
	if (pGroup->immune_table == -1)
dvander@335
   624
	{
dvander@335
   625
		tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table);
dvander@1356
   626
		pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   627
		table[0] = 0;
dvander@335
   628
	} else {
dvander@1356
   629
		int *old_table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@433
   630
		/* Break out if this group is already in the list */
dvander@433
   631
		for (int i=0; i<old_table[0]; i++)
dvander@433
   632
		{
dvander@433
   633
			if (old_table[1+i] == other_id)
dvander@433
   634
			{
dvander@433
   635
				return;
dvander@433
   636
			}
dvander@433
   637
		}
dvander@335
   638
		tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table);
dvander@433
   639
		/* Get the old address again in case of resize */
dvander@1356
   640
		pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@1356
   641
		old_table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@335
   642
		table[0] = old_table[0];
dvander@335
   643
		for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++)
dvander@335
   644
		{
dvander@335
   645
			table[i] = old_table[i];
dvander@335
   646
		}
dvander@335
   647
	}
dvander@335
   648
dvander@335
   649
	/* Assign */
dvander@1356
   650
	pGroup->immune_table = tblidx;
dvander@335
   651
dvander@335
   652
	/* Add to the array */
dvander@335
   653
	table[0]++;
dvander@335
   654
	table[table[0]] = other_id;
dvander@335
   655
}
dvander@335
   656
dvander@335
   657
unsigned int AdminCache::GetGroupImmunityCount(GroupId id)
dvander@335
   658
{
dvander@335
   659
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   660
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   661
	{
dvander@335
   662
		return 0;
dvander@335
   663
	}
dvander@335
   664
dvander@335
   665
	if (pGroup->immune_table == -1)
dvander@335
   666
	{
dvander@335
   667
		return 0;
dvander@335
   668
	}
dvander@335
   669
dvander@335
   670
	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@335
   671
dvander@335
   672
	return table[0];
dvander@335
   673
}
dvander@335
   674
dvander@335
   675
GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number)
dvander@335
   676
{
dvander@335
   677
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   678
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   679
	{
dvander@335
   680
		return INVALID_GROUP_ID;
dvander@335
   681
	}
dvander@335
   682
dvander@335
   683
	if (pGroup->immune_table == -1)
dvander@335
   684
	{
dvander@335
   685
		return INVALID_GROUP_ID;
dvander@335
   686
	}
dvander@335
   687
dvander@335
   688
	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@335
   689
	if (number >= (unsigned int)table[0])
dvander@335
   690
	{
dvander@335
   691
		return INVALID_GROUP_ID;
dvander@335
   692
	}
dvander@335
   693
dvander@335
   694
	return table[1 + number];
dvander@335
   695
}
dvander@335
   696
dvander@335
   697
void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule)
dvander@335
   698
{
dvander@335
   699
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   700
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   701
	{
dvander@335
   702
		return;
dvander@335
   703
	}
dvander@335
   704
dvander@4081
   705
	OverrideMap *map;
dvander@335
   706
	if (type == Override_Command)
dvander@335
   707
	{
dvander@335
   708
		if (pGroup->pCmdTable == NULL)
dvander@4081
   709
			pGroup->pCmdTable = new OverrideMap();
dvander@4081
   710
		map = pGroup->pCmdTable;
dvander@335
   711
	} else if (type == Override_CommandGroup) {
dvander@335
   712
		if (pGroup->pCmdGrpTable == NULL)
dvander@4081
   713
			pGroup->pCmdGrpTable = new OverrideMap();
dvander@4081
   714
		map = pGroup->pCmdGrpTable;
dvander@335
   715
	} else {
dvander@335
   716
		return;
dvander@335
   717
	}
dvander@335
   718
dvander@4081
   719
	map->insert(name, rule);
dvander@335
   720
}
dvander@335
   721
dvander@335
   722
bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule)
dvander@335
   723
{
dvander@335
   724
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   725
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   726
	{
dvander@335
   727
		return false;
dvander@335
   728
	}
dvander@335
   729
dvander@4081
   730
	OverrideMap *map;
dvander@335
   731
	if (type == Override_Command)
dvander@335
   732
	{
dvander@335
   733
		if (pGroup->pCmdTable == NULL)
dvander@335
   734
			return false;
dvander@4081
   735
		map = pGroup->pCmdTable;
dvander@335
   736
	} else if (type == Override_CommandGroup) {
dvander@335
   737
		if (pGroup->pCmdGrpTable == NULL)
dvander@335
   738
			return false;
dvander@4081
   739
		map = pGroup->pCmdGrpTable;
dvander@335
   740
	} else {
dvander@335
   741
		return false;
dvander@335
   742
	}
dvander@335
   743
dvander@4081
   744
	return map->retrieve(name, pRule);
dvander@335
   745
}
dvander@335
   746
dvander@4081
   747
AuthMethod *AdminCache::GetMethodByIndex(unsigned int index)
dvander@404
   748
{
dvander@4081
   749
	List<AuthMethod *>::iterator iter;
dvander@404
   750
	for (iter=m_AuthMethods.begin();
dvander@404
   751
		 iter!=m_AuthMethods.end();
dvander@404
   752
		 iter++)
dvander@404
   753
	{
dvander@404
   754
		if (index-- == 0)
dvander@404
   755
		{
dvander@4081
   756
			return *iter;
dvander@404
   757
		}
dvander@404
   758
	}
dvander@404
   759
dvander@404
   760
	return NULL;
dvander@404
   761
}
dvander@404
   762
dvander@404
   763
bool AdminCache::InvalidateAdmin(AdminId id)
dvander@404
   764
{
dvander@404
   765
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
   766
	AdminUser *pOther;
dvander@404
   767
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
   768
	{
dvander@404
   769
		return false;
dvander@404
   770
	}
dvander@404
   771
dvander@520
   772
	if (!m_InvalidatingAdmins && !m_destroying)
dvander@458
   773
	{
dvander@458
   774
		g_Players.ClearAdminId(id);
dvander@458
   775
	}
dvander@458
   776
dvander@404
   777
	/* Unlink from the dbl link list */
dvander@404
   778
	if (id == m_FirstUser && id == m_LastUser)
dvander@404
   779
	{
dvander@404
   780
		m_FirstUser = INVALID_ADMIN_ID;
dvander@404
   781
		m_LastUser = INVALID_ADMIN_ID;
dvander@404
   782
	} else if (id == m_FirstUser) {
dvander@404
   783
		m_FirstUser = pUser->next_user;
dvander@404
   784
		pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser);
dvander@404
   785
		pOther->prev_user = INVALID_ADMIN_ID;
dvander@404
   786
	} else if (id == m_LastUser) {
dvander@404
   787
		m_LastUser = pUser->prev_user;
dvander@404
   788
		pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
dvander@404
   789
		pOther->next_user = INVALID_ADMIN_ID;
dvander@404
   790
	} else {
dvander@404
   791
		pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user);
dvander@404
   792
		pOther->next_user = pUser->next_user;
dvander@404
   793
		pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user);
dvander@404
   794
		pOther->prev_user = pUser->prev_user;
dvander@404
   795
	}
dvander@404
   796
dvander@404
   797
	/* Unlink from auth tables */
dvander@405
   798
	if (pUser->auth.identidx != -1)
dvander@404
   799
	{
dvander@4081
   800
		AuthMethod *method = GetMethodByIndex(pUser->auth.index);
dvander@4081
   801
		if (method)
dvander@4081
   802
			method->identities.remove(m_pStrings->GetString(pUser->auth.identidx));
dvander@404
   803
	}
dvander@404
   804
dvander@404
   805
	/* Clear table counts */
dvander@404
   806
	pUser->grp_count = 0;
dvander@405
   807
	
dvander@404
   808
	/* Link into free list */
dvander@404
   809
	pUser->magic = USR_MAGIC_UNSET;
dvander@404
   810
	pUser->next_user = m_FreeUserList;
dvander@404
   811
	m_FreeUserList = id;
dvander@404
   812
dvander@1349
   813
	/* Unset serial change */
dvander@1349
   814
	pUser->serialchange = 0;
dvander@1349
   815
dvander@404
   816
	return true;
dvander@404
   817
}
dvander@404
   818
dvander@404
   819
dvander@335
   820
void AdminCache::InvalidateGroup(GroupId id)
dvander@335
   821
{
dvander@335
   822
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   823
	AdminGroup *pOther;
dvander@335
   824
dvander@335
   825
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   826
	{
dvander@335
   827
		return;
dvander@335
   828
	}
dvander@335
   829
dvander@335
   830
	const char *str = m_pStrings->GetString(pGroup->nameidx);
dvander@4081
   831
	m_Groups.remove(str);
dvander@335
   832
dvander@335
   833
	/* Unlink from the live dbllink list */
dvander@335
   834
	if (id == m_FirstGroup && id == m_LastGroup)
dvander@335
   835
	{
dvander@335
   836
		m_LastGroup = INVALID_GROUP_ID;
dvander@335
   837
		m_FirstGroup = INVALID_GROUP_ID;
dvander@335
   838
	} else if (id == m_FirstGroup) {
dvander@335
   839
		m_FirstGroup = pGroup->next_grp;
dvander@335
   840
		pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup);
dvander@335
   841
		pOther->prev_grp = INVALID_GROUP_ID;
dvander@335
   842
	} else if (id == m_LastGroup) {
dvander@335
   843
		m_LastGroup = pGroup->prev_grp;
dvander@335
   844
		pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
dvander@335
   845
		pOther->next_grp = INVALID_GROUP_ID;
dvander@335
   846
	} else {
dvander@335
   847
		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp);
dvander@335
   848
		pOther->next_grp = pGroup->next_grp;
dvander@335
   849
		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp);
dvander@335
   850
		pOther->prev_grp = pGroup->prev_grp;
dvander@335
   851
	}
dvander@335
   852
dvander@4081
   853
	/* Free any used memory */
dvander@4081
   854
	delete pGroup->pCmdGrpTable;
dvander@4081
   855
	pGroup->pCmdGrpTable = NULL;
dvander@4081
   856
	delete pGroup->pCmdTable;
dvander@4081
   857
	pGroup->pCmdTable = NULL;
dvander@335
   858
dvander@335
   859
	/* Link into the free list */
dvander@335
   860
	pGroup->magic = GRP_MAGIC_UNSET;
dvander@335
   861
	pGroup->next_grp = m_FreeGroupList;
dvander@335
   862
	m_FreeGroupList = id;
dvander@335
   863
dvander@404
   864
	int idx = m_FirstUser;
dvander@404
   865
	AdminUser *pUser;
dvander@404
   866
	int *table;
dvander@404
   867
	while (idx != INVALID_ADMIN_ID)
dvander@404
   868
	{
dvander@404
   869
		pUser = (AdminUser *)m_pMemory->GetAddress(idx);
dvander@404
   870
		if (pUser->grp_count > 0)
dvander@404
   871
		{
dvander@404
   872
			table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
   873
			for (unsigned int i=0; i<pUser->grp_count; i++)
dvander@404
   874
			{
dvander@404
   875
				if (table[i] == id)
dvander@404
   876
				{
dvander@404
   877
					/* We have to remove this entry */
dvander@404
   878
					for (unsigned int j=i+1; j<pUser->grp_count; j++)
dvander@404
   879
					{
dvander@404
   880
						/* Move everything down by one */
dvander@404
   881
						table[j-1] = table[j];
dvander@404
   882
					}
dvander@404
   883
					/* Decrease count */
dvander@404
   884
					pUser->grp_count--;
dvander@404
   885
					/* Recalculate effective flags */
dvander@433
   886
					pUser->eflags = pUser->flags;
dvander@404
   887
					for (unsigned int j=0; j<pUser->grp_count; j++)
dvander@404
   888
					{
dvander@404
   889
						pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]);
dvander@433
   890
						pUser->eflags |= pOther->addflags;
dvander@404
   891
					}
dvander@1349
   892
					/* Mark as changed */
dvander@1349
   893
					pUser->serialchange++;
dvander@404
   894
					/* Break now, duplicates aren't allowed */
dvander@404
   895
					break;
dvander@404
   896
				}
dvander@404
   897
			}
dvander@404
   898
		}
dvander@404
   899
		idx = pUser->next_user;
dvander@404
   900
	}
dvander@335
   901
}
dvander@335
   902
dvander@335
   903
void AdminCache::InvalidateGroupCache()
dvander@335
   904
{
dvander@335
   905
	/* Nuke the free list */
dvander@335
   906
	m_FreeGroupList = -1;
dvander@335
   907
dvander@335
   908
	/* Nuke reverse lookups */
dvander@4081
   909
	m_Groups.clear();
dvander@335
   910
dvander@335
   911
	/* Free memory on groups */
dvander@335
   912
	GroupId cur = m_FirstGroup;
dvander@335
   913
	AdminGroup *pGroup;
dvander@335
   914
	while (cur != INVALID_GROUP_ID)
dvander@335
   915
	{
dvander@335
   916
		pGroup = (AdminGroup *)m_pMemory->GetAddress(cur);
dvander@335
   917
		assert(pGroup->magic == GRP_MAGIC_SET);
dvander@4081
   918
		delete pGroup->pCmdGrpTable;
dvander@4081
   919
		delete pGroup->pCmdTable;
dvander@335
   920
		cur = pGroup->next_grp;
dvander@335
   921
	}
dvander@335
   922
dvander@335
   923
	m_FirstGroup = INVALID_GROUP_ID;
dvander@335
   924
	m_LastGroup = INVALID_GROUP_ID;
dvander@335
   925
dvander@404
   926
	InvalidateAdminCache(false);
dvander@335
   927
dvander@335
   928
	/* Reset the memory table */
dvander@335
   929
	m_pMemory->Reset();
dvander@335
   930
}
dvander@336
   931
dvander@336
   932
void AdminCache::AddAdminListener(IAdminListener *pListener)
dvander@336
   933
{
dvander@336
   934
	m_hooks.push_back(pListener);
dvander@336
   935
}
dvander@336
   936
dvander@336
   937
void AdminCache::RemoveAdminListener(IAdminListener *pListener)
dvander@336
   938
{
dvander@336
   939
	m_hooks.remove(pListener);
dvander@336
   940
}
dvander@336
   941
dvander@404
   942
void AdminCache::RegisterAuthIdentType(const char *name)
dvander@404
   943
{
dvander@4081
   944
	if (m_AuthTables.contains(name))
dvander@404
   945
		return;
dvander@404
   946
dvander@4081
   947
	AuthMethod *method = new AuthMethod(name);
dvander@404
   948
	m_AuthMethods.push_back(method);
dvander@4081
   949
	m_AuthTables.insert(name, method);
dvander@404
   950
}
dvander@404
   951
dvander@404
   952
void AdminCache::InvalidateAdminCache(bool unlink_admins)
dvander@404
   953
{
dvander@458
   954
	m_InvalidatingAdmins = true;
dvander@520
   955
	if (!m_destroying)
dvander@520
   956
	{
dvander@520
   957
		g_Players.ClearAllAdmins();
dvander@520
   958
	}
dvander@404
   959
	/* Wipe the identity cache first */
dvander@4081
   960
	List<AuthMethod *>::iterator iter;
dvander@404
   961
	for (iter=m_AuthMethods.begin();
dvander@404
   962
		 iter!=m_AuthMethods.end();
dvander@404
   963
		 iter++)
dvander@404
   964
	{
dvander@4081
   965
		(*iter)->identities.clear();
dvander@404
   966
	}
dvander@404
   967
	
dvander@405
   968
	if (unlink_admins)
dvander@404
   969
	{
dvander@405
   970
		while (m_FirstUser != INVALID_ADMIN_ID)
dvander@405
   971
		{
dvander@405
   972
			InvalidateAdmin(m_FirstUser);
dvander@405
   973
		}
dvander@405
   974
	} else {
dvander@405
   975
		m_FirstUser = -1;
dvander@405
   976
		m_LastUser = -1;
dvander@405
   977
		m_FreeUserList = -1;
dvander@404
   978
	}
dvander@458
   979
	m_InvalidatingAdmins = false;
dvander@404
   980
}
dvander@404
   981
dvander@438
   982
void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
dvander@336
   983
{
dvander@438
   984
	List<IAdminListener *>::iterator iter;
dvander@438
   985
	IAdminListener *pListener;
dvander@438
   986
	cell_t result;
dvander@438
   987
dvander@438
   988
	if (part == AdminCache_Overrides)
dvander@336
   989
	{
dvander@336
   990
		DumpCommandOverrideCache(Override_Command);
dvander@336
   991
		DumpCommandOverrideCache(Override_CommandGroup);
dvander@520
   992
		if (rebuild && !m_destroying)
dvander@438
   993
		{
dvander@438
   994
			for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
   995
			{
dvander@438
   996
				pListener = (*iter);
dvander@438
   997
				pListener->OnRebuildOverrideCache();
dvander@438
   998
			}
dvander@438
   999
			m_pCacheFwd->PushCell(part);
dvander@438
  1000
			m_pCacheFwd->Execute(&result);
dvander@438
  1001
		}
dvander@438
  1002
	} else if (part == AdminCache_Groups || part == AdminCache_Admins) {
dvander@438
  1003
		if (part == AdminCache_Groups)
dvander@438
  1004
		{
dvander@438
  1005
			InvalidateGroupCache();
dvander@520
  1006
			if (rebuild && !m_destroying)
dvander@438
  1007
			{
dvander@438
  1008
				for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
  1009
				{
dvander@438
  1010
					pListener = (*iter);
dvander@438
  1011
					pListener->OnRebuildGroupCache();
dvander@438
  1012
				}
dvander@438
  1013
				m_pCacheFwd->PushCell(part);
dvander@438
  1014
				m_pCacheFwd->Execute(&result);
dvander@438
  1015
			}
dvander@438
  1016
		}
dvander@404
  1017
		InvalidateAdminCache(true);
dvander@520
  1018
		if (rebuild && !m_destroying)
dvander@336
  1019
		{
dvander@438
  1020
			for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
  1021
			{
dvander@438
  1022
				pListener = (*iter);
dvander@438
  1023
				pListener->OnRebuildAdminCache((part == AdminCache_Groups));
dvander@438
  1024
			}
dvander@438
  1025
			m_pCacheFwd->PushCell(AdminCache_Admins);
dvander@438
  1026
			m_pCacheFwd->Execute(&result);
dvander@1165
  1027
			g_Players.RecheckAnyAdmins();
dvander@336
  1028
		}
dvander@336
  1029
	}
dvander@336
  1030
}
dvander@404
  1031
dvander@404
  1032
const char *AdminCache::GetAdminName(AdminId id)
dvander@404
  1033
{
dvander@404
  1034
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1035
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1036
	{
dvander@404
  1037
		return NULL;
dvander@404
  1038
	}
dvander@404
  1039
dvander@404
  1040
	return m_pStrings->GetString(pUser->nameidx);
dvander@404
  1041
}
dvander@404
  1042
dvander@405
  1043
bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index)
dvander@405
  1044
{
dvander@4081
  1045
	List<AuthMethod *>::iterator iter;
dvander@405
  1046
	unsigned int index = 0;
dvander@405
  1047
	for (iter=m_AuthMethods.begin();
dvander@405
  1048
		 iter!=m_AuthMethods.end();
dvander@405
  1049
		 iter++,index++)
dvander@405
  1050
	{
dvander@4081
  1051
		if ((*iter)->name.compare(name) == 0)
dvander@405
  1052
		{
dvander@405
  1053
			*_index = index;
dvander@405
  1054
			return true;
dvander@405
  1055
		}
dvander@405
  1056
	}
dvander@405
  1057
dvander@405
  1058
	return false;
dvander@405
  1059
}
dvander@405
  1060
dvander@404
  1061
bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident)
dvander@404
  1062
{
rbutler14@2491
  1063
	if (ident[0] == '\0')
rbutler14@2490
  1064
	{
rbutler14@2490
  1065
		return false;
rbutler14@2490
  1066
	}
rbutler14@2490
  1067
dvander@404
  1068
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1069
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1070
	{
dvander@404
  1071
		return false;
dvander@404
  1072
	}
dvander@404
  1073
dvander@4081
  1074
	AuthMethod *method;
dvander@4081
  1075
	if (!m_AuthTables.retrieve(auth, &method))
dvander@404
  1076
		return false;
dvander@404
  1077
pred@2420
  1078
	/* If the id was a steam id strip off the STEAM_*: part */
pred@2420
  1079
	if (strcmp(auth, "steam") == 0 && strncmp(ident, "STEAM_", 6) == 0)
pred@2420
  1080
	{
pred@2420
  1081
		ident += 8;
pred@2420
  1082
	}
pred@2420
  1083
dvander@4081
  1084
	if (method->identities.contains(ident))
dvander@404
  1085
		return false;
dvander@404
  1086
dvander@1356
  1087
	int i_ident = m_pStrings->AddString(ident);
dvander@1356
  1088
dvander@1356
  1089
	pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1356
  1090
	pUser->auth.identidx = i_ident;
dvander@405
  1091
	GetMethodIndex(auth, &pUser->auth.index);
dvander@405
  1092
dvander@4081
  1093
	return method->identities.insert(ident, id);
dvander@404
  1094
}
dvander@404
  1095
dvander@404
  1096
AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity)
dvander@404
  1097
{
dvander@4081
  1098
	AuthMethod *method;
dvander@4081
  1099
	if (!m_AuthTables.retrieve(auth, &method))
dvander@404
  1100
		return INVALID_ADMIN_ID;
dvander@404
  1101
pred@2420
  1102
	/* If the id was a steam id strip off the STEAM_*: part */
pred@2420
  1103
	if (strcmp(auth, "steam") == 0 && strncmp(identity, "STEAM_", 6) == 0)
pred@2420
  1104
	{
pred@2420
  1105
		identity += 8;
pred@2420
  1106
	}
pred@2420
  1107
dvander@4081
  1108
	AdminId id;
dvander@4081
  1109
	if (!method->identities.retrieve(identity, &id))
dvander@404
  1110
		return INVALID_ADMIN_ID;
dvander@4081
  1111
	return id;
dvander@404
  1112
}
dvander@404
  1113
dvander@404
  1114
void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled)
dvander@404
  1115
{
dvander@404
  1116
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1117
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1118
	{
dvander@404
  1119
		return;
dvander@404
  1120
	}
dvander@404
  1121
dvander@433
  1122
	if (flag < Admin_Reservation
dvander@404
  1123
		|| flag >= AdminFlags_TOTAL)
dvander@404
  1124
	{
dvander@404
  1125
		return;
dvander@404
  1126
	}
dvander@436
  1127
	
dvander@436
  1128
	FlagBits bits = (1<<(FlagBits)flag);
dvander@404
  1129
dvander@436
  1130
	if (enabled)
dvander@436
  1131
	{
dvander@436
  1132
		pUser->flags |= bits;
dvander@436
  1133
		pUser->eflags |= bits;
dvander@436
  1134
	} else {
dvander@436
  1135
		pUser->flags &= ~bits;
dvander@436
  1136
		pUser->eflags &= ~bits;
dvander@436
  1137
	}
dvander@1349
  1138
dvander@1349
  1139
	pUser->serialchange++;
dvander@404
  1140
}
dvander@404
  1141
dvander@404
  1142
bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode)
dvander@404
  1143
{
dvander@404
  1144
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1145
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1146
	{
dvander@404
  1147
		return false;
dvander@404
  1148
	}
dvander@404
  1149
dvander@433
  1150
	if (flag < Admin_Reservation
dvander@404
  1151
		|| flag >= AdminFlags_TOTAL)
dvander@404
  1152
	{
dvander@404
  1153
		return false;
dvander@404
  1154
	}
dvander@404
  1155
dvander@433
  1156
	FlagBits bit = (1<<(FlagBits)flag);
dvander@433
  1157
dvander@404
  1158
	if (mode == Access_Real)
dvander@404
  1159
	{
dvander@433
  1160
		return ((pUser->flags & bit) == bit);
dvander@404
  1161
	} else if (mode == Access_Effective) {
dvander@907
  1162
		bool has_bit = ((pUser->eflags & bit) == bit);
dvander@907
  1163
		if (!has_bit && flag != Admin_Root && ((pUser->eflags & ADMFLAG_ROOT) == ADMFLAG_ROOT))
dvander@907
  1164
		{
dvander@907
  1165
			has_bit = true;
dvander@907
  1166
		}
dvander@907
  1167
		return has_bit;
dvander@404
  1168
	}
dvander@404
  1169
dvander@404
  1170
	return false;
dvander@404
  1171
}
dvander@404
  1172
dvander@433
  1173
FlagBits AdminCache::GetAdminFlags(AdminId id, AccessMode mode)
dvander@404
  1174
{
dvander@404
  1175
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1176
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1177
	{
dvander@404
  1178
		return 0;
dvander@404
  1179
	}
dvander@404
  1180
dvander@404
  1181
	if (mode == Access_Real)
dvander@404
  1182
	{
dvander@433
  1183
		return pUser->flags;
dvander@404
  1184
	} else if (mode == Access_Effective) {
dvander@433
  1185
		return pUser->eflags;
dvander@404
  1186
	}
dvander@404
  1187
dvander@433
  1188
	return 0;
dvander@404
  1189
}
dvander@404
  1190
dvander@458
  1191
void AdminCache::SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits)
dvander@458
  1192
{
dvander@458
  1193
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@458
  1194
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@458
  1195
	{
dvander@458
  1196
		return;
dvander@458
  1197
	}
dvander@458
  1198
dvander@458
  1199
	if (mode == Access_Real)
dvander@458
  1200
	{
dvander@458
  1201
		pUser->flags = bits;
dvander@458
  1202
		pUser->eflags = bits;
dvander@458
  1203
	} else if (mode == Access_Effective) {
dvander@458
  1204
		pUser->eflags = bits;
dvander@458
  1205
	}
dvander@1349
  1206
dvander@1349
  1207
	pUser->serialchange++;
dvander@458
  1208
}
dvander@458
  1209
dvander@404
  1210
bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid)
dvander@404
  1211
{
dvander@404
  1212
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1213
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1214
	{
dvander@404
  1215
		return false;
dvander@404
  1216
	}
dvander@404
  1217
dvander@404
  1218
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@405
  1219
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@404
  1220
	{
dvander@404
  1221
		return false;
dvander@404
  1222
	}
dvander@404
  1223
dvander@433
  1224
	/* First check for duplicates */
dvander@433
  1225
	if (pUser->grp_count != 0)
dvander@433
  1226
	{
dvander@433
  1227
		int *temp_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@433
  1228
		for (unsigned int i=0; i<pUser->grp_count; i++)
dvander@433
  1229
		{
dvander@433
  1230
			if (temp_table[i] == gid)
dvander@433
  1231
			{
dvander@433
  1232
				return false;
dvander@433
  1233
			}
dvander@433
  1234
		}
dvander@433
  1235
	}
dvander@433
  1236
dvander@404
  1237
	int *table;
dvander@404
  1238
	if (pUser->grp_count + 1 > pUser->grp_size)
dvander@404
  1239
	{
dvander@404
  1240
		int new_size = 0;
dvander@404
  1241
		int tblidx;
dvander@404
  1242
		
dvander@404
  1243
		if (pUser->grp_size == 0)
dvander@404
  1244
		{
dvander@404
  1245
			new_size = 2;
dvander@404
  1246
		} else {
dvander@404
  1247
			new_size = pUser->grp_size * 2;
dvander@404
  1248
		}
dvander@404
  1249
		
dvander@404
  1250
		/* Create and refresh pointers */
dvander@404
  1251
		tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table);
dvander@404
  1252
		pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1253
		pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@404
  1254
dvander@404
  1255
		/* Copy old data if necessary */
dvander@404
  1256
		if (pUser->grp_table != -1)
dvander@404
  1257
		{
dvander@404
  1258
			int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1259
			memcpy(table, old_table, sizeof(int) * pUser->grp_count);
dvander@404
  1260
		}
dvander@404
  1261
		pUser->grp_table = tblidx;
dvander@404
  1262
		pUser->grp_size = new_size;
dvander@404
  1263
	} else {
dvander@404
  1264
		table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1265
	}
dvander@404
  1266
dvander@404
  1267
	table[pUser->grp_count] = gid;
dvander@404
  1268
	pUser->grp_count++;
dvander@404
  1269
dvander@434
  1270
	/* Compute new effective permissions */
dvander@433
  1271
	pUser->eflags |= pGroup->addflags;
dvander@404
  1272
dvander@1403
  1273
	if (pGroup->immunity_level > pUser->immunity_level)
dvander@434
  1274
	{
dvander@1403
  1275
		pUser->immunity_level = pGroup->immunity_level;
dvander@434
  1276
	}
dvander@434
  1277
dvander@1349
  1278
	pUser->serialchange++;
dvander@1349
  1279
dvander@404
  1280
	return true;
dvander@404
  1281
}
dvander@404
  1282
dvander@458
  1283
bool AdminCache::IsValidAdmin(AdminId id)
dvander@458
  1284
{
dvander@458
  1285
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@458
  1286
	return (pUser != NULL && pUser->magic == USR_MAGIC_SET);
dvander@458
  1287
}
dvander@458
  1288
dvander@404
  1289
unsigned int AdminCache::GetAdminGroupCount(AdminId id)
dvander@404
  1290
{
dvander@404
  1291
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1292
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1293
	{
dvander@404
  1294
		return 0;
dvander@404
  1295
	}
dvander@404
  1296
dvander@404
  1297
	return pUser->grp_count;
dvander@404
  1298
}
dvander@404
  1299
dvander@404
  1300
GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name)
dvander@404
  1301
{
dvander@404
  1302
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1303
	if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count)
dvander@404
  1304
	{
dvander@404
  1305
		return INVALID_GROUP_ID;
dvander@404
  1306
	}
dvander@404
  1307
dvander@404
  1308
	int *table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1309
dvander@1356
  1310
	GroupId gid = table[index];
dvander@1356
  1311
dvander@1356
  1312
	if (name)
dvander@1356
  1313
	{
dvander@1356
  1314
		*name = GetGroupName(gid);
dvander@1356
  1315
	}
dvander@1356
  1316
dvander@1356
  1317
	return gid;
dvander@404
  1318
}
dvander@404
  1319
dvander@404
  1320
const char *AdminCache::GetAdminPassword(AdminId id)
dvander@404
  1321
{
dvander@404
  1322
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1323
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1324
	{
dvander@404
  1325
		return NULL;
dvander@404
  1326
	}
dvander@404
  1327
dvander@404
  1328
	return m_pStrings->GetString(pUser->password);
dvander@404
  1329
}
dvander@404
  1330
dvander@404
  1331
void AdminCache::SetAdminPassword(AdminId id, const char *password)
dvander@404
  1332
{	
dvander@404
  1333
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1334
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1335
	{
dvander@404
  1336
		return;
dvander@404
  1337
	}
dvander@404
  1338
dvander@2073
  1339
	if (password[0] == '\0')
dvander@2073
  1340
	{
dvander@2073
  1341
		pUser->password = -1;
dvander@2073
  1342
		return;
dvander@2073
  1343
	}
dvander@2073
  1344
dvander@1356
  1345
	int i_password = m_pStrings->AddString(password);
dvander@1356
  1346
	pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1356
  1347
	pUser->password = i_password;
dvander@404
  1348
}
dvander@404
  1349
dvander@433
  1350
unsigned int AdminCache::FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize)
dvander@433
  1351
{
dvander@433
  1352
	unsigned int i;
dvander@433
  1353
	for (i=0; i<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1354
	{
dvander@464
  1355
		array[i] = ((bits & (1<<i)) == (unsigned)(1<<i));
dvander@433
  1356
	}
dvander@433
  1357
dvander@433
  1358
	return i;
dvander@433
  1359
}
dvander@433
  1360
dvander@433
  1361
FlagBits AdminCache::FlagBitArrayToBits(const bool array[], unsigned int maxSize)
dvander@433
  1362
{
dvander@433
  1363
	FlagBits bits = 0;
dvander@433
  1364
	for (unsigned int i=0; i<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1365
	{
dvander@433
  1366
		if (array[i])
dvander@433
  1367
		{
dvander@433
  1368
			bits |= (1<<i);
dvander@433
  1369
		}
dvander@433
  1370
	}
dvander@433
  1371
dvander@433
  1372
	return bits;
dvander@433
  1373
}
dvander@433
  1374
dvander@433
  1375
FlagBits AdminCache::FlagArrayToBits(const AdminFlag array[], unsigned int numFlags)
dvander@433
  1376
{
dvander@433
  1377
	FlagBits bits = 0;
dvander@433
  1378
	for (unsigned int i=0; i<numFlags && i<AdminFlags_TOTAL; i++)
dvander@433
  1379
	{
dvander@433
  1380
		bits |= (1 << (FlagBits)array[i]);
dvander@433
  1381
	}
dvander@433
  1382
dvander@433
  1383
	return bits;
dvander@433
  1384
}
dvander@433
  1385
dvander@433
  1386
unsigned int AdminCache::FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize)
dvander@433
  1387
{
dvander@433
  1388
	unsigned int i, num=0;
dvander@1050
  1389
	for (i=0; num<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1390
	{
dvander@464
  1391
		if ((bits & (1<<i)) == (unsigned)(1<<i))
dvander@433
  1392
		{
dvander@433
  1393
			array[num++] = (AdminFlag)i;
dvander@433
  1394
		}
dvander@433
  1395
	}
dvander@433
  1396
dvander@433
  1397
	return num;
dvander@433
  1398
}
dvander@434
  1399
dvander@434
  1400
bool AdminCache::CheckAdminFlags(AdminId id, FlagBits bits)
dvander@434
  1401
{
dvander@434
  1402
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@434
  1403
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@434
  1404
	{
dvander@434
  1405
		return false;
dvander@434
  1406
	}
dvander@434
  1407
dvander@434
  1408
	return ((pUser->eflags & bits) == bits);
dvander@434
  1409
}
dvander@434
  1410
dvander@434
  1411
bool AdminCache::CanAdminTarget(AdminId id, AdminId target)
dvander@434
  1412
{
dvander@434
  1413
	/** 
dvander@434
  1414
	 * Zeroth, if the targeting AdminId is INVALID_ADMIN_ID, targeting fails.
ds@729
  1415
	 * First, if the targeted AdminId is INVALID_ADMIN_ID, targeting succeeds.
dvander@434
  1416
	 */
dvander@434
  1417
dvander@434
  1418
	if (id == INVALID_ADMIN_ID)
dvander@434
  1419
	{
dvander@434
  1420
		return false;
dvander@434
  1421
	}
dvander@434
  1422
dvander@434
  1423
	if (target == INVALID_ADMIN_ID)
dvander@434
  1424
	{
dvander@434
  1425
		return true;
dvander@434
  1426
	}
dvander@434
  1427
dvander@1403
  1428
	if (id == target)
dvander@1403
  1429
	{
dvander@1403
  1430
		return true;
dvander@1403
  1431
	}
dvander@1403
  1432
dvander@434
  1433
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@434
  1434
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@434
  1435
	{
dvander@434
  1436
		return false;
dvander@434
  1437
	}
dvander@434
  1438
dvander@434
  1439
	AdminUser *pTarget = (AdminUser *)m_pMemory->GetAddress(target);
dvander@434
  1440
	if (!pTarget || pTarget->magic != USR_MAGIC_SET)
dvander@434
  1441
	{
dvander@434
  1442
		return false;
dvander@434
  1443
	}
dvander@434
  1444
dvander@434
  1445
	/** 
ds@729
  1446
	 * Second, if the targeting admin is root, targeting succeeds.
dvander@434
  1447
	 */
dvander@434
  1448
	if (pUser->eflags & ADMFLAG_ROOT)
dvander@434
  1449
	{
dvander@434
  1450
		return true;
dvander@434
  1451
	}
dvander@434
  1452
dvander@1403
  1453
	/** Fourth, if the targeted admin is immune from targeting admin. */
dvander@1403
  1454
	int mode = sm_immunity_mode.GetInt();
dvander@1403
  1455
	switch (mode)
dvander@434
  1456
	{
dvander@1403
  1457
		case 1:
dvander@1403
  1458
		{
dvander@1403
  1459
			if (pTarget->immunity_level > pUser->immunity_level)
dvander@1403
  1460
			{
dvander@1403
  1461
				return false;
dvander@1403
  1462
			}
dvander@1403
  1463
			break;
dvander@1403
  1464
		}
dvander@1403
  1465
		case 3:
dvander@1403
  1466
		{
dvander@1403
  1467
			/* If neither has any immunity, let this pass. */
dvander@1403
  1468
			if (!pUser->immunity_level && !pTarget->immunity_level)
dvander@1403
  1469
			{
dvander@1403
  1470
				return true;
dvander@1403
  1471
			}
dvander@1403
  1472
			/* Don't break, go to the next case. */
dvander@1403
  1473
		}
dvander@1403
  1474
		case 2:
dvander@1403
  1475
		{
dvander@1403
  1476
			if (pTarget->immunity_level >= pUser->immunity_level)
dvander@1403
  1477
			{
dvander@1403
  1478
				return false;
dvander@1403
  1479
			}
dvander@1403
  1480
			break;
dvander@1403
  1481
		}
dvander@434
  1482
	}
dvander@434
  1483
dvander@434
  1484
	/** 
dvander@1403
  1485
	 * Fifth, if the targeted admin has specific immunity from the
dvander@434
  1486
	 *  targeting admin via group immunities, targeting fails.
dvander@434
  1487
	 */
dvander@434
  1488
	//:TODO: speed this up... maybe with trie hacks.
dvander@434
  1489
	//idea is to insert %d.%d in the trie after computing this and use it as a cache lookup.
dvander@434
  1490
	//problem is the trie cannot delete prefixes, so we'd have a problem with invalidations.
dvander@434
  1491
	if (pTarget->grp_count > 0 && pUser->grp_count > 0)
dvander@434
  1492
	{
dvander@434
  1493
		int *grp_table = (int *)m_pMemory->GetAddress(pTarget->grp_table);
dvander@434
  1494
		int *src_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@434
  1495
		GroupId id, other;
dvander@434
  1496
		unsigned int num;
dvander@434
  1497
		for (unsigned int i=0; i<pTarget->grp_count; i++)
dvander@434
  1498
		{
dvander@434
  1499
			id = grp_table[i];
dvander@434
  1500
			num = GetGroupImmunityCount(id);
dvander@434
  1501
			for (unsigned int j=0; j<num; i++)
dvander@434
  1502
			{
dvander@434
  1503
				other = GetGroupImmunity(id, j);
dvander@434
  1504
				for (unsigned int k=0; k<pUser->grp_count; k++)
dvander@434
  1505
				{
dvander@434
  1506
					if (other == src_table[k])
dvander@434
  1507
					{
dvander@434
  1508
						return false;
dvander@434
  1509
					}
dvander@434
  1510
				}
dvander@434
  1511
			}
dvander@434
  1512
		}
dvander@434
  1513
	}
dvander@434
  1514
	
dvander@434
  1515
	return true;
dvander@434
  1516
}
dvander@1298
  1517
dvander@1298
  1518
bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
dvander@1298
  1519
{
dvander@1965
  1520
	if (c < 'a' 
dvander@1965
  1521
		|| c > 'z'
dvander@1965
  1522
		|| !g_FlagSet[(unsigned)c - (unsigned)'a'])
dvander@1298
  1523
	{
dvander@1298
  1524
		return false;
dvander@1298
  1525
	}
dvander@1298
  1526
dvander@1305
  1527
	if (pAdmFlag)
dvander@1298
  1528
	{
dvander@1298
  1529
		*pAdmFlag = g_FlagLetters[(unsigned)c - (unsigned)'a'];
dvander@1298
  1530
	}
dvander@1298
  1531
dvander@1298
  1532
	return true;
dvander@1298
  1533
}
dvander@1298
  1534
dvander@1965
  1535
bool AdminCache::FindFlagChar(AdminFlag flag, char *c)
dvander@1965
  1536
{
dvander@1965
  1537
	if (!g_FlagSet[flag])
dvander@1965
  1538
	{
dvander@1965
  1539
		return false;
dvander@1965
  1540
	}
dvander@1965
  1541
dvander@1965
  1542
	if (c)
dvander@1965
  1543
	{
dvander@1965
  1544
		*c = g_ReverseFlags[flag];
dvander@1965
  1545
	}
dvander@1965
  1546
dvander@1965
  1547
	return true;
dvander@1965
  1548
}
dvander@1965
  1549
dvander@1298
  1550
FlagBits AdminCache::ReadFlagString(const char *flags, const char **end)
dvander@1298
  1551
{
dvander@1298
  1552
	FlagBits bits = 0;
dvander@1298
  1553
dvander@1298
  1554
	while (flags && (*flags != '\0'))
dvander@1298
  1555
	{
dvander@1298
  1556
		AdminFlag flag;
dvander@1298
  1557
		if (!FindFlag(*flags, &flag))
dvander@1298
  1558
		{
dvander@1298
  1559
			break;
dvander@1298
  1560
		}
dvander@1298
  1561
		bits |= FlagArrayToBits(&flag, 1);
dvander@1298
  1562
		flags++;
dvander@1298
  1563
	}
dvander@1298
  1564
dvander@1298
  1565
	if (end)
dvander@1298
  1566
	{
dvander@1298
  1567
		*end = flags;
dvander@1298
  1568
	}
dvander@1298
  1569
dvander@1298
  1570
	return bits;
dvander@1298
  1571
}
dvander@1349
  1572
dvander@1349
  1573
unsigned int AdminCache::GetAdminSerialChange(AdminId id)
dvander@1349
  1574
{
dvander@1349
  1575
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1349
  1576
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@1349
  1577
	{
dvander@1349
  1578
		return 0;
dvander@1349
  1579
	}
dvander@1349
  1580
dvander@1349
  1581
	return pUser->serialchange;
dvander@1349
  1582
}
dvander@1349
  1583
dvander@1349
  1584
bool AdminCache::CanAdminUseCommand(int client, const char *cmd)
dvander@1349
  1585
{
dvander@1349
  1586
	FlagBits bits;
dvander@1349
  1587
	OverrideType otype = Override_Command;
dvander@1349
  1588
dvander@1349
  1589
	if (cmd[0] == '@')
dvander@1349
  1590
	{
dvander@1349
  1591
		otype = Override_CommandGroup;
dvander@1349
  1592
		cmd++;
dvander@1349
  1593
	}
dvander@1349
  1594
dvander@1349
  1595
	if (!g_ConCmds.LookForCommandAdminFlags(cmd, &bits))
dvander@1349
  1596
	{
dvander@1349
  1597
		if (!GetCommandOverride(cmd, otype, &bits))
dvander@1349
  1598
		{
dvander@1349
  1599
			bits = 0;
dvander@1349
  1600
		}
dvander@1349
  1601
	}
dvander@1349
  1602
skamonkey@3389
  1603
	return g_ConCmds.CheckClientCommandAccess(client, cmd, bits);
dvander@1349
  1604
}
dvander@1403
  1605
dvander@1403
  1606
unsigned int AdminCache::SetGroupImmunityLevel(GroupId gid, unsigned int level)
dvander@1403
  1607
{
dvander@1403
  1608
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@1403
  1609
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@1403
  1610
	{
dvander@1403
  1611
		return 0;
dvander@1403
  1612
	}
dvander@1403
  1613
dvander@1403
  1614
	unsigned int old_level = pGroup->immunity_level;
dvander@1403
  1615
dvander@1403
  1616
	pGroup->immunity_level = level;
dvander@1403
  1617
dvander@1403
  1618
	return old_level;
dvander@1403
  1619
}
dvander@1403
  1620
dvander@1403
  1621
unsigned int AdminCache::GetGroupImmunityLevel(GroupId gid)
dvander@1403
  1622
{
dvander@1403
  1623
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@1403
  1624
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@1403
  1625
	{
dvander@1403
  1626
		return 0;
dvander@1403
  1627
	}
dvander@1403
  1628
dvander@1403
  1629
	return pGroup->immunity_level;
dvander@1403
  1630
}
dvander@1403
  1631
dvander@1403
  1632
unsigned int AdminCache::SetAdminImmunityLevel(AdminId id, unsigned int level)
dvander@1403
  1633
{
dvander@1403
  1634
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1403
  1635
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@1403
  1636
	{
dvander@1403
  1637
		return 0;
dvander@1403
  1638
	}
dvander@1403
  1639
dvander@1403
  1640
	unsigned int old_level = pUser->immunity_level;
dvander@1403
  1641
dvander@1403
  1642
	pUser->immunity_level = level;
dvander@1403
  1643
dvander@1403
  1644
	return old_level;
dvander@1403
  1645
}
dvander@1403
  1646
dvander@1403
  1647
unsigned int AdminCache::GetAdminImmunityLevel(AdminId id)
dvander@1403
  1648
{
dvander@1403
  1649
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1403
  1650
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@1403
  1651
	{
dvander@1403
  1652
		return 0;
dvander@1403
  1653
	}
dvander@1403
  1654
dvander@1403
  1655
	return pUser->immunity_level;
dvander@1403
  1656
}
dvander@1403
  1657
dvander@1477
  1658
bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool override_only)
dvander@1473
  1659
{
dvander@1473
  1660
	if (client == 0)
dvander@1473
  1661
	{
dvander@1473
  1662
		return true;
dvander@1473
  1663
	}
dvander@1473
  1664
dvander@1473
  1665
	/* Auto-detect a command if we can */
dvander@1473
  1666
	FlagBits bits = flags;
dvander@1473
  1667
	bool found_command = false;
dvander@1473
  1668
	if (!override_only)
dvander@1473
  1669
	{
dvander@1473
  1670
		found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits);
dvander@1473
  1671
	}
dvander@1473
  1672
dvander@1473
  1673
	if (!found_command)
dvander@1473
  1674
	{
dvander@1473
  1675
		GetCommandOverride(cmd, Override_Command, &bits);
dvander@1473
  1676
	}
dvander@1473
  1677
skamonkey@3389
  1678
	return g_ConCmds.CheckClientCommandAccess(client, cmd, bits) ? 1 : 0;
dvander@1473
  1679
}
dvander@1965
  1680
dvander@4081
  1681
void iterator_glob_basic_override(FILE *fp, const char *key, FlagBits flags)
dvander@1965
  1682
{
dvander@1965
  1683
	char flagstr[64];
dvander@1965
  1684
	g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr));
dvander@1965
  1685
	fprintf(fp, "\t\"%s\"\t\t\"%s\"\n", key, flagstr);
dvander@1965
  1686
}
dvander@1965
  1687
dvander@4081
  1688
void iterator_glob_grp_override(FILE *fp, const char *key, FlagBits flags)
dvander@1965
  1689
{
dvander@1965
  1690
	char flagstr[64];
dvander@1965
  1691
	g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr));
dvander@1965
  1692
	fprintf(fp, "\t\"@%s\"\t\t\"%s\"\n", key, flagstr);
dvander@1965
  1693
}
dvander@1965
  1694
dvander@4081
  1695
void iterator_group_basic_override(FILE *fp, const char *key, OverrideRule rule)
dvander@1965
  1696
{
dvander@4081
  1697
	const char *str = (rule == Command_Allow) ? "allow" : "deny";
dvander@4081
  1698
	fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n", key, str);
dvander@1965
  1699
}
dvander@1965
  1700
dvander@4081
  1701
void iterator_group_grp_override(FILE *fp, const char *key, OverrideRule rule)
dvander@1965
  1702
{
dvander@4081
  1703
	const char *str = (rule == Command_Allow) ? "allow" : "deny";
dvander@4081
  1704
	fprintf(fp, "\t\t\t\"@%s\"\t\t\"%s\"\n", key, str);
dvander@1965
  1705
}
dvander@1965
  1706
dvander@1965
  1707
void AdminCache::DumpCache(FILE *fp)
dvander@1965
  1708
{
dvander@1965
  1709
	int *itable;
dvander@1965
  1710
	AdminId aid;
dvander@1965
  1711
	GroupId gid;
dvander@1965
  1712
	char flagstr[64];
dvander@1965
  1713
	unsigned int num;
dvander@1965
  1714
	AdminUser *pAdmin;
dvander@1965
  1715
	AdminGroup *pGroup;
dvander@1965
  1716
	char name_buffer[512];
dvander@1965
  1717
dvander@1965
  1718
	fprintf(fp, "\"Groups\"\n{\n");
dvander@1965
  1719
	
dvander@1965
  1720
	num = 0;
dvander@1965
  1721
	gid = m_FirstGroup;
dvander@1965
  1722
	while (gid != INVALID_GROUP_ID
dvander@1965
  1723
			&& (pGroup = GetGroup(gid)) != NULL)
dvander@1965
  1724
	{
dvander@1965
  1725
		num++;
dvander@1965
  1726
		FillFlagString(pGroup->addflags, flagstr, sizeof(flagstr));
dvander@1965
  1727
dvander@1965
  1728
		fprintf(fp, "\t/* num = %d, gid = 0x%X */\n", num, gid);
dvander@1965
  1729
		fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pGroup->nameidx));
dvander@1965
  1730
		fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr);
dvander@1965
  1731
		fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pGroup->immunity_level);
dvander@1965
  1732
		
dvander@1965
  1733
		if (pGroup->immune_table != -1
dvander@1965
  1734
			&& (itable = (int *)m_pMemory->GetAddress(pGroup->immune_table)) != NULL)
dvander@1965
  1735
		{
dvander@1965
  1736
			AdminGroup *pAltGroup;
dvander@1965
  1737
			const char *gname, *mod;
dvander@1965
  1738
dvander@1965
  1739
			for (int i = 1; i <= itable[0]; i++)
dvander@1965
  1740
			{
dvander@1965
  1741
				if ((pAltGroup = GetGroup(itable[i])) == NULL)
dvander@1965
  1742
				{
dvander@1965
  1743
					/* Assume the rest of the table is corrupt */
dvander@1965
  1744
					break;
dvander@1965
  1745
				}
dvander@1965
  1746
				gname = GetString(pAltGroup->nameidx);
dvander@1965
  1747
				if (atoi(gname) != 0)
dvander@1965
  1748
				{
dvander@1965
  1749
					mod = "@";
dvander@1965
  1750
				}
dvander@1965
  1751
				else
dvander@1965
  1752
				{
dvander@1965
  1753
					mod = "";
dvander@1965
  1754
				}
dvander@1965
  1755
				fprintf(fp, "\t\t\"immunity\"\t\t\"%s%s\"\n", mod, gname);
dvander@1965
  1756
			}
dvander@1965
  1757
		}
dvander@1965
  1758
dvander@1965
  1759
		fprintf(fp, "\n\t\t\"Overrides\"\n\t\t{\n");
dvander@1965
  1760
		if (pGroup->pCmdGrpTable != NULL)
dvander@1965
  1761
		{
dvander@4081
  1762
			for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next())
dvander@4081
  1763
				iterator_group_grp_override(fp, iter->key.chars(), iter->value);
dvander@1965
  1764
		}
dvander@1965
  1765
		if (pGroup->pCmdTable != NULL)
dvander@1965
  1766
		{
dvander@4081
  1767
			for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next())
dvander@4081
  1768
				iterator_group_basic_override(fp, iter->key.chars(), iter->value);
dvander@1965
  1769
		}
dvander@1965
  1770
		fprintf(fp, "\t\t}\n");
dvander@1965
  1771
dvander@1965
  1772
		fprintf(fp, "\t}\n");
dvander@1965
  1773
dvander@1965
  1774
		if ((gid = pGroup->next_grp) != INVALID_GROUP_ID)
dvander@1965
  1775
		{
dvander@1965
  1776
			fprintf(fp, "\n");
dvander@1965
  1777
		}
dvander@1965
  1778
	}
dvander@1965
  1779
dvander@1965
  1780
	fprintf(fp, "}\n\n");
dvander@1965
  1781
	fprintf(fp, "\"Admins\"\n{\n");
dvander@1965
  1782
dvander@1965
  1783
	num = 0;
dvander@1965
  1784
	aid = m_FirstUser;
dvander@1965
  1785
	while (aid != INVALID_ADMIN_ID
dvander@1965
  1786
			&& (pAdmin = GetUser(aid)) != NULL)
dvander@1965
  1787
	{
dvander@1965
  1788
		num++;
dvander@1965
  1789
		FillFlagString(pAdmin->flags, flagstr, sizeof(flagstr));
dvander@1965
  1790
dvander@1965
  1791
		fprintf(fp, "\t/* num = %d, aid = 0x%X, serialno = 0x%X*/\n", num, aid, pAdmin->serialchange);
dvander@1965
  1792
dvander@1965
  1793
		if (pAdmin->nameidx != -1)
dvander@1965
  1794
		{
dvander@1965
  1795
			fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pAdmin->nameidx));
dvander@1965
  1796
		}
dvander@1965
  1797
		else
dvander@1965
  1798
		{
dvander@1965
  1799
			fprintf(fp, "\t\"\"\n\t{\n");
dvander@1965
  1800
		}
dvander@1965
  1801
dvander@1965
  1802
		if (pAdmin->auth.identidx != -1)
dvander@1965
  1803
		{
dvander@1965
  1804
			fprintf(fp, "\t\t\"auth\"\t\t\t\"%s\"\n", GetMethodName(pAdmin->auth.index));
dvander@1965
  1805
			fprintf(fp, "\t\t\"identity\"\t\t\"%s\"\n", GetString(pAdmin->auth.identidx));
dvander@1965
  1806
		}
dvander@1965
  1807
		if (pAdmin->password != -1)
dvander@1965
  1808
		{
dvander@1965
  1809
			fprintf(fp, "\t\t\"password\"\t\t\"%s\"\n", GetString(pAdmin->password));
dvander@1965
  1810
		}
dvander@1965
  1811
		fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr);
dvander@1965
  1812
		fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pAdmin->immunity_level);
dvander@1965
  1813
dvander@1965
  1814
		if (pAdmin->grp_count != 0 
dvander@1965
  1815
			&& pAdmin->grp_table != -1 
dvander@1965
  1816
			&& (itable = (int *)m_pMemory->GetAddress(pAdmin->grp_table)) != NULL)
dvander@1965
  1817
		{
dvander@1965
  1818
			unsigned int i;
dvander@1965
  1819
dvander@1965
  1820
			for (i = 0; i < pAdmin->grp_count; i++)
dvander@1965
  1821
			{
dvander@1965
  1822
				if ((pGroup = GetGroup(itable[i])) == NULL)
dvander@1965
  1823
				{
dvander@1965
  1824
					/* Assume the rest of the table is corrupt */
dvander@1965
  1825
					break;
dvander@1965
  1826
				}
dvander@1965
  1827
				fprintf(fp, "\t\t\"group\"\t\t\t\"%s\"\n", GetString(pGroup->nameidx));
dvander@1965
  1828
			}
dvander@1965
  1829
		}
dvander@1965
  1830
dvander@1965
  1831
		fprintf(fp, "\t}\n");
dvander@1965
  1832
dvander@1965
  1833
		if ((aid = pAdmin->next_user) != INVALID_ADMIN_ID)
dvander@1965
  1834
		{
dvander@1965
  1835
			fprintf(fp, "\n");
dvander@1965
  1836
		}
dvander@1965
  1837
	}
dvander@1965
  1838
dvander@1965
  1839
	fprintf(fp, "}\n\n");
dvander@1965
  1840
dvander@1965
  1841
	fprintf(fp, "\"Overrides\"\n{\n");
dvander@4081
  1842
	for (FlagMap::iterator iter = m_CmdGrpOverrides.iter(); !iter.empty(); iter.next())
dvander@4081
  1843
		iterator_glob_grp_override(fp, iter->key.chars(), iter->value);
dvander@4081
  1844
	for (FlagMap::iterator iter = m_CmdOverrides.iter(); !iter.empty(); iter.next())
dvander@4081
  1845
		iterator_glob_basic_override(fp, iter->key.chars(), iter->value);
dvander@1965
  1846
	fprintf(fp, "}\n");
dvander@1965
  1847
}
dvander@1965
  1848
dvander@1965
  1849
AdminGroup *AdminCache::GetGroup(GroupId gid)
dvander@1965
  1850
{
dvander@1965
  1851
	AdminGroup *pGroup;
dvander@1965
  1852
	
dvander@1965
  1853
	pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@1965
  1854
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@1965
  1855
	{
dvander@1965
  1856
		return NULL;
dvander@1965
  1857
	}
dvander@1965
  1858
dvander@1965
  1859
	return pGroup;
dvander@1965
  1860
}
dvander@1965
  1861
dvander@1965
  1862
AdminUser *AdminCache::GetUser(AdminId aid)
dvander@1965
  1863
{
dvander@1965
  1864
	AdminUser *pAdmin;
dvander@1965
  1865
dvander@1965
  1866
	pAdmin = (AdminUser *)m_pMemory->GetAddress(aid);
dvander@1965
  1867
	if (!pAdmin || pAdmin->magic != USR_MAGIC_SET)
dvander@1965
  1868
	{
dvander@1965
  1869
		return NULL;
dvander@1965
  1870
	}
dvander@1965
  1871
dvander@1965
  1872
	return pAdmin;
dvander@1965
  1873
}
dvander@1965
  1874
dvander@1965
  1875
const char *AdminCache::GetMethodName(unsigned int index)
dvander@1965
  1876
{
dvander@4081
  1877
	List<AuthMethod *>::iterator iter;
dvander@1965
  1878
	for (iter=m_AuthMethods.begin();
dvander@1965
  1879
		iter!=m_AuthMethods.end();
dvander@1965
  1880
		iter++)
dvander@1965
  1881
	{
dvander@1965
  1882
		if (index-- == 0)
dvander@1965
  1883
		{
dvander@4081
  1884
			return (*iter)->name.c_str();
dvander@1965
  1885
		}
dvander@1965
  1886
	}
dvander@1965
  1887
dvander@1965
  1888
	return NULL;
dvander@1965
  1889
}
dvander@1965
  1890
dvander@1965
  1891
const char *AdminCache::GetString(int idx)
dvander@1965
  1892
{
dvander@1965
  1893
	return m_pStrings->GetString(idx);
dvander@1965
  1894
}
dvander@1965
  1895
dvander@1965
  1896
size_t AdminCache::FillFlagString(FlagBits bits, char *buffer, size_t maxlen)
dvander@1965
  1897
{
dvander@1965
  1898
	size_t pos;
dvander@1965
  1899
	unsigned int i, num_flags;
dvander@1965
  1900
	AdminFlag flags[AdminFlags_TOTAL];
dvander@1965
  1901
dvander@1965
  1902
	num_flags = FlagBitsToArray(bits, flags, AdminFlags_TOTAL);
dvander@1965
  1903
dvander@1965
  1904
	pos = 0;
dvander@1965
  1905
	for (i = 0; pos < maxlen && i < num_flags; i++)
dvander@1965
  1906
	{
dvander@1965
  1907
		if (FindFlagChar(flags[i], &buffer[pos]))
dvander@1965
  1908
		{
dvander@1965
  1909
			pos++;
dvander@1965
  1910
		}
dvander@1965
  1911
	}
dvander@1965
  1912
	buffer[pos] = '\0';
dvander@1965
  1913
dvander@1965
  1914
	return pos;
dvander@1965
  1915
}
dvander@1965
  1916
dvander@1965
  1917
CON_COMMAND(sm_dump_admcache, "Dumps the admin cache for debugging")
dvander@1965
  1918
{
dvander@1965
  1919
	FILE *fp;
dvander@1965
  1920
	char buffer[PLATFORM_MAX_PATH];
dvander@1965
  1921
dvander@1965
  1922
	g_SourceMod.BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt");
dvander@1965
  1923
dvander@1965
  1924
	if ((fp = fopen(buffer, "wt")) == NULL)
dvander@1965
  1925
	{
dvander@1965
  1926
		g_RootMenu.ConsolePrint("Could not open file for writing: %s", buffer);
dvander@1965
  1927
		return;
dvander@1965
  1928
	}
dvander@1965
  1929
dvander@1965
  1930
	g_Admins.DumpCache(fp);
dvander@1965
  1931
dvander@1965
  1932
	g_RootMenu.ConsolePrint("Admin cache dumped to: %s", buffer);
dvander@1965
  1933
dvander@1965
  1934
	fclose(fp);
dvander@1965
  1935
}