#include #include #include "AdminCache.h" #include "ShareSys.h" AdminCache g_Admins; AdminCache::AdminCache() { m_pCmdOverrides = NULL; m_pCmdGrpOverrides = NULL; m_pStrings = new BaseStringTable(1024); m_pMemory = m_pStrings->GetMemTable(); m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID; m_pGroups = sm_trie_create(); } AdminCache::~AdminCache() { if (m_pCmdGrpOverrides) { sm_trie_destroy(m_pCmdGrpOverrides); } if (m_pCmdOverrides) { sm_trie_destroy(m_pCmdOverrides); } InvalidateGroupCache(); if (m_pGroups) { sm_trie_destroy(m_pGroups); } delete m_pStrings; } void AdminCache::OnSourceModAllInitialized() { g_ShareSys.AddInterface(NULL, this); } void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag) { if (type == Override_Command) { _AddCommandOverride(cmd, flag); } else if (type == Override_CommandGroup) { _AddCommandGroupOverride(cmd, flag); } } bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag) { if (type == Override_Command) { return _GetCommandOverride(cmd, pFlag); } else if (type == Override_CommandGroup) { return _GetCommandGroupOverride(cmd, pFlag); } return false; } void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type) { if (type == Override_Command) { return _UnsetCommandOverride(cmd); } else if (type == Override_CommandGroup) { return _UnsetCommandGroupOverride(cmd); } } void AdminCache::_AddCommandGroupOverride(const char *group, AdminFlag flag) { if (!m_pCmdGrpOverrides) { m_pCmdGrpOverrides = sm_trie_create(); } /* :TODO: Notify command system */ sm_trie_insert(m_pCmdGrpOverrides, group, (void *)flag); } void AdminCache::_AddCommandOverride(const char *cmd, AdminFlag flag) { if (!m_pCmdOverrides) { m_pCmdOverrides = sm_trie_create(); } /* :TODO: Notify command system */ sm_trie_insert(m_pCmdOverrides, cmd, (void *)flag); } bool AdminCache::_GetCommandGroupOverride(const char *cmd, AdminFlag *pFlag) { if (!m_pCmdGrpOverrides) { return false; } if (!pFlag) { return sm_trie_retrieve(m_pCmdGrpOverrides, cmd, NULL); } else { void *object; bool ret; if (ret=sm_trie_retrieve(m_pCmdGrpOverrides, cmd, &object)) { *pFlag = (AdminFlag)(int)object; } return ret; } } bool AdminCache::_GetCommandOverride(const char *cmd, AdminFlag *pFlag) { if (!m_pCmdOverrides) { return false; } if (!pFlag) { return sm_trie_retrieve(m_pCmdOverrides, cmd, NULL); } else { void *object; bool ret; if (ret=sm_trie_retrieve(m_pCmdOverrides, cmd, &object)) { *pFlag = (AdminFlag)(int)object; } return ret; } } void AdminCache::_UnsetCommandGroupOverride(const char *group) { if (!m_pCmdGrpOverrides) { return; } /* :TODO: Notify command system */ sm_trie_delete(m_pCmdGrpOverrides, group); } void AdminCache::_UnsetCommandOverride(const char *cmd) { if (!m_pCmdOverrides) { return; } /* :TODO: Notify command system */ sm_trie_delete(m_pCmdOverrides, cmd); } void AdminCache::DumpCommandOverrideCache(OverrideType type) { if (type == Override_Command && m_pCmdOverrides) { sm_trie_clear(m_pCmdOverrides); } else if (type == Override_CommandGroup && m_pCmdGrpOverrides) { sm_trie_clear(m_pCmdGrpOverrides); } } GroupId AdminCache::AddGroup(const char *group_name) { if (sm_trie_retrieve(m_pGroups, group_name, NULL)) { return INVALID_GROUP_ID; } GroupId id; AdminGroup *pGroup; if (m_FreeGroupList != INVALID_GROUP_ID) { pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList); assert(pGroup->magic == GRP_MAGIC_UNSET); id = m_FreeGroupList; m_FreeGroupList = pGroup->next_grp; } else { id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup); } pGroup->immune_default = false; pGroup->immune_global = false; pGroup->immune_table = -1; pGroup->magic = GRP_MAGIC_SET; pGroup->next_grp = INVALID_GROUP_ID; pGroup->pCmdGrpTable = NULL; pGroup->pCmdTable = NULL; pGroup->nameidx = m_pStrings->AddString(group_name); memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL); if (m_FirstGroup == INVALID_GROUP_ID) { m_FirstGroup = id; m_LastGroup = id; pGroup->prev_grp = INVALID_GROUP_ID; } else { AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); assert(pPrev->magic == GRP_MAGIC_SET); pPrev->next_grp = id; pGroup->prev_grp = m_LastGroup; m_LastGroup = id; } sm_trie_insert(m_pGroups, group_name, (void *)id); return id; } GroupId AdminCache::FindGroupByName(const char *group_name) { void *object; if (!sm_trie_retrieve(m_pGroups, group_name, &object)) { return INVALID_GROUP_ID; } GroupId id = (GroupId)object; AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return INVALID_GROUP_ID; } return id; } void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return; } if (flag < Admin_None || flag >= AdminFlags_TOTAL) { return; } pGroup->addflags[flag] = enabled; } bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return false; } if (flag < Admin_None || flag >= AdminFlags_TOTAL) { return false; } return pGroup->addflags[flag]; } unsigned int AdminCache::GetGroupAddFlags(GroupId id, AdminFlag flags[], unsigned int total) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return 0; } unsigned int r = 0; for (unsigned int i = Admin_None + 1; i < AdminFlags_TOTAL && r < total; i++) { if (pGroup->addflags[i]) { flags[r++] = (AdminFlag)i; } } return r; } void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return; } if (type == Immunity_Default) { pGroup->immune_default = enabled; } else if (type == Immunity_Global) { pGroup->immune_global = enabled; } } bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return false; } if (type == Immunity_Default) { return pGroup->immune_default; } else if (type == Immunity_Global) { return pGroup->immune_global; } return false; } void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return; } AdminGroup *pOther = (AdminGroup *)m_pMemory->GetAddress(id); if (!pOther || pOther->magic != GRP_MAGIC_SET) { return; } /* We always need to resize the immunity table */ int *table, tblidx; if (pOther->immune_table == -1) { tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table); table[0] = 0; } else { int *old_table = (int *)m_pMemory->GetAddress(pOther->immune_table); tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table); /* Get the old address again in caes of resize */ old_table = (int *)m_pMemory->GetAddress(pOther->immune_table); table[0] = old_table[0]; for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++) { table[i] = old_table[i]; } } /* Assign */ pOther->immune_table = tblidx; /* Add to the array */ table[0]++; table[table[0]] = other_id; } unsigned int AdminCache::GetGroupImmunityCount(GroupId id) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return 0; } if (pGroup->immune_table == -1) { return 0; } int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); return table[0]; } GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return INVALID_GROUP_ID; } if (pGroup->immune_table == -1) { return INVALID_GROUP_ID; } int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); if (number >= (unsigned int)table[0]) { return INVALID_GROUP_ID; } return table[1 + number]; } void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return; } Trie *pTrie = NULL; if (type == Override_Command) { if (pGroup->pCmdTable == NULL) { pGroup->pCmdTable = sm_trie_create(); } pTrie = pGroup->pCmdTable; } else if (type == Override_CommandGroup) { if (pGroup->pCmdGrpTable == NULL) { pGroup->pCmdGrpTable = sm_trie_create(); } pTrie = pGroup->pCmdGrpTable; } else { return; } sm_trie_insert(pTrie, name, (void *)(int)rule); } bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return false; } Trie *pTrie = NULL; if (type == Override_Command) { if (pGroup->pCmdTable == NULL) { return false; } pTrie = pGroup->pCmdTable; } else if (type == Override_CommandGroup) { if (pGroup->pCmdGrpTable == NULL) { return false; } pTrie = pGroup->pCmdGrpTable; } else { return false; } void *object; if (!sm_trie_retrieve(pTrie, name, &object)) { return false; } if (pRule) { *pRule = (OverrideRule)(int)object; } return true; } void AdminCache::InvalidateGroup(GroupId id) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); AdminGroup *pOther; if (!pGroup || pGroup->magic != GRP_MAGIC_SET) { return; } const char *str = m_pStrings->GetString(pGroup->nameidx); sm_trie_delete(m_pGroups, str); /* Unlink from the live dbllink list */ if (id == m_FirstGroup && id == m_LastGroup) { m_LastGroup = INVALID_GROUP_ID; m_FirstGroup = INVALID_GROUP_ID; } else if (id == m_FirstGroup) { m_FirstGroup = pGroup->next_grp; pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup); pOther->prev_grp = INVALID_GROUP_ID; } else if (id == m_LastGroup) { m_LastGroup = pGroup->prev_grp; pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); pOther->next_grp = INVALID_GROUP_ID; } else { pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp); pOther->next_grp = pGroup->next_grp; pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp); pOther->prev_grp = pGroup->prev_grp; } /* Free any used memory to be safe */ if (pGroup->pCmdGrpTable) { sm_trie_destroy(pGroup->pCmdGrpTable); pGroup->pCmdGrpTable = NULL; } if (pGroup->pCmdTable) { sm_trie_destroy(pGroup->pCmdTable); pGroup->pCmdTable = NULL; } /* Link into the free list */ pGroup->magic = GRP_MAGIC_UNSET; pGroup->next_grp = m_FreeGroupList; m_FreeGroupList = id; /* :TODO: remove this group from any users */ } void AdminCache::InvalidateGroupCache() { /* Nuke the free list */ m_FreeGroupList = -1; /* Nuke reverse lookups */ sm_trie_clear(m_pGroups); /* Free memory on groups */ GroupId cur = m_FirstGroup; AdminGroup *pGroup; while (cur != INVALID_GROUP_ID) { pGroup = (AdminGroup *)m_pMemory->GetAddress(cur); assert(pGroup->magic == GRP_MAGIC_SET); if (pGroup->pCmdGrpTable) { sm_trie_destroy(pGroup->pCmdGrpTable); } if (pGroup->pCmdTable) { sm_trie_destroy(pGroup->pCmdTable); } cur = pGroup->next_grp; } m_FirstGroup = INVALID_GROUP_ID; m_LastGroup = INVALID_GROUP_ID; /* :TODO: dump the admin cache */ /* Reset the memory table */ m_pMemory->Reset(); }