core/AdminCache.cpp
author Michael McKoy <ferret99gt@gmail.com>
Wed Aug 08 23:45:24 2007 +0000 (2007-08-08)
changeset 1284 ac293d8351a3
parent 1231 17badaf66ce4
child 1298 9cddbed74581
permissions -rw-r--r--
Import of baseplugins.sp
dvander@370
     1
/**
ds@653
     2
 * vim: set ts=4 :
dvander@1231
     3
 * ================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
dvander@1231
     6
 * ================================================================
dvander@370
     7
 *
dvander@1231
     8
 * This program is free software; you can redistribute it and/or 
dvander@1231
     9
 * modify it under the terms of the GNU General Public License, 
dvander@1231
    10
 * version 3.0, as published by the Free Software Foundation.
dvander@1231
    11
 * 
dvander@1231
    12
 * This program is distributed in the hope that it will be useful,
dvander@1231
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
dvander@1231
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dvander@1231
    15
 * GNU General Public License for more details.
dvander@1231
    16
 *
dvander@1231
    17
 * You should have received a copy of the GNU General Public License
dvander@1231
    18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
dvander@1231
    20
 * As a special exception, AlliedModders LLC gives you permission to 
dvander@1231
    21
 * link the code of this program (as well as its derivative works) to 
dvander@1231
    22
 * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
dvander@1231
    23
 * Game MODs that run on software by the Valve Corporation.  You must 
dvander@1231
    24
 * obey the GNU General Public License in all respects for all other 
dvander@1231
    25
 * code used. Additionally, AlliedModders LLC grants this exception 
dvander@1231
    26
 * to all derivative works. AlliedModders LLC defines further 
dvander@1231
    27
 * exceptions, found in LICENSE.txt (as of this writing, version 
dvander@1231
    28
 * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
dvander@370
    29
 *
dvander@370
    30
 * Version: $Id$
dvander@370
    31
 */
dvander@370
    32
dvander@335
    33
#include <string.h>
dvander@335
    34
#include <assert.h>
dvander@335
    35
#include "AdminCache.h"
dvander@335
    36
#include "ShareSys.h"
dvander@336
    37
#include "ForwardSys.h"
dvander@591
    38
#include "PlayerManager.h"
dvander@583
    39
#include "ConCmdManager.h"
dvander@335
    40
dvander@335
    41
AdminCache g_Admins;
dvander@335
    42
dvander@335
    43
AdminCache::AdminCache()
dvander@335
    44
{
dvander@433
    45
	m_pCmdOverrides = sm_trie_create();
dvander@433
    46
	m_pCmdGrpOverrides = sm_trie_create();
dvander@335
    47
	m_pStrings = new BaseStringTable(1024);
dvander@335
    48
	m_pMemory = m_pStrings->GetMemTable();
dvander@335
    49
	m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
dvander@404
    50
	m_FreeUserList = m_FirstUser = m_LastUser = INVALID_ADMIN_ID;
dvander@335
    51
	m_pGroups = sm_trie_create();
dvander@336
    52
	m_pCacheFwd = NULL;
dvander@404
    53
	m_FirstGroup = -1;
dvander@405
    54
	m_pAuthTables = sm_trie_create();
dvander@458
    55
	m_InvalidatingAdmins = false;
dvander@520
    56
	m_destroying = false;
dvander@335
    57
}
dvander@335
    58
dvander@335
    59
AdminCache::~AdminCache()
dvander@335
    60
{
dvander@520
    61
	m_destroying = true;
dvander@438
    62
	DumpAdminCache(AdminCache_Overrides, false);
dvander@438
    63
	DumpAdminCache(AdminCache_Groups, false);
dvander@438
    64
dvander@434
    65
	sm_trie_destroy(m_pCmdGrpOverrides);
dvander@434
    66
	sm_trie_destroy(m_pCmdOverrides);
dvander@335
    67
dvander@335
    68
	if (m_pGroups)
dvander@335
    69
	{
dvander@335
    70
		sm_trie_destroy(m_pGroups);
dvander@335
    71
	}
dvander@335
    72
dvander@405
    73
	List<AuthMethod>::iterator iter;
dvander@405
    74
	for (iter=m_AuthMethods.begin();
dvander@405
    75
		 iter!=m_AuthMethods.end();
dvander@405
    76
		 iter++)
dvander@405
    77
	{
dvander@405
    78
		sm_trie_destroy((*iter).table);
dvander@405
    79
	}
dvander@405
    80
dvander@405
    81
	sm_trie_destroy(m_pAuthTables);
dvander@405
    82
dvander@335
    83
	delete m_pStrings;
dvander@335
    84
}
dvander@335
    85
dvander@404
    86
void AdminCache::OnSourceModStartup(bool late)
dvander@404
    87
{
dvander@404
    88
	RegisterAuthIdentType("steam");
dvander@404
    89
	RegisterAuthIdentType("name");
dvander@404
    90
	RegisterAuthIdentType("ip");
dvander@404
    91
}
dvander@404
    92
dvander@335
    93
void AdminCache::OnSourceModAllInitialized()
dvander@335
    94
{
dvander@336
    95
	m_pCacheFwd = g_Forwards.CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell);
dvander@335
    96
	g_ShareSys.AddInterface(NULL, this);
dvander@335
    97
}
dvander@335
    98
dvander@336
    99
void AdminCache::OnSourceModShutdown()
dvander@336
   100
{
dvander@336
   101
	g_Forwards.ReleaseForward(m_pCacheFwd);
dvander@336
   102
	m_pCacheFwd = NULL;
dvander@336
   103
}
dvander@336
   104
dvander@673
   105
void AdminCache::OnSourceModPluginsLoaded()
dvander@673
   106
{
dvander@673
   107
	DumpAdminCache(AdminCache_Overrides, true);
dvander@673
   108
	DumpAdminCache(AdminCache_Groups, true);
dvander@673
   109
}
dvander@673
   110
dvander@433
   111
void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags)
dvander@335
   112
{
dvander@433
   113
	Trie *pTrie = NULL;
dvander@335
   114
	if (type == Override_Command)
dvander@335
   115
	{
dvander@433
   116
		pTrie = m_pCmdOverrides;
dvander@335
   117
	} else if (type == Override_CommandGroup) {
dvander@433
   118
		pTrie = m_pCmdGrpOverrides;
dvander@433
   119
	} else {
dvander@433
   120
		return;
dvander@335
   121
	}
dvander@433
   122
dvander@433
   123
	sm_trie_insert(pTrie, cmd, (void *)(unsigned int)flags);
dvander@514
   124
dvander@514
   125
	g_ConCmds.UpdateAdminCmdFlags(cmd, type, flags);
dvander@335
   126
}
dvander@335
   127
dvander@433
   128
bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, FlagBits *pFlags)
dvander@335
   129
{
dvander@433
   130
	Trie *pTrie = NULL;
dvander@433
   131
dvander@335
   132
	if (type == Override_Command)
dvander@335
   133
	{
dvander@433
   134
		pTrie = m_pCmdOverrides;
dvander@335
   135
	} else if (type == Override_CommandGroup) {
dvander@433
   136
		pTrie = m_pCmdGrpOverrides;
dvander@433
   137
	} else {
dvander@433
   138
		return false;
dvander@433
   139
	}
dvander@433
   140
dvander@433
   141
	void *object;
dvander@433
   142
	if (sm_trie_retrieve(pTrie, cmd, &object))
dvander@433
   143
	{
dvander@433
   144
		if (pFlags)
dvander@433
   145
		{
dvander@433
   146
			*pFlags = (FlagBits)object;
dvander@433
   147
		}
dvander@433
   148
		return true;
dvander@335
   149
	}
dvander@335
   150
dvander@335
   151
	return false;
dvander@335
   152
}
dvander@335
   153
dvander@335
   154
void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
dvander@335
   155
{
dvander@335
   156
	if (type == Override_Command)
dvander@335
   157
	{
dvander@335
   158
		return _UnsetCommandOverride(cmd);
dvander@335
   159
	} else if (type == Override_CommandGroup) {
dvander@335
   160
		return _UnsetCommandGroupOverride(cmd);
dvander@335
   161
	}
dvander@335
   162
}
dvander@335
   163
dvander@335
   164
void AdminCache::_UnsetCommandGroupOverride(const char *group)
dvander@335
   165
{
dvander@335
   166
	if (!m_pCmdGrpOverrides)
dvander@335
   167
	{
dvander@335
   168
		return;
dvander@335
   169
	}
dvander@335
   170
dvander@514
   171
	sm_trie_delete(m_pCmdGrpOverrides, group);
dvander@335
   172
dvander@514
   173
	g_ConCmds.UpdateAdminCmdFlags(group, Override_CommandGroup, 0);
dvander@335
   174
}
dvander@335
   175
dvander@335
   176
void AdminCache::_UnsetCommandOverride(const char *cmd)
dvander@335
   177
{
dvander@335
   178
	if (!m_pCmdOverrides)
dvander@335
   179
	{
dvander@335
   180
		return;
dvander@335
   181
	}
dvander@335
   182
dvander@514
   183
	sm_trie_delete(m_pCmdOverrides, cmd);
dvander@335
   184
dvander@514
   185
	g_ConCmds.UpdateAdminCmdFlags(cmd, Override_Command, 0);
dvander@335
   186
}
dvander@335
   187
dvander@335
   188
void AdminCache::DumpCommandOverrideCache(OverrideType type)
dvander@335
   189
{
dvander@335
   190
	if (type == Override_Command && m_pCmdOverrides)
dvander@335
   191
	{
dvander@335
   192
		sm_trie_clear(m_pCmdOverrides);
dvander@335
   193
	} else if (type == Override_CommandGroup && m_pCmdGrpOverrides) {
dvander@335
   194
		sm_trie_clear(m_pCmdGrpOverrides);
dvander@335
   195
	}
dvander@335
   196
}
dvander@335
   197
dvander@404
   198
AdminId AdminCache::CreateAdmin(const char *name)
dvander@404
   199
{
dvander@404
   200
	AdminId id;
dvander@404
   201
	AdminUser *pUser;
dvander@404
   202
dvander@404
   203
	if (m_FreeUserList != INVALID_ADMIN_ID)
dvander@404
   204
	{
dvander@404
   205
		pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList);
dvander@404
   206
		assert(pUser->magic == USR_MAGIC_UNSET);
dvander@404
   207
		id = m_FreeUserList;
dvander@404
   208
		m_FreeUserList = pUser->next_user;
dvander@404
   209
	} else {
dvander@404
   210
		id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser);
dvander@404
   211
		pUser->grp_size = 0;
dvander@404
   212
		pUser->grp_table = -1;
dvander@404
   213
	}
dvander@404
   214
dvander@433
   215
	pUser->flags = 0;
dvander@433
   216
	pUser->eflags = 0;
dvander@404
   217
	pUser->grp_count = 0;
dvander@404
   218
	pUser->password = -1;
dvander@404
   219
	pUser->magic = USR_MAGIC_SET;
dvander@405
   220
	pUser->auth.identidx = -1;
dvander@405
   221
	pUser->auth.index = 0;
dvander@434
   222
	pUser->immune_default = false;
dvander@434
   223
	pUser->immune_global = false;
dvander@404
   224
dvander@404
   225
	if (m_FirstUser == INVALID_ADMIN_ID)
dvander@404
   226
	{
dvander@404
   227
		m_FirstUser = id;
dvander@404
   228
		m_LastUser = id;
dvander@404
   229
	} else {
dvander@404
   230
		AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
dvander@404
   231
		pPrev->next_user = id;
dvander@404
   232
		pUser->prev_user = m_LastUser;
dvander@404
   233
		m_LastUser = id;
dvander@404
   234
	}
dvander@404
   235
dvander@404
   236
	if (name && name[0] != '\0')
dvander@404
   237
	{
dvander@404
   238
		pUser->nameidx = m_pStrings->AddString(name);
dvander@404
   239
	}
dvander@404
   240
dvander@404
   241
	return id;
dvander@404
   242
}
dvander@404
   243
dvander@335
   244
GroupId AdminCache::AddGroup(const char *group_name)
dvander@335
   245
{
dvander@335
   246
	if (sm_trie_retrieve(m_pGroups, group_name, NULL))
dvander@335
   247
	{
dvander@335
   248
		return INVALID_GROUP_ID;
dvander@335
   249
	}
dvander@335
   250
dvander@335
   251
	GroupId id;
dvander@335
   252
	AdminGroup *pGroup;
dvander@335
   253
	if (m_FreeGroupList != INVALID_GROUP_ID)
dvander@335
   254
	{
dvander@335
   255
		pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList);
dvander@335
   256
		assert(pGroup->magic == GRP_MAGIC_UNSET);
dvander@335
   257
		id = m_FreeGroupList;
dvander@335
   258
		m_FreeGroupList = pGroup->next_grp;
dvander@335
   259
	} else {
dvander@335
   260
		id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup);
dvander@335
   261
	}
dvander@335
   262
dvander@335
   263
	pGroup->immune_default = false;
dvander@335
   264
	pGroup->immune_global = false;
dvander@335
   265
	pGroup->immune_table = -1;
dvander@335
   266
	pGroup->magic = GRP_MAGIC_SET;
dvander@335
   267
	pGroup->next_grp = INVALID_GROUP_ID;
dvander@335
   268
	pGroup->pCmdGrpTable = NULL;
dvander@335
   269
	pGroup->pCmdTable = NULL;
dvander@433
   270
	pGroup->addflags = 0;
dvander@335
   271
dvander@335
   272
	if (m_FirstGroup == INVALID_GROUP_ID)
dvander@335
   273
	{
dvander@335
   274
		m_FirstGroup = id;
dvander@335
   275
		m_LastGroup = id;
dvander@335
   276
		pGroup->prev_grp = INVALID_GROUP_ID;
dvander@335
   277
	} else {
dvander@335
   278
		AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
dvander@335
   279
		assert(pPrev->magic == GRP_MAGIC_SET);
dvander@335
   280
		pPrev->next_grp = id;
dvander@335
   281
		pGroup->prev_grp = m_LastGroup;
dvander@335
   282
		m_LastGroup = id;
dvander@335
   283
	}
dvander@335
   284
dvander@404
   285
	pGroup->nameidx = m_pStrings->AddString(group_name);
dvander@404
   286
dvander@335
   287
	sm_trie_insert(m_pGroups, group_name, (void *)id);
dvander@335
   288
dvander@335
   289
	return id;
dvander@335
   290
}
dvander@335
   291
dvander@335
   292
GroupId AdminCache::FindGroupByName(const char *group_name)
dvander@335
   293
{
dvander@335
   294
	void *object;
dvander@335
   295
dvander@335
   296
	if (!sm_trie_retrieve(m_pGroups, group_name, &object))
dvander@335
   297
	{
dvander@335
   298
		return INVALID_GROUP_ID;
dvander@335
   299
	}
dvander@335
   300
dvander@335
   301
	GroupId id = (GroupId)object;
dvander@335
   302
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   303
dvander@335
   304
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   305
	{
dvander@335
   306
		return INVALID_GROUP_ID;
dvander@335
   307
	}
dvander@335
   308
dvander@335
   309
	return id;
dvander@335
   310
}
dvander@335
   311
dvander@335
   312
void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled)
dvander@335
   313
{
dvander@335
   314
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   315
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   316
	{
dvander@335
   317
		return;
dvander@335
   318
	}
dvander@335
   319
dvander@433
   320
	if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL)
dvander@335
   321
	{
dvander@335
   322
		return;
dvander@335
   323
	}
dvander@335
   324
dvander@436
   325
	FlagBits bits = (1<<(FlagBits)flag);
dvander@436
   326
dvander@436
   327
	if (enabled)
dvander@436
   328
	{
dvander@436
   329
		pGroup->addflags |= bits;
dvander@436
   330
	} else {
dvander@436
   331
		pGroup->addflags &= ~bits;
dvander@436
   332
	}
dvander@335
   333
}
dvander@335
   334
dvander@335
   335
bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag)
dvander@335
   336
{
dvander@335
   337
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   338
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   339
	{
dvander@335
   340
		return false;
dvander@335
   341
	}
dvander@335
   342
dvander@433
   343
	if (flag < Admin_Reservation || flag >= AdminFlags_TOTAL)
dvander@335
   344
	{
dvander@335
   345
		return false;
dvander@335
   346
	}
dvander@335
   347
dvander@433
   348
	FlagBits bit = 1<<(FlagBits)flag;
dvander@433
   349
	return ((pGroup->addflags & bit) == bit);
dvander@335
   350
}
dvander@335
   351
dvander@433
   352
FlagBits AdminCache::GetGroupAddFlags(GroupId id)
dvander@335
   353
{
dvander@335
   354
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   355
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   356
	{
dvander@335
   357
		return 0;
dvander@335
   358
	}
dvander@335
   359
dvander@433
   360
	return pGroup->addflags;
dvander@335
   361
}
dvander@335
   362
dvander@335
   363
void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled)
dvander@335
   364
{
dvander@335
   365
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   366
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   367
	{
dvander@335
   368
		return;
dvander@335
   369
	}
dvander@335
   370
dvander@335
   371
	if (type == Immunity_Default)
dvander@335
   372
	{
dvander@335
   373
		pGroup->immune_default = enabled;
dvander@335
   374
	} else if (type == Immunity_Global) {
dvander@335
   375
		pGroup->immune_global = enabled;
dvander@335
   376
	} 
dvander@335
   377
}
dvander@335
   378
dvander@335
   379
bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type)
dvander@335
   380
{
dvander@335
   381
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   382
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   383
	{
dvander@335
   384
		return false;
dvander@335
   385
	}
dvander@335
   386
dvander@335
   387
	if (type == Immunity_Default)
dvander@335
   388
	{
dvander@335
   389
		return pGroup->immune_default;
dvander@335
   390
	} else if (type == Immunity_Global) {
dvander@335
   391
		return pGroup->immune_global;
dvander@335
   392
	}
dvander@335
   393
dvander@335
   394
	return false;
dvander@335
   395
}
dvander@335
   396
dvander@335
   397
void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id)
dvander@335
   398
{
dvander@335
   399
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   400
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   401
	{
dvander@335
   402
		return;
dvander@335
   403
	}
dvander@335
   404
dvander@335
   405
	AdminGroup *pOther = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   406
	if (!pOther || pOther->magic != GRP_MAGIC_SET)
dvander@335
   407
	{
dvander@335
   408
		return;
dvander@335
   409
	}
dvander@335
   410
dvander@335
   411
	/* We always need to resize the immunity table */
dvander@335
   412
	int *table, tblidx;
dvander@335
   413
	if (pOther->immune_table == -1)
dvander@335
   414
	{
dvander@335
   415
		tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table);
dvander@335
   416
		table[0] = 0;
dvander@335
   417
	} else {
dvander@335
   418
		int *old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
dvander@433
   419
		/* Break out if this group is already in the list */
dvander@433
   420
		for (int i=0; i<old_table[0]; i++)
dvander@433
   421
		{
dvander@433
   422
			if (old_table[1+i] == other_id)
dvander@433
   423
			{
dvander@433
   424
				return;
dvander@433
   425
			}
dvander@433
   426
		}
dvander@335
   427
		tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table);
dvander@433
   428
		/* Get the old address again in case of resize */
dvander@335
   429
		old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
dvander@335
   430
		table[0] = old_table[0];
dvander@335
   431
		for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++)
dvander@335
   432
		{
dvander@335
   433
			table[i] = old_table[i];
dvander@335
   434
		}
dvander@335
   435
	}
dvander@335
   436
dvander@335
   437
	/* Assign */
dvander@335
   438
	pOther->immune_table = tblidx;
dvander@335
   439
dvander@335
   440
	/* Add to the array */
dvander@335
   441
	table[0]++;
dvander@335
   442
	table[table[0]] = other_id;
dvander@335
   443
}
dvander@335
   444
dvander@335
   445
unsigned int AdminCache::GetGroupImmunityCount(GroupId id)
dvander@335
   446
{
dvander@335
   447
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   448
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   449
	{
dvander@335
   450
		return 0;
dvander@335
   451
	}
dvander@335
   452
dvander@335
   453
	if (pGroup->immune_table == -1)
dvander@335
   454
	{
dvander@335
   455
		return 0;
dvander@335
   456
	}
dvander@335
   457
dvander@335
   458
	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@335
   459
dvander@335
   460
	return table[0];
dvander@335
   461
}
dvander@335
   462
dvander@335
   463
GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number)
dvander@335
   464
{
dvander@335
   465
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   466
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   467
	{
dvander@335
   468
		return INVALID_GROUP_ID;
dvander@335
   469
	}
dvander@335
   470
dvander@335
   471
	if (pGroup->immune_table == -1)
dvander@335
   472
	{
dvander@335
   473
		return INVALID_GROUP_ID;
dvander@335
   474
	}
dvander@335
   475
dvander@335
   476
	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
dvander@335
   477
	if (number >= (unsigned int)table[0])
dvander@335
   478
	{
dvander@335
   479
		return INVALID_GROUP_ID;
dvander@335
   480
	}
dvander@335
   481
dvander@335
   482
	return table[1 + number];
dvander@335
   483
}
dvander@335
   484
dvander@335
   485
void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule)
dvander@335
   486
{
dvander@335
   487
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   488
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   489
	{
dvander@335
   490
		return;
dvander@335
   491
	}
dvander@335
   492
dvander@335
   493
	Trie *pTrie = NULL;
dvander@335
   494
	if (type == Override_Command)
dvander@335
   495
	{
dvander@335
   496
		if (pGroup->pCmdTable == NULL)
dvander@335
   497
		{
dvander@335
   498
			pGroup->pCmdTable = sm_trie_create();
dvander@335
   499
		}
dvander@335
   500
		pTrie = pGroup->pCmdTable;
dvander@335
   501
	} else if (type == Override_CommandGroup) {
dvander@335
   502
		if (pGroup->pCmdGrpTable == NULL)
dvander@335
   503
		{
dvander@335
   504
			pGroup->pCmdGrpTable = sm_trie_create();
dvander@335
   505
		}
dvander@335
   506
		pTrie = pGroup->pCmdGrpTable;
dvander@335
   507
	} else {
dvander@335
   508
		return;
dvander@335
   509
	}
dvander@335
   510
dvander@335
   511
	sm_trie_insert(pTrie, name, (void *)(int)rule);
dvander@335
   512
}
dvander@335
   513
dvander@335
   514
bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule)
dvander@335
   515
{
dvander@335
   516
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   517
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   518
	{
dvander@335
   519
		return false;
dvander@335
   520
	}
dvander@335
   521
dvander@335
   522
	Trie *pTrie = NULL;
dvander@335
   523
	if (type == Override_Command)
dvander@335
   524
	{
dvander@335
   525
		if (pGroup->pCmdTable == NULL)
dvander@335
   526
		{
dvander@335
   527
			return false;
dvander@335
   528
		}
dvander@335
   529
		pTrie = pGroup->pCmdTable;
dvander@335
   530
	} else if (type == Override_CommandGroup) {
dvander@335
   531
		if (pGroup->pCmdGrpTable == NULL)
dvander@335
   532
		{
dvander@335
   533
			return false;
dvander@335
   534
		}
dvander@335
   535
		pTrie = pGroup->pCmdGrpTable;
dvander@335
   536
	} else {
dvander@335
   537
		return false;
dvander@335
   538
	}
dvander@335
   539
dvander@335
   540
	void *object;
dvander@335
   541
	if (!sm_trie_retrieve(pTrie, name, &object))
dvander@335
   542
	{
dvander@335
   543
		return false;
dvander@335
   544
	}
dvander@335
   545
dvander@335
   546
	if (pRule)
dvander@335
   547
	{
dvander@335
   548
		*pRule = (OverrideRule)(int)object;
dvander@335
   549
	}
dvander@335
   550
	
dvander@335
   551
	return true;
dvander@335
   552
}
dvander@335
   553
dvander@404
   554
Trie *AdminCache::GetMethodByIndex(unsigned int index)
dvander@404
   555
{
dvander@404
   556
	List<AuthMethod>::iterator iter;
dvander@404
   557
	for (iter=m_AuthMethods.begin();
dvander@404
   558
		 iter!=m_AuthMethods.end();
dvander@404
   559
		 iter++)
dvander@404
   560
	{
dvander@404
   561
		if (index-- == 0)
dvander@404
   562
		{
dvander@404
   563
			return (*iter).table;
dvander@404
   564
		}
dvander@404
   565
	}
dvander@404
   566
dvander@404
   567
	return NULL;
dvander@404
   568
}
dvander@404
   569
dvander@404
   570
bool AdminCache::InvalidateAdmin(AdminId id)
dvander@404
   571
{
dvander@404
   572
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
   573
	AdminUser *pOther;
dvander@404
   574
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
   575
	{
dvander@404
   576
		return false;
dvander@404
   577
	}
dvander@404
   578
dvander@520
   579
	if (!m_InvalidatingAdmins && !m_destroying)
dvander@458
   580
	{
dvander@458
   581
		g_Players.ClearAdminId(id);
dvander@458
   582
	}
dvander@458
   583
dvander@404
   584
	/* Unlink from the dbl link list */
dvander@404
   585
	if (id == m_FirstUser && id == m_LastUser)
dvander@404
   586
	{
dvander@404
   587
		m_FirstUser = INVALID_ADMIN_ID;
dvander@404
   588
		m_LastUser = INVALID_ADMIN_ID;
dvander@404
   589
	} else if (id == m_FirstUser) {
dvander@404
   590
		m_FirstUser = pUser->next_user;
dvander@404
   591
		pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser);
dvander@404
   592
		pOther->prev_user = INVALID_ADMIN_ID;
dvander@404
   593
	} else if (id == m_LastUser) {
dvander@404
   594
		m_LastUser = pUser->prev_user;
dvander@404
   595
		pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
dvander@404
   596
		pOther->next_user = INVALID_ADMIN_ID;
dvander@404
   597
	} else {
dvander@404
   598
		pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user);
dvander@404
   599
		pOther->next_user = pUser->next_user;
dvander@404
   600
		pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user);
dvander@404
   601
		pOther->prev_user = pUser->prev_user;
dvander@404
   602
	}
dvander@404
   603
dvander@404
   604
	/* Unlink from auth tables */
dvander@405
   605
	if (pUser->auth.identidx != -1)
dvander@404
   606
	{
dvander@405
   607
		Trie *pTrie = GetMethodByIndex(pUser->auth.index);
dvander@405
   608
		if (pTrie)
dvander@404
   609
		{
dvander@405
   610
			sm_trie_delete(pTrie, m_pStrings->GetString(pUser->auth.identidx));
dvander@404
   611
		}
dvander@404
   612
	}
dvander@404
   613
dvander@404
   614
	/* Clear table counts */
dvander@404
   615
	pUser->grp_count = 0;
dvander@405
   616
	
dvander@404
   617
	/* Link into free list */
dvander@404
   618
	pUser->magic = USR_MAGIC_UNSET;
dvander@404
   619
	pUser->next_user = m_FreeUserList;
dvander@404
   620
	m_FreeUserList = id;
dvander@404
   621
dvander@404
   622
	return true;
dvander@404
   623
}
dvander@404
   624
dvander@404
   625
dvander@335
   626
void AdminCache::InvalidateGroup(GroupId id)
dvander@335
   627
{
dvander@335
   628
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
dvander@335
   629
	AdminGroup *pOther;
dvander@335
   630
dvander@335
   631
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@335
   632
	{
dvander@335
   633
		return;
dvander@335
   634
	}
dvander@335
   635
dvander@335
   636
	const char *str = m_pStrings->GetString(pGroup->nameidx);
dvander@335
   637
	sm_trie_delete(m_pGroups, str);
dvander@335
   638
dvander@335
   639
	/* Unlink from the live dbllink list */
dvander@335
   640
	if (id == m_FirstGroup && id == m_LastGroup)
dvander@335
   641
	{
dvander@335
   642
		m_LastGroup = INVALID_GROUP_ID;
dvander@335
   643
		m_FirstGroup = INVALID_GROUP_ID;
dvander@335
   644
	} else if (id == m_FirstGroup) {
dvander@335
   645
		m_FirstGroup = pGroup->next_grp;
dvander@335
   646
		pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup);
dvander@335
   647
		pOther->prev_grp = INVALID_GROUP_ID;
dvander@335
   648
	} else if (id == m_LastGroup) {
dvander@335
   649
		m_LastGroup = pGroup->prev_grp;
dvander@335
   650
		pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
dvander@335
   651
		pOther->next_grp = INVALID_GROUP_ID;
dvander@335
   652
	} else {
dvander@335
   653
		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp);
dvander@335
   654
		pOther->next_grp = pGroup->next_grp;
dvander@335
   655
		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp);
dvander@335
   656
		pOther->prev_grp = pGroup->prev_grp;
dvander@335
   657
	}
dvander@335
   658
dvander@335
   659
	/* Free any used memory to be safe */
dvander@335
   660
	if (pGroup->pCmdGrpTable)
dvander@335
   661
	{
dvander@335
   662
		sm_trie_destroy(pGroup->pCmdGrpTable);
dvander@335
   663
		pGroup->pCmdGrpTable = NULL;
dvander@335
   664
	}
dvander@335
   665
	if (pGroup->pCmdTable)
dvander@335
   666
	{
dvander@335
   667
		sm_trie_destroy(pGroup->pCmdTable);
dvander@335
   668
		pGroup->pCmdTable = NULL;
dvander@335
   669
	}
dvander@335
   670
dvander@335
   671
	/* Link into the free list */
dvander@335
   672
	pGroup->magic = GRP_MAGIC_UNSET;
dvander@335
   673
	pGroup->next_grp = m_FreeGroupList;
dvander@335
   674
	m_FreeGroupList = id;
dvander@335
   675
dvander@404
   676
	int idx = m_FirstUser;
dvander@404
   677
	AdminUser *pUser;
dvander@404
   678
	int *table;
dvander@404
   679
	while (idx != INVALID_ADMIN_ID)
dvander@404
   680
	{
dvander@404
   681
		pUser = (AdminUser *)m_pMemory->GetAddress(idx);
dvander@404
   682
		if (pUser->grp_count > 0)
dvander@404
   683
		{
dvander@404
   684
			table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
   685
			for (unsigned int i=0; i<pUser->grp_count; i++)
dvander@404
   686
			{
dvander@404
   687
				if (table[i] == id)
dvander@404
   688
				{
dvander@404
   689
					/* We have to remove this entry */
dvander@404
   690
					for (unsigned int j=i+1; j<pUser->grp_count; j++)
dvander@404
   691
					{
dvander@404
   692
						/* Move everything down by one */
dvander@404
   693
						table[j-1] = table[j];
dvander@404
   694
					}
dvander@404
   695
					/* Decrease count */
dvander@404
   696
					pUser->grp_count--;
dvander@404
   697
					/* Recalculate effective flags */
dvander@433
   698
					pUser->eflags = pUser->flags;
dvander@404
   699
					for (unsigned int j=0; j<pUser->grp_count; j++)
dvander@404
   700
					{
dvander@404
   701
						pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]);
dvander@433
   702
						pUser->eflags |= pOther->addflags;
dvander@404
   703
					}
dvander@404
   704
					/* Break now, duplicates aren't allowed */
dvander@404
   705
					break;
dvander@404
   706
				}
dvander@404
   707
			}
dvander@404
   708
		}
dvander@404
   709
		idx = pUser->next_user;
dvander@404
   710
	}
dvander@335
   711
}
dvander@335
   712
dvander@335
   713
void AdminCache::InvalidateGroupCache()
dvander@335
   714
{
dvander@335
   715
	/* Nuke the free list */
dvander@335
   716
	m_FreeGroupList = -1;
dvander@335
   717
dvander@335
   718
	/* Nuke reverse lookups */
dvander@335
   719
	sm_trie_clear(m_pGroups);
dvander@335
   720
dvander@335
   721
	/* Free memory on groups */
dvander@335
   722
	GroupId cur = m_FirstGroup;
dvander@335
   723
	AdminGroup *pGroup;
dvander@335
   724
	while (cur != INVALID_GROUP_ID)
dvander@335
   725
	{
dvander@335
   726
		pGroup = (AdminGroup *)m_pMemory->GetAddress(cur);
dvander@335
   727
		assert(pGroup->magic == GRP_MAGIC_SET);
dvander@335
   728
		if (pGroup->pCmdGrpTable)
dvander@335
   729
		{
dvander@335
   730
			sm_trie_destroy(pGroup->pCmdGrpTable);
dvander@335
   731
		}
dvander@335
   732
		if (pGroup->pCmdTable)
dvander@335
   733
		{
dvander@335
   734
			sm_trie_destroy(pGroup->pCmdTable);
dvander@335
   735
		}
dvander@335
   736
		cur = pGroup->next_grp;
dvander@335
   737
	}
dvander@335
   738
dvander@335
   739
	m_FirstGroup = INVALID_GROUP_ID;
dvander@335
   740
	m_LastGroup = INVALID_GROUP_ID;
dvander@335
   741
dvander@404
   742
	InvalidateAdminCache(false);
dvander@335
   743
dvander@335
   744
	/* Reset the memory table */
dvander@335
   745
	m_pMemory->Reset();
dvander@335
   746
}
dvander@336
   747
dvander@336
   748
void AdminCache::AddAdminListener(IAdminListener *pListener)
dvander@336
   749
{
dvander@336
   750
	m_hooks.push_back(pListener);
dvander@336
   751
}
dvander@336
   752
dvander@336
   753
void AdminCache::RemoveAdminListener(IAdminListener *pListener)
dvander@336
   754
{
dvander@336
   755
	m_hooks.remove(pListener);
dvander@336
   756
}
dvander@336
   757
dvander@404
   758
void AdminCache::RegisterAuthIdentType(const char *name)
dvander@404
   759
{
dvander@404
   760
	if (sm_trie_retrieve(m_pAuthTables, name, NULL))
dvander@404
   761
	{
dvander@404
   762
		return;
dvander@404
   763
	}
dvander@404
   764
dvander@404
   765
	Trie *pAuth = sm_trie_create();
dvander@404
   766
dvander@404
   767
	AuthMethod method;
dvander@404
   768
	method.name.assign(name);
dvander@404
   769
	method.table = pAuth;
dvander@404
   770
dvander@404
   771
	m_AuthMethods.push_back(method);
dvander@404
   772
dvander@404
   773
	sm_trie_insert(m_pAuthTables, name, pAuth);
dvander@404
   774
}
dvander@404
   775
dvander@404
   776
void AdminCache::InvalidateAdminCache(bool unlink_admins)
dvander@404
   777
{
dvander@458
   778
	m_InvalidatingAdmins = true;
dvander@520
   779
	if (!m_destroying)
dvander@520
   780
	{
dvander@520
   781
		g_Players.ClearAllAdmins();
dvander@520
   782
	}
dvander@404
   783
	/* Wipe the identity cache first */
dvander@404
   784
	List<AuthMethod>::iterator iter;
dvander@404
   785
	for (iter=m_AuthMethods.begin();
dvander@404
   786
		 iter!=m_AuthMethods.end();
dvander@404
   787
		 iter++)
dvander@404
   788
	{
dvander@404
   789
		sm_trie_clear((*iter).table);
dvander@404
   790
	}
dvander@404
   791
	
dvander@405
   792
	if (unlink_admins)
dvander@404
   793
	{
dvander@405
   794
		while (m_FirstUser != INVALID_ADMIN_ID)
dvander@405
   795
		{
dvander@405
   796
			InvalidateAdmin(m_FirstUser);
dvander@405
   797
		}
dvander@405
   798
	} else {
dvander@405
   799
		m_FirstUser = -1;
dvander@405
   800
		m_LastUser = -1;
dvander@405
   801
		m_FreeUserList = -1;
dvander@404
   802
	}
dvander@458
   803
	m_InvalidatingAdmins = false;
dvander@404
   804
}
dvander@404
   805
dvander@438
   806
void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
dvander@336
   807
{
dvander@438
   808
	List<IAdminListener *>::iterator iter;
dvander@438
   809
	IAdminListener *pListener;
dvander@438
   810
	cell_t result;
dvander@438
   811
dvander@438
   812
	if (part == AdminCache_Overrides)
dvander@336
   813
	{
dvander@336
   814
		DumpCommandOverrideCache(Override_Command);
dvander@336
   815
		DumpCommandOverrideCache(Override_CommandGroup);
dvander@520
   816
		if (rebuild && !m_destroying)
dvander@438
   817
		{
dvander@438
   818
			for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
   819
			{
dvander@438
   820
				pListener = (*iter);
dvander@438
   821
				pListener->OnRebuildOverrideCache();
dvander@438
   822
			}
dvander@438
   823
			m_pCacheFwd->PushCell(part);
dvander@438
   824
			m_pCacheFwd->Execute(&result);
dvander@438
   825
		}
dvander@438
   826
	} else if (part == AdminCache_Groups || part == AdminCache_Admins) {
dvander@438
   827
		if (part == AdminCache_Groups)
dvander@438
   828
		{
dvander@438
   829
			InvalidateGroupCache();
dvander@520
   830
			if (rebuild && !m_destroying)
dvander@438
   831
			{
dvander@438
   832
				for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
   833
				{
dvander@438
   834
					pListener = (*iter);
dvander@438
   835
					pListener->OnRebuildGroupCache();
dvander@438
   836
				}
dvander@438
   837
				m_pCacheFwd->PushCell(part);
dvander@438
   838
				m_pCacheFwd->Execute(&result);
dvander@438
   839
			}
dvander@438
   840
		}
dvander@404
   841
		InvalidateAdminCache(true);
dvander@520
   842
		if (rebuild && !m_destroying)
dvander@336
   843
		{
dvander@438
   844
			for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
dvander@438
   845
			{
dvander@438
   846
				pListener = (*iter);
dvander@438
   847
				pListener->OnRebuildAdminCache((part == AdminCache_Groups));
dvander@438
   848
			}
dvander@438
   849
			m_pCacheFwd->PushCell(AdminCache_Admins);
dvander@438
   850
			m_pCacheFwd->Execute(&result);
dvander@1165
   851
			g_Players.RecheckAnyAdmins();
dvander@336
   852
		}
dvander@336
   853
	}
dvander@336
   854
}
dvander@404
   855
dvander@404
   856
const char *AdminCache::GetAdminName(AdminId id)
dvander@404
   857
{
dvander@404
   858
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
   859
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
   860
	{
dvander@404
   861
		return NULL;
dvander@404
   862
	}
dvander@404
   863
dvander@404
   864
	return m_pStrings->GetString(pUser->nameidx);
dvander@404
   865
}
dvander@404
   866
dvander@405
   867
bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index)
dvander@405
   868
{
dvander@405
   869
	List<AuthMethod>::iterator iter;
dvander@405
   870
	unsigned int index = 0;
dvander@405
   871
	for (iter=m_AuthMethods.begin();
dvander@405
   872
		 iter!=m_AuthMethods.end();
dvander@405
   873
		 iter++,index++)
dvander@405
   874
	{
dvander@405
   875
		if ((*iter).name.compare(name) == 0)
dvander@405
   876
		{
dvander@405
   877
			*_index = index;
dvander@405
   878
			return true;
dvander@405
   879
		}
dvander@405
   880
	}
dvander@405
   881
dvander@405
   882
	return false;
dvander@405
   883
}
dvander@405
   884
dvander@404
   885
bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident)
dvander@404
   886
{
dvander@404
   887
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
   888
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
   889
	{
dvander@404
   890
		return false;
dvander@404
   891
	}
dvander@404
   892
dvander@404
   893
	Trie *pTable;
dvander@404
   894
	if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable))
dvander@404
   895
	{
dvander@404
   896
		return false;
dvander@404
   897
	}
dvander@404
   898
dvander@404
   899
	if (sm_trie_retrieve(pTable, ident, NULL))
dvander@404
   900
	{
dvander@404
   901
		return false;
dvander@404
   902
	}
dvander@404
   903
dvander@405
   904
	pUser->auth.identidx = m_pStrings->AddString(ident);
dvander@405
   905
	GetMethodIndex(auth, &pUser->auth.index);
dvander@405
   906
dvander@404
   907
	return sm_trie_insert(pTable, ident, (void **)id);
dvander@404
   908
}
dvander@404
   909
dvander@404
   910
AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity)
dvander@404
   911
{
dvander@404
   912
	Trie *pTable;
dvander@404
   913
	if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable))
dvander@404
   914
	{
dvander@404
   915
		return INVALID_ADMIN_ID;
dvander@404
   916
	}
dvander@404
   917
dvander@404
   918
	void *object;
dvander@404
   919
	if (!sm_trie_retrieve(pTable, identity, &object))
dvander@404
   920
	{
dvander@404
   921
		return INVALID_ADMIN_ID;
dvander@404
   922
	}
dvander@404
   923
dvander@404
   924
	return (AdminId)object;
dvander@404
   925
}
dvander@404
   926
dvander@404
   927
void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled)
dvander@404
   928
{
dvander@404
   929
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
   930
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
   931
	{
dvander@404
   932
		return;
dvander@404
   933
	}
dvander@404
   934
dvander@433
   935
	if (flag < Admin_Reservation
dvander@404
   936
		|| flag >= AdminFlags_TOTAL)
dvander@404
   937
	{
dvander@404
   938
		return;
dvander@404
   939
	}
dvander@436
   940
	
dvander@436
   941
	FlagBits bits = (1<<(FlagBits)flag);
dvander@404
   942
dvander@436
   943
	if (enabled)
dvander@436
   944
	{
dvander@436
   945
		pUser->flags |= bits;
dvander@436
   946
		pUser->eflags |= bits;
dvander@436
   947
	} else {
dvander@436
   948
		pUser->flags &= ~bits;
dvander@436
   949
		pUser->eflags &= ~bits;
dvander@436
   950
	}
dvander@404
   951
}
dvander@404
   952
dvander@404
   953
bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode)
dvander@404
   954
{
dvander@404
   955
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
   956
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
   957
	{
dvander@404
   958
		return false;
dvander@404
   959
	}
dvander@404
   960
dvander@433
   961
	if (flag < Admin_Reservation
dvander@404
   962
		|| flag >= AdminFlags_TOTAL)
dvander@404
   963
	{
dvander@404
   964
		return false;
dvander@404
   965
	}
dvander@404
   966
dvander@433
   967
	FlagBits bit = (1<<(FlagBits)flag);
dvander@433
   968
dvander@404
   969
	if (mode == Access_Real)
dvander@404
   970
	{
dvander@433
   971
		return ((pUser->flags & bit) == bit);
dvander@404
   972
	} else if (mode == Access_Effective) {
dvander@907
   973
		bool has_bit = ((pUser->eflags & bit) == bit);
dvander@907
   974
		if (!has_bit && flag != Admin_Root && ((pUser->eflags & ADMFLAG_ROOT) == ADMFLAG_ROOT))
dvander@907
   975
		{
dvander@907
   976
			has_bit = true;
dvander@907
   977
		}
dvander@907
   978
		return has_bit;
dvander@404
   979
	}
dvander@404
   980
dvander@404
   981
	return false;
dvander@404
   982
}
dvander@404
   983
dvander@433
   984
FlagBits AdminCache::GetAdminFlags(AdminId id, AccessMode mode)
dvander@404
   985
{
dvander@404
   986
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
   987
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
   988
	{
dvander@404
   989
		return 0;
dvander@404
   990
	}
dvander@404
   991
dvander@404
   992
	if (mode == Access_Real)
dvander@404
   993
	{
dvander@433
   994
		return pUser->flags;
dvander@404
   995
	} else if (mode == Access_Effective) {
dvander@433
   996
		return pUser->eflags;
dvander@404
   997
	}
dvander@404
   998
dvander@433
   999
	return 0;
dvander@404
  1000
}
dvander@404
  1001
dvander@458
  1002
void AdminCache::SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits)
dvander@458
  1003
{
dvander@458
  1004
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@458
  1005
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@458
  1006
	{
dvander@458
  1007
		return;
dvander@458
  1008
	}
dvander@458
  1009
dvander@458
  1010
	if (mode == Access_Real)
dvander@458
  1011
	{
dvander@458
  1012
		pUser->flags = bits;
dvander@458
  1013
		pUser->eflags = bits;
dvander@458
  1014
	} else if (mode == Access_Effective) {
dvander@458
  1015
		pUser->eflags = bits;
dvander@458
  1016
	}
dvander@458
  1017
}
dvander@458
  1018
dvander@404
  1019
bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid)
dvander@404
  1020
{
dvander@404
  1021
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1022
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1023
	{
dvander@404
  1024
		return false;
dvander@404
  1025
	}
dvander@404
  1026
dvander@404
  1027
	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@405
  1028
	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
dvander@404
  1029
	{
dvander@404
  1030
		return false;
dvander@404
  1031
	}
dvander@404
  1032
dvander@433
  1033
	/* First check for duplicates */
dvander@433
  1034
	if (pUser->grp_count != 0)
dvander@433
  1035
	{
dvander@433
  1036
		int *temp_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@433
  1037
		for (unsigned int i=0; i<pUser->grp_count; i++)
dvander@433
  1038
		{
dvander@433
  1039
			if (temp_table[i] == gid)
dvander@433
  1040
			{
dvander@433
  1041
				return false;
dvander@433
  1042
			}
dvander@433
  1043
		}
dvander@433
  1044
	}
dvander@433
  1045
dvander@404
  1046
	int *table;
dvander@404
  1047
	if (pUser->grp_count + 1 > pUser->grp_size)
dvander@404
  1048
	{
dvander@404
  1049
		int new_size = 0;
dvander@404
  1050
		int tblidx;
dvander@404
  1051
		
dvander@404
  1052
		if (pUser->grp_size == 0)
dvander@404
  1053
		{
dvander@404
  1054
			new_size = 2;
dvander@404
  1055
		} else {
dvander@404
  1056
			new_size = pUser->grp_size * 2;
dvander@404
  1057
		}
dvander@404
  1058
		
dvander@404
  1059
		/* Create and refresh pointers */
dvander@404
  1060
		tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table);
dvander@404
  1061
		pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1062
		pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
dvander@404
  1063
dvander@404
  1064
		/* Copy old data if necessary */
dvander@404
  1065
		if (pUser->grp_table != -1)
dvander@404
  1066
		{
dvander@404
  1067
			int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1068
			memcpy(table, old_table, sizeof(int) * pUser->grp_count);
dvander@404
  1069
		}
dvander@404
  1070
		pUser->grp_table = tblidx;
dvander@404
  1071
		pUser->grp_size = new_size;
dvander@404
  1072
	} else {
dvander@404
  1073
		table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1074
	}
dvander@404
  1075
dvander@404
  1076
	table[pUser->grp_count] = gid;
dvander@404
  1077
	pUser->grp_count++;
dvander@404
  1078
dvander@434
  1079
	/* Compute new effective permissions */
dvander@433
  1080
	pUser->eflags |= pGroup->addflags;
dvander@404
  1081
dvander@434
  1082
	if (pGroup->immune_default)
dvander@434
  1083
	{
dvander@434
  1084
		pUser->immune_default = true;
dvander@434
  1085
	}
dvander@434
  1086
	if (pGroup->immune_global)
dvander@434
  1087
	{
dvander@434
  1088
		pUser->immune_global = true;
dvander@434
  1089
	}
dvander@434
  1090
dvander@404
  1091
	return true;
dvander@404
  1092
}
dvander@404
  1093
dvander@458
  1094
bool AdminCache::IsValidAdmin(AdminId id)
dvander@458
  1095
{
dvander@458
  1096
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@458
  1097
	return (pUser != NULL && pUser->magic == USR_MAGIC_SET);
dvander@458
  1098
}
dvander@458
  1099
dvander@404
  1100
unsigned int AdminCache::GetAdminGroupCount(AdminId id)
dvander@404
  1101
{
dvander@404
  1102
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1103
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1104
	{
dvander@404
  1105
		return 0;
dvander@404
  1106
	}
dvander@404
  1107
dvander@404
  1108
	return pUser->grp_count;
dvander@404
  1109
}
dvander@404
  1110
dvander@404
  1111
GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name)
dvander@404
  1112
{
dvander@404
  1113
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1114
	if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count)
dvander@404
  1115
	{
dvander@404
  1116
		return INVALID_GROUP_ID;
dvander@404
  1117
	}
dvander@404
  1118
dvander@404
  1119
	int *table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@404
  1120
dvander@404
  1121
	return table[index];
dvander@404
  1122
}
dvander@404
  1123
dvander@404
  1124
const char *AdminCache::GetAdminPassword(AdminId id)
dvander@404
  1125
{
dvander@404
  1126
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1127
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1128
	{
dvander@404
  1129
		return NULL;
dvander@404
  1130
	}
dvander@404
  1131
dvander@404
  1132
	return m_pStrings->GetString(pUser->password);
dvander@404
  1133
}
dvander@404
  1134
dvander@404
  1135
void AdminCache::SetAdminPassword(AdminId id, const char *password)
dvander@404
  1136
{	
dvander@404
  1137
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@404
  1138
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@404
  1139
	{
dvander@404
  1140
		return;
dvander@404
  1141
	}
dvander@404
  1142
dvander@404
  1143
	pUser->password = m_pStrings->AddString(password);
dvander@404
  1144
}
dvander@404
  1145
dvander@433
  1146
unsigned int AdminCache::FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize)
dvander@433
  1147
{
dvander@433
  1148
	unsigned int i;
dvander@433
  1149
	for (i=0; i<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1150
	{
dvander@464
  1151
		array[i] = ((bits & (1<<i)) == (unsigned)(1<<i));
dvander@433
  1152
	}
dvander@433
  1153
dvander@433
  1154
	return i;
dvander@433
  1155
}
dvander@433
  1156
dvander@433
  1157
FlagBits AdminCache::FlagBitArrayToBits(const bool array[], unsigned int maxSize)
dvander@433
  1158
{
dvander@433
  1159
	FlagBits bits = 0;
dvander@433
  1160
	for (unsigned int i=0; i<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1161
	{
dvander@433
  1162
		if (array[i])
dvander@433
  1163
		{
dvander@433
  1164
			bits |= (1<<i);
dvander@433
  1165
		}
dvander@433
  1166
	}
dvander@433
  1167
dvander@433
  1168
	return bits;
dvander@433
  1169
}
dvander@433
  1170
dvander@433
  1171
FlagBits AdminCache::FlagArrayToBits(const AdminFlag array[], unsigned int numFlags)
dvander@433
  1172
{
dvander@433
  1173
	FlagBits bits = 0;
dvander@433
  1174
	for (unsigned int i=0; i<numFlags && i<AdminFlags_TOTAL; i++)
dvander@433
  1175
	{
dvander@433
  1176
		bits |= (1 << (FlagBits)array[i]);
dvander@433
  1177
	}
dvander@433
  1178
dvander@433
  1179
	return bits;
dvander@433
  1180
}
dvander@433
  1181
dvander@433
  1182
unsigned int AdminCache::FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize)
dvander@433
  1183
{
dvander@433
  1184
	unsigned int i, num=0;
dvander@1050
  1185
	for (i=0; num<maxSize && i<AdminFlags_TOTAL; i++)
dvander@433
  1186
	{
dvander@464
  1187
		if ((bits & (1<<i)) == (unsigned)(1<<i))
dvander@433
  1188
		{
dvander@433
  1189
			array[num++] = (AdminFlag)i;
dvander@433
  1190
		}
dvander@433
  1191
	}
dvander@433
  1192
dvander@433
  1193
	return num;
dvander@433
  1194
}
dvander@434
  1195
dvander@434
  1196
bool AdminCache::CheckAdminFlags(AdminId id, FlagBits bits)
dvander@434
  1197
{
dvander@434
  1198
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@434
  1199
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@434
  1200
	{
dvander@434
  1201
		return false;
dvander@434
  1202
	}
dvander@434
  1203
dvander@434
  1204
	return ((pUser->eflags & bits) == bits);
dvander@434
  1205
}
dvander@434
  1206
dvander@434
  1207
bool AdminCache::CanAdminTarget(AdminId id, AdminId target)
dvander@434
  1208
{
dvander@434
  1209
	/** 
dvander@434
  1210
	 * Zeroth, if the targeting AdminId is INVALID_ADMIN_ID, targeting fails.
ds@729
  1211
	 * First, if the targeted AdminId is INVALID_ADMIN_ID, targeting succeeds.
dvander@434
  1212
	 */
dvander@434
  1213
dvander@434
  1214
	if (id == INVALID_ADMIN_ID)
dvander@434
  1215
	{
dvander@434
  1216
		return false;
dvander@434
  1217
	}
dvander@434
  1218
dvander@434
  1219
	if (target == INVALID_ADMIN_ID)
dvander@434
  1220
	{
dvander@434
  1221
		return true;
dvander@434
  1222
	}
dvander@434
  1223
dvander@434
  1224
	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
dvander@434
  1225
	if (!pUser || pUser->magic != USR_MAGIC_SET)
dvander@434
  1226
	{
dvander@434
  1227
		return false;
dvander@434
  1228
	}
dvander@434
  1229
dvander@434
  1230
	AdminUser *pTarget = (AdminUser *)m_pMemory->GetAddress(target);
dvander@434
  1231
	if (!pTarget || pTarget->magic != USR_MAGIC_SET)
dvander@434
  1232
	{
dvander@434
  1233
		return false;
dvander@434
  1234
	}
dvander@434
  1235
dvander@434
  1236
	/** 
ds@729
  1237
	 * Second, if the targeting admin is root, targeting succeeds.
dvander@434
  1238
	 */
dvander@434
  1239
	if (pUser->eflags & ADMFLAG_ROOT)
dvander@434
  1240
	{
dvander@434
  1241
		return true;
dvander@434
  1242
	}
dvander@434
  1243
ds@729
  1244
	/** Fourth, if the targeted admin has global immunity, targeting fails. */
dvander@434
  1245
	if (pTarget->immune_global)
dvander@434
  1246
	{
dvander@434
  1247
		return false;
dvander@434
  1248
	}
dvander@434
  1249
dvander@434
  1250
	/** 
ds@729
  1251
	 * Fifth, if the targeted admin has default immunity 
dvander@434
  1252
	 *  and the admin belongs to no groups, targeting fails.
dvander@434
  1253
	 */
dvander@434
  1254
	if (pTarget->immune_default && pUser->grp_count < 1)
dvander@434
  1255
	{
dvander@434
  1256
		return false;
dvander@434
  1257
	}
dvander@434
  1258
dvander@434
  1259
	/** 
ds@729
  1260
	 * Sixth, if the targeted admin has specific immunity from the
dvander@434
  1261
	 *  targeting admin via group immunities, targeting fails.
dvander@434
  1262
	 */
dvander@434
  1263
	//:TODO: speed this up... maybe with trie hacks.
dvander@434
  1264
	//idea is to insert %d.%d in the trie after computing this and use it as a cache lookup.
dvander@434
  1265
	//problem is the trie cannot delete prefixes, so we'd have a problem with invalidations.
dvander@434
  1266
	if (pTarget->grp_count > 0 && pUser->grp_count > 0)
dvander@434
  1267
	{
dvander@434
  1268
		int *grp_table = (int *)m_pMemory->GetAddress(pTarget->grp_table);
dvander@434
  1269
		int *src_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
dvander@434
  1270
		GroupId id, other;
dvander@434
  1271
		unsigned int num;
dvander@434
  1272
		for (unsigned int i=0; i<pTarget->grp_count; i++)
dvander@434
  1273
		{
dvander@434
  1274
			id = grp_table[i];
dvander@434
  1275
			num = GetGroupImmunityCount(id);
dvander@434
  1276
			for (unsigned int j=0; j<num; i++)
dvander@434
  1277
			{
dvander@434
  1278
				other = GetGroupImmunity(id, j);
dvander@434
  1279
				for (unsigned int k=0; k<pUser->grp_count; k++)
dvander@434
  1280
				{
dvander@434
  1281
					if (other == src_table[k])
dvander@434
  1282
					{
dvander@434
  1283
						return false;
dvander@434
  1284
					}
dvander@434
  1285
				}
dvander@434
  1286
			}
dvander@434
  1287
		}
dvander@434
  1288
	}
dvander@434
  1289
	
dvander@434
  1290
	return true;
dvander@434
  1291
}