inspircd

A modular C++ IRC daemon (ircd). https://www.inspircd.org/
Log | Files | Refs | README

commit c202169f925b8316264b931d3900ed481c65e4b7
parent a032cd90ad5582914759e226085efee5aae1a1ef
Author: Peter Powell <petpow@saberuk.com>
Date:   Mon, 28 Jan 2019 21:24:39 +0000

Fix sending the modes in RPL_CHANNELMODEIS as one big parameter.

Diffstat:
Msrc/coremods/core_user/cmd_mode.cpp | 46+++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/coremods/core_user/cmd_mode.cpp b/src/coremods/core_user/cmd_mode.cpp @@ -144,12 +144,56 @@ static std::string GetSnomasks(const User* user) return snomaskstr; } +namespace +{ + void GetModeList(Numeric::Numeric& num, Channel* chan, User* user) + { + // We should only show the value of secret parameters (i.e. key) if + // the user is a member of the channel. + bool show_secret = chan->HasUser(user); + + std::string& modes = num.push("+").GetParams().back(); + std::string param; + for (unsigned char chr = 65; chr < 123; ++chr) + { + // Check that the mode exists and is set. + ModeHandler* mh = ServerInstance->Modes->FindMode(chr, MODETYPE_CHANNEL); + if (!mh || !chan->IsModeSet(mh)) + continue; + + // Add the mode to the set list. + modes.push_back(mh->GetModeChar()); + + // If the mode has a parameter we need to include that too. + ParamModeBase* pm = mh->IsParameterMode(); + if (!pm) + continue; + + // If a mode has a secret parameter and the user is not privy to + // the value of it then we use <name> instead of the value. + if (pm->IsParameterSecret() && !show_secret) + { + num.push("<" + pm->name + ">"); + continue; + } + + // Retrieve the parameter and add it to the mode list. + pm->GetParameter(chan, param); + num.push(param); + param.clear(); + } + } +} + void CommandMode::DisplayCurrentModes(User* user, User* targetuser, Channel* targetchannel) { if (targetchannel) { // Display channel's current mode string - user->WriteNumeric(RPL_CHANNELMODEIS, targetchannel->name, (std::string("+") + targetchannel->ChanModes(targetchannel->HasUser(user)))); + Numeric::Numeric modenum(RPL_CHANNELMODEIS); + modenum.push(targetchannel->name); + GetModeList(modenum, targetchannel, user); + user->WriteNumeric(modenum); user->WriteNumeric(RPL_CHANNELCREATED, targetchannel->name, (unsigned long)targetchannel->age); } else