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