diff options
author | Adam <Adam@anope.org> | 2011-08-01 22:37:27 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2011-08-01 22:37:27 -0400 |
commit | f7adc0b35b50f06706872a161f1c7476e6e6981e (patch) | |
tree | 91fbe281f2772136a327fd4fc4c64740d1ab65ab /src | |
parent | 710c02f3bd3581b7c5b3d48e7604756975219fc8 (diff) |
Rewrote the access systems and added a flags access system
Diffstat (limited to 'src')
-rw-r--r-- | src/access.cpp | 140 | ||||
-rw-r--r-- | src/botserv.cpp | 14 | ||||
-rw-r--r-- | src/channels.cpp | 38 | ||||
-rw-r--r-- | src/chanserv.cpp | 189 | ||||
-rw-r--r-- | src/config.cpp | 2 | ||||
-rw-r--r-- | src/regchannel.cpp | 195 |
6 files changed, 223 insertions, 355 deletions
diff --git a/src/access.cpp b/src/access.cpp new file mode 100644 index 000000000..5fba02c98 --- /dev/null +++ b/src/access.cpp @@ -0,0 +1,140 @@ +/* + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "services.h" +#include "modules.h" +#include "access.h" + +AccessProvider::AccessProvider(Module *o, const Anope::string &n) : Service(o, n) +{ +} + +AccessProvider::~AccessProvider() +{ +} + +ChanAccess::ChanAccess(AccessProvider *p) : provider(p) +{ +} + +ChanAccess::~ChanAccess() +{ +} + +bool ChanAccess::operator>(ChanAccess &other) +{ + for (size_t i = CA_SIZE; i > 0; --i) + if (this->HasPriv(static_cast<ChannelAccess>(i - 1)) && !other.HasPriv(static_cast<ChannelAccess>(i - 1))) + return true; + return false; +} + +bool ChanAccess::operator<(ChanAccess &other) +{ + for (size_t i = CA_SIZE; i > 0; --i) + if (!this->HasPriv(static_cast<ChannelAccess>(i - 1)) && other.HasPriv(static_cast<ChannelAccess>(i - 1))) + return true; + return false; +} + +bool ChanAccess::operator>=(ChanAccess &other) +{ + for (size_t i = CA_SIZE; i > 0; --i) + { + bool this_p = this->HasPriv(static_cast<ChannelAccess>(i - 1)), + other_p = other.HasPriv(static_cast<ChannelAccess>(i - 1)); + + if ((this_p && !other_p) || (this_p && other_p)) + return true; + } + + return false; +} + +bool ChanAccess::operator<=(ChanAccess &other) +{ + for (size_t i = CA_SIZE; i > 0; --i) + { + bool this_p = this->HasPriv(static_cast<ChannelAccess>(i - 1)), + other_p = other.HasPriv(static_cast<ChannelAccess>(i - 1)); + + if ((!this_p && other_p) || (this_p && other_p)) + return true; + } + + return false; +} + +AccessGroup::AccessGroup() : std::vector<ChanAccess *>() +{ +} + +bool AccessGroup::HasPriv(ChannelAccess priv) const +{ + for (unsigned i = this->size(); i > 0; --i) + if (this->at(i - 1)->HasPriv(priv)) + return true; + return false; +} + +ChanAccess *AccessGroup::Highest() const +{ + for (size_t i = CA_SIZE; i > 0; --i) + for (unsigned j = this->size(); j > 0; --j) + if (this->at(j - 1)->HasPriv(static_cast<ChannelAccess>(i - 1))) + return this->at(j - 1); + return NULL; +} + +bool AccessGroup::operator>(const AccessGroup &other) const +{ + for (size_t i = CA_SIZE; i > 0; --i) + if (this->HasPriv(static_cast<ChannelAccess>(i - 1)) && !other.HasPriv(static_cast<ChannelAccess>(i - 1))) + return true; + return true; +} + +bool AccessGroup::operator<(const AccessGroup &other) const +{ + for (size_t i = CA_SIZE; i > 0; --i) + if (!this->HasPriv(static_cast<ChannelAccess>(i - 1)) && other.HasPriv(static_cast<ChannelAccess>(i - 1))) + return true; + return false; +} + +bool AccessGroup::operator>=(const AccessGroup &other) const +{ + for (size_t i = CA_SIZE; i > 0; --i) + { + bool this_p = this->HasPriv(static_cast<ChannelAccess>(i - 1)), + other_p = other.HasPriv(static_cast<ChannelAccess>(i - 1)); + + if ((this_p && !other_p) || (this_p && other_p)) + return true; + } + + return false; +} + +bool AccessGroup::operator<=(const AccessGroup &other) const +{ + for (size_t i = CA_SIZE; i > 0; --i) + { + bool this_p = this->HasPriv(static_cast<ChannelAccess>(i - 1)), + other_p = other.HasPriv(static_cast<ChannelAccess>(i - 1)); + + if ((!this_p && other_p) || (this_p && other_p)) + return true; + } + + return false; +} + diff --git a/src/botserv.cpp b/src/botserv.cpp index 9d7c38817..1670283be 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -55,9 +55,8 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, User *u, const Anope::string return; } - ChanAccess *u_access = ci->GetAccess(u), *req_access = ci->GetAccess(requester); - int16 u_level = u_access ? u_access->level : 0, req_level = req_access ? req_access->level : 0; - if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(u->nick) && u_level >= req_level) + AccessGroup u_access = ci->AccessFor(u), req_access = ci->AccessFor(requester); + if (ci->HasFlag(CI_PEACE) && u != requester && u_access >= req_access) return; if (matches_list(ci->c, u, CMODE_EXCEPT)) @@ -72,7 +71,7 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, User *u, const Anope::string ci->c->SetMode(NULL, CMODE_BAN, mask); /* Check if we need to do a signkick or not -GD */ - if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(requester, ci, CA_SIGNKICK))) + if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !req_access.HasPriv(CA_SIGNKICK))) ci->c->Kick(ci->bi, u, "%s (%s)", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str(), requester->nick.c_str()); else ci->c->Kick(ci->bi, u, "%s", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str()); @@ -97,12 +96,11 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, User *u, const Anope::string return; } - ChanAccess *u_access = ci->GetAccess(u), *req_access = ci->GetAccess(requester); - int16 u_level = u_access ? u_access->level : 0, req_level = req_access ? req_access->level : 0; - if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(u->nick) && u_level >= req_level) + AccessGroup u_access = ci->AccessFor(u), req_access = ci->AccessFor(requester); + if (ci->HasFlag(CI_PEACE) && requester != u && u_access >= req_access) return; - if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(requester, ci, CA_SIGNKICK))) + if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !req_access.HasPriv(CA_SIGNKICK))) ci->c->Kick(ci->bi, u, "%s (%s)", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str(), requester->nick.c_str()); else ci->c->Kick(ci->bi, u, "%s", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str()); diff --git a/src/channels.cpp b/src/channels.cpp index fe97c5b46..17ed8a629 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -1071,47 +1071,51 @@ void do_cmode(const Anope::string &source, const Anope::string &channel, const A **/ void chan_set_correct_modes(User *user, Channel *c, int give_modes) { - ChannelInfo *ci; - ChannelMode *owner, *admin, *op, *halfop, *voice; + ChannelMode *owner = ModeManager::FindChannelModeByName(CMODE_OWNER), + *admin = ModeManager::FindChannelModeByName(CMODE_PROTECT), + *op = ModeManager::FindChannelModeByName(CMODE_OP), + *halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP), + *voice = ModeManager::FindChannelModeByName(CMODE_VOICE); - owner = ModeManager::FindChannelModeByName(CMODE_OWNER); - admin = ModeManager::FindChannelModeByName(CMODE_PROTECT); - op = ModeManager::FindChannelModeByName(CMODE_OP); - halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP); - voice = ModeManager::FindChannelModeByName(CMODE_VOICE); + if (user == NULL || c == NULL) + return; + + ChannelInfo *ci = c->ci; - if (!c || !(ci = c->ci)) + if (ci == NULL) return; Log(LOG_DEBUG) << "Setting correct user modes for " << user->nick << " on " << c->name << " (" << (give_modes ? "" : "not ") << "giving modes)"; + AccessGroup u_access = ci->AccessFor(user); + if (give_modes && (!user->Account() || user->Account()->HasFlag(NI_AUTOOP))) { - if (owner && check_access(user, ci, CA_AUTOOWNER)) + if (owner && u_access.HasPriv(CA_AUTOOWNER)) c->SetMode(NULL, CMODE_OWNER, user->nick); - else if (admin && check_access(user, ci, CA_AUTOPROTECT)) + else if (admin && u_access.HasPriv(CA_AUTOPROTECT)) c->SetMode(NULL, CMODE_PROTECT, user->nick); - if (op && check_access(user, ci, CA_AUTOOP)) + if (op && u_access.HasPriv(CA_AUTOOP)) c->SetMode(NULL, CMODE_OP, user->nick); - else if (halfop && check_access(user, ci, CA_AUTOHALFOP)) + else if (halfop && u_access.HasPriv(CA_AUTOHALFOP)) c->SetMode(NULL, CMODE_HALFOP, user->nick); - else if (voice && check_access(user, ci, CA_AUTOVOICE)) + else if (voice && u_access.HasPriv(CA_AUTOVOICE)) c->SetMode(NULL, CMODE_VOICE, user->nick); } /* If this channel has secureops or the channel is syncing and they are not ulined, check to remove modes */ if ((ci->HasFlag(CI_SECUREOPS) || (c->HasFlag(CH_SYNCING) && user->server->IsSynced())) && !user->server->IsULined()) { - if (owner && c->HasUserStatus(user, CMODE_OWNER) && !check_access(user, ci, CA_FOUNDER)) + if (owner && c->HasUserStatus(user, CMODE_OWNER) && !u_access.HasPriv(CA_AUTOOWNER) && !u_access.HasPriv(CA_PROTECTME)) c->RemoveMode(NULL, CMODE_OWNER, user->nick); - if (admin && c->HasUserStatus(user, CMODE_PROTECT) && !check_access(user, ci, CA_AUTOPROTECT) && !check_access(user, ci, CA_PROTECTME)) + if (admin && c->HasUserStatus(user, CMODE_PROTECT) && !u_access.HasPriv(CA_AUTOPROTECT) && !u_access.HasPriv(CA_PROTECTME)) c->RemoveMode(NULL, CMODE_PROTECT, user->nick); - if (op && c->HasUserStatus(user, CMODE_OP) && !check_access(user, ci, CA_AUTOOP) && !check_access(user, ci, CA_OPDEOPME)) + if (op && c->HasUserStatus(user, CMODE_OP) && !u_access.HasPriv(CA_AUTOOP) && !u_access.HasPriv(CA_OPDEOPME)) c->RemoveMode(NULL, CMODE_OP, user->nick); - if (halfop && c->HasUserStatus(user, CMODE_HALFOP) && !check_access(user, ci, CA_AUTOHALFOP) && !check_access(user, ci, CA_HALFOPME)) + if (halfop && c->HasUserStatus(user, CMODE_HALFOP) && !u_access.HasPriv(CA_AUTOHALFOP) && !u_access.HasPriv(CA_HALFOPME)) c->RemoveMode(NULL, CMODE_HALFOP, user->nick); } diff --git a/src/chanserv.cpp b/src/chanserv.cpp index 6a39340ae..c7bbe11f8 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -16,93 +16,6 @@ registered_channel_map RegisteredChannelList; -static int def_levels[][2] = { - { CA_AUTOOP, 5 }, - { CA_AUTOVOICE, 3 }, - { CA_NOJOIN, -2 }, - { CA_INVITE, 5 }, - { CA_AKICK, 10 }, - { CA_SET, ACCESS_QOP }, - { CA_UNBAN, 5 }, - { CA_OPDEOP, 5 }, - { CA_ACCESS_LIST, 1 }, - { CA_ACCESS_CHANGE, 10 }, - { CA_MEMO, 10 }, - { CA_ASSIGN, ACCESS_FOUNDER }, - { CA_BADWORDS, 10 }, - { CA_NOKICK, 1 }, - { CA_FANTASIA, 3 }, - { CA_SAY, 5 }, - { CA_GREET, 5 }, - { CA_VOICEME, 3 }, - { CA_VOICE, 5 }, - { CA_GETKEY, 5 }, - { CA_AUTOHALFOP, 4 }, - { CA_AUTOPROTECT, 10 }, - { CA_OPDEOPME, 5 }, - { CA_HALFOPME, 4 }, - { CA_HALFOP, 5 }, - { CA_PROTECTME, 10 }, - { CA_PROTECT, ACCESS_QOP }, - { CA_KICKME, 5 }, - { CA_KICK, 5 }, - { CA_SIGNKICK, ACCESS_FOUNDER }, - { CA_BANME, 5 }, - { CA_BAN, 5 }, - { CA_TOPIC, ACCESS_FOUNDER }, - { CA_MODE, ACCESS_FOUNDER }, - { CA_INFO, ACCESS_QOP }, - { CA_AUTOOWNER, ACCESS_QOP }, - { CA_OWNER, ACCESS_FOUNDER }, - { CA_OWNERME, ACCESS_QOP }, - { CA_FOUNDER, ACCESS_QOP }, - { -1 } -}; - -LevelInfo levelinfo[] = { - { CA_AUTOHALFOP, "AUTOHALFOP", _("Automatic mode +h") }, - { CA_AUTOOP, "AUTOOP", _("Automatic channel operator status") }, - { CA_AUTOPROTECT, "AUTOPROTECT", _("Automatic mode +a") }, - { CA_AUTOVOICE, "AUTOVOICE", _("Automatic mode +v") }, - { CA_NOJOIN, "NOJOIN", _("Not allowed to join channel") }, - { CA_SIGNKICK, "SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used") }, - { CA_ACCESS_LIST, "ACC-LIST", _("Allowed to view the access list") }, - { CA_ACCESS_CHANGE, "ACC-CHANGE", _("Allowed to modify the access list") }, - { CA_AKICK, "AKICK", _("Allowed to use AKICK command") }, - { CA_SET, "SET", _("Allowed to use SET command (not FOUNDER/PASSWORD)"), }, - { CA_BAN, "BAN", _("Allowed to use BAN command") }, - { CA_BANME, "BANME", _("Allowed to ban him/herself") }, - { CA_GETKEY, "GETKEY", _("Allowed to use GETKEY command") }, - { CA_HALFOP, "HALFOP", _("Allowed to (de)halfop him/herself") }, - { CA_HALFOPME, "HALFOPME", _("Allowed to (de)halfop him/herself") }, - { CA_INFO, "INFO", _("Allowed to use INFO command with ALL option") }, - { CA_KICK, "KICK", _("Allowed to use KICK command") }, - { CA_KICKME, "KICKME", _("Allowed to kick him/herself") }, - { CA_INVITE, "INVITE", _("Allowed to use INVITE command") }, - { CA_OPDEOP, "OPDEOP", _("Allowed to use OP/DEOP commands") }, - { CA_OPDEOPME, "OPDEOPME", _("Allowed to (de)op him/herself") }, - { CA_PROTECT, "PROTECT", _("Allowed to use PROTECT/DEPROTECT commands") }, - { CA_PROTECTME, "PROTECTME", _("Allowed to (de)protect him/herself"), }, - { CA_TOPIC, "TOPIC", _("Allowed to use TOPIC command") }, - { CA_MODE, "MODE", _("Allowed to use MODE command") }, - { CA_UNBAN, "UNBAN", _("Allowed to use UNBAN command") }, - { CA_VOICE, "VOICE", _("Allowed to use VOICE/DEVOICE commands") }, - { CA_VOICEME, "VOICEME", _("Allowed to (de)voice him/herself") }, - { CA_MEMO, "MEMO", _("Allowed to list/read channel memos") }, - { CA_ASSIGN, "ASSIGN", _("Allowed to assign/unassign a bot") }, - { CA_BADWORDS, "BADWORDS", _("Allowed to use BADWORDS command") }, - { CA_FANTASIA, "FANTASIA", _("Allowed to use fantaisist commands") }, - { CA_GREET, "GREET", _("Greet message displayed") }, - { CA_NOKICK, "NOKICK", _("Never kicked by the bot's kickers") }, - { CA_SAY, "SAY", _("Allowed to use SAY and ACT commands") }, - { CA_AUTOOWNER, "AUTOOWNER", _("Automatic mode +q") }, - { CA_OWNER, "OWNER", _("Allowed to use OWNER command") }, - { CA_OWNERME, "OWNERME", _("Allowed to (de)owner him/herself") }, - { CA_FOUNDER, "FOUNDER", _("Allowed to issue commands restricted to channel founders") }, - { -1 } -}; -int levelinfo_maxwidth = 0; - /*************************************************************************/ /* Check the current modes on a channel; if they conflict with a mode lock, @@ -201,72 +114,6 @@ ChannelInfo *cs_findchan(const Anope::string &chan) /*************************************************************************/ -/* Return 1 if the user's access level on the given channel falls into the - * given category, 0 otherwise. Note that this may seem slightly confusing - * in some cases: for example, check_access(..., CA_NOJOIN) returns true if - * the user does _not_ have access to the channel (i.e. matches the NOJOIN - * criterion). */ - -int check_access(User *user, ChannelInfo *ci, int what) -{ - int level, limit; - - if (!user || !ci) - return 0; - - ChanAccess *u_access = ci->GetAccess(user); - level = u_access ? u_access->level : 0; - limit = ci->levels[what]; - - // Set should never be disabled, if it is it is db-converter screwup - // This all needs rewritten anyway... - if (what == CA_SET && limit == ACCESS_INVALID) - { - ci->levels[what] = ACCESS_FOUNDER; - limit = ACCESS_FOUNDER; - } - - /* Resetting the last used time */ - if (level > 0) - ci->last_used = Anope::CurTime; - - /* Superadmin always wins. Always. */ - if (user->isSuperAdmin) - return what == CA_NOJOIN ? 0 : 1; - /* If the access of the level we are checking is disabled, they *always* get denied */ - if (limit == ACCESS_INVALID) - return 0; - /* If the level of the user is >= the level for "founder" of this channel and "founder" isn't disabled, they can do anything */ - if (ci->levels[CA_FOUNDER] != ACCESS_INVALID && level >= ci->levels[CA_FOUNDER]) - return what == CA_NOJOIN ? 0 : 1; - - if (what == CA_NOJOIN) - return level <= ci->levels[what]; - else - return level >= ci->levels[what]; -} - -/* Reset channel access level values to their default state. */ - -void reset_levels(ChannelInfo *ci) -{ - int i; - - if (!ci) - { - Log() << "reset_levels() called with NULL values"; - return; - } - - if (ci->levels) - delete [] ci->levels; - ci->levels = new int16[CA_SIZE]; - for (i = 0; def_levels[i][0] >= 0; ++i) - ci->levels[def_levels[i][0]] = def_levels[i][1]; -} - -/*************************************************************************/ - /** Is the user the real founder? * @param user The user * @param ci The channel @@ -290,14 +137,12 @@ bool IsFounder(User *user, ChannelInfo *ci) void update_cs_lastseen(User *user, ChannelInfo *ci) { - ChanAccess *access; - - if (!ci || !user || !user->Account()) + if (!ci || !user) return; - - if (IsFounder(user, ci) || user->IsIdentified() || (user->IsRecognized() && !ci->HasFlag(CI_SECURE))) - if ((access = ci->GetAccess(user))) - access->last_seen = Anope::CurTime; + + AccessGroup u_access = ci->AccessFor(user); + for (unsigned i = u_access.size(); i > 0; --i) + u_access[i - 1]->last_seen = Anope::CurTime; } /*************************************************************************/ @@ -339,30 +184,6 @@ int get_idealban(ChannelInfo *ci, User *u, Anope::string &ret) } } -/*************************************************************************/ - -Anope::string get_xop_level(int level) -{ - ChannelMode *halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP); - - if (level < ACCESS_VOP) - return "Err"; - else if (halfop && level < ACCESS_HOP) - return "VOP"; - else if (!halfop && level < ACCESS_AOP) - return "VOP"; - else if (halfop && level < ACCESS_AOP) - return "HOP"; - else if (level < ACCESS_SOP) - return "AOP"; - else if (level < ACCESS_QOP) - return "SOP"; - else if (level < ACCESS_FOUNDER) - return "QOP"; - else - return "Founder"; -} - ChanServTimer::ChanServTimer(Channel *chan) : Timer(Config->CSInhabit), c(chan) { BotInfo *bi = findbot(Config->ChanServ); diff --git a/src/config.cpp b/src/config.cpp index 5938d3f67..4790cd34d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -110,8 +110,6 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C this->CSDefFlags.SetFlag(CI_SIGNKICK_LEVEL); else if (option.equals_ci("opnotice")) this->CSDefFlags.SetFlag(CI_OPNOTICE); - else if (option.equals_ci("xop")) - this->CSDefFlags.SetFlag(CI_XOP); else if (option.equals_ci("peace")) this->CSDefFlags.SetFlag(CI_PEACE); else if (option.equals_ci("persist")) diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 65613097b..1220669e0 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -12,25 +12,6 @@ #include "services.h" #include "modules.h" -ChanAccess::ChanAccess(const Anope::string &umask) -{ - NickAlias *na = findnick(umask); - if (na != NULL) - this->nc = na->nc; - else - { - this->nc = NULL; - this->mask = umask; - } -} - -const Anope::string &ChanAccess::GetMask() -{ - if (this->nc != NULL) - return this->nc->display; - return this->mask; -} - /** Default constructor * @param chname The channel name */ @@ -41,7 +22,6 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) : Flags<ChannelInfoFlag, C this->founder = this->successor = NULL; this->last_topic_time = 0; - this->levels = NULL; this->c = findchan(chname); if (this->c) this->c->ci = this; @@ -69,12 +49,12 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) : Flags<ChannelInfoFlag, C this->memos.memomax = Config->MSMaxMemos; this->last_used = this->time_registered = Anope::CurTime; - this->ttb = new int16[TTB_SIZE]; + for (int i = 0; i < CA_SIZE; ++i) + this->levels[i] = 0; + for (int i = 0; i < TTB_SIZE; ++i) this->ttb[i] = 0; - reset_levels(this); - RegisteredChannelList[this->name] = this; } @@ -95,19 +75,11 @@ ChannelInfo::ChannelInfo(ChannelInfo *ci) : Flags<ChannelInfoFlag, CI_END>(Chann if (this->bi) ++this->bi->chancount; - this->ttb = new int16[TTB_SIZE]; for (int i = 0; i < TTB_SIZE; ++i) this->ttb[i] = ci->ttb[i]; + + // XXX access - this->levels = new int16[CA_SIZE]; - for (int i = 0; i < CA_SIZE; ++i) - this->levels[i] = ci->levels[i]; - - for (unsigned i = 0; i < ci->GetAccessCount(); ++i) - { - ChanAccess *taccess = ci->GetAccess(i); - this->AddAccess(taccess->GetMask(), taccess->level, taccess->creator, taccess->last_seen); - } for (unsigned i = 0; i < ci->GetAkickCount(); ++i) { AutoKick *takick = ci->GetAkick(i); @@ -145,8 +117,6 @@ ChannelInfo::~ChannelInfo() this->ClearAccess(); this->ClearAkick(); this->ClearBadWords(); - if (this->levels) - delete [] this->levels; if (!this->memos.memos.empty()) { @@ -155,9 +125,6 @@ ChannelInfo::~ChannelInfo() this->memos.memos.clear(); } - if (this->ttb) - delete [] this->ttb; - if (this->founder) --this->founder->channelcount; } @@ -200,29 +167,11 @@ BotInfo *ChannelInfo::WhoSends() } /** Add an entry to the channel access list - * - * @param mask The mask of the access entry - * @param level The channel access level the user has on the channel - * @param creator The user who added the access - * @param last_seen When the user was last seen within the channel - * @return The new access class - * - * Creates a new access list entry and inserts it into the access list. + * @param access The entry */ - -ChanAccess *ChannelInfo::AddAccess(const Anope::string &mask, int16 level, const Anope::string &creator, int32 last_seen) +void ChannelInfo::AddAccess(ChanAccess *access) { - ChanAccess *new_access = new ChanAccess(mask); - new_access->level = level; - new_access->last_seen = last_seen; - if (!creator.empty()) - new_access->creator = creator; - else - new_access->creator = "Unknown"; - - this->access.push_back(new_access); - - return new_access; + this->access.push_back(access); } /** Get an entry from the channel access list by index @@ -240,104 +189,68 @@ ChanAccess *ChannelInfo::GetAccess(unsigned index) return this->access[index]; } -/** Get an entry from the channel access list by NickCore +/** Check if a user has a privilege on a channel * * @param u The User to find within the access list vector - * @param level Optional channel access level to compare the access entries to - * @return A ChanAccess struct corresponding to the NickCore, or NULL if not found + * @param priv The privilege to check for. + * @return true if the user has the privilege * - * Retrieves an entry from the access list that matches the given NickCore, optionally also matching a certain level. + * Retrieves an entry from the access list that matches the given User and NickCore. */ - -ChanAccess *ChannelInfo::GetAccess(User *u, int16 level) +bool ChannelInfo::HasPriv(User *u, ChannelAccess priv) { - if (!u) - return NULL; + AccessGroup group = this->AccessFor(u); - if (u->isSuperAdmin || IsFounder(u, this)) + if (this->founder && u->Account() == this->founder) { - static ChanAccess dummy_access(""); - new(&dummy_access) ChanAccess(u->nick + "!*@*"); - dummy_access.level = u->isSuperAdmin ? ACCESS_SUPERADMIN : ACCESS_FOUNDER; - dummy_access.last_seen = Anope::CurTime; - return &dummy_access; + switch (priv) + { + case CA_AUTOOWNER: + case CA_AUTOPROTECT: + case CA_AUTOOP: + case CA_AUTOHALFOP: + case CA_AUTOVOICE: + break; + default: + return true; + } } - - if (this->access.empty()) - return NULL; - - ChanAccess *highest = NULL; - for (unsigned i = 0, end = this->access.size(); i < end; ++i) - { - ChanAccess *taccess = this->access[i]; - if (level && level != taccess->level) - continue; - /* Access entry is a mask and we match it */ - else if (!taccess->nc && (Anope::Match(u->nick, taccess->GetMask()) || Anope::Match(u->GetDisplayedMask(), taccess->GetMask()))) - ; - /* Access entry is a nick core and we are identified for that account */ - else if (taccess->nc && (u->IsIdentified() || (u->IsRecognized() && !this->HasFlag(CI_SECURE))) && u->Account() == taccess->nc) - ; - else - continue; - /* Use the highest level access available */ - if (!highest || taccess->level > highest->level) - highest = taccess; - } + if (group.HasPriv(CA_FOUNDER) || group.HasPriv(priv)) + return true; - return highest; + return false; } -/** Get an entry from the channel access list by NickCore - * - * @param u The NickCore to find within the access list vector - * @param level Optional channel access level to compare the access entries to - * @return A ChanAccess struct corresponding to the NickCore, or NULL if not found - * - * Retrieves an entry from the access list that matches the given NickCore, optionally also matching a certain level. - */ -ChanAccess *ChannelInfo::GetAccess(NickCore *nc, int16 level) +AccessGroup ChannelInfo::AccessFor(User *u) { - if (nc == this->founder) + NickCore *nc = u->Account(); + if (nc == NULL && u->IsRecognized()) { - static ChanAccess dummy_access(""); - new(&dummy_access) ChanAccess(nc->display); - dummy_access.level = ACCESS_FOUNDER; - dummy_access.last_seen = Anope::CurTime; - return &dummy_access; + NickAlias *na = findnick(u->nick); + if (na != NULL) + nc = na->nc; } + + AccessGroup group; + for (unsigned i = 0, end = this->access.size(); i < end; ++i) - { - if (level && this->access[i]->level != level) - continue; - if (this->access[i]->nc && this->access[i]->nc == nc) - return this->access[i]; - } - return NULL; + if (this->access[i]->Matches(u, nc)) + group.push_back(this->access[i]); + + return group; } -/** Get an entry from the channel access list by mask - * - * @param u The mask to find within the access list vector - * @param level Optional channel access level to compare the access entries to - * @param wildcard True to match using wildcards - * @return A ChanAccess struct corresponding to the mask, or NULL if not found - * - * Retrieves an entry from the access list that matches the given mask, optionally also matching a certain level. - */ -ChanAccess *ChannelInfo::GetAccess(const Anope::string &mask, int16 level, bool wildcard) +AccessGroup ChannelInfo::AccessFor(NickCore *nc) { + AccessGroup group; + for (unsigned i = 0, end = this->access.size(); i < end; ++i) - if (this->access[i]->nc != NULL) - { - if (wildcard ? Anope::Match(this->access[i]->nc->display, mask) : this->access[i]->nc->display.equals_ci(mask)) - return this->access[i]; - } - else if (wildcard ? Anope::Match(this->access[i]->GetMask(), mask) : this->access[i]->GetMask().equals_ci(mask)) - return this->access[i]; - return NULL; + if (this->access[i]->Matches(NULL, nc)) + group.push_back(this->access[i]); + + return group; } /** Get the size of the accss vector for this channel @@ -345,7 +258,7 @@ ChanAccess *ChannelInfo::GetAccess(const Anope::string &mask, int16 level, bool */ unsigned ChannelInfo::GetAccessCount() const { - return this->access.empty() ? 0 : this->access.size(); + return this->access.size(); } /** Erase an entry from the channel access list @@ -375,6 +288,7 @@ void ChannelInfo::EraseAccess(ChanAccess *taccess) { if (this->access[i] == taccess) { + delete this->access[i]; this->access.erase(this->access.begin() + i); break; } @@ -838,13 +752,6 @@ bool ChannelInfo::CheckKick(User *user) } } - if (!do_kick && check_access(user, this, CA_NOJOIN)) - { - get_idealban(this, user, mask); - reason = translate(user, CHAN_NOT_ALLOWED_TO_JOIN); - do_kick = true; - } - if (!do_kick) return false; |