aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Sadie Powell2022-03-22 17:05:30 +0000
committerGravatar Sadie Powell2022-03-22 17:15:38 +0000
commit2468fc2582a2f8ac0b69b7d9e2cfb511e700f2eb (patch)
tree72336ebbda6e849cd4f5e0456bb08399df5b2ae8 /src
parentFix a typo in the connectban example config docs. (diff)
downloadinspircd++-2468fc2582a2f8ac0b69b7d9e2cfb511e700f2eb.tar.gz
inspircd++-2468fc2582a2f8ac0b69b7d9e2cfb511e700f2eb.tar.bz2
inspircd++-2468fc2582a2f8ac0b69b7d9e2cfb511e700f2eb.zip
Fix our WHO oplevels being incompatible with the WHOX spec.
Unlike in InspIRCd where 0 is an unprivileged member and higher levels grant more privileges the WHOX spec defines the oplevel field as using n/a for unprivileged users and the lower an oplevel is the more privileges it grants. InspIRCd also uses values between 0 and UINT_MAX whereas WHOX only uses values between 0 and 999. In order to work around this we now lazily build dummy oplevels for the InspIRCd member ranks.
Diffstat (limited to 'src')
-rw-r--r--src/coremods/core_who.cpp50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/coremods/core_who.cpp b/src/coremods/core_who.cpp
index b853ef4b1..a459b49d3 100644
--- a/src/coremods/core_who.cpp
+++ b/src/coremods/core_who.cpp
@@ -120,6 +120,33 @@ class CommandWho : public SplitCommand
UserModeReference invisiblemode;
Events::ModuleEventProvider whoevprov;
+ void BuildOpLevels()
+ {
+ // Build a map of prefixes ordered descending by their rank.
+ std::multimap<unsigned int, const PrefixMode*, std::greater<unsigned int> > ranks;
+ const ModeParser::PrefixModeList& modes = ServerInstance->Modes.GetPrefixModes();
+ for (ModeParser::PrefixModeList::const_iterator iter = modes.begin(); iter != modes.end(); ++iter)
+ {
+ const PrefixMode* pm = *iter;
+ ranks.insert(std::make_pair(pm->GetPrefixRank(), pm));
+ }
+
+ // Now we have the ranks ordered we can assign them levels.
+ unsigned int lastrank;
+ unsigned int oplevel = 0;
+ for (std::multimap<unsigned int, const PrefixMode*>::const_iterator iter = ranks.begin(); iter != ranks.end(); ++iter)
+ {
+ const PrefixMode* pm = iter->second;
+ if (iter != ranks.begin() && pm->GetPrefixRank() != lastrank)
+ oplevel++; // Keep the same op level for modes with the same prefix rank.
+
+ lastrank = pm->GetPrefixRank();
+ oplevels[pm->GetModeChar()] = ConvToStr(oplevel);
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Assigned oplevel %u to the %c (%s) prefix mode.",
+ oplevel, pm->GetModeChar(), pm->name.c_str());
+ }
+ }
+
/** Determines whether a user can view the users of a channel. */
bool CanView(Channel* chan, User* user)
{
@@ -168,6 +195,8 @@ class CommandWho : public SplitCommand
void WhoUsers(LocalUser* source, const std::vector<std::string>& parameters, const T& users, WhoData& data);
public:
+ insp::flat_map<char, std::string> oplevels;
+
CommandWho(Module* parent)
: SplitCommand(parent, "WHO", 1, 3)
, secretmode(parent, "secret")
@@ -496,7 +525,14 @@ void CommandWho::SendWhoLine(LocalUser* source, const std::vector<std::string>&
// Include the user's operator rank level.
if (data.whox_fields['o'])
- wholine.push(memb ? ConvToStr(memb->getRank()) : "0");
+ {
+ // If we haven't built a table to convert from InspIRCd member
+ // ranks to WHOX oplevels yet we need to do that here.
+ if (oplevels.empty())
+ BuildOpLevels();
+
+ wholine.push(memb && memb->getRank() ? oplevels[memb->GetPrefixChar()] : "n/a");
+ }
// Include the user's real name.
if (data.whox_fields['r'])
@@ -598,6 +634,18 @@ class CoreModWho : public Module
tokens["WHOX"];
}
+ void OnServiceAdd(ServiceProvider& provider) CXX11_OVERRIDE
+ {
+ // If the service is a prefix mode we need to rebuild the oplevel map.
+ if (provider.service == SERVICE_MODE && static_cast<ModeHandler&>(provider).IsPrefixMode())
+ cmd.oplevels.clear();
+ }
+
+ void OnServiceDel(ServiceProvider& provider) CXX11_OVERRIDE
+ {
+ this->OnServiceAdd(provider);
+ }
+
Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the WHO command", VF_VENDOR|VF_CORE);