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