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