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