core/AdminCache.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jan 24 23:43:31 2007 +0000 (2007-01-24)
changeset 336 3f4073018d76
parent 335 02cc96355b09
child 345 df0b05b4f50d
permissions -rw-r--r--
Added initial admin system natives
Added a few API changes to the admin system
Exposed more interfaces
     1 #include <string.h>
     2 #include <assert.h>
     3 #include "AdminCache.h"
     4 #include "ShareSys.h"
     5 #include "ForwardSys.h"
     6 
     7 AdminCache g_Admins;
     8 
     9 AdminCache::AdminCache()
    10 {
    11 	m_pCmdOverrides = NULL;
    12 	m_pCmdGrpOverrides = NULL;
    13 	m_pStrings = new BaseStringTable(1024);
    14 	m_pMemory = m_pStrings->GetMemTable();
    15 	m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
    16 	m_pGroups = sm_trie_create();
    17 	m_pCacheFwd = NULL;
    18 }
    19 
    20 AdminCache::~AdminCache()
    21 {
    22 	if (m_pCmdGrpOverrides)
    23 	{
    24 		sm_trie_destroy(m_pCmdGrpOverrides);
    25 	}
    26 
    27 	if (m_pCmdOverrides)
    28 	{
    29 		sm_trie_destroy(m_pCmdOverrides);
    30 	}
    31 
    32 	InvalidateGroupCache();
    33 
    34 	if (m_pGroups)
    35 	{
    36 		sm_trie_destroy(m_pGroups);
    37 	}
    38 
    39 	delete m_pStrings;
    40 }
    41 
    42 void AdminCache::OnSourceModAllInitialized()
    43 {
    44 	m_pCacheFwd = g_Forwards.CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell);
    45 	g_ShareSys.AddInterface(NULL, this);
    46 }
    47 
    48 void AdminCache::OnSourceModShutdown()
    49 {
    50 	g_Forwards.ReleaseForward(m_pCacheFwd);
    51 	m_pCacheFwd = NULL;
    52 }
    53 
    54 void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag)
    55 {
    56 	if (type == Override_Command)
    57 	{
    58 		_AddCommandOverride(cmd, flag);
    59 	} else if (type == Override_CommandGroup) {
    60 		_AddCommandGroupOverride(cmd, flag);
    61 	}
    62 }
    63 
    64 bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag)
    65 {
    66 	if (type == Override_Command)
    67 	{
    68 		return _GetCommandOverride(cmd, pFlag);
    69 	} else if (type == Override_CommandGroup) {
    70 		return _GetCommandGroupOverride(cmd, pFlag);
    71 	}
    72 
    73 	return false;
    74 }
    75 
    76 void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
    77 {
    78 	if (type == Override_Command)
    79 	{
    80 		return _UnsetCommandOverride(cmd);
    81 	} else if (type == Override_CommandGroup) {
    82 		return _UnsetCommandGroupOverride(cmd);
    83 	}
    84 }
    85 
    86 void AdminCache::_AddCommandGroupOverride(const char *group, AdminFlag flag)
    87 {
    88 	if (!m_pCmdGrpOverrides)
    89 	{
    90 		m_pCmdGrpOverrides = sm_trie_create();
    91 	}
    92 
    93 	/* :TODO: Notify command system */
    94 
    95 	sm_trie_insert(m_pCmdGrpOverrides, group, (void *)flag);
    96 }
    97 
    98 void AdminCache::_AddCommandOverride(const char *cmd, AdminFlag flag)
    99 {
   100 	if (!m_pCmdOverrides)
   101 	{
   102 		m_pCmdOverrides = sm_trie_create();
   103 	}
   104 
   105 	/* :TODO: Notify command system */
   106 
   107 	sm_trie_insert(m_pCmdOverrides, cmd, (void *)flag);
   108 }
   109 
   110 bool AdminCache::_GetCommandGroupOverride(const char *cmd, AdminFlag *pFlag)
   111 {
   112 	if (!m_pCmdGrpOverrides)
   113 	{
   114 		return false;
   115 	}
   116 
   117 	if (!pFlag)
   118 	{
   119 		return sm_trie_retrieve(m_pCmdGrpOverrides, cmd, NULL);
   120 	} else {
   121 		void *object;
   122 		bool ret;
   123 		if (ret=sm_trie_retrieve(m_pCmdGrpOverrides, cmd, &object))
   124 		{
   125 			*pFlag = (AdminFlag)(int)object;
   126 		}
   127 		return ret;
   128 	}
   129 }
   130 
   131 bool AdminCache::_GetCommandOverride(const char *cmd, AdminFlag *pFlag)
   132 {
   133 	if (!m_pCmdOverrides)
   134 	{
   135 		return false;
   136 	}
   137 
   138 	if (!pFlag)
   139 	{
   140 		return sm_trie_retrieve(m_pCmdOverrides, cmd, NULL);
   141 	} else {
   142 		void *object;
   143 		bool ret;
   144 		if (ret=sm_trie_retrieve(m_pCmdOverrides, cmd, &object))
   145 		{
   146 			*pFlag = (AdminFlag)(int)object;
   147 		}
   148 		return ret;
   149 	}
   150 }
   151 
   152 void AdminCache::_UnsetCommandGroupOverride(const char *group)
   153 {
   154 	if (!m_pCmdGrpOverrides)
   155 	{
   156 		return;
   157 	}
   158 
   159 	/* :TODO: Notify command system */
   160 
   161 	sm_trie_delete(m_pCmdGrpOverrides, group);
   162 }
   163 
   164 void AdminCache::_UnsetCommandOverride(const char *cmd)
   165 {
   166 	if (!m_pCmdOverrides)
   167 	{
   168 		return;
   169 	}
   170 
   171 	/* :TODO: Notify command system */
   172 
   173 	sm_trie_delete(m_pCmdOverrides, cmd);
   174 }
   175 
   176 void AdminCache::DumpCommandOverrideCache(OverrideType type)
   177 {
   178 	if (type == Override_Command && m_pCmdOverrides)
   179 	{
   180 		sm_trie_clear(m_pCmdOverrides);
   181 	} else if (type == Override_CommandGroup && m_pCmdGrpOverrides) {
   182 		sm_trie_clear(m_pCmdGrpOverrides);
   183 	}
   184 }
   185 
   186 GroupId AdminCache::AddGroup(const char *group_name)
   187 {
   188 	if (sm_trie_retrieve(m_pGroups, group_name, NULL))
   189 	{
   190 		return INVALID_GROUP_ID;
   191 	}
   192 
   193 	GroupId id;
   194 	AdminGroup *pGroup;
   195 	if (m_FreeGroupList != INVALID_GROUP_ID)
   196 	{
   197 		pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList);
   198 		assert(pGroup->magic == GRP_MAGIC_UNSET);
   199 		id = m_FreeGroupList;
   200 		m_FreeGroupList = pGroup->next_grp;
   201 	} else {
   202 		id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup);
   203 	}
   204 
   205 	pGroup->immune_default = false;
   206 	pGroup->immune_global = false;
   207 	pGroup->immune_table = -1;
   208 	pGroup->magic = GRP_MAGIC_SET;
   209 	pGroup->next_grp = INVALID_GROUP_ID;
   210 	pGroup->pCmdGrpTable = NULL;
   211 	pGroup->pCmdTable = NULL;
   212 	pGroup->nameidx = m_pStrings->AddString(group_name);
   213 	memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL);
   214 
   215 	if (m_FirstGroup == INVALID_GROUP_ID)
   216 	{
   217 		m_FirstGroup = id;
   218 		m_LastGroup = id;
   219 		pGroup->prev_grp = INVALID_GROUP_ID;
   220 	} else {
   221 		AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
   222 		assert(pPrev->magic == GRP_MAGIC_SET);
   223 		pPrev->next_grp = id;
   224 		pGroup->prev_grp = m_LastGroup;
   225 		m_LastGroup = id;
   226 	}
   227 
   228 	sm_trie_insert(m_pGroups, group_name, (void *)id);
   229 
   230 	return id;
   231 }
   232 
   233 GroupId AdminCache::FindGroupByName(const char *group_name)
   234 {
   235 	void *object;
   236 
   237 	if (!sm_trie_retrieve(m_pGroups, group_name, &object))
   238 	{
   239 		return INVALID_GROUP_ID;
   240 	}
   241 
   242 	GroupId id = (GroupId)object;
   243 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   244 
   245 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   246 	{
   247 		return INVALID_GROUP_ID;
   248 	}
   249 
   250 	return id;
   251 }
   252 
   253 void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled)
   254 {
   255 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   256 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   257 	{
   258 		return;
   259 	}
   260 
   261 	if (flag < Admin_None || flag >= AdminFlags_TOTAL)
   262 	{
   263 		return;
   264 	}
   265 
   266 	pGroup->addflags[flag] = enabled;
   267 }
   268 
   269 bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag)
   270 {
   271 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   272 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   273 	{
   274 		return false;
   275 	}
   276 
   277 	if (flag < Admin_None || flag >= AdminFlags_TOTAL)
   278 	{
   279 		return false;
   280 	}
   281 
   282 	return pGroup->addflags[flag];
   283 }
   284 
   285 unsigned int AdminCache::GetGroupAddFlagBits(GroupId id, bool flags[], unsigned int total)
   286 {
   287 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   288 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   289 	{
   290 		return 0;
   291 	}
   292 
   293 	unsigned int i;
   294 
   295 	for (i = Admin_None;
   296 		 i < AdminFlags_TOTAL && i < total;
   297 		 i++)
   298 	{
   299 		flags[i] = pGroup->addflags[i];
   300 	}
   301 
   302 	return i;
   303 }
   304 
   305 void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled)
   306 {
   307 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   308 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   309 	{
   310 		return;
   311 	}
   312 
   313 	if (type == Immunity_Default)
   314 	{
   315 		pGroup->immune_default = enabled;
   316 	} else if (type == Immunity_Global) {
   317 		pGroup->immune_global = enabled;
   318 	} 
   319 }
   320 
   321 bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type)
   322 {
   323 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   324 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   325 	{
   326 		return false;
   327 	}
   328 
   329 	if (type == Immunity_Default)
   330 	{
   331 		return pGroup->immune_default;
   332 	} else if (type == Immunity_Global) {
   333 		return pGroup->immune_global;
   334 	}
   335 
   336 	return false;
   337 }
   338 
   339 void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id)
   340 {
   341 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   342 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   343 	{
   344 		return;
   345 	}
   346 
   347 	AdminGroup *pOther = (AdminGroup *)m_pMemory->GetAddress(id);
   348 	if (!pOther || pOther->magic != GRP_MAGIC_SET)
   349 	{
   350 		return;
   351 	}
   352 
   353 	/* We always need to resize the immunity table */
   354 	int *table, tblidx;
   355 	if (pOther->immune_table == -1)
   356 	{
   357 		tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table);
   358 		table[0] = 0;
   359 	} else {
   360 		int *old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
   361 		tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table);
   362 		/* Get the old address again in caes of resize */
   363 		old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
   364 		table[0] = old_table[0];
   365 		for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++)
   366 		{
   367 			table[i] = old_table[i];
   368 		}
   369 	}
   370 
   371 	/* Assign */
   372 	pOther->immune_table = tblidx;
   373 
   374 	/* Add to the array */
   375 	table[0]++;
   376 	table[table[0]] = other_id;
   377 }
   378 
   379 unsigned int AdminCache::GetGroupImmunityCount(GroupId id)
   380 {
   381 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   382 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   383 	{
   384 		return 0;
   385 	}
   386 
   387 	if (pGroup->immune_table == -1)
   388 	{
   389 		return 0;
   390 	}
   391 
   392 	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
   393 
   394 	return table[0];
   395 }
   396 
   397 GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number)
   398 {
   399 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   400 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   401 	{
   402 		return INVALID_GROUP_ID;
   403 	}
   404 
   405 	if (pGroup->immune_table == -1)
   406 	{
   407 		return INVALID_GROUP_ID;
   408 	}
   409 
   410 	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
   411 	if (number >= (unsigned int)table[0])
   412 	{
   413 		return INVALID_GROUP_ID;
   414 	}
   415 
   416 	return table[1 + number];
   417 }
   418 
   419 void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule)
   420 {
   421 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   422 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   423 	{
   424 		return;
   425 	}
   426 
   427 	Trie *pTrie = NULL;
   428 	if (type == Override_Command)
   429 	{
   430 		if (pGroup->pCmdTable == NULL)
   431 		{
   432 			pGroup->pCmdTable = sm_trie_create();
   433 		}
   434 		pTrie = pGroup->pCmdTable;
   435 	} else if (type == Override_CommandGroup) {
   436 		if (pGroup->pCmdGrpTable == NULL)
   437 		{
   438 			pGroup->pCmdGrpTable = sm_trie_create();
   439 		}
   440 		pTrie = pGroup->pCmdGrpTable;
   441 	} else {
   442 		return;
   443 	}
   444 
   445 	sm_trie_insert(pTrie, name, (void *)(int)rule);
   446 }
   447 
   448 bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule)
   449 {
   450 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   451 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   452 	{
   453 		return false;
   454 	}
   455 
   456 	Trie *pTrie = NULL;
   457 	if (type == Override_Command)
   458 	{
   459 		if (pGroup->pCmdTable == NULL)
   460 		{
   461 			return false;
   462 		}
   463 		pTrie = pGroup->pCmdTable;
   464 	} else if (type == Override_CommandGroup) {
   465 		if (pGroup->pCmdGrpTable == NULL)
   466 		{
   467 			return false;
   468 		}
   469 		pTrie = pGroup->pCmdGrpTable;
   470 	} else {
   471 		return false;
   472 	}
   473 
   474 	void *object;
   475 	if (!sm_trie_retrieve(pTrie, name, &object))
   476 	{
   477 		return false;
   478 	}
   479 
   480 	if (pRule)
   481 	{
   482 		*pRule = (OverrideRule)(int)object;
   483 	}
   484 	
   485 	return true;
   486 }
   487 
   488 void AdminCache::InvalidateGroup(GroupId id)
   489 {
   490 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   491 	AdminGroup *pOther;
   492 
   493 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   494 	{
   495 		return;
   496 	}
   497 
   498 	const char *str = m_pStrings->GetString(pGroup->nameidx);
   499 	sm_trie_delete(m_pGroups, str);
   500 
   501 	/* Unlink from the live dbllink list */
   502 	if (id == m_FirstGroup && id == m_LastGroup)
   503 	{
   504 		m_LastGroup = INVALID_GROUP_ID;
   505 		m_FirstGroup = INVALID_GROUP_ID;
   506 	} else if (id == m_FirstGroup) {
   507 		m_FirstGroup = pGroup->next_grp;
   508 		pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup);
   509 		pOther->prev_grp = INVALID_GROUP_ID;
   510 	} else if (id == m_LastGroup) {
   511 		m_LastGroup = pGroup->prev_grp;
   512 		pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
   513 		pOther->next_grp = INVALID_GROUP_ID;
   514 	} else {
   515 		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp);
   516 		pOther->next_grp = pGroup->next_grp;
   517 		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp);
   518 		pOther->prev_grp = pGroup->prev_grp;
   519 	}
   520 
   521 	/* Free any used memory to be safe */
   522 	if (pGroup->pCmdGrpTable)
   523 	{
   524 		sm_trie_destroy(pGroup->pCmdGrpTable);
   525 		pGroup->pCmdGrpTable = NULL;
   526 	}
   527 	if (pGroup->pCmdTable)
   528 	{
   529 		sm_trie_destroy(pGroup->pCmdTable);
   530 		pGroup->pCmdTable = NULL;
   531 	}
   532 
   533 	/* Link into the free list */
   534 	pGroup->magic = GRP_MAGIC_UNSET;
   535 	pGroup->next_grp = m_FreeGroupList;
   536 	m_FreeGroupList = id;
   537 
   538 	/* :TODO: remove this group from any users */
   539 }
   540 
   541 void AdminCache::InvalidateGroupCache()
   542 {
   543 	/* Nuke the free list */
   544 	m_FreeGroupList = -1;
   545 
   546 	/* Nuke reverse lookups */
   547 	sm_trie_clear(m_pGroups);
   548 
   549 	/* Free memory on groups */
   550 	GroupId cur = m_FirstGroup;
   551 	AdminGroup *pGroup;
   552 	while (cur != INVALID_GROUP_ID)
   553 	{
   554 		pGroup = (AdminGroup *)m_pMemory->GetAddress(cur);
   555 		assert(pGroup->magic == GRP_MAGIC_SET);
   556 		if (pGroup->pCmdGrpTable)
   557 		{
   558 			sm_trie_destroy(pGroup->pCmdGrpTable);
   559 		}
   560 		if (pGroup->pCmdTable)
   561 		{
   562 			sm_trie_destroy(pGroup->pCmdTable);
   563 		}
   564 		cur = pGroup->next_grp;
   565 	}
   566 
   567 	m_FirstGroup = INVALID_GROUP_ID;
   568 	m_LastGroup = INVALID_GROUP_ID;
   569 
   570 	/* :TODO: dump the admin cache */
   571 
   572 	/* Reset the memory table */
   573 	m_pMemory->Reset();
   574 }
   575 
   576 void AdminCache::AddAdminListener(IAdminListener *pListener)
   577 {
   578 	m_hooks.push_back(pListener);
   579 }
   580 
   581 void AdminCache::RemoveAdminListener(IAdminListener *pListener)
   582 {
   583 	m_hooks.remove(pListener);
   584 }
   585 
   586 void AdminCache::DumpAdminCache(int cache_flags, bool rebuild)
   587 {
   588 	if (cache_flags & ADMIN_CACHE_OVERRIDES)
   589 	{
   590 		DumpCommandOverrideCache(Override_Command);
   591 		DumpCommandOverrideCache(Override_CommandGroup);
   592 	}
   593 
   594 	if ((cache_flags & ADMIN_CACHE_ADMINS) ||
   595 		(cache_flags & ADMIN_CACHE_GROUPS))
   596 	{
   597 		/* Make sure the flag is set */
   598 		cache_flags |= ADMIN_CACHE_ADMINS;
   599 		/* :TODO: Dump admin cache */
   600 	}
   601 
   602 	if (cache_flags & ADMIN_CACHE_GROUPS)
   603 	{
   604 		InvalidateGroupCache();
   605 	}
   606 
   607 	if (rebuild)
   608 	{
   609 		List<IAdminListener *>::iterator iter;
   610 		IAdminListener *pListener;
   611 		for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
   612 		{
   613 			pListener = (*iter);
   614 			pListener->OnRebuildAdminCache(cache_flags);
   615 		}
   616 	}
   617 }