diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/botserv.cpp | 18 | ||||
-rw-r--r-- | src/channels.cpp | 6 | ||||
-rw-r--r-- | src/chanserv.cpp | 80 | ||||
-rw-r--r-- | src/language.cpp | 50 | ||||
-rw-r--r-- | src/regchannel.cpp | 124 |
5 files changed, 157 insertions, 121 deletions
diff --git a/src/botserv.cpp b/src/botserv.cpp index 1e7eb9551..32b6a42a3 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -511,7 +511,7 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co Anope::string mask; User *u = finduser(nick); - if (!u) + if (!u || !ci) return; if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && requester != u) @@ -520,7 +520,9 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co return; } - if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && get_access(u, ci) >= get_access(requester, ci)) + 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(nick) && u_level >= req_level) return; if (ModeManager::FindChannelModeByName(CMODE_EXCEPT) && is_excepted(ci, u) == 1) @@ -548,7 +550,7 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, c { User *u = finduser(nick); - if (!u || !ci->c->FindUser(u)) + if (!u || !ci || !ci->c || !ci->c->FindUser(u)) return; if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && requester != u) @@ -557,7 +559,9 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, c return; } - if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && get_access(u, ci) >= get_access(requester, ci)) + 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(nick) && u_level >= req_level) return; if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(requester, ci, CA_SIGNKICK))) @@ -577,7 +581,7 @@ void bot_raw_mode(User *requester, ChannelInfo *ci, const Anope::string &mode, c u = finduser(nick); - if (!u || !ci->c->FindUser(u)) + if (!u || !ci || !ci->c || !ci->c->FindUser(u)) return; snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(Anope::CurTime)); @@ -588,7 +592,9 @@ void bot_raw_mode(User *requester, ChannelInfo *ci, const Anope::string &mode, c return; } - if (mode[0] == '-' && ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && get_access(u, ci) >= get_access(requester, ci)) + 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 (mode[0] == '-' && ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && u_level >= req_level) return; ci->c->SetModes(NULL, "%s %s", mode.c_str(), nick.c_str()); diff --git a/src/channels.cpp b/src/channels.cpp index 85752a774..f146c17dd 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -459,7 +459,7 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo /* Enforce secureops, etc */ if (EnforceMLock) - chan_set_correct_modes(u, this, 1); + chan_set_correct_modes(u, this, 0); return; } @@ -1207,9 +1207,9 @@ void chan_set_correct_modes(User *user, Channel *c, int give_modes) { if ((ml.set && !c->HasUserStatus(user, ml.name)) || (!ml.set && c->HasUserStatus(user, ml.name))) { - if (ml.set && give_modes) + if (ml.set) c->SetMode(NULL, cm, user->nick, false); - else if (!ml.set && !give_modes) + else if (!ml.set) c->RemoveMode(NULL, cm, user->nick, false); } } diff --git a/src/chanserv.cpp b/src/chanserv.cpp index a2307a082..e3a8993b0 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -401,19 +401,15 @@ void expire_chans() /*************************************************************************/ // XXX this is slightly inefficient -void cs_remove_nick(const NickCore *nc) +void cs_remove_nick(NickCore *nc) { for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it) { ChannelInfo *ci = it->second; - for (unsigned j = ci->GetAccessCount(); j > 0; --j) - { - ChanAccess *ca = ci->GetAccess(j - 1); - - if (ca->nc == nc) - ci->EraseAccess(j - 1); - } + ChanAccess *access = ci->GetAccess(nc); + if (access) + ci->EraseAccess(access); for (unsigned j = ci->GetAkickCount(); j > 0; --j) { @@ -497,7 +493,8 @@ int check_access(User *user, ChannelInfo *ci, int what) if (!user || !ci) return 0; - level = get_access(user, ci); + ChanAccess *u_access = ci->GetAccess(user); + level = u_access ? u_access->level : 0; limit = ci->levels[what]; /* Resetting the last used time */ @@ -564,45 +561,6 @@ bool IsFounder(User *user, ChannelInfo *ci) return false; } -/** Return the access level for the user on the channel. - * If the channel doesn't exist, the user isn't on the access list, or the - * channel is CI_SECURE and the user isn't identified, return 0 - * @param user The user - * @param ci The cahnnel - * @return The level, or 0 - */ -int get_access(User *user, ChannelInfo *ci) -{ - ChanAccess *access = NULL; - - if (!ci || !user) - return 0; - - /* SuperAdmin always has highest level */ - if (user->isSuperAdmin) - return ACCESS_SUPERADMIN; - - if (IsFounder(user, ci)) - return ACCESS_FOUNDER; - - if (user->IsIdentified()) - { - access = ci->GetAccess(user->Account()); - if (access) - return access->level; - } - else - { - NickAlias *na = findnick(user->nick); - if (na) - access = ci->GetAccess(na->nc); - if (access && user->IsRecognized() && !ci->HasFlag(CI_SECURE)) - return access->level; - } - - return 0; -} - /*************************************************************************/ void update_cs_lastseen(User *user, ChannelInfo *ci) @@ -613,7 +571,7 @@ void update_cs_lastseen(User *user, ChannelInfo *ci) return; if (IsFounder(user, ci) || user->IsIdentified() || (user->IsRecognized() && !ci->HasFlag(CI_SECURE))) - if ((access = ci->GetAccess(user->Account()))) + if ((access = ci->GetAccess(user))) access->last_seen = Anope::CurTime; } @@ -658,30 +616,6 @@ int get_idealban(ChannelInfo *ci, User *u, Anope::string &ret) /*************************************************************************/ -int get_access_level(ChannelInfo *ci, NickCore *nc) -{ - if (!ci || !nc) - return 0; - - if (nc == ci->founder) - return ACCESS_FOUNDER; - - ChanAccess *access = ci->GetAccess(nc); - - if (!access) - return 0; - else - return access->level; -} - -int get_access_level(ChannelInfo *ci, NickAlias *na) -{ - if (!na) - return 0; - - return get_access_level(ci, na->nc); -} - Anope::string get_xop_level(int level) { ChannelMode *halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP); diff --git a/src/language.cpp b/src/language.cpp index 649398cb3..3372bc9ff 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -958,8 +958,6 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("QOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"), /* CHAN_QOP_DISABLED */ _("Sorry, channel QOP list modification is temporarily disabled."), - /* CHAN_QOP_NICKS_ONLY */ - _("Channel QOP lists may only contain registered nicknames."), /* CHAN_QOP_ADDED */ _("%s added to %s QOP list."), /* CHAN_QOP_MOVED */ @@ -987,8 +985,6 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("AOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"), /* CHAN_AOP_DISABLED */ _("Sorry, channel AOP list modification is temporarily disabled."), - /* CHAN_AOP_NICKS_ONLY */ - _("Channel AOP lists may only contain registered nicknames."), /* CHAN_AOP_ADDED */ _("%s added to %s AOP list."), /* CHAN_AOP_MOVED */ @@ -1016,8 +1012,6 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("HOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"), /* CHAN_HOP_DISABLED */ _("Sorry, channel HOP list modification is temporarily disabled."), - /* CHAN_HOP_NICKS_ONLY */ - _("Channel HOP lists may only contain registered nicknames."), /* CHAN_HOP_ADDED */ _("%s added to %s HOP list."), /* CHAN_HOP_MOVED */ @@ -1045,8 +1039,6 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("SOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"), /* CHAN_SOP_DISABLED */ _("Sorry, channel SOP list modification is temporarily disabled."), - /* CHAN_SOP_NICKS_ONLY */ - _("Channel SOP lists may only contain registered nicknames."), /* CHAN_SOP_ADDED */ _("%s added to %s SOP list."), /* CHAN_SOP_MOVED */ @@ -1074,8 +1066,6 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("VOP channel {ADD|DEL|LIST|CLEAR} [nick | entry-list]"), /* CHAN_VOP_DISABLED */ _("Sorry, channel VOP list modification is temporarily disabled."), - /* CHAN_VOP_NICKS_ONLY */ - _("Channel VOP lists may only contain registered nicknames."), /* CHAN_VOP_ADDED */ _("%s added to %s VOP list."), /* CHAN_VOP_MOVED */ @@ -1100,7 +1090,7 @@ const char *const language_strings[LANG_STRING_COUNT] = { /* CHAN_VOP_CLEAR */ _("Channel %s VOP list has been cleared."), /* CHAN_ACCESS_SYNTAX */ - _("ACCESS channel {ADD|DEL|LIST|VIEW|CLEAR} [nick [level] | entry-list]"), + _("ACCESS channel {ADD|DEL|LIST|VIEW|CLEAR} [mask [level] | entry-list]"), /* CHAN_ACCESS_XOP */ _("You can't use this command. \n" "Use the AOP, SOP and VOP commands instead.\n" @@ -1115,8 +1105,6 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("Access level must be non-zero."), /* CHAN_ACCESS_LEVEL_RANGE */ _("Access level must be between %d and %d inclusive."), - /* CHAN_ACCESS_NICKS_ONLY */ - _("Channel access lists may only contain registered nicknames."), /* CHAN_ACCESS_REACHED_LIMIT */ _("Sorry, you can only have %d access entries on a channel."), /* CHAN_ACCESS_LEVEL_UNCHANGED */ @@ -1139,7 +1127,7 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("%s access list is empty."), /* CHAN_ACCESS_LIST_HEADER */ _("Access list for %s:\n" - " Num Lev Nick"), + " Num Lev Mask"), /* CHAN_ACCESS_LIST_FOOTER */ _("End of access list."), /* CHAN_ACCESS_LIST_XOP_FORMAT */ @@ -3625,8 +3613,8 @@ const char *const language_strings[LANG_STRING_COUNT] = { "channel whenever the OP or DEOP commands are used for a user\n" "in the channel."), /* CHAN_HELP_QOP */ - _("Syntax: QOP channel ADD nick\n" - " QOP channel DEL {nick | entry-num | list}\n" + _("Syntax: QOP channel ADD mask\n" + " QOP channel DEL {mask | entry-num | list}\n" " QOP channel LIST [mask | list]\n" " QOP channel CLEAR\n" " \n" @@ -3662,8 +3650,8 @@ const char *const language_strings[LANG_STRING_COUNT] = { "and %R%S HELP SET XOP to know how to toggle between \n" "the access list and xOP list systems."), /* CHAN_HELP_AOP */ - _("Syntax: AOP channel ADD nick\n" - " AOP channel DEL {nick | entry-num | list}\n" + _("Syntax: AOP channel ADD mask\n" + " AOP channel DEL {mask | entry-num | list}\n" " AOP channel LIST [mask | list]\n" " AOP channel CLEAR\n" " \n" @@ -3701,8 +3689,8 @@ const char *const language_strings[LANG_STRING_COUNT] = { "and %R%S HELP SET XOP to know how to toggle between \n" "the access list and xOP list systems."), /* CHAN_HELP_HOP */ - _("Syntax: HOP channel ADD nick\n" - " HOP channel DEL {nick | entry-num | list}\n" + _("Syntax: HOP channel ADD mask\n" + " HOP channel DEL {mask | entry-num | list}\n" " HOP channel LIST [mask | list]\n" " HOP channel CLEAR\n" " \n" @@ -3738,8 +3726,8 @@ const char *const language_strings[LANG_STRING_COUNT] = { "and %R%S HELP SET XOP to know how to toggle between \n" "the access list and xOP list systems."), /* CHAN_HELP_SOP */ - _("Syntax: SOP channel ADD nick\n" - " SOP channel DEL {nick | entry-num | list}\n" + _("Syntax: SOP channel ADD mask\n" + " SOP channel DEL {mask | entry-num | list}\n" " SOP channel LIST [mask | list]\n" " SOP channel CLEAR\n" " \n" @@ -3776,8 +3764,8 @@ const char *const language_strings[LANG_STRING_COUNT] = { "and %R%S HELP SET XOP to know how to toggle between \n" "the access list and xOP list systems."), /* CHAN_HELP_VOP */ - _("Syntax: VOP channel ADD nick\n" - " VOP channel DEL {nick | entry-num | list}\n" + _("Syntax: VOP channel ADD mask\n" + " VOP channel DEL {mask | entry-num | list}\n" " VOP channel LIST [mask | list]\n" " VOP channel CLEAR\n" " \n" @@ -3813,8 +3801,8 @@ const char *const language_strings[LANG_STRING_COUNT] = { "and %R%S HELP SET XOP to know how to toggle between \n" "the access list and xOP list systems."), /* CHAN_HELP_ACCESS */ - _("Syntax: ACCESS channel ADD nick level\n" - " ACCESS channel DEL {nick | entry-num | list}\n" + _("Syntax: ACCESS channel ADD mask level\n" + " ACCESS channel DEL {mask | entry-num | list}\n" " ACCESS channel LIST [mask | list]\n" " ACCESS channel VIEW [mask | list]\n" " ACCESS channel CLEAR\n" @@ -3827,14 +3815,16 @@ const char *const language_strings[LANG_STRING_COUNT] = { "specific information. Any nick not on the access list has\n" "a user level of 0.\n" " \n" - "The ACCESS ADD command adds the given nickname to the\n" - "access list with the given user level; if the nick is\n" + "The ACCESS ADD command adds the given mask to the\n" + "access list with the given user level; if the mask is\n" "already present on the list, its access level is changed to\n" "the level specified in the command. The level specified\n" "must be less than that of the user giving the command, and\n" - "if the nick is already on the access list, the current\n" + "if the mask is already on the access list, the current\n" "access level of that nick must be less than the access level\n" - "of the user giving the command.\n" + "of the user giving the command. When a user joins the channel\n" + "the access they receive is from the highest level entry in the\n" + "access list.\n" " \n" "The ACCESS DEL command removes the given nick from the\n" "access list. If a list of entry numbers is given, those\n" diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 8228e4ffb..d5afbfbcf 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -12,6 +12,9 @@ #include "services.h" #include "modules.h" +// Awesome channel access hack for superadmin and founder +static ChanAccess dummy_access; + /** Default constructor * @param chname The channel name */ @@ -87,7 +90,7 @@ ChannelInfo::ChannelInfo(ChannelInfo *ci) for (unsigned i = 0; i < ci->GetAccessCount(); ++i) { ChanAccess *access = ci->GetAccess(i); - this->AddAccess(access->nc, access->level, access->creator, access->last_seen); + this->AddAccess(access->mask, access->level, access->creator, access->last_seen); } for (unsigned i = 0; i < ci->GetAkickCount(); ++i) { @@ -145,18 +148,20 @@ ChannelInfo::~ChannelInfo() /** Add an entry to the channel access list * - * @param nc The NickCore of the user that the access entry should be tied to + * @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. */ -void ChannelInfo::AddAccess(NickCore *nc, int16 level, const Anope::string &creator, int32 last_seen) +ChanAccess *ChannelInfo::AddAccess(const Anope::string &mask, int16 level, const Anope::string &creator, int32 last_seen) { ChanAccess *new_access = new ChanAccess(); - new_access->nc = nc; + new_access->mask = mask; + new_access->nc = findcore(mask); new_access->level = level; new_access->last_seen = last_seen; if (!creator.empty()) @@ -165,6 +170,8 @@ void ChannelInfo::AddAccess(NickCore *nc, int16 level, const Anope::string &crea new_access->creator = "Unknown"; this->access.push_back(new_access); + + return new_access; } /** Get an entry from the channel access list by index @@ -184,22 +191,102 @@ ChanAccess *ChannelInfo::GetAccess(unsigned index) /** Get an entry from the channel access list by NickCore * - * @param nc The NickCore to find within the access list vector + * @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 * * Retrieves an entry from the access list that matches the given NickCore, optionally also matching a certain level. */ -ChanAccess *ChannelInfo::GetAccess(const NickCore *nc, int16 level) +ChanAccess *ChannelInfo::GetAccess(User *u, int16 level) { + if (!u) + return NULL; + + if (u->isSuperAdmin || IsFounder(u, this)) + { + dummy_access.level = u->isSuperAdmin ? ACCESS_SUPERADMIN : ACCESS_FOUNDER; + dummy_access.mask = u->nick + "!*@*"; + dummy_access.nc = NULL; + dummy_access.last_seen = Anope::CurTime; + return &dummy_access; + } + if (this->access.empty()) return NULL; + + NickAlias *na = NULL; + if (!u->IsIdentified()) + na = findnick(u->nick); + + ChanAccess *highest = NULL; + for (unsigned i = 0, end = this->access.size(); i < end; ++i) + { + ChanAccess *access = this->access[i]; + + if (level && level != access->level) + continue; + /* Access entry is a mask and we match it */ + if (!access->nc && (Anope::Match(u->nick, access->mask) || Anope::Match(u->GetDisplayedMask(), access->mask))) + ; + /* Access entry is a nick core and we are identified for that account */ + else if (access->nc && u->IsIdentified() && u->Account() == access->nc) + ; + /* User is not identified but on a registered nick, and is recognized, and is on an insecure channel */ + else if (na && u->IsRecognized() && !this->HasFlag(CI_SECURE)) + ; + else + continue; + + /* Use the highest level access available */ + if (!highest || access->level > highest->level) + highest = access; + } + + return highest; +} +/** 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) +{ + if (nc == this->founder) + { + dummy_access.level = ACCESS_FOUNDER; + dummy_access.mask = nc->display; + dummy_access.nc = nc; + dummy_access.last_seen = Anope::CurTime; + return &dummy_access; + } for (unsigned i = 0, end = this->access.size(); i < end; ++i) - if (this->access[i]->nc == nc && (level ? this->access[i]->level == level : true)) + { + if (level && this->access[i]->level != level) + continue; + if (this->access[i]->nc && this->access[i]->nc == nc) return this->access[i]; + } + return NULL; +} +/** 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 + * @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) +{ + for (unsigned i = 0, end = this->access.size(); i < end; ++i) + if (Anope::Match(this->access[i]->mask, mask)) + return this->access[i]; return NULL; } @@ -226,14 +313,33 @@ void ChannelInfo::EraseAccess(unsigned index) this->access.erase(this->access.begin() + index); } +/** Erase an entry from the channel access list + * + * @param access The access to remove + * + * Clears the memory used by the given access entry and removes it from the vector. + */ +void ChannelInfo::EraseAccess(ChanAccess *access) +{ + for (unsigned i = 0, end = this->access.size(); i < end; ++i) + { + if (this->access[i] == access) + { + this->access.erase(this->access.begin() + i); + break; + } + } +} + /** Clear the entire channel access list * * Clears the entire access list by deleting every item and then clearing the vector. */ void ChannelInfo::ClearAccess() { - while (!this->access.empty()) - EraseAccess(0); + for (unsigned i = this->access.size(); i > 0; --i) + delete this->access[i - 1]; + this->access.clear(); } /** Add an akick entry to the channel by NickCore |