diff options
-rw-r--r-- | include/modes.h | 9 | ||||
-rw-r--r-- | modules/commands/cs_mode.cpp | 58 | ||||
-rw-r--r-- | modules/protocol/bahamut.cpp | 4 | ||||
-rw-r--r-- | modules/protocol/inspircd11.cpp | 13 | ||||
-rw-r--r-- | modules/protocol/inspircd12.cpp | 13 | ||||
-rw-r--r-- | modules/protocol/inspircd20.cpp | 19 | ||||
-rw-r--r-- | modules/protocol/plexus.cpp | 10 | ||||
-rw-r--r-- | modules/protocol/ratbox.cpp | 4 | ||||
-rw-r--r-- | modules/protocol/unreal.cpp | 10 | ||||
-rw-r--r-- | src/modes.cpp | 3 |
10 files changed, 91 insertions, 52 deletions
diff --git a/include/modes.h b/include/modes.h index 20d4378bc..2fce7e9f7 100644 --- a/include/modes.h +++ b/include/modes.h @@ -276,13 +276,18 @@ class CoreExport ChannelModeStatus : public ChannelMode public: /* The symbol, eg @ % + */ char Symbol; + /* The "level" of the mode, used to compare with other modes. + * Used so we know op > halfop > voice etc. + */ + unsigned short Level; /** Default constructor * @param mName The mode name * @param modeChar The mode char - * @param mSymbol The symbol for the mode, eg @ % + + * @param mSymbol The symbol for the mode, eg @ % + * @param mLevel A level for the mode, which is usually determined by the PREFIX capab */ - ChannelModeStatus(ChannelModeName mName, char modeChar, char mSymbol); + ChannelModeStatus(ChannelModeName mName, char modeChar, char mSymbol, unsigned short mLevel = 0); /** Default destructor */ diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index 36ac60b0f..7c98292d3 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -15,25 +15,29 @@ class CommandCSMode : public Command { - bool CanSet(User *u, ChannelInfo *ci, ChannelModeName mode) + bool CanSet(User *u, ChannelInfo *ci, ChannelMode *cm) { - switch (mode) - { - case CMODE_OWNER: - return ci->AccessFor(u).HasPriv(CA_OWNER); - case CMODE_PROTECT: - return ci->AccessFor(u).HasPriv(CA_PROTECT); - case CMODE_OP: - return ci->AccessFor(u).HasPriv(CA_OPDEOP); - case CMODE_HALFOP: - return ci->AccessFor(u).HasPriv(CA_HALFOP); - case CMODE_VOICE: - return ci->AccessFor(u).HasPriv(CA_VOICE); - default: - break; - } + if (!u || !ci || !cm || cm->Type != MODE_STATUS) + return false; - return false; + const ChannelAccess accesses[] = { CA_VOICE, CA_HALFOP, CA_OPDEOP, CA_PROTECT, CA_OWNER, CA_SIZE }; + const ChannelModeName modes[] = { CMODE_VOICE, CMODE_HALFOP, CMODE_OP, CMODE_PROTECT, CMODE_OWNER }; + ChannelModeStatus *cms = debug_cast<ChannelModeStatus *>(cm); + AccessGroup access = ci->AccessFor(u); + unsigned short u_level = 0; + + for (int i = 0; accesses[i] != CA_SIZE; ++i) + if (access.HasPriv(accesses[i])) + { + ChannelMode *cm2 = ModeManager::FindChannelModeByName(modes[i]); + if (cm2 == NULL || cm2->Type != MODE_STATUS) + continue; + ChannelModeStatus *cms2 = debug_cast<ChannelModeStatus *>(cm2); + if (cms2->Level > u_level) + u_level = cms2->Level; + } + + return u_level >= cms->Level; } void DoLock(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) @@ -222,7 +226,7 @@ class CommandCSMode : public Command if (!sep.GetToken(param)) break; - if (!this->CanSet(u, ci, cm->Name)) + if (!this->CanSet(u, ci, cm)) { source.Reply(_("You do not have access to set mode %c."), cm->ModeChar); break; @@ -256,15 +260,19 @@ class CommandCSMode : public Command else { User *target = finduser(param); - if (target != NULL) + if (target == NULL) { - AccessGroup targ_access = ci->AccessFor(target); - if (targ_access > u_access) - { - source.Reply(_("You do not have the access to change %s's modes."), target->nick.c_str()); - break; - } + source.Reply(NICK_X_NOT_IN_USE, param.c_str()); + break; + } + + AccessGroup targ_access = ci->AccessFor(target); + if (targ_access > u_access) + { + source.Reply(_("You do not have the access to change %s's modes."), target->nick.c_str()); + break; } + if (adding) ci->c->SetMode(NULL, cm, param); else diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 796e021e1..9aae47086 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -537,8 +537,8 @@ class ProtoBahamut : public Module ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b')); /* v/h/o/a/q */ - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+', 0)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@', 1)); /* Add channel modes */ ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, 'c')); diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index a5f8e1d86..2a1b4e435 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -524,26 +524,29 @@ class InspircdIRCdMessage : public IRCdMessage { Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')')); Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end()); + unsigned short level = modes.length() - 1; for (size_t t = 0, end = modes.length(); t < end; ++t) { switch (modes[t]) { case 'q': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', '~')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', '~', level--)); continue; case 'a': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', '&')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', '&', level--)); continue; case 'o': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@', level--)); continue; case 'h': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', '%')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', '%', level--)); continue; case 'v': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+', level--)); continue; + default: + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_END, modes[t], chars[t], level--)); } } } diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index a2e0e0920..6175e2f52 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -656,26 +656,29 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage { Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')')); Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end()); + unsigned short level = modes.length() - 1; for (size_t t = 0, end = modes.length(); t < end; ++t) { switch (modes[t]) { case 'q': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', chars[t])); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', chars[t], level--)); continue; case 'a': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', chars[t])); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', chars[t], level--)); continue; case 'o': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', chars[t])); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', chars[t], level--)); continue; case 'h': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', chars[t])); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', chars[t], level--)); continue; case 'v': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', chars[t])); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', chars[t], level--)); continue; + default: + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_END, modes[t], chars[t], level--)); } } } diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index f210525c5..852f0c4e0 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -688,6 +688,25 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage Anope::string maxmodes(capab.begin() + 9, capab.end()); ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; } + else if (capab.find("PREFIX=") != Anope::string::npos) + { + Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')')); + Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end()); + unsigned short level = modes.length() - 1; + + for (size_t t = 0, end = modes.length(); t < end; ++t) + { + ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[t]); + if (cm == NULL || cm->Type != MODE_STATUS) + { + Log() << "CAPAB PREFIX gave unknown channel status mode " << modes[t]; + continue; + } + + ChannelModeStatus *cms = debug_cast<ChannelModeStatus *>(cm); + cms->Level = level--; + } + } } } else if (params[0].equals_cs("END")) diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index fa5f88f5a..8bc3e21b9 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -631,11 +631,11 @@ class ProtoPlexus : public Module ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, 'l')); /* v/h/o/a/q */ - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', '%')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', '&')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', '~')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+', 0)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', '%', 1)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@', 2)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', '&', 3)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', '~', 4)); /* Add channel modes */ ModeManager::AddChannelMode(new ChannelMode(CMODE_BANDWIDTH, 'B')); diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index c47189736..d4208760e 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -565,8 +565,8 @@ class ProtoRatbox : public Module ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); /* v/h/o/a/q */ - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+', 0)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@', 1)); /* Add channel modes */ ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i')); diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index 38b9da82b..cbb23dcc5 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -1065,12 +1065,12 @@ class ProtoUnreal : public Module void AddModes() { - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', '%')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+', 0)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, 'h', '%', 1)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@', 2)); /* Unreal sends +q as * and +a as ~ */ - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', '~')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', '*')); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, 'a', '~', 3)); + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, 'q', '*', 4)); /* Add user modes */ ModeManager::AddUserMode(new UserMode(UMODE_SERV_ADMIN, 'A')); diff --git a/src/modes.cpp b/src/modes.cpp index daada4322..d51622e22 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -222,8 +222,9 @@ ChannelModeParam::~ChannelModeParam() * @param mName The mode name * @param modeChar The mode char * @param mSymbol The symbol for the mode, eg @ % + + * @param mLevel A level for the mode, which is usually determined by the PREFIX capab */ -ChannelModeStatus::ChannelModeStatus(ChannelModeName mName, char modeChar, char mSymbol) : ChannelMode(mName, modeChar), Symbol(mSymbol) +ChannelModeStatus::ChannelModeStatus(ChannelModeName mName, char modeChar, char mSymbol, unsigned short mLevel) : ChannelMode(mName, modeChar), Symbol(mSymbol), Level(mLevel) { this->Type = MODE_STATUS; } |