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