1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/AdminCache.cpp Wed Jan 24 21:51:49 2007 +0000
1.3 @@ -0,0 +1,568 @@
1.4 +#include <string.h>
1.5 +#include <assert.h>
1.6 +#include "AdminCache.h"
1.7 +#include "ShareSys.h"
1.8 +
1.9 +AdminCache g_Admins;
1.10 +
1.11 +AdminCache::AdminCache()
1.12 +{
1.13 + m_pCmdOverrides = NULL;
1.14 + m_pCmdGrpOverrides = NULL;
1.15 + m_pStrings = new BaseStringTable(1024);
1.16 + m_pMemory = m_pStrings->GetMemTable();
1.17 + m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
1.18 + m_pGroups = sm_trie_create();
1.19 +}
1.20 +
1.21 +AdminCache::~AdminCache()
1.22 +{
1.23 + if (m_pCmdGrpOverrides)
1.24 + {
1.25 + sm_trie_destroy(m_pCmdGrpOverrides);
1.26 + }
1.27 +
1.28 + if (m_pCmdOverrides)
1.29 + {
1.30 + sm_trie_destroy(m_pCmdOverrides);
1.31 + }
1.32 +
1.33 + InvalidateGroupCache();
1.34 +
1.35 + if (m_pGroups)
1.36 + {
1.37 + sm_trie_destroy(m_pGroups);
1.38 + }
1.39 +
1.40 + delete m_pStrings;
1.41 +}
1.42 +
1.43 +void AdminCache::OnSourceModAllInitialized()
1.44 +{
1.45 + g_ShareSys.AddInterface(NULL, this);
1.46 +}
1.47 +
1.48 +void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag)
1.49 +{
1.50 + if (type == Override_Command)
1.51 + {
1.52 + _AddCommandOverride(cmd, flag);
1.53 + } else if (type == Override_CommandGroup) {
1.54 + _AddCommandGroupOverride(cmd, flag);
1.55 + }
1.56 +}
1.57 +
1.58 +bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag)
1.59 +{
1.60 + if (type == Override_Command)
1.61 + {
1.62 + return _GetCommandOverride(cmd, pFlag);
1.63 + } else if (type == Override_CommandGroup) {
1.64 + return _GetCommandGroupOverride(cmd, pFlag);
1.65 + }
1.66 +
1.67 + return false;
1.68 +}
1.69 +
1.70 +void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
1.71 +{
1.72 + if (type == Override_Command)
1.73 + {
1.74 + return _UnsetCommandOverride(cmd);
1.75 + } else if (type == Override_CommandGroup) {
1.76 + return _UnsetCommandGroupOverride(cmd);
1.77 + }
1.78 +}
1.79 +
1.80 +void AdminCache::_AddCommandGroupOverride(const char *group, AdminFlag flag)
1.81 +{
1.82 + if (!m_pCmdGrpOverrides)
1.83 + {
1.84 + m_pCmdGrpOverrides = sm_trie_create();
1.85 + }
1.86 +
1.87 + /* :TODO: Notify command system */
1.88 +
1.89 + sm_trie_insert(m_pCmdGrpOverrides, group, (void *)flag);
1.90 +}
1.91 +
1.92 +void AdminCache::_AddCommandOverride(const char *cmd, AdminFlag flag)
1.93 +{
1.94 + if (!m_pCmdOverrides)
1.95 + {
1.96 + m_pCmdOverrides = sm_trie_create();
1.97 + }
1.98 +
1.99 + /* :TODO: Notify command system */
1.100 +
1.101 + sm_trie_insert(m_pCmdOverrides, cmd, (void *)flag);
1.102 +}
1.103 +
1.104 +bool AdminCache::_GetCommandGroupOverride(const char *cmd, AdminFlag *pFlag)
1.105 +{
1.106 + if (!m_pCmdGrpOverrides)
1.107 + {
1.108 + return false;
1.109 + }
1.110 +
1.111 + if (!pFlag)
1.112 + {
1.113 + return sm_trie_retrieve(m_pCmdGrpOverrides, cmd, NULL);
1.114 + } else {
1.115 + void *object;
1.116 + bool ret;
1.117 + if (ret=sm_trie_retrieve(m_pCmdGrpOverrides, cmd, &object))
1.118 + {
1.119 + *pFlag = (AdminFlag)(int)object;
1.120 + }
1.121 + return ret;
1.122 + }
1.123 +}
1.124 +
1.125 +bool AdminCache::_GetCommandOverride(const char *cmd, AdminFlag *pFlag)
1.126 +{
1.127 + if (!m_pCmdOverrides)
1.128 + {
1.129 + return false;
1.130 + }
1.131 +
1.132 + if (!pFlag)
1.133 + {
1.134 + return sm_trie_retrieve(m_pCmdOverrides, cmd, NULL);
1.135 + } else {
1.136 + void *object;
1.137 + bool ret;
1.138 + if (ret=sm_trie_retrieve(m_pCmdOverrides, cmd, &object))
1.139 + {
1.140 + *pFlag = (AdminFlag)(int)object;
1.141 + }
1.142 + return ret;
1.143 + }
1.144 +}
1.145 +
1.146 +void AdminCache::_UnsetCommandGroupOverride(const char *group)
1.147 +{
1.148 + if (!m_pCmdGrpOverrides)
1.149 + {
1.150 + return;
1.151 + }
1.152 +
1.153 + /* :TODO: Notify command system */
1.154 +
1.155 + sm_trie_delete(m_pCmdGrpOverrides, group);
1.156 +}
1.157 +
1.158 +void AdminCache::_UnsetCommandOverride(const char *cmd)
1.159 +{
1.160 + if (!m_pCmdOverrides)
1.161 + {
1.162 + return;
1.163 + }
1.164 +
1.165 + /* :TODO: Notify command system */
1.166 +
1.167 + sm_trie_delete(m_pCmdOverrides, cmd);
1.168 +}
1.169 +
1.170 +void AdminCache::DumpCommandOverrideCache(OverrideType type)
1.171 +{
1.172 + if (type == Override_Command && m_pCmdOverrides)
1.173 + {
1.174 + sm_trie_clear(m_pCmdOverrides);
1.175 + } else if (type == Override_CommandGroup && m_pCmdGrpOverrides) {
1.176 + sm_trie_clear(m_pCmdGrpOverrides);
1.177 + }
1.178 +}
1.179 +
1.180 +GroupId AdminCache::AddGroup(const char *group_name)
1.181 +{
1.182 + if (sm_trie_retrieve(m_pGroups, group_name, NULL))
1.183 + {
1.184 + return INVALID_GROUP_ID;
1.185 + }
1.186 +
1.187 + GroupId id;
1.188 + AdminGroup *pGroup;
1.189 + if (m_FreeGroupList != INVALID_GROUP_ID)
1.190 + {
1.191 + pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList);
1.192 + assert(pGroup->magic == GRP_MAGIC_UNSET);
1.193 + id = m_FreeGroupList;
1.194 + m_FreeGroupList = pGroup->next_grp;
1.195 + } else {
1.196 + id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup);
1.197 + }
1.198 +
1.199 + pGroup->immune_default = false;
1.200 + pGroup->immune_global = false;
1.201 + pGroup->immune_table = -1;
1.202 + pGroup->magic = GRP_MAGIC_SET;
1.203 + pGroup->next_grp = INVALID_GROUP_ID;
1.204 + pGroup->pCmdGrpTable = NULL;
1.205 + pGroup->pCmdTable = NULL;
1.206 + pGroup->nameidx = m_pStrings->AddString(group_name);
1.207 + memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL);
1.208 +
1.209 + if (m_FirstGroup == INVALID_GROUP_ID)
1.210 + {
1.211 + m_FirstGroup = id;
1.212 + m_LastGroup = id;
1.213 + pGroup->prev_grp = INVALID_GROUP_ID;
1.214 + } else {
1.215 + AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
1.216 + assert(pPrev->magic == GRP_MAGIC_SET);
1.217 + pPrev->next_grp = id;
1.218 + pGroup->prev_grp = m_LastGroup;
1.219 + m_LastGroup = id;
1.220 + }
1.221 +
1.222 + sm_trie_insert(m_pGroups, group_name, (void *)id);
1.223 +
1.224 + return id;
1.225 +}
1.226 +
1.227 +GroupId AdminCache::FindGroupByName(const char *group_name)
1.228 +{
1.229 + void *object;
1.230 +
1.231 + if (!sm_trie_retrieve(m_pGroups, group_name, &object))
1.232 + {
1.233 + return INVALID_GROUP_ID;
1.234 + }
1.235 +
1.236 + GroupId id = (GroupId)object;
1.237 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.238 +
1.239 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.240 + {
1.241 + return INVALID_GROUP_ID;
1.242 + }
1.243 +
1.244 + return id;
1.245 +}
1.246 +
1.247 +void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled)
1.248 +{
1.249 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.250 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.251 + {
1.252 + return;
1.253 + }
1.254 +
1.255 + if (flag < Admin_None || flag >= AdminFlags_TOTAL)
1.256 + {
1.257 + return;
1.258 + }
1.259 +
1.260 + pGroup->addflags[flag] = enabled;
1.261 +}
1.262 +
1.263 +bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag)
1.264 +{
1.265 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.266 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.267 + {
1.268 + return false;
1.269 + }
1.270 +
1.271 + if (flag < Admin_None || flag >= AdminFlags_TOTAL)
1.272 + {
1.273 + return false;
1.274 + }
1.275 +
1.276 + return pGroup->addflags[flag];
1.277 +}
1.278 +
1.279 +unsigned int AdminCache::GetGroupAddFlags(GroupId id, AdminFlag flags[], unsigned int total)
1.280 +{
1.281 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.282 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.283 + {
1.284 + return 0;
1.285 + }
1.286 +
1.287 + unsigned int r = 0;
1.288 +
1.289 + for (unsigned int i = Admin_None + 1;
1.290 + i < AdminFlags_TOTAL && r < total;
1.291 + i++)
1.292 + {
1.293 + if (pGroup->addflags[i])
1.294 + {
1.295 + flags[r++] = (AdminFlag)i;
1.296 + }
1.297 + }
1.298 +
1.299 + return r;
1.300 +}
1.301 +
1.302 +void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled)
1.303 +{
1.304 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.305 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.306 + {
1.307 + return;
1.308 + }
1.309 +
1.310 + if (type == Immunity_Default)
1.311 + {
1.312 + pGroup->immune_default = enabled;
1.313 + } else if (type == Immunity_Global) {
1.314 + pGroup->immune_global = enabled;
1.315 + }
1.316 +}
1.317 +
1.318 +bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type)
1.319 +{
1.320 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.321 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.322 + {
1.323 + return false;
1.324 + }
1.325 +
1.326 + if (type == Immunity_Default)
1.327 + {
1.328 + return pGroup->immune_default;
1.329 + } else if (type == Immunity_Global) {
1.330 + return pGroup->immune_global;
1.331 + }
1.332 +
1.333 + return false;
1.334 +}
1.335 +
1.336 +void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id)
1.337 +{
1.338 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.339 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.340 + {
1.341 + return;
1.342 + }
1.343 +
1.344 + AdminGroup *pOther = (AdminGroup *)m_pMemory->GetAddress(id);
1.345 + if (!pOther || pOther->magic != GRP_MAGIC_SET)
1.346 + {
1.347 + return;
1.348 + }
1.349 +
1.350 + /* We always need to resize the immunity table */
1.351 + int *table, tblidx;
1.352 + if (pOther->immune_table == -1)
1.353 + {
1.354 + tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table);
1.355 + table[0] = 0;
1.356 + } else {
1.357 + int *old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
1.358 + tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table);
1.359 + /* Get the old address again in caes of resize */
1.360 + old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
1.361 + table[0] = old_table[0];
1.362 + for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++)
1.363 + {
1.364 + table[i] = old_table[i];
1.365 + }
1.366 + }
1.367 +
1.368 + /* Assign */
1.369 + pOther->immune_table = tblidx;
1.370 +
1.371 + /* Add to the array */
1.372 + table[0]++;
1.373 + table[table[0]] = other_id;
1.374 +}
1.375 +
1.376 +unsigned int AdminCache::GetGroupImmunityCount(GroupId id)
1.377 +{
1.378 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.379 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.380 + {
1.381 + return 0;
1.382 + }
1.383 +
1.384 + if (pGroup->immune_table == -1)
1.385 + {
1.386 + return 0;
1.387 + }
1.388 +
1.389 + int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
1.390 +
1.391 + return table[0];
1.392 +}
1.393 +
1.394 +GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number)
1.395 +{
1.396 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.397 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.398 + {
1.399 + return INVALID_GROUP_ID;
1.400 + }
1.401 +
1.402 + if (pGroup->immune_table == -1)
1.403 + {
1.404 + return INVALID_GROUP_ID;
1.405 + }
1.406 +
1.407 + int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
1.408 + if (number >= (unsigned int)table[0])
1.409 + {
1.410 + return INVALID_GROUP_ID;
1.411 + }
1.412 +
1.413 + return table[1 + number];
1.414 +}
1.415 +
1.416 +void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule)
1.417 +{
1.418 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.419 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.420 + {
1.421 + return;
1.422 + }
1.423 +
1.424 + Trie *pTrie = NULL;
1.425 + if (type == Override_Command)
1.426 + {
1.427 + if (pGroup->pCmdTable == NULL)
1.428 + {
1.429 + pGroup->pCmdTable = sm_trie_create();
1.430 + }
1.431 + pTrie = pGroup->pCmdTable;
1.432 + } else if (type == Override_CommandGroup) {
1.433 + if (pGroup->pCmdGrpTable == NULL)
1.434 + {
1.435 + pGroup->pCmdGrpTable = sm_trie_create();
1.436 + }
1.437 + pTrie = pGroup->pCmdGrpTable;
1.438 + } else {
1.439 + return;
1.440 + }
1.441 +
1.442 + sm_trie_insert(pTrie, name, (void *)(int)rule);
1.443 +}
1.444 +
1.445 +bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule)
1.446 +{
1.447 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.448 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.449 + {
1.450 + return false;
1.451 + }
1.452 +
1.453 + Trie *pTrie = NULL;
1.454 + if (type == Override_Command)
1.455 + {
1.456 + if (pGroup->pCmdTable == NULL)
1.457 + {
1.458 + return false;
1.459 + }
1.460 + pTrie = pGroup->pCmdTable;
1.461 + } else if (type == Override_CommandGroup) {
1.462 + if (pGroup->pCmdGrpTable == NULL)
1.463 + {
1.464 + return false;
1.465 + }
1.466 + pTrie = pGroup->pCmdGrpTable;
1.467 + } else {
1.468 + return false;
1.469 + }
1.470 +
1.471 + void *object;
1.472 + if (!sm_trie_retrieve(pTrie, name, &object))
1.473 + {
1.474 + return false;
1.475 + }
1.476 +
1.477 + if (pRule)
1.478 + {
1.479 + *pRule = (OverrideRule)(int)object;
1.480 + }
1.481 +
1.482 + return true;
1.483 +}
1.484 +
1.485 +void AdminCache::InvalidateGroup(GroupId id)
1.486 +{
1.487 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.488 + AdminGroup *pOther;
1.489 +
1.490 + if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
1.491 + {
1.492 + return;
1.493 + }
1.494 +
1.495 + const char *str = m_pStrings->GetString(pGroup->nameidx);
1.496 + sm_trie_delete(m_pGroups, str);
1.497 +
1.498 + /* Unlink from the live dbllink list */
1.499 + if (id == m_FirstGroup && id == m_LastGroup)
1.500 + {
1.501 + m_LastGroup = INVALID_GROUP_ID;
1.502 + m_FirstGroup = INVALID_GROUP_ID;
1.503 + } else if (id == m_FirstGroup) {
1.504 + m_FirstGroup = pGroup->next_grp;
1.505 + pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup);
1.506 + pOther->prev_grp = INVALID_GROUP_ID;
1.507 + } else if (id == m_LastGroup) {
1.508 + m_LastGroup = pGroup->prev_grp;
1.509 + pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
1.510 + pOther->next_grp = INVALID_GROUP_ID;
1.511 + } else {
1.512 + pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp);
1.513 + pOther->next_grp = pGroup->next_grp;
1.514 + pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp);
1.515 + pOther->prev_grp = pGroup->prev_grp;
1.516 + }
1.517 +
1.518 + /* Free any used memory to be safe */
1.519 + if (pGroup->pCmdGrpTable)
1.520 + {
1.521 + sm_trie_destroy(pGroup->pCmdGrpTable);
1.522 + pGroup->pCmdGrpTable = NULL;
1.523 + }
1.524 + if (pGroup->pCmdTable)
1.525 + {
1.526 + sm_trie_destroy(pGroup->pCmdTable);
1.527 + pGroup->pCmdTable = NULL;
1.528 + }
1.529 +
1.530 + /* Link into the free list */
1.531 + pGroup->magic = GRP_MAGIC_UNSET;
1.532 + pGroup->next_grp = m_FreeGroupList;
1.533 + m_FreeGroupList = id;
1.534 +
1.535 + /* :TODO: remove this group from any users */
1.536 +}
1.537 +
1.538 +void AdminCache::InvalidateGroupCache()
1.539 +{
1.540 + /* Nuke the free list */
1.541 + m_FreeGroupList = -1;
1.542 +
1.543 + /* Nuke reverse lookups */
1.544 + sm_trie_clear(m_pGroups);
1.545 +
1.546 + /* Free memory on groups */
1.547 + GroupId cur = m_FirstGroup;
1.548 + AdminGroup *pGroup;
1.549 + while (cur != INVALID_GROUP_ID)
1.550 + {
1.551 + pGroup = (AdminGroup *)m_pMemory->GetAddress(cur);
1.552 + assert(pGroup->magic == GRP_MAGIC_SET);
1.553 + if (pGroup->pCmdGrpTable)
1.554 + {
1.555 + sm_trie_destroy(pGroup->pCmdGrpTable);
1.556 + }
1.557 + if (pGroup->pCmdTable)
1.558 + {
1.559 + sm_trie_destroy(pGroup->pCmdTable);
1.560 + }
1.561 + cur = pGroup->next_grp;
1.562 + }
1.563 +
1.564 + m_FirstGroup = INVALID_GROUP_ID;
1.565 + m_LastGroup = INVALID_GROUP_ID;
1.566 +
1.567 + /* :TODO: dump the admin cache */
1.568 +
1.569 + /* Reset the memory table */
1.570 + m_pMemory->Reset();
1.571 +}