core/AdminCache.cpp
author Peace-Maker <januk@freenet.de>
Wed Apr 23 08:55:09 2014 -0400 (2014-04-23)
changeset 4330 98726cea1607
parent 4308 317352596197
permissions -rw-r--r--
Mark CS:S as supporting HudMsg (bug 6108, r=psychonic).
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
skamonkey@4308
   290
	memset(g_ReverseFlags, '?', sizeof(g_ReverseFlags));
skamonkey@4308
   291
dvander@1965
   292
	for (i = 0; i < 26; i++)
dvander@1965
   293
	{
dvander@1965
   294
		if (FindFlag('a' + i, &flag))
dvander@1965
   295
		{
dvander@1965
   296
			g_ReverseFlags[flag] = 'a' + i;
dvander@1965
   297
		}
dvander@1965
   298
	}
dvander@1298
   299
}
dvander@1298
   300
dvander@336
   301
void AdminCache::OnSourceModShutdown()
dvander@336
   302
{
skamonkey@4139
   303
	forwardsys->ReleaseForward(m_pCacheFwd);
dvander@336
   304
	m_pCacheFwd = NULL;
dvander@336
   305
}
dvander@336
   306
dvander@673
   307
void AdminCache::OnSourceModPluginsLoaded()
dvander@673
   308
{
dvander@673
   309
	DumpAdminCache(AdminCache_Overrides, true);
dvander@673
   310
	DumpAdminCache(AdminCache_Groups, true);
dvander@673
   311
}
dvander@673
   312
dvander@1298
   313
void AdminCache::NameFlag(const char *str, AdminFlag flag)
dvander@1298
   314
{
dvander@4081
   315
	m_LevelNames.insert(str, flag);
dvander@1298
   316
}
dvander@1298
   317
dvander@1298
   318
bool AdminCache::FindFlag(const char *str, AdminFlag *pFlag)
dvander@1298
   319
{
dvander@4081
   320
	return m_LevelNames.retrieve(str, pFlag);
dvander@1298
   321
}
dvander@1298
   322
dvander@433
   323
void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags)
dvander@335
   324
{
dvander@4081
   325
	FlagMap *map;
dvander@335
   326
	if (type == Override_Command)
dvander@4081
   327
		map = &m_CmdOverrides;
dvander@4081
   328
	else if (type == Override_CommandGroup)
dvander@4081
   329
		map = &m_CmdGrpOverrides;
dvander@4081
   330
	else
dvander@433
   331
		return;
dvander@433
   332
dvander@4081
   333
	map->insert(cmd, flags);
dvander@1435
   334
	g_ConCmds.UpdateAdminCmdFlags(cmd, type, flags, false);
dvander@335
   335
}
dvander@335
   336
dvander@433
   337
bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, FlagBits *pFlags)
dvander@335
   338
{
dvander@4081
   339
	FlagMap *map;
dvander@335
   340
	if (type == Override_Command)
dvander@4081
   341
		map = &m_CmdOverrides;
dvander@4081
   342
	else if (type == Override_CommandGroup)
dvander@4081
   343
		map = &m_CmdGrpOverrides;
dvander@4081
   344
	else
dvander@433
   345
		return false;
dvander@433
   346
dvander@4081
   347
	return map->retrieve(cmd, pFlags);
dvander@335
   348
}
dvander@335
   349
dvander@335
   350
void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
dvander@335
   351
{
dvander@335
   352
	if (type == Override_Command)
dvander@335
   353
	{
dvander@335
   354
		return _UnsetCommandOverride(cmd);
dvander@335
   355
	} else if (type == Override_CommandGroup) {
dvander@335
   356
		return _UnsetCommandGroupOverride(cmd);
dvander@335
   357
	}
dvander@335
   358
}
dvander@335
   359
dvander@335
   360
void AdminCache::_UnsetCommandGroupOverride(const char *group)
dvander@335
   361
{
dvander@4081
   362
	m_CmdGrpOverrides.remove(group);
dvander@1435
   363
	g_ConCmds.UpdateAdminCmdFlags(group, Override_CommandGroup, 0, true);
dvander@335
   364
}
dvander@335
   365
dvander@335
   366
void AdminCache::_UnsetCommandOverride(const char *cmd)
dvander@335
   367
{
dvander@4081
   368
	m_CmdOverrides.remove(cmd);
dvander@1435
   369
	g_ConCmds.UpdateAdminCmdFlags(cmd, Override_Command, 0, true);
dvander@335
   370
}
dvander@335
   371
dvander@335
   372
void AdminCache::DumpCommandOverrideCache(OverrideType type)
dvander@335
   373
{
dvander@4081
   374
	if (type == Override_Command)
dvander@4081
   375
		m_CmdOverrides.clear();
dvander@4081
   376
	else if (type == Override_CommandGroup)
dvander@4081
   377
		m_CmdGrpOverrides.clear();
dvander@335
   378
}
dvander@335
   379
dvander@404
   380
AdminId AdminCache::CreateAdmin(const char *name)
dvander@404
   381
{
dvander@404
   382
	AdminId id;
dvander@404
   383
	AdminUser *pUser;
dvander@404
   384
dvander@404
   385
	if (m_FreeUserList != INVALID_ADMIN_ID)
dvander@404
   386
	{
dvander@404
   387
		pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList);
dvander@404
   388
		assert(pUser->magic == USR_MAGIC_UNSET);
dvander@404
   389
		id = m_FreeUserList;
dvander@404
   390
		m_FreeUserList = pUser->next_user;
dvander@1965
   391
	}
dvander@1965
   392
	else
dvander@1965
   393
	{
dvander@404
   394
		id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser);
dvander@404
   395
		pUser->grp_size = 0;
dvander@404
   396
		pUser->grp_table = -1;
dvander@404
   397
	}
dvander@404
   398
dvander@433
   399
	pUser->flags = 0;
dvander@433
   400
	pUser->eflags = 0;
dvander@404
   401
	pUser->grp_count = 0;
dvander@404
   402
	pUser->password = -1;
dvander@404
   403
	pUser->magic = USR_MAGIC_SET;
dvander@405
   404
	pUser->auth.identidx = -1;
dvander@405
   405
	pUser->auth.index = 0;
dvander@1403
   406
	pUser->immunity_level = 0;
dvander@1349
   407
	pUser->serialchange = 1;
dvander@404
   408
dvander@404
   409
	if (m_FirstUser == INVALID_ADMIN_ID)
dvander@404
   410
	{
dvander@404
   411
		m_FirstUser = id;
dvander@404
   412
		m_LastUser = id;
dvander@1965
   413
	}
dvander@1965
   414
	else
dvander@1965
   415
	{
dvander@404
   416
		AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
dvander@404
   417
		pPrev->next_user = id;
dvander@404
   418
		pUser->prev_user = m_LastUser;
dvander@404
   419
		m_LastUser = id;
dvander@404
   420
	}
dvander@404
   421
dvander@1965
   422
	/* Since we always append to the tail, we should invalidate their next */
dvander@1965
   423
	pUser->next_user = -1;
dvander@1965
   424
dvander@404
   425
	if (name && name[0] != '\0')
dvander@404
   426
	{
dvander@1356
   427
		int nameidx = m_pStrings->AddString(name);
dvander@1356
   428
		pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1356
   429
		pUser->nameidx = nameidx;
dvander@404
   430
	}
dvander@1965
   431
	else
dvander@1965
   432
	{
dvander@1965
   433
		pUser->nameidx = -1;
dvander@1965
   434
	}
dvander@404
   435
dvander@404
   436
	return id;
dvander@404
   437
}
dvander@404
   438
dvander@335
   439
GroupId AdminCache::AddGroup(const char *group_name)
dvander@335
   440
{
dvander@4081
   441
	if (m_Groups.contains(group_name))
dvander@335
   442
		return INVALID_GROUP_ID;
dvander@335
   443
dvander@335
   444
	GroupId id;
dvander@335
   445
	AdminGroup *pGroup;
dvander@335
   446
	if (m_FreeGroupList != INVALID_GROUP_ID)
dvander@335
   447
	{
dvander@335
   448
		pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList);
dvander@335
   449
		assert(pGroup->magic == GRP_MAGIC_UNSET);
dvander@335
   450
		id = m_FreeGroupList;
dvander@335
   451
		m_FreeGroupList = pGroup->next_grp;
dvander@335
   452
	} else {
dvander@335
   453
		id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup);
dvander@335
   454
	}
dvander@335
   455
dvander@1403
   456
	pGroup->immunity_level = 0;
dvander@335
   457
	pGroup->immune_table = -1;
dvander@335
   458
	pGroup->magic = GRP_MAGIC_SET;
dvander@335
   459
	pGroup->next_grp = INVALID_GROUP_ID;
dvander@335
   460
	pGroup->pCmdGrpTable = NULL;
dvander@335
   461
	pGroup->pCmdTable = NULL;
dvander@433
   462
	pGroup->addflags = 0;
dvander@335
   463
dvander@335
   464
	if (m_FirstGroup == INVALID_GROUP_ID)
dvander@335
   465
	{
dvander@335
   466
		m_FirstGroup = id;
dvander@335
   467
		m_LastGroup = id;
dvander@335
   468
		pGroup->prev_grp = INVALID_GROUP_ID;
dvander@335
   469
	} else {
dvander@335
   470
		AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
dvander@335
   471
		assert(pPrev->magic == GRP_MAGIC_SET);
dvander@335
   472
		pPrev->next_grp = id;
dvander@335
   473
		pGroup->prev_grp = m_LastGroup;
dvander@335
   474
		m_LastGroup = id;
dvander@335
   475
	}
dvander@335
   476
dvander@1356
   477
	int nameidx = m_pStrings->AddString(group_name);
dvander@1356
   478
	pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@1356
   479
	pGroup->nameidx = nameidx;
dvander@404
   480
dvander@4081
   481
	m_Groups.insert(group_name, id);
dvander@335
   482
	return id;
dvander@335
   483
}
dvander@335
   484
dvander@335
   485
GroupId AdminCache::FindGroupByName(const char *group_name)
dvander@335
   486
{
dvander@4081
   487
	GroupId id;
dvander@4081
   488
	if (!m_Groups.retrieve(group_name, &id))
dvander@335
   489
		return INVALID_GROUP_ID;
dvander@335
   490
dvander@335
   491
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   492
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   493
		return INVALID_GROUP_ID;
dvander@335
   494
dvander@335
   495
	return id;
dvander@335
   496
}
dvander@335
   497
dvander@335
   498
void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled)
dvander@335
   499
{
dvander@335
   500
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   501
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   502
	{
dvander@335
   503
		return;
dvander@335
   504
	}
dvander@335
   505
dvander@433
   506
	if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL)
dvander@335
   507
	{
dvander@335
   508
		return;
dvander@335
   509
	}
dvander@335
   510
dvander@436
   511
	FlagBits bits = (1<<(FlagBits)flag);
dvander@436
   512
dvander@436
   513
	if (enabled)
dvander@436
   514
	{
dvander@436
   515
		pGroup->addflags |= bits;
dvander@436
   516
	} else {
dvander@436
   517
		pGroup->addflags &= ~bits;
dvander@436
   518
	}
dvander@335
   519
}
dvander@335
   520
dvander@335
   521
bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag)
dvander@335
   522
{
dvander@335
   523
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   524
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   525
	{
dvander@335
   526
		return false;
dvander@335
   527
	}
dvander@335
   528
dvander@433
   529
	if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL)
dvander@335
   530
	{
dvander@335
   531
		return false;
dvander@335
   532
	}
dvander@335
   533
dvander@433
   534
	FlagBits bit = 1<<(FlagBits)flag;
dvander@433
   535
	return ((pGroup->addflags & bit) == bit);
dvander@335
   536
}
dvander@335
   537
dvander@433
   538
FlagBits AdminCache::GetGroupAddFlags(GroupId id)
dvander@335
   539
{
dvander@335
   540
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   541
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   542
	{
dvander@335
   543
		return 0;
dvander@335
   544
	}
dvander@335
   545
dvander@433
   546
	return pGroup->addflags;
dvander@335
   547
}
dvander@335
   548
dvander@1356
   549
const char *AdminCache::GetGroupName(GroupId gid)
dvander@1356
   550
{
dvander@1356
   551
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@1356
   552
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@1356
   553
	{
dvander@1403
   554
		return NULL;
dvander@1356
   555
	}
dvander@1356
   556
dvander@1356
   557
	return m_pStrings->GetString(pGroup->nameidx);
dvander@1356
   558
}
dvander@1356
   559
dvander@335
   560
void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled)
dvander@335
   561
{
dvander@335
   562
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   563
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   564
	{
dvander@335
   565
		return;
dvander@335
   566
	}
dvander@335
   567
dvander@1403
   568
	unsigned int level = 0;
dvander@1403
   569
dvander@1403
   570
	if (enabled)
dvander@335
   571
	{
dvander@1403
   572
		if (type == Immunity_Default)
dvander@1403
   573
		{
dvander@1403
   574
			level = 1;
dvander@1403
   575
		} else if (type == Immunity_Global) {
dvander@1403
   576
			level = 2;
dvander@1403
   577
		}
dvander@1403
   578
		if (level > pGroup->immunity_level)
dvander@1403
   579
		{
dvander@1403
   580
			pGroup->immunity_level = level;
dvander@1403
   581
		}
dvander@1403
   582
	} else {
dvander@1403
   583
		pGroup->immunity_level = 0;
dvander@1403
   584
	}
dvander@335
   585
}
dvander@335
   586
dvander@335
   587
bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type)
dvander@335
   588
{
dvander@335
   589
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   590
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   591
	{
dvander@335
   592
		return false;
dvander@335
   593
	}
dvander@335
   594
dvander@1403
   595
	if (type == Immunity_Default && pGroup->immunity_level >= 1)
dvander@335
   596
	{
dvander@1403
   597
		return true;
dvander@1403
   598
	} else if (type == Immunity_Global && pGroup->immunity_level >= 2) {
dvander@1403
   599
		return true;
dvander@335
   600
	}
dvander@335
   601
dvander@335
   602
	return false;
dvander@335
   603
}
dvander@335
   604
dvander@335
   605
void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id)
dvander@335
   606
{
dvander@1356
   607
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(other_id);
dvander@335
   608
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   609
	{
dvander@335
   610
		return;
dvander@335
   611
	}
dvander@335
   612
dvander@1356
   613
	pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@1356
   614
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   615
	{
dvander@335
   616
		return;
dvander@335
   617
	}
dvander@335
   618
dvander@335
   619
	/* We always need to resize the immunity table */
dvander@335
   620
	int *table, tblidx;
dvander@1356
   621
	if (pGroup->immune_table == -1)
dvander@335
   622
	{
dvander@335
   623
		tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table);
dvander@1356
   624
		pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   625
		table[0] = 0;
dvander@335
   626
	} else {
dvander@1356
   627
		int *old_table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@433
   628
		/* Break out if this group is already in the list */
dvander@433
   629
		for (int i=0; i<old_table[0]; i++)
dvander@433
   630
		{
dvander@433
   631
			if (old_table[1+i] == other_id)
dvander@433
   632
			{
dvander@433
   633
				return;
dvander@433
   634
			}
dvander@433
   635
		}
dvander@335
   636
		tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table);
dvander@433
   637
		/* Get the old address again in case of resize */
dvander@1356
   638
		pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@1356
   639
		old_table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@335
   640
		table[0] = old_table[0];
dvander@335
   641
		for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++)
dvander@335
   642
		{
dvander@335
   643
			table[i] = old_table[i];
dvander@335
   644
		}
dvander@335
   645
	}
dvander@335
   646
dvander@335
   647
	/* Assign */
dvander@1356
   648
	pGroup->immune_table = tblidx;
dvander@335
   649
dvander@335
   650
	/* Add to the array */
dvander@335
   651
	table[0]++;
dvander@335
   652
	table[table[0]] = other_id;
dvander@335
   653
}
dvander@335
   654
dvander@335
   655
unsigned int AdminCache::GetGroupImmunityCount(GroupId id)
dvander@335
   656
{
dvander@335
   657
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   658
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   659
	{
dvander@335
   660
		return 0;
dvander@335
   661
	}
dvander@335
   662
dvander@335
   663
	if (pGroup->immune_table == -1)
dvander@335
   664
	{
dvander@335
   665
		return 0;
dvander@335
   666
	}
dvander@335
   667
dvander@335
   668
	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@335
   669
dvander@335
   670
	return table[0];
dvander@335
   671
}
dvander@335
   672
dvander@335
   673
GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number)
dvander@335
   674
{
dvander@335
   675
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   676
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   677
	{
dvander@335
   678
		return INVALID_GROUP_ID;
dvander@335
   679
	}
dvander@335
   680
dvander@335
   681
	if (pGroup->immune_table == -1)
dvander@335
   682
	{
dvander@335
   683
		return INVALID_GROUP_ID;
dvander@335
   684
	}
dvander@335
   685
dvander@335
   686
	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@335
   687
	if (number >= (unsigned int)table[0])
dvander@335
   688
	{
dvander@335
   689
		return INVALID_GROUP_ID;
dvander@335
   690
	}
dvander@335
   691
dvander@335
   692
	return table[1 + number];
dvander@335
   693
}
dvander@335
   694
dvander@335
   695
void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule)
dvander@335
   696
{
dvander@335
   697
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   698
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   699
	{
dvander@335
   700
		return;
dvander@335
   701
	}
dvander@335
   702
dvander@4081
   703
	OverrideMap *map;
dvander@335
   704
	if (type == Override_Command)
dvander@335
   705
	{
dvander@335
   706
		if (pGroup->pCmdTable == NULL)
dvander@4081
   707
			pGroup->pCmdTable = new OverrideMap();
dvander@4081
   708
		map = pGroup->pCmdTable;
dvander@335
   709
	} else if (type == Override_CommandGroup) {
dvander@335
   710
		if (pGroup->pCmdGrpTable == NULL)
dvander@4081
   711
			pGroup->pCmdGrpTable = new OverrideMap();
dvander@4081
   712
		map = pGroup->pCmdGrpTable;
dvander@335
   713
	} else {
dvander@335
   714
		return;
dvander@335
   715
	}
dvander@335
   716
dvander@4081
   717
	map->insert(name, rule);
dvander@335
   718
}
dvander@335
   719
dvander@335
   720
bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule)
dvander@335
   721
{
dvander@335
   722
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   723
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   724
	{
dvander@335
   725
		return false;
dvander@335
   726
	}
dvander@335
   727
dvander@4081
   728
	OverrideMap *map;
dvander@335
   729
	if (type == Override_Command)
dvander@335
   730
	{
dvander@335
   731
		if (pGroup->pCmdTable == NULL)
dvander@335
   732
			return false;
dvander@4081
   733
		map = pGroup->pCmdTable;
dvander@335
   734
	} else if (type == Override_CommandGroup) {
dvander@335
   735
		if (pGroup->pCmdGrpTable == NULL)
dvander@335
   736
			return false;
dvander@4081
   737
		map = pGroup->pCmdGrpTable;
dvander@335
   738
	} else {
dvander@335
   739
		return false;
dvander@335
   740
	}
dvander@335
   741
dvander@4081
   742
	return map->retrieve(name, pRule);
dvander@335
   743
}
dvander@335
   744
dvander@4081
   745
AuthMethod *AdminCache::GetMethodByIndex(unsigned int index)
dvander@404
   746
{
dvander@4081
   747
	List<AuthMethod *>::iterator iter;
dvander@404
   748
	for (iter=m_AuthMethods.begin();
dvander@404
   749
		 iter!=m_AuthMethods.end();
dvander@404
   750
		 iter++)
dvander@404
   751
	{
dvander@404
   752
		if (index-- == 0)
dvander@404
   753
		{
dvander@4081
   754
			return *iter;
dvander@404
   755
		}
dvander@404
   756
	}
dvander@404
   757
dvander@404
   758
	return NULL;
dvander@404
   759
}
dvander@404
   760
dvander@404
   761
bool AdminCache::InvalidateAdmin(AdminId id)
dvander@404
   762
{
dvander@404
   763
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
   764
	AdminUser *pOther;
dvander@404
   765
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
   766
	{
dvander@404
   767
		return false;
dvander@404
   768
	}
dvander@404
   769
dvander@520
   770
	if (!m_InvalidatingAdmins && !m_destroying)
dvander@458
   771
	{
dvander@458
   772
		g_Players.ClearAdminId(id);
dvander@458
   773
	}
dvander@458
   774
dvander@404
   775
	/* Unlink from the dbl link list */
dvander@404
   776
	if (id == m_FirstUser && id == m_LastUser)
dvander@404
   777
	{
dvander@404
   778
		m_FirstUser = INVALID_ADMIN_ID;
dvander@404
   779
		m_LastUser = INVALID_ADMIN_ID;
dvander@404
   780
	} else if (id == m_FirstUser) {
dvander@404
   781
		m_FirstUser = pUser->next_user;
dvander@404
   782
		pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser);
dvander@404
   783
		pOther->prev_user = INVALID_ADMIN_ID;
dvander@404
   784
	} else if (id == m_LastUser) {
dvander@404
   785
		m_LastUser = pUser->prev_user;
dvander@404
   786
		pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
dvander@404
   787
		pOther->next_user = INVALID_ADMIN_ID;
dvander@404
   788
	} else {
dvander@404
   789
		pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user);
dvander@404
   790
		pOther->next_user = pUser->next_user;
dvander@404
   791
		pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user);
dvander@404
   792
		pOther->prev_user = pUser->prev_user;
dvander@404
   793
	}
dvander@404
   794
dvander@404
   795
	/* Unlink from auth tables */
dvander@405
   796
	if (pUser->auth.identidx != -1)
dvander@404
   797
	{
dvander@4081
   798
		AuthMethod *method = GetMethodByIndex(pUser->auth.index);
dvander@4081
   799
		if (method)
dvander@4081
   800
			method->identities.remove(m_pStrings->GetString(pUser->auth.identidx));
dvander@404
   801
	}
dvander@404
   802
dvander@404
   803
	/* Clear table counts */
dvander@404
   804
	pUser->grp_count = 0;
dvander@405
   805
	
dvander@404
   806
	/* Link into free list */
dvander@404
   807
	pUser->magic = USR_MAGIC_UNSET;
dvander@404
   808
	pUser->next_user = m_FreeUserList;
dvander@404
   809
	m_FreeUserList = id;
dvander@404
   810
dvander@1349
   811
	/* Unset serial change */
dvander@1349
   812
	pUser->serialchange = 0;
dvander@1349
   813
dvander@404
   814
	return true;
dvander@404
   815
}
dvander@404
   816
dvander@404
   817
dvander@335
   818
void AdminCache::InvalidateGroup(GroupId id)
dvander@335
   819
{
dvander@335
   820
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   821
	AdminGroup *pOther;
dvander@335
   822
dvander@335
   823
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   824
	{
dvander@335
   825
		return;
dvander@335
   826
	}
dvander@335
   827
dvander@335
   828
	const char *str = m_pStrings->GetString(pGroup->nameidx);
dvander@4081
   829
	m_Groups.remove(str);
dvander@335
   830
dvander@335
   831
	/* Unlink from the live dbllink list */
dvander@335
   832
	if (id == m_FirstGroup && id == m_LastGroup)
dvander@335
   833
	{
dvander@335
   834
		m_LastGroup = INVALID_GROUP_ID;
dvander@335
   835
		m_FirstGroup = INVALID_GROUP_ID;
dvander@335
   836
	} else if (id == m_FirstGroup) {
dvander@335
   837
		m_FirstGroup = pGroup->next_grp;
dvander@335
   838
		pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup);
dvander@335
   839
		pOther->prev_grp = INVALID_GROUP_ID;
dvander@335
   840
	} else if (id == m_LastGroup) {
dvander@335
   841
		m_LastGroup = pGroup->prev_grp;
dvander@335
   842
		pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
dvander@335
   843
		pOther->next_grp = INVALID_GROUP_ID;
dvander@335
   844
	} else {
dvander@335
   845
		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp);
dvander@335
   846
		pOther->next_grp = pGroup->next_grp;
dvander@335
   847
		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp);
dvander@335
   848
		pOther->prev_grp = pGroup->prev_grp;
dvander@335
   849
	}
dvander@335
   850
dvander@4081
   851
	/* Free any used memory */
dvander@4081
   852
	delete pGroup->pCmdGrpTable;
dvander@4081
   853
	pGroup->pCmdGrpTable = NULL;
dvander@4081
   854
	delete pGroup->pCmdTable;
dvander@4081
   855
	pGroup->pCmdTable = NULL;
dvander@335
   856
dvander@335
   857
	/* Link into the free list */
dvander@335
   858
	pGroup->magic = GRP_MAGIC_UNSET;
dvander@335
   859
	pGroup->next_grp = m_FreeGroupList;
dvander@335
   860
	m_FreeGroupList = id;
dvander@335
   861
dvander@404
   862
	int idx = m_FirstUser;
dvander@404
   863
	AdminUser *pUser;
dvander@404
   864
	int *table;
dvander@404
   865
	while (idx != INVALID_ADMIN_ID)
dvander@404
   866
	{
dvander@404
   867
		pUser = (AdminUser *)m_pMemory->GetAddress(idx);
dvander@404
   868
		if (pUser->grp_count > 0)
dvander@404
   869
		{
dvander@404
   870
			table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
   871
			for (unsigned int i=0; i<pUser->grp_count; i++)
dvander@404
   872
			{
dvander@404
   873
				if (table[i] == id)
dvander@404
   874
				{
dvander@404
   875
					/* We have to remove this entry */
dvander@404
   876
					for (unsigned int j=i+1; j<pUser->grp_count; j++)
dvander@404
   877
					{
dvander@404
   878
						/* Move everything down by one */
dvander@404
   879
						table[j-1] = table[j];
dvander@404
   880
					}
dvander@404
   881
					/* Decrease count */
dvander@404
   882
					pUser->grp_count--;
dvander@404
   883
					/* Recalculate effective flags */
dvander@433
   884
					pUser->eflags = pUser->flags;
dvander@404
   885
					for (unsigned int j=0; j<pUser->grp_count; j++)
dvander@404
   886
					{
dvander@404
   887
						pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]);
dvander@433
   888
						pUser->eflags |= pOther->addflags;
dvander@404
   889
					}
dvander@1349
   890
					/* Mark as changed */
dvander@1349
   891
					pUser->serialchange++;
dvander@404
   892
					/* Break now, duplicates aren't allowed */
dvander@404
   893
					break;
dvander@404
   894
				}
dvander@404
   895
			}
dvander@404
   896
		}
dvander@404
   897
		idx = pUser->next_user;
dvander@404
   898
	}
dvander@335
   899
}
dvander@335
   900
dvander@335
   901
void AdminCache::InvalidateGroupCache()
dvander@335
   902
{
dvander@335
   903
	/* Nuke the free list */
dvander@335
   904
	m_FreeGroupList = -1;
dvander@335
   905
dvander@335
   906
	/* Nuke reverse lookups */
dvander@4081
   907
	m_Groups.clear();
dvander@335
   908
dvander@335
   909
	/* Free memory on groups */
dvander@335
   910
	GroupId cur = m_FirstGroup;
dvander@335
   911
	AdminGroup *pGroup;
dvander@335
   912
	while (cur != INVALID_GROUP_ID)
dvander@335
   913
	{
dvander@335
   914
		pGroup = (AdminGroup *)m_pMemory->GetAddress(cur);
dvander@335
   915
		assert(pGroup->magic == GRP_MAGIC_SET);
dvander@4081
   916
		delete pGroup->pCmdGrpTable;
dvander@4081
   917
		delete pGroup->pCmdTable;
dvander@335
   918
		cur = pGroup->next_grp;
dvander@335
   919
	}
dvander@335
   920
dvander@335
   921
	m_FirstGroup = INVALID_GROUP_ID;
dvander@335
   922
	m_LastGroup = INVALID_GROUP_ID;
dvander@335
   923
dvander@404
   924
	InvalidateAdminCache(false);
dvander@335
   925
dvander@335
   926
	/* Reset the memory table */
dvander@335
   927
	m_pMemory->Reset();
dvander@335
   928
}
dvander@336
   929
dvander@336
   930
void AdminCache::AddAdminListener(IAdminListener *pListener)
dvander@336
   931
{
dvander@336
   932
	m_hooks.push_back(pListener);
dvander@336
   933
}
dvander@336
   934
dvander@336
   935
void AdminCache::RemoveAdminListener(IAdminListener *pListener)
dvander@336
   936
{
dvander@336
   937
	m_hooks.remove(pListener);
dvander@336
   938
}
dvander@336
   939
dvander@404
   940
void AdminCache::RegisterAuthIdentType(const char *name)
dvander@404
   941
{
dvander@4081
   942
	if (m_AuthTables.contains(name))
dvander@404
   943
		return;
dvander@404
   944
dvander@4081
   945
	AuthMethod *method = new AuthMethod(name);
dvander@404
   946
	m_AuthMethods.push_back(method);
dvander@4081
   947
	m_AuthTables.insert(name, method);
dvander@404
   948
}
dvander@404
   949
dvander@404
   950
void AdminCache::InvalidateAdminCache(bool unlink_admins)
dvander@404
   951
{
dvander@458
   952
	m_InvalidatingAdmins = true;
dvander@520
   953
	if (!m_destroying)
dvander@520
   954
	{
dvander@520
   955
		g_Players.ClearAllAdmins();
dvander@520
   956
	}
dvander@404
   957
	/* Wipe the identity cache first */
dvander@4081
   958
	List<AuthMethod *>::iterator iter;
dvander@404
   959
	for (iter=m_AuthMethods.begin();
dvander@404
   960
		 iter!=m_AuthMethods.end();
dvander@404
   961
		 iter++)
dvander@404
   962
	{
dvander@4081
   963
		(*iter)->identities.clear();
dvander@404
   964
	}
dvander@404
   965
	
dvander@405
   966
	if (unlink_admins)
dvander@404
   967
	{
dvander@405
   968
		while (m_FirstUser != INVALID_ADMIN_ID)
dvander@405
   969
		{
dvander@405
   970
			InvalidateAdmin(m_FirstUser);
dvander@405
   971
		}
dvander@405
   972
	} else {
dvander@405
   973
		m_FirstUser = -1;
dvander@405
   974
		m_LastUser = -1;
dvander@405
   975
		m_FreeUserList = -1;
dvander@404
   976
	}
dvander@458
   977
	m_InvalidatingAdmins = false;
dvander@404
   978
}
dvander@404
   979
dvander@438
   980
void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
dvander@336
   981
{
dvander@438
   982
	List<IAdminListener *>::iterator iter;
dvander@438
   983
	IAdminListener *pListener;
dvander@438
   984
	cell_t result;
dvander@438
   985
dvander@438
   986
	if (part == AdminCache_Overrides)
dvander@336
   987
	{
dvander@336
   988
		DumpCommandOverrideCache(Override_Command);
dvander@336
   989
		DumpCommandOverrideCache(Override_CommandGroup);
dvander@520
   990
		if (rebuild && !m_destroying)
dvander@438
   991
		{
dvander@438
   992
			for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
   993
			{
dvander@438
   994
				pListener = (*iter);
dvander@438
   995
				pListener->OnRebuildOverrideCache();
dvander@438
   996
			}
dvander@438
   997
			m_pCacheFwd->PushCell(part);
dvander@438
   998
			m_pCacheFwd->Execute(&result);
dvander@438
   999
		}
dvander@438
  1000
	} else if (part == AdminCache_Groups || part == AdminCache_Admins) {
dvander@438
  1001
		if (part == AdminCache_Groups)
dvander@438
  1002
		{
dvander@438
  1003
			InvalidateGroupCache();
dvander@520
  1004
			if (rebuild && !m_destroying)
dvander@438
  1005
			{
dvander@438
  1006
				for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
  1007
				{
dvander@438
  1008
					pListener = (*iter);
dvander@438
  1009
					pListener->OnRebuildGroupCache();
dvander@438
  1010
				}
dvander@438
  1011
				m_pCacheFwd->PushCell(part);
dvander@438
  1012
				m_pCacheFwd->Execute(&result);
dvander@438
  1013
			}
dvander@438
  1014
		}
dvander@404
  1015
		InvalidateAdminCache(true);
dvander@520
  1016
		if (rebuild && !m_destroying)
dvander@336
  1017
		{
dvander@438
  1018
			for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
  1019
			{
dvander@438
  1020
				pListener = (*iter);
dvander@438
  1021
				pListener->OnRebuildAdminCache((part == AdminCache_Groups));
dvander@438
  1022
			}
dvander@438
  1023
			m_pCacheFwd->PushCell(AdminCache_Admins);
dvander@438
  1024
			m_pCacheFwd->Execute(&result);
dvander@1165
  1025
			g_Players.RecheckAnyAdmins();
dvander@336
  1026
		}
dvander@336
  1027
	}
dvander@336
  1028
}
dvander@404
  1029
dvander@404
  1030
const char *AdminCache::GetAdminName(AdminId id)
dvander@404
  1031
{
dvander@404
  1032
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1033
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1034
	{
dvander@404
  1035
		return NULL;
dvander@404
  1036
	}
dvander@404
  1037
dvander@404
  1038
	return m_pStrings->GetString(pUser->nameidx);
dvander@404
  1039
}
dvander@404
  1040
dvander@405
  1041
bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index)
dvander@405
  1042
{
dvander@4081
  1043
	List<AuthMethod *>::iterator iter;
dvander@405
  1044
	unsigned int index = 0;
dvander@405
  1045
	for (iter=m_AuthMethods.begin();
dvander@405
  1046
		 iter!=m_AuthMethods.end();
dvander@405
  1047
		 iter++,index++)
dvander@405
  1048
	{
dvander@4081
  1049
		if ((*iter)->name.compare(name) == 0)
dvander@405
  1050
		{
dvander@405
  1051
			*_index = index;
dvander@405
  1052
			return true;
dvander@405
  1053
		}
dvander@405
  1054
	}
dvander@405
  1055
dvander@405
  1056
	return false;
dvander@405
  1057
}
dvander@405
  1058
dvander@404
  1059
bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident)
dvander@404
  1060
{
rbutler14@2491
  1061
	if (ident[0] == '\0')
rbutler14@2490
  1062
	{
rbutler14@2490
  1063
		return false;
rbutler14@2490
  1064
	}
rbutler14@2490
  1065
dvander@404
  1066
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1067
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1068
	{
dvander@404
  1069
		return false;
dvander@404
  1070
	}
dvander@404
  1071
dvander@4081
  1072
	AuthMethod *method;
dvander@4081
  1073
	if (!m_AuthTables.retrieve(auth, &method))
dvander@404
  1074
		return false;
dvander@404
  1075
pred@2420
  1076
	/* If the id was a steam id strip off the STEAM_*: part */
pred@2420
  1077
	if (strcmp(auth, "steam") == 0 && strncmp(ident, "STEAM_", 6) == 0)
pred@2420
  1078
	{
pred@2420
  1079
		ident += 8;
pred@2420
  1080
	}
pred@2420
  1081
dvander@4081
  1082
	if (method->identities.contains(ident))
dvander@404
  1083
		return false;
dvander@404
  1084
dvander@1356
  1085
	int i_ident = m_pStrings->AddString(ident);
dvander@1356
  1086
dvander@1356
  1087
	pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1356
  1088
	pUser->auth.identidx = i_ident;
dvander@405
  1089
	GetMethodIndex(auth, &pUser->auth.index);
dvander@405
  1090
dvander@4081
  1091
	return method->identities.insert(ident, id);
dvander@404
  1092
}
dvander@404
  1093
dvander@404
  1094
AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity)
dvander@404
  1095
{
dvander@4081
  1096
	AuthMethod *method;
dvander@4081
  1097
	if (!m_AuthTables.retrieve(auth, &method))
dvander@404
  1098
		return INVALID_ADMIN_ID;
dvander@404
  1099
pred@2420
  1100
	/* If the id was a steam id strip off the STEAM_*: part */
pred@2420
  1101
	if (strcmp(auth, "steam") == 0 && strncmp(identity, "STEAM_", 6) == 0)
pred@2420
  1102
	{
pred@2420
  1103
		identity += 8;
pred@2420
  1104
	}
pred@2420
  1105
dvander@4081
  1106
	AdminId id;
dvander@4081
  1107
	if (!method->identities.retrieve(identity, &id))
dvander@404
  1108
		return INVALID_ADMIN_ID;
dvander@4081
  1109
	return id;
dvander@404
  1110
}
dvander@404
  1111
dvander@404
  1112
void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled)
dvander@404
  1113
{
dvander@404
  1114
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1115
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1116
	{
dvander@404
  1117
		return;
dvander@404
  1118
	}
dvander@404
  1119
dvander@433
  1120
	if (flag < Admin_Reservation
dvander@404
  1121
		|| flag >= AdminFlags_TOTAL)
dvander@404
  1122
	{
dvander@404
  1123
		return;
dvander@404
  1124
	}
dvander@436
  1125
	
dvander@436
  1126
	FlagBits bits = (1<<(FlagBits)flag);
dvander@404
  1127
dvander@436
  1128
	if (enabled)
dvander@436
  1129
	{
dvander@436
  1130
		pUser->flags |= bits;
dvander@436
  1131
		pUser->eflags |= bits;
dvander@436
  1132
	} else {
dvander@436
  1133
		pUser->flags &= ~bits;
dvander@436
  1134
		pUser->eflags &= ~bits;
dvander@436
  1135
	}
dvander@1349
  1136
dvander@1349
  1137
	pUser->serialchange++;
dvander@404
  1138
}
dvander@404
  1139
dvander@404
  1140
bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode)
dvander@404
  1141
{
dvander@404
  1142
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1143
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1144
	{
dvander@404
  1145
		return false;
dvander@404
  1146
	}
dvander@404
  1147
dvander@433
  1148
	if (flag < Admin_Reservation
dvander@404
  1149
		|| flag >= AdminFlags_TOTAL)
dvander@404
  1150
	{
dvander@404
  1151
		return false;
dvander@404
  1152
	}
dvander@404
  1153
dvander@433
  1154
	FlagBits bit = (1<<(FlagBits)flag);
dvander@433
  1155
dvander@404
  1156
	if (mode == Access_Real)
dvander@404
  1157
	{
dvander@433
  1158
		return ((pUser->flags & bit) == bit);
dvander@404
  1159
	} else if (mode == Access_Effective) {
dvander@907
  1160
		bool has_bit = ((pUser->eflags & bit) == bit);
dvander@907
  1161
		if (!has_bit && flag != Admin_Root && ((pUser->eflags & ADMFLAG_ROOT) == ADMFLAG_ROOT))
dvander@907
  1162
		{
dvander@907
  1163
			has_bit = true;
dvander@907
  1164
		}
dvander@907
  1165
		return has_bit;
dvander@404
  1166
	}
dvander@404
  1167
dvander@404
  1168
	return false;
dvander@404
  1169
}
dvander@404
  1170
dvander@433
  1171
FlagBits AdminCache::GetAdminFlags(AdminId id, AccessMode mode)
dvander@404
  1172
{
dvander@404
  1173
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1174
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1175
	{
dvander@404
  1176
		return 0;
dvander@404
  1177
	}
dvander@404
  1178
dvander@404
  1179
	if (mode == Access_Real)
dvander@404
  1180
	{
dvander@433
  1181
		return pUser->flags;
dvander@404
  1182
	} else if (mode == Access_Effective) {
dvander@433
  1183
		return pUser->eflags;
dvander@404
  1184
	}
dvander@404
  1185
dvander@433
  1186
	return 0;
dvander@404
  1187
}
dvander@404
  1188
dvander@458
  1189
void AdminCache::SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits)
dvander@458
  1190
{
dvander@458
  1191
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@458
  1192
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@458
  1193
	{
dvander@458
  1194
		return;
dvander@458
  1195
	}
dvander@458
  1196
dvander@458
  1197
	if (mode == Access_Real)
dvander@458
  1198
	{
dvander@458
  1199
		pUser->flags = bits;
dvander@458
  1200
		pUser->eflags = bits;
dvander@458
  1201
	} else if (mode == Access_Effective) {
dvander@458
  1202
		pUser->eflags = bits;
dvander@458
  1203
	}
dvander@1349
  1204
dvander@1349
  1205
	pUser->serialchange++;
dvander@458
  1206
}
dvander@458
  1207
dvander@404
  1208
bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid)
dvander@404
  1209
{
dvander@404
  1210
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1211
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1212
	{
dvander@404
  1213
		return false;
dvander@404
  1214
	}
dvander@404
  1215
dvander@404
  1216
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@405
  1217
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@404
  1218
	{
dvander@404
  1219
		return false;
dvander@404
  1220
	}
dvander@404
  1221
dvander@433
  1222
	/* First check for duplicates */
dvander@433
  1223
	if (pUser->grp_count != 0)
dvander@433
  1224
	{
dvander@433
  1225
		int *temp_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@433
  1226
		for (unsigned int i=0; i<pUser->grp_count; i++)
dvander@433
  1227
		{
dvander@433
  1228
			if (temp_table[i] == gid)
dvander@433
  1229
			{
dvander@433
  1230
				return false;
dvander@433
  1231
			}
dvander@433
  1232
		}
dvander@433
  1233
	}
dvander@433
  1234
dvander@404
  1235
	int *table;
dvander@404
  1236
	if (pUser->grp_count + 1 > pUser->grp_size)
dvander@404
  1237
	{
dvander@404
  1238
		int new_size = 0;
dvander@404
  1239
		int tblidx;
dvander@404
  1240
		
dvander@404
  1241
		if (pUser->grp_size == 0)
dvander@404
  1242
		{
dvander@404
  1243
			new_size = 2;
dvander@404
  1244
		} else {
dvander@404
  1245
			new_size = pUser->grp_size * 2;
dvander@404
  1246
		}
dvander@404
  1247
		
dvander@404
  1248
		/* Create and refresh pointers */
dvander@404
  1249
		tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table);
dvander@404
  1250
		pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1251
		pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@404
  1252
dvander@404
  1253
		/* Copy old data if necessary */
dvander@404
  1254
		if (pUser->grp_table != -1)
dvander@404
  1255
		{
dvander@404
  1256
			int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1257
			memcpy(table, old_table, sizeof(int) * pUser->grp_count);
dvander@404
  1258
		}
dvander@404
  1259
		pUser->grp_table = tblidx;
dvander@404
  1260
		pUser->grp_size = new_size;
dvander@404
  1261
	} else {
dvander@404
  1262
		table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1263
	}
dvander@404
  1264
dvander@404
  1265
	table[pUser->grp_count] = gid;
dvander@404
  1266
	pUser->grp_count++;
dvander@404
  1267
dvander@434
  1268
	/* Compute new effective permissions */
dvander@433
  1269
	pUser->eflags |= pGroup->addflags;
dvander@404
  1270
dvander@1403
  1271
	if (pGroup->immunity_level > pUser->immunity_level)
dvander@434
  1272
	{
dvander@1403
  1273
		pUser->immunity_level = pGroup->immunity_level;
dvander@434
  1274
	}
dvander@434
  1275
dvander@1349
  1276
	pUser->serialchange++;
dvander@1349
  1277
dvander@404
  1278
	return true;
dvander@404
  1279
}
dvander@404
  1280
dvander@458
  1281
bool AdminCache::IsValidAdmin(AdminId id)
dvander@458
  1282
{
dvander@458
  1283
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@458
  1284
	return (pUser != NULL && pUser->magic == USR_MAGIC_SET);
dvander@458
  1285
}
dvander@458
  1286
dvander@404
  1287
unsigned int AdminCache::GetAdminGroupCount(AdminId id)
dvander@404
  1288
{
dvander@404
  1289
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1290
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1291
	{
dvander@404
  1292
		return 0;
dvander@404
  1293
	}
dvander@404
  1294
dvander@404
  1295
	return pUser->grp_count;
dvander@404
  1296
}
dvander@404
  1297
dvander@404
  1298
GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name)
dvander@404
  1299
{
dvander@404
  1300
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1301
	if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count)
dvander@404
  1302
	{
dvander@404
  1303
		return INVALID_GROUP_ID;
dvander@404
  1304
	}
dvander@404
  1305
dvander@404
  1306
	int *table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1307
dvander@1356
  1308
	GroupId gid = table[index];
dvander@1356
  1309
dvander@1356
  1310
	if (name)
dvander@1356
  1311
	{
dvander@1356
  1312
		*name = GetGroupName(gid);
dvander@1356
  1313
	}
dvander@1356
  1314
dvander@1356
  1315
	return gid;
dvander@404
  1316
}
dvander@404
  1317
dvander@404
  1318
const char *AdminCache::GetAdminPassword(AdminId id)
dvander@404
  1319
{
dvander@404
  1320
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1321
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1322
	{
dvander@404
  1323
		return NULL;
dvander@404
  1324
	}
dvander@404
  1325
dvander@404
  1326
	return m_pStrings->GetString(pUser->password);
dvander@404
  1327
}
dvander@404
  1328
dvander@404
  1329
void AdminCache::SetAdminPassword(AdminId id, const char *password)
dvander@404
  1330
{	
dvander@404
  1331
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1332
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1333
	{
dvander@404
  1334
		return;
dvander@404
  1335
	}
dvander@404
  1336
dvander@2073
  1337
	if (password[0] == '\0')
dvander@2073
  1338
	{
dvander@2073
  1339
		pUser->password = -1;
dvander@2073
  1340
		return;
dvander@2073
  1341
	}
dvander@2073
  1342
dvander@1356
  1343
	int i_password = m_pStrings->AddString(password);
dvander@1356
  1344
	pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1356
  1345
	pUser->password = i_password;
dvander@404
  1346
}
dvander@404
  1347
dvander@433
  1348
unsigned int AdminCache::FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize)
dvander@433
  1349
{
dvander@433
  1350
	unsigned int i;
dvander@433
  1351
	for (i=0; i<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1352
	{
dvander@464
  1353
		array[i] = ((bits & (1<<i)) == (unsigned)(1<<i));
dvander@433
  1354
	}
dvander@433
  1355
dvander@433
  1356
	return i;
dvander@433
  1357
}
dvander@433
  1358
dvander@433
  1359
FlagBits AdminCache::FlagBitArrayToBits(const bool array[], unsigned int maxSize)
dvander@433
  1360
{
dvander@433
  1361
	FlagBits bits = 0;
dvander@433
  1362
	for (unsigned int i=0; i<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1363
	{
dvander@433
  1364
		if (array[i])
dvander@433
  1365
		{
dvander@433
  1366
			bits |= (1<<i);
dvander@433
  1367
		}
dvander@433
  1368
	}
dvander@433
  1369
dvander@433
  1370
	return bits;
dvander@433
  1371
}
dvander@433
  1372
dvander@433
  1373
FlagBits AdminCache::FlagArrayToBits(const AdminFlag array[], unsigned int numFlags)
dvander@433
  1374
{
dvander@433
  1375
	FlagBits bits = 0;
dvander@433
  1376
	for (unsigned int i=0; i<numFlags && i<AdminFlags_TOTAL; i++)
dvander@433
  1377
	{
dvander@433
  1378
		bits |= (1 << (FlagBits)array[i]);
dvander@433
  1379
	}
dvander@433
  1380
dvander@433
  1381
	return bits;
dvander@433
  1382
}
dvander@433
  1383
dvander@433
  1384
unsigned int AdminCache::FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize)
dvander@433
  1385
{
dvander@433
  1386
	unsigned int i, num=0;
dvander@1050
  1387
	for (i=0; num<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1388
	{
dvander@464
  1389
		if ((bits & (1<<i)) == (unsigned)(1<<i))
dvander@433
  1390
		{
dvander@433
  1391
			array[num++] = (AdminFlag)i;
dvander@433
  1392
		}
dvander@433
  1393
	}
dvander@433
  1394
dvander@433
  1395
	return num;
dvander@433
  1396
}
dvander@434
  1397
dvander@434
  1398
bool AdminCache::CheckAdminFlags(AdminId id, FlagBits bits)
dvander@434
  1399
{
dvander@434
  1400
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@434
  1401
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@434
  1402
	{
dvander@434
  1403
		return false;
dvander@434
  1404
	}
dvander@434
  1405
dvander@434
  1406
	return ((pUser->eflags & bits) == bits);
dvander@434
  1407
}
dvander@434
  1408
dvander@434
  1409
bool AdminCache::CanAdminTarget(AdminId id, AdminId target)
dvander@434
  1410
{
dvander@434
  1411
	/** 
dvander@434
  1412
	 * Zeroth, if the targeting AdminId is INVALID_ADMIN_ID, targeting fails.
ds@729
  1413
	 * First, if the targeted AdminId is INVALID_ADMIN_ID, targeting succeeds.
dvander@434
  1414
	 */
dvander@434
  1415
dvander@434
  1416
	if (id == INVALID_ADMIN_ID)
dvander@434
  1417
	{
dvander@434
  1418
		return false;
dvander@434
  1419
	}
dvander@434
  1420
dvander@434
  1421
	if (target == INVALID_ADMIN_ID)
dvander@434
  1422
	{
dvander@434
  1423
		return true;
dvander@434
  1424
	}
dvander@434
  1425
dvander@1403
  1426
	if (id == target)
dvander@1403
  1427
	{
dvander@1403
  1428
		return true;
dvander@1403
  1429
	}
dvander@1403
  1430
dvander@434
  1431
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@434
  1432
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@434
  1433
	{
dvander@434
  1434
		return false;
dvander@434
  1435
	}
dvander@434
  1436
dvander@434
  1437
	AdminUser *pTarget = (AdminUser *)m_pMemory->GetAddress(target);
dvander@434
  1438
	if (!pTarget || pTarget->magic != USR_MAGIC_SET)
dvander@434
  1439
	{
dvander@434
  1440
		return false;
dvander@434
  1441
	}
dvander@434
  1442
dvander@434
  1443
	/** 
ds@729
  1444
	 * Second, if the targeting admin is root, targeting succeeds.
dvander@434
  1445
	 */
dvander@434
  1446
	if (pUser->eflags & ADMFLAG_ROOT)
dvander@434
  1447
	{
dvander@434
  1448
		return true;
dvander@434
  1449
	}
dvander@434
  1450
dvander@1403
  1451
	/** Fourth, if the targeted admin is immune from targeting admin. */
dvander@1403
  1452
	int mode = sm_immunity_mode.GetInt();
dvander@1403
  1453
	switch (mode)
dvander@434
  1454
	{
dvander@1403
  1455
		case 1:
dvander@1403
  1456
		{
dvander@1403
  1457
			if (pTarget->immunity_level > pUser->immunity_level)
dvander@1403
  1458
			{
dvander@1403
  1459
				return false;
dvander@1403
  1460
			}
dvander@1403
  1461
			break;
dvander@1403
  1462
		}
dvander@1403
  1463
		case 3:
dvander@1403
  1464
		{
dvander@1403
  1465
			/* If neither has any immunity, let this pass. */
dvander@1403
  1466
			if (!pUser->immunity_level && !pTarget->immunity_level)
dvander@1403
  1467
			{
dvander@1403
  1468
				return true;
dvander@1403
  1469
			}
dvander@1403
  1470
			/* Don't break, go to the next case. */
dvander@1403
  1471
		}
dvander@1403
  1472
		case 2:
dvander@1403
  1473
		{
dvander@1403
  1474
			if (pTarget->immunity_level >= pUser->immunity_level)
dvander@1403
  1475
			{
dvander@1403
  1476
				return false;
dvander@1403
  1477
			}
dvander@1403
  1478
			break;
dvander@1403
  1479
		}
dvander@434
  1480
	}
dvander@434
  1481
dvander@434
  1482
	/** 
dvander@1403
  1483
	 * Fifth, if the targeted admin has specific immunity from the
dvander@434
  1484
	 *  targeting admin via group immunities, targeting fails.
dvander@434
  1485
	 */
dvander@434
  1486
	//:TODO: speed this up... maybe with trie hacks.
dvander@434
  1487
	//idea is to insert %d.%d in the trie after computing this and use it as a cache lookup.
dvander@434
  1488
	//problem is the trie cannot delete prefixes, so we'd have a problem with invalidations.
dvander@434
  1489
	if (pTarget->grp_count > 0 && pUser->grp_count > 0)
dvander@434
  1490
	{
dvander@434
  1491
		int *grp_table = (int *)m_pMemory->GetAddress(pTarget->grp_table);
dvander@434
  1492
		int *src_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@434
  1493
		GroupId id, other;
dvander@434
  1494
		unsigned int num;
dvander@434
  1495
		for (unsigned int i=0; i<pTarget->grp_count; i++)
dvander@434
  1496
		{
dvander@434
  1497
			id = grp_table[i];
dvander@434
  1498
			num = GetGroupImmunityCount(id);
dvander@434
  1499
			for (unsigned int j=0; j<num; i++)
dvander@434
  1500
			{
dvander@434
  1501
				other = GetGroupImmunity(id, j);
dvander@434
  1502
				for (unsigned int k=0; k<pUser->grp_count; k++)
dvander@434
  1503
				{
dvander@434
  1504
					if (other == src_table[k])
dvander@434
  1505
					{
dvander@434
  1506
						return false;
dvander@434
  1507
					}
dvander@434
  1508
				}
dvander@434
  1509
			}
dvander@434
  1510
		}
dvander@434
  1511
	}
dvander@434
  1512
	
dvander@434
  1513
	return true;
dvander@434
  1514
}
dvander@1298
  1515
dvander@1298
  1516
bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
dvander@1298
  1517
{
dvander@1965
  1518
	if (c < 'a' 
dvander@1965
  1519
		|| c > 'z'
dvander@1965
  1520
		|| !g_FlagSet[(unsigned)c - (unsigned)'a'])
dvander@1298
  1521
	{
dvander@1298
  1522
		return false;
dvander@1298
  1523
	}
dvander@1298
  1524
dvander@1305
  1525
	if (pAdmFlag)
dvander@1298
  1526
	{
dvander@1298
  1527
		*pAdmFlag = g_FlagLetters[(unsigned)c - (unsigned)'a'];
dvander@1298
  1528
	}
dvander@1298
  1529
dvander@1298
  1530
	return true;
dvander@1298
  1531
}
dvander@1298
  1532
dvander@1965
  1533
bool AdminCache::FindFlagChar(AdminFlag flag, char *c)
dvander@1965
  1534
{
dvander@1965
  1535
	if (!g_FlagSet[flag])
dvander@1965
  1536
	{
dvander@1965
  1537
		return false;
dvander@1965
  1538
	}
dvander@1965
  1539
dvander@1965
  1540
	if (c)
dvander@1965
  1541
	{
dvander@1965
  1542
		*c = g_ReverseFlags[flag];
dvander@1965
  1543
	}
dvander@1965
  1544
dvander@1965
  1545
	return true;
dvander@1965
  1546
}
dvander@1965
  1547
dvander@1298
  1548
FlagBits AdminCache::ReadFlagString(const char *flags, const char **end)
dvander@1298
  1549
{
dvander@1298
  1550
	FlagBits bits = 0;
dvander@1298
  1551
dvander@1298
  1552
	while (flags && (*flags != '\0'))
dvander@1298
  1553
	{
dvander@1298
  1554
		AdminFlag flag;
dvander@1298
  1555
		if (!FindFlag(*flags, &flag))
dvander@1298
  1556
		{
dvander@1298
  1557
			break;
dvander@1298
  1558
		}
dvander@1298
  1559
		bits |= FlagArrayToBits(&flag, 1);
dvander@1298
  1560
		flags++;
dvander@1298
  1561
	}
dvander@1298
  1562
dvander@1298
  1563
	if (end)
dvander@1298
  1564
	{
dvander@1298
  1565
		*end = flags;
dvander@1298
  1566
	}
dvander@1298
  1567
dvander@1298
  1568
	return bits;
dvander@1298
  1569
}
dvander@1349
  1570
dvander@1349
  1571
unsigned int AdminCache::GetAdminSerialChange(AdminId id)
dvander@1349
  1572
{
dvander@1349
  1573
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1349
  1574
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@1349
  1575
	{
dvander@1349
  1576
		return 0;
dvander@1349
  1577
	}
dvander@1349
  1578
dvander@1349
  1579
	return pUser->serialchange;
dvander@1349
  1580
}
dvander@1349
  1581
dvander@1349
  1582
bool AdminCache::CanAdminUseCommand(int client, const char *cmd)
dvander@1349
  1583
{
dvander@1349
  1584
	FlagBits bits;
dvander@1349
  1585
	OverrideType otype = Override_Command;
dvander@1349
  1586
dvander@1349
  1587
	if (cmd[0] == '@')
dvander@1349
  1588
	{
dvander@1349
  1589
		otype = Override_CommandGroup;
dvander@1349
  1590
		cmd++;
dvander@1349
  1591
	}
dvander@1349
  1592
dvander@1349
  1593
	if (!g_ConCmds.LookForCommandAdminFlags(cmd, &bits))
dvander@1349
  1594
	{
dvander@1349
  1595
		if (!GetCommandOverride(cmd, otype, &bits))
dvander@1349
  1596
		{
dvander@1349
  1597
			bits = 0;
dvander@1349
  1598
		}
dvander@1349
  1599
	}
dvander@1349
  1600
skamonkey@3389
  1601
	return g_ConCmds.CheckClientCommandAccess(client, cmd, bits);
dvander@1349
  1602
}
dvander@1403
  1603
dvander@1403
  1604
unsigned int AdminCache::SetGroupImmunityLevel(GroupId gid, unsigned int level)
dvander@1403
  1605
{
dvander@1403
  1606
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@1403
  1607
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@1403
  1608
	{
dvander@1403
  1609
		return 0;
dvander@1403
  1610
	}
dvander@1403
  1611
dvander@1403
  1612
	unsigned int old_level = pGroup->immunity_level;
dvander@1403
  1613
dvander@1403
  1614
	pGroup->immunity_level = level;
dvander@1403
  1615
dvander@1403
  1616
	return old_level;
dvander@1403
  1617
}
dvander@1403
  1618
dvander@1403
  1619
unsigned int AdminCache::GetGroupImmunityLevel(GroupId gid)
dvander@1403
  1620
{
dvander@1403
  1621
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@1403
  1622
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@1403
  1623
	{
dvander@1403
  1624
		return 0;
dvander@1403
  1625
	}
dvander@1403
  1626
dvander@1403
  1627
	return pGroup->immunity_level;
dvander@1403
  1628
}
dvander@1403
  1629
dvander@1403
  1630
unsigned int AdminCache::SetAdminImmunityLevel(AdminId id, unsigned int level)
dvander@1403
  1631
{
dvander@1403
  1632
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1403
  1633
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@1403
  1634
	{
dvander@1403
  1635
		return 0;
dvander@1403
  1636
	}
dvander@1403
  1637
dvander@1403
  1638
	unsigned int old_level = pUser->immunity_level;
dvander@1403
  1639
dvander@1403
  1640
	pUser->immunity_level = level;
dvander@1403
  1641
dvander@1403
  1642
	return old_level;
dvander@1403
  1643
}
dvander@1403
  1644
dvander@1403
  1645
unsigned int AdminCache::GetAdminImmunityLevel(AdminId id)
dvander@1403
  1646
{
dvander@1403
  1647
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@1403
  1648
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@1403
  1649
	{
dvander@1403
  1650
		return 0;
dvander@1403
  1651
	}
dvander@1403
  1652
dvander@1403
  1653
	return pUser->immunity_level;
dvander@1403
  1654
}
dvander@1403
  1655
dvander@1477
  1656
bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool override_only)
dvander@1473
  1657
{
dvander@1473
  1658
	if (client == 0)
dvander@1473
  1659
	{
dvander@1473
  1660
		return true;
dvander@1473
  1661
	}
dvander@1473
  1662
dvander@1473
  1663
	/* Auto-detect a command if we can */
dvander@1473
  1664
	FlagBits bits = flags;
dvander@1473
  1665
	bool found_command = false;
dvander@1473
  1666
	if (!override_only)
dvander@1473
  1667
	{
dvander@1473
  1668
		found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits);
dvander@1473
  1669
	}
dvander@1473
  1670
dvander@1473
  1671
	if (!found_command)
dvander@1473
  1672
	{
dvander@1473
  1673
		GetCommandOverride(cmd, Override_Command, &bits);
dvander@1473
  1674
	}
dvander@1473
  1675
skamonkey@3389
  1676
	return g_ConCmds.CheckClientCommandAccess(client, cmd, bits) ? 1 : 0;
dvander@1473
  1677
}
dvander@1965
  1678
dvander@4081
  1679
void iterator_glob_basic_override(FILE *fp, const char *key, FlagBits flags)
dvander@1965
  1680
{
dvander@1965
  1681
	char flagstr[64];
dvander@1965
  1682
	g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr));
dvander@1965
  1683
	fprintf(fp, "\t\"%s\"\t\t\"%s\"\n", key, flagstr);
dvander@1965
  1684
}
dvander@1965
  1685
dvander@4081
  1686
void iterator_glob_grp_override(FILE *fp, const char *key, FlagBits flags)
dvander@1965
  1687
{
dvander@1965
  1688
	char flagstr[64];
dvander@1965
  1689
	g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr));
dvander@1965
  1690
	fprintf(fp, "\t\"@%s\"\t\t\"%s\"\n", key, flagstr);
dvander@1965
  1691
}
dvander@1965
  1692
dvander@4081
  1693
void iterator_group_basic_override(FILE *fp, const char *key, OverrideRule rule)
dvander@1965
  1694
{
dvander@4081
  1695
	const char *str = (rule == Command_Allow) ? "allow" : "deny";
dvander@4081
  1696
	fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n", key, str);
dvander@1965
  1697
}
dvander@1965
  1698
dvander@4081
  1699
void iterator_group_grp_override(FILE *fp, const char *key, OverrideRule rule)
dvander@1965
  1700
{
dvander@4081
  1701
	const char *str = (rule == Command_Allow) ? "allow" : "deny";
dvander@4081
  1702
	fprintf(fp, "\t\t\t\"@%s\"\t\t\"%s\"\n", key, str);
dvander@1965
  1703
}
dvander@1965
  1704
dvander@1965
  1705
void AdminCache::DumpCache(FILE *fp)
dvander@1965
  1706
{
dvander@1965
  1707
	int *itable;
dvander@1965
  1708
	AdminId aid;
dvander@1965
  1709
	GroupId gid;
dvander@1965
  1710
	char flagstr[64];
dvander@1965
  1711
	unsigned int num;
dvander@1965
  1712
	AdminUser *pAdmin;
dvander@1965
  1713
	AdminGroup *pGroup;
dvander@1965
  1714
dvander@1965
  1715
	fprintf(fp, "\"Groups\"\n{\n");
dvander@1965
  1716
	
dvander@1965
  1717
	num = 0;
dvander@1965
  1718
	gid = m_FirstGroup;
dvander@1965
  1719
	while (gid != INVALID_GROUP_ID
dvander@1965
  1720
			&& (pGroup = GetGroup(gid)) != NULL)
dvander@1965
  1721
	{
dvander@1965
  1722
		num++;
dvander@1965
  1723
		FillFlagString(pGroup->addflags, flagstr, sizeof(flagstr));
dvander@1965
  1724
dvander@1965
  1725
		fprintf(fp, "\t/* num = %d, gid = 0x%X */\n", num, gid);
dvander@1965
  1726
		fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pGroup->nameidx));
dvander@1965
  1727
		fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr);
dvander@1965
  1728
		fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pGroup->immunity_level);
dvander@1965
  1729
		
dvander@1965
  1730
		if (pGroup->immune_table != -1
dvander@1965
  1731
			&& (itable = (int *)m_pMemory->GetAddress(pGroup->immune_table)) != NULL)
dvander@1965
  1732
		{
dvander@1965
  1733
			AdminGroup *pAltGroup;
dvander@1965
  1734
			const char *gname, *mod;
dvander@1965
  1735
dvander@1965
  1736
			for (int i = 1; i <= itable[0]; i++)
dvander@1965
  1737
			{
dvander@1965
  1738
				if ((pAltGroup = GetGroup(itable[i])) == NULL)
dvander@1965
  1739
				{
dvander@1965
  1740
					/* Assume the rest of the table is corrupt */
dvander@1965
  1741
					break;
dvander@1965
  1742
				}
dvander@1965
  1743
				gname = GetString(pAltGroup->nameidx);
dvander@1965
  1744
				if (atoi(gname) != 0)
dvander@1965
  1745
				{
dvander@1965
  1746
					mod = "@";
dvander@1965
  1747
				}
dvander@1965
  1748
				else
dvander@1965
  1749
				{
dvander@1965
  1750
					mod = "";
dvander@1965
  1751
				}
dvander@1965
  1752
				fprintf(fp, "\t\t\"immunity\"\t\t\"%s%s\"\n", mod, gname);
dvander@1965
  1753
			}
dvander@1965
  1754
		}
dvander@1965
  1755
dvander@1965
  1756
		fprintf(fp, "\n\t\t\"Overrides\"\n\t\t{\n");
dvander@1965
  1757
		if (pGroup->pCmdGrpTable != NULL)
dvander@1965
  1758
		{
dvander@4081
  1759
			for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next())
dvander@4081
  1760
				iterator_group_grp_override(fp, iter->key.chars(), iter->value);
dvander@1965
  1761
		}
dvander@1965
  1762
		if (pGroup->pCmdTable != NULL)
dvander@1965
  1763
		{
dvander@4081
  1764
			for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next())
dvander@4081
  1765
				iterator_group_basic_override(fp, iter->key.chars(), iter->value);
dvander@1965
  1766
		}
dvander@1965
  1767
		fprintf(fp, "\t\t}\n");
dvander@1965
  1768
dvander@1965
  1769
		fprintf(fp, "\t}\n");
dvander@1965
  1770
dvander@1965
  1771
		if ((gid = pGroup->next_grp) != INVALID_GROUP_ID)
dvander@1965
  1772
		{
dvander@1965
  1773
			fprintf(fp, "\n");
dvander@1965
  1774
		}
dvander@1965
  1775
	}
dvander@1965
  1776
dvander@1965
  1777
	fprintf(fp, "}\n\n");
dvander@1965
  1778
	fprintf(fp, "\"Admins\"\n{\n");
dvander@1965
  1779
dvander@1965
  1780
	num = 0;
dvander@1965
  1781
	aid = m_FirstUser;
dvander@1965
  1782
	while (aid != INVALID_ADMIN_ID
dvander@1965
  1783
			&& (pAdmin = GetUser(aid)) != NULL)
dvander@1965
  1784
	{
dvander@1965
  1785
		num++;
dvander@1965
  1786
		FillFlagString(pAdmin->flags, flagstr, sizeof(flagstr));
dvander@1965
  1787
dvander@1965
  1788
		fprintf(fp, "\t/* num = %d, aid = 0x%X, serialno = 0x%X*/\n", num, aid, pAdmin->serialchange);
dvander@1965
  1789
dvander@1965
  1790
		if (pAdmin->nameidx != -1)
dvander@1965
  1791
		{
dvander@1965
  1792
			fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pAdmin->nameidx));
dvander@1965
  1793
		}
dvander@1965
  1794
		else
dvander@1965
  1795
		{
dvander@1965
  1796
			fprintf(fp, "\t\"\"\n\t{\n");
dvander@1965
  1797
		}
dvander@1965
  1798
dvander@1965
  1799
		if (pAdmin->auth.identidx != -1)
dvander@1965
  1800
		{
dvander@1965
  1801
			fprintf(fp, "\t\t\"auth\"\t\t\t\"%s\"\n", GetMethodName(pAdmin->auth.index));
dvander@1965
  1802
			fprintf(fp, "\t\t\"identity\"\t\t\"%s\"\n", GetString(pAdmin->auth.identidx));
dvander@1965
  1803
		}
dvander@1965
  1804
		if (pAdmin->password != -1)
dvander@1965
  1805
		{
dvander@1965
  1806
			fprintf(fp, "\t\t\"password\"\t\t\"%s\"\n", GetString(pAdmin->password));
dvander@1965
  1807
		}
dvander@1965
  1808
		fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr);
dvander@1965
  1809
		fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pAdmin->immunity_level);
dvander@1965
  1810
dvander@1965
  1811
		if (pAdmin->grp_count != 0 
dvander@1965
  1812
			&& pAdmin->grp_table != -1 
dvander@1965
  1813
			&& (itable = (int *)m_pMemory->GetAddress(pAdmin->grp_table)) != NULL)
dvander@1965
  1814
		{
dvander@1965
  1815
			unsigned int i;
dvander@1965
  1816
dvander@1965
  1817
			for (i = 0; i < pAdmin->grp_count; i++)
dvander@1965
  1818
			{
dvander@1965
  1819
				if ((pGroup = GetGroup(itable[i])) == NULL)
dvander@1965
  1820
				{
dvander@1965
  1821
					/* Assume the rest of the table is corrupt */
dvander@1965
  1822
					break;
dvander@1965
  1823
				}
dvander@1965
  1824
				fprintf(fp, "\t\t\"group\"\t\t\t\"%s\"\n", GetString(pGroup->nameidx));
dvander@1965
  1825
			}
dvander@1965
  1826
		}
dvander@1965
  1827
dvander@1965
  1828
		fprintf(fp, "\t}\n");
dvander@1965
  1829
dvander@1965
  1830
		if ((aid = pAdmin->next_user) != INVALID_ADMIN_ID)
dvander@1965
  1831
		{
dvander@1965
  1832
			fprintf(fp, "\n");
dvander@1965
  1833
		}
dvander@1965
  1834
	}
dvander@1965
  1835
dvander@1965
  1836
	fprintf(fp, "}\n\n");
dvander@1965
  1837
dvander@1965
  1838
	fprintf(fp, "\"Overrides\"\n{\n");
dvander@4081
  1839
	for (FlagMap::iterator iter = m_CmdGrpOverrides.iter(); !iter.empty(); iter.next())
dvander@4081
  1840
		iterator_glob_grp_override(fp, iter->key.chars(), iter->value);
dvander@4081
  1841
	for (FlagMap::iterator iter = m_CmdOverrides.iter(); !iter.empty(); iter.next())
dvander@4081
  1842
		iterator_glob_basic_override(fp, iter->key.chars(), iter->value);
dvander@1965
  1843
	fprintf(fp, "}\n");
dvander@1965
  1844
}
dvander@1965
  1845
dvander@1965
  1846
AdminGroup *AdminCache::GetGroup(GroupId gid)
dvander@1965
  1847
{
dvander@1965
  1848
	AdminGroup *pGroup;
dvander@1965
  1849
	
dvander@1965
  1850
	pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@1965
  1851
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@1965
  1852
	{
dvander@1965
  1853
		return NULL;
dvander@1965
  1854
	}
dvander@1965
  1855
dvander@1965
  1856
	return pGroup;
dvander@1965
  1857
}
dvander@1965
  1858
dvander@1965
  1859
AdminUser *AdminCache::GetUser(AdminId aid)
dvander@1965
  1860
{
dvander@1965
  1861
	AdminUser *pAdmin;
dvander@1965
  1862
dvander@1965
  1863
	pAdmin = (AdminUser *)m_pMemory->GetAddress(aid);
dvander@1965
  1864
	if (!pAdmin || pAdmin->magic != USR_MAGIC_SET)
dvander@1965
  1865
	{
dvander@1965
  1866
		return NULL;
dvander@1965
  1867
	}
dvander@1965
  1868
dvander@1965
  1869
	return pAdmin;
dvander@1965
  1870
}
dvander@1965
  1871
dvander@1965
  1872
const char *AdminCache::GetMethodName(unsigned int index)
dvander@1965
  1873
{
dvander@4081
  1874
	List<AuthMethod *>::iterator iter;
dvander@1965
  1875
	for (iter=m_AuthMethods.begin();
dvander@1965
  1876
		iter!=m_AuthMethods.end();
dvander@1965
  1877
		iter++)
dvander@1965
  1878
	{
dvander@1965
  1879
		if (index-- == 0)
dvander@1965
  1880
		{
dvander@4081
  1881
			return (*iter)->name.c_str();
dvander@1965
  1882
		}
dvander@1965
  1883
	}
dvander@1965
  1884
dvander@1965
  1885
	return NULL;
dvander@1965
  1886
}
dvander@1965
  1887
dvander@1965
  1888
const char *AdminCache::GetString(int idx)
dvander@1965
  1889
{
dvander@1965
  1890
	return m_pStrings->GetString(idx);
dvander@1965
  1891
}
dvander@1965
  1892
dvander@1965
  1893
size_t AdminCache::FillFlagString(FlagBits bits, char *buffer, size_t maxlen)
dvander@1965
  1894
{
dvander@1965
  1895
	size_t pos;
dvander@1965
  1896
	unsigned int i, num_flags;
dvander@1965
  1897
	AdminFlag flags[AdminFlags_TOTAL];
dvander@1965
  1898
dvander@1965
  1899
	num_flags = FlagBitsToArray(bits, flags, AdminFlags_TOTAL);
dvander@1965
  1900
dvander@1965
  1901
	pos = 0;
dvander@1965
  1902
	for (i = 0; pos < maxlen && i < num_flags; i++)
dvander@1965
  1903
	{
dvander@1965
  1904
		if (FindFlagChar(flags[i], &buffer[pos]))
dvander@1965
  1905
		{
dvander@1965
  1906
			pos++;
dvander@1965
  1907
		}
dvander@1965
  1908
	}
dvander@1965
  1909
	buffer[pos] = '\0';
dvander@1965
  1910
dvander@1965
  1911
	return pos;
dvander@1965
  1912
}
dvander@1965
  1913
dvander@1965
  1914
CON_COMMAND(sm_dump_admcache, "Dumps the admin cache for debugging")
dvander@1965
  1915
{
dvander@1965
  1916
	FILE *fp;
dvander@1965
  1917
	char buffer[PLATFORM_MAX_PATH];
dvander@1965
  1918
dvander@1965
  1919
	g_SourceMod.BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt");
dvander@1965
  1920
dvander@1965
  1921
	if ((fp = fopen(buffer, "wt")) == NULL)
dvander@1965
  1922
	{
dvander@1965
  1923
		g_RootMenu.ConsolePrint("Could not open file for writing: %s", buffer);
dvander@1965
  1924
		return;
dvander@1965
  1925
	}
dvander@1965
  1926
dvander@1965
  1927
	g_Admins.DumpCache(fp);
dvander@1965
  1928
dvander@1965
  1929
	g_RootMenu.ConsolePrint("Admin cache dumped to: %s", buffer);
dvander@1965
  1930
dvander@1965
  1931
	fclose(fp);
dvander@1965
  1932
}