summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorPeter Powell <petpow@saberuk.com>2018-08-13 20:17:46 +0100
committerPeter Powell <petpow@saberuk.com>2018-08-13 21:51:11 +0100
commit58a0a7e01422e62de1565a8eb0a1febdc463d04d (patch)
tree8861789deefe9df3524690de8ccd11e5366f1f2e /src/modules
parente2a820cce21342478653a34cf8ce2b593128d035 (diff)
Implement IRCv3 message tag support.
Co-authored-by: Attila Molnar <attilamolnar@hush.com>
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/m_alias.cpp2
-rw-r--r--src/modules/m_auditorium.cpp51
-rw-r--r--src/modules/m_cap.cpp37
-rw-r--r--src/modules/m_chanhistory.cpp25
-rw-r--r--src/modules/m_chanlog.cpp3
-rw-r--r--src/modules/m_cloaking.cpp8
-rw-r--r--src/modules/m_conn_waitpong.cpp6
-rw-r--r--src/modules/m_delayjoin.cpp63
-rw-r--r--src/modules/m_hostcycle.cpp34
-rw-r--r--src/modules/m_ircv3.cpp230
-rw-r--r--src/modules/m_ircv3_capnotify.cpp54
-rw-r--r--src/modules/m_ircv3_chghost.cpp10
-rw-r--r--src/modules/m_ircv3_echomessage.cpp24
-rw-r--r--src/modules/m_ircv3_invitenotify.cpp8
-rw-r--r--src/modules/m_knock.cpp8
-rw-r--r--src/modules/m_ldapoper.cpp3
-rw-r--r--src/modules/m_passforward.cpp4
-rw-r--r--src/modules/m_samode.cpp42
-rw-r--r--src/modules/m_sasl.cpp17
-rw-r--r--src/modules/m_showfile.cpp7
-rw-r--r--src/modules/m_spanningtree/main.cpp6
-rw-r--r--src/modules/m_spanningtree/main.h2
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp3
-rw-r--r--src/modules/m_sqloper.cpp3
-rw-r--r--src/modules/m_timedbans.cpp8
25 files changed, 421 insertions, 237 deletions
diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp
index 76ccc6ebc..75ab57e94 100644
--- a/src/modules/m_alias.cpp
+++ b/src/modules/m_alias.cpp
@@ -129,7 +129,7 @@ class ModuleAlias : public Module
return word;
}
- std::string CreateRFCMessage(const std::string& command, Command::Params& parameters)
+ std::string CreateRFCMessage(const std::string& command, CommandBase::Params& parameters)
{
std::string message(command);
for (CommandBase::Params::const_iterator iter = parameters.begin(); iter != parameters.end();)
diff --git a/src/modules/m_auditorium.cpp b/src/modules/m_auditorium.cpp
index 7acbd2fff..8485f1d7a 100644
--- a/src/modules/m_auditorium.cpp
+++ b/src/modules/m_auditorium.cpp
@@ -32,6 +32,29 @@ class AuditoriumMode : public SimpleChannelModeHandler
}
};
+class ModuleAuditorium;
+
+namespace
+{
+
+/** Hook handler for join client protocol events.
+ * This allows us to block join protocol events completely, including all associated messages (e.g. MODE, away-notify AWAY).
+ * This is not the same as OnUserJoin() because that runs only when a real join happens but this runs also when a module
+ * such as delayjoin or hostcycle generates a join.
+ */
+class JoinHook : public ClientProtocol::EventHook
+{
+ ModuleAuditorium* const parentmod;
+ bool active;
+
+ public:
+ JoinHook(ModuleAuditorium* mod);
+ void OnEventInit(const ClientProtocol::Event& ev) CXX11_OVERRIDE;
+ ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) CXX11_OVERRIDE;
+};
+
+}
+
class ModuleAuditorium : public Module
{
CheckExemption::EventProvider exemptionprov;
@@ -39,11 +62,13 @@ class ModuleAuditorium : public Module
bool OpsVisible;
bool OpsCanSee;
bool OperCanSee;
+ JoinHook joinhook;
public:
ModuleAuditorium()
: exemptionprov(this)
, aum(this)
+ , joinhook(this)
{
}
@@ -115,11 +140,6 @@ class ModuleAuditorium : public Module
}
}
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) CXX11_OVERRIDE
- {
- BuildExcept(memb, excepts);
- }
-
void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts) CXX11_OVERRIDE
{
BuildExcept(memb, excepts);
@@ -165,4 +185,25 @@ class ModuleAuditorium : public Module
}
};
+JoinHook::JoinHook(ModuleAuditorium* mod)
+ : ClientProtocol::EventHook(mod, "JOIN", 10)
+ , parentmod(mod)
+{
+}
+
+void JoinHook::OnEventInit(const ClientProtocol::Event& ev)
+{
+ const ClientProtocol::Events::Join& join = static_cast<const ClientProtocol::Events::Join&>(ev);
+ active = !parentmod->IsVisible(join.GetMember());
+}
+
+ModResult JoinHook::OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist)
+{
+ if (!active)
+ return MOD_RES_PASSTHRU;
+
+ const ClientProtocol::Events::Join& join = static_cast<const ClientProtocol::Events::Join&>(ev);
+ return ((parentmod->CanSee(user, join.GetMember())) ? MOD_RES_PASSTHRU : MOD_RES_DENY);
+}
+
MODULE_INIT(ModuleAuditorium)
diff --git a/src/modules/m_cap.cpp b/src/modules/m_cap.cpp
index 80e70d3e5..922061757 100644
--- a/src/modules/m_cap.cpp
+++ b/src/modules/m_cap.cpp
@@ -341,16 +341,35 @@ void Cap::ExtItem::unserialize(SerializeFormat format, Extensible* container, co
managerimpl->HandleReq(user, caplist);
}
+class CapMessage : public Cap::MessageBase
+{
+ public:
+ CapMessage(LocalUser* user, const std::string& subcmd, const std::string& result)
+ : Cap::MessageBase(subcmd)
+ {
+ SetUser(user);
+ PushParamRef(result);
+ }
+};
+
class CommandCap : public SplitCommand
{
Events::ModuleEventProvider evprov;
Cap::ManagerImpl manager;
+ ClientProtocol::EventProvider protoevprov;
- static void DisplayResult(LocalUser* user, std::string& result)
+ void DisplayResult(LocalUser* user, const std::string& subcmd, std::string& result)
{
if (*result.rbegin() == ' ')
result.erase(result.end()-1);
- user->WriteCommand("CAP", result);
+ DisplayResult2(user, subcmd, result);
+ }
+
+ void DisplayResult2(LocalUser* user, const std::string& subcmd, const std::string& result)
+ {
+ CapMessage msg(user, subcmd, result);
+ ClientProtocol::Event ev(protoevprov, msg);
+ user->Send(ev);
}
public:
@@ -360,6 +379,7 @@ class CommandCap : public SplitCommand
: SplitCommand(mod, "CAP", 1)
, evprov(mod, "event/cap")
, manager(mod, evprov)
+ , protoevprov(mod, name)
, holdext("cap_hold", ExtensionItem::EXT_USER, mod)
{
works_before_reg = true;
@@ -378,9 +398,8 @@ class CommandCap : public SplitCommand
if (parameters.size() < 2)
return CMD_FAILURE;
- std::string result = (manager.HandleReq(user, parameters[1]) ? "ACK :" : "NAK :");
- result.append(parameters[1]);
- user->WriteCommand("CAP", result);
+ const std::string replysubcmd = (manager.HandleReq(user, parameters[1]) ? "ACK" : "NAK");
+ DisplayResult2(user, replysubcmd, parameters[1]);
}
else if (subcommand == "END")
{
@@ -392,16 +411,16 @@ class CommandCap : public SplitCommand
if ((is_ls) && (parameters.size() > 1) && (parameters[1] == "302"))
manager.Set302Protocol(user);
- std::string result = subcommand + " :";
+ std::string result;
// Show values only if supports v3.2 and doing LS
manager.HandleList(result, user, is_ls, ((is_ls) && (manager.GetProtocol(user) != Cap::CAP_LEGACY)));
- DisplayResult(user, result);
+ DisplayResult(user, subcommand, result);
}
else if ((subcommand == "CLEAR") && (manager.GetProtocol(user) == Cap::CAP_LEGACY))
{
- std::string result = "ACK :";
+ std::string result;
manager.HandleClear(user, result);
- DisplayResult(user, result);
+ DisplayResult(user, "ACK", result);
}
else
{
diff --git a/src/modules/m_chanhistory.cpp b/src/modules/m_chanhistory.cpp
index 081731126..0c3945346 100644
--- a/src/modules/m_chanhistory.cpp
+++ b/src/modules/m_chanhistory.cpp
@@ -22,8 +22,15 @@
struct HistoryItem
{
time_t ts;
- std::string line;
- HistoryItem(const std::string& Line) : ts(ServerInstance->Time()), line(Line) {}
+ std::string text;
+ std::string sourcemask;
+
+ HistoryItem(User* source, const std::string& Text)
+ : ts(ServerInstance->Time())
+ , text(Text)
+ , sourcemask(source->GetFullHost())
+ {
+ }
};
struct HistoryList
@@ -136,8 +143,7 @@ class ModuleChanHistory : public Module
HistoryList* list = m.ext.get(c);
if (list)
{
- const std::string line = ":" + user->GetFullHost() + " PRIVMSG " + c->name + " :" + details.text;
- list->lines.push_back(HistoryItem(line));
+ list->lines.push_back(HistoryItem(user, details.text));
if (list->lines.size() > list->maxlen)
list->lines.pop_front();
}
@@ -146,7 +152,8 @@ class ModuleChanHistory : public Module
void OnPostJoin(Membership* memb) CXX11_OVERRIDE
{
- if (IS_REMOTE(memb->user))
+ LocalUser* localuser = IS_LOCAL(memb->user);
+ if (!localuser)
return;
if (memb->user->IsModeSet(botmode) && !dobots)
@@ -169,8 +176,12 @@ class ModuleChanHistory : public Module
for(std::deque<HistoryItem>::iterator i = list->lines.begin(); i != list->lines.end(); ++i)
{
- if (i->ts >= mintime)
- memb->user->Write(i->line);
+ const HistoryItem& item = *i;
+ if (item.ts >= mintime)
+ {
+ ClientProtocol::Messages::Privmsg msg(ClientProtocol::Messages::Privmsg::nocopy, item.sourcemask, memb->chan, item.text);
+ localuser->Send(ServerInstance->GetRFCEvents().privmsg, msg);
+ }
}
}
diff --git a/src/modules/m_chanlog.cpp b/src/modules/m_chanlog.cpp
index f618a539c..85e7ca2eb 100644
--- a/src/modules/m_chanlog.cpp
+++ b/src/modules/m_chanlog.cpp
@@ -70,7 +70,8 @@ class ModuleChanLog : public Module
Channel *c = ServerInstance->FindChan(it->second);
if (c)
{
- c->WriteChannelWithServ(ServerInstance->Config->ServerName, "PRIVMSG %s :%s", c->name.c_str(), snotice.c_str());
+ ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->Config->ServerName, c, snotice);
+ c->Write(ServerInstance->GetRFCEvents().privmsg, privmsg);
ServerInstance->PI->SendMessage(c, 0, snotice);
}
}
diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp
index c277759d1..b9ff085c3 100644
--- a/src/modules/m_cloaking.cpp
+++ b/src/modules/m_cloaking.cpp
@@ -313,7 +313,13 @@ class ModuleCloaking : public Module
if (u->IsModeSet(cu) && !cu.active)
{
u->SetMode(cu, false);
- u->WriteCommand("MODE", "-" + ConvToStr(cu.GetModeChar()));
+
+ if (!IS_LOCAL(u))
+ return;
+ Modes::ChangeList modechangelist;
+ modechangelist.push_remove(&cu);
+ ClientProtocol::Events::Mode modeevent(ServerInstance->FakeClient, NULL, u, modechangelist);
+ static_cast<LocalUser*>(u)->Send(modeevent);
}
cu.active = false;
}
diff --git a/src/modules/m_conn_waitpong.cpp b/src/modules/m_conn_waitpong.cpp
index b4441c88c..f2e9590c8 100644
--- a/src/modules/m_conn_waitpong.cpp
+++ b/src/modules/m_conn_waitpong.cpp
@@ -46,8 +46,10 @@ class ModuleWaitPong : public Module
ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
std::string pingrpl = ServerInstance->GenRandomStr(10);
-
- user->Write("PING :%s", pingrpl.c_str());
+ {
+ ClientProtocol::Messages::Ping pingmsg(pingrpl);
+ user->Send(ServerInstance->GetRFCEvents().ping, pingmsg);
+ }
if(sendsnotice)
user->WriteNotice("*** If you are having problems connecting due to ping timeouts, please type /quote PONG " + pingrpl + " or /raw PONG " + pingrpl + " now.");
diff --git a/src/modules/m_delayjoin.cpp b/src/modules/m_delayjoin.cpp
index f9cd837d7..7c557eb35 100644
--- a/src/modules/m_delayjoin.cpp
+++ b/src/modules/m_delayjoin.cpp
@@ -33,14 +33,50 @@ class DelayJoinMode : public ModeHandler
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE;
};
+
+namespace
+{
+
+/** Hook handler for join client protocol events.
+ * This allows us to block join protocol events completely, including all associated messages (e.g. MODE, away-notify AWAY).
+ * This is not the same as OnUserJoin() because that runs only when a real join happens but this runs also when a module
+ * such as hostcycle generates a join.
+ */
+class JoinHook : public ClientProtocol::EventHook
+{
+ const LocalIntExt& unjoined;
+
+ public:
+ JoinHook(Module* mod, const LocalIntExt& unjoinedref)
+ : ClientProtocol::EventHook(mod, "JOIN", 10)
+ , unjoined(unjoinedref)
+ {
+ }
+
+ ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) CXX11_OVERRIDE
+ {
+ const ClientProtocol::Events::Join& join = static_cast<const ClientProtocol::Events::Join&>(ev);
+ const User* const u = join.GetMember()->user;
+ if ((unjoined.get(u)) && (u != user))
+ return MOD_RES_DENY;
+ return MOD_RES_PASSTHRU;
+ }
+};
+
+}
+
class ModuleDelayJoin : public Module
{
DelayJoinMode djm;
+ void RevealUser(User* user, Channel* chan);
public:
LocalIntExt unjoined;
+ JoinHook joinhook;
+
ModuleDelayJoin()
: djm(this)
, unjoined("delayjoin", ExtensionItem::EXT_MEMBERSHIP, this)
+ , joinhook(this, unjoined)
{
}
@@ -68,7 +104,7 @@ ModeAction DelayJoinMode::OnModeChange(User* source, User* dest, Channel* channe
* they remain permanently invisible on this channel!
*/
MessageTarget msgtarget(channel, 0);
- MessageDetails msgdetails(MSG_PRIVMSG, "");
+ MessageDetails msgdetails(MSG_PRIVMSG, "", ClientProtocol::TagMap());
const Channel::MemberMap& users = channel->GetUsers();
for (Channel::MemberMap::const_iterator n = users.begin(); n != users.end(); ++n)
{
@@ -111,10 +147,7 @@ static void populate(CUList& except, Membership* memb)
void ModuleDelayJoin::OnUserJoin(Membership* memb, bool sync, bool created, CUList& except)
{
if (memb->chan->IsModeSet(djm))
- {
unjoined.set(memb, 1);
- populate(except, memb);
- }
}
void ModuleDelayJoin::OnUserPart(Membership* memb, std::string &partmessage, CUList& except)
@@ -147,20 +180,20 @@ void ModuleDelayJoin::OnUserMessage(User* user, const MessageTarget& target, con
return;
Channel* channel = target.Get<Channel>();
+ RevealUser(user, channel);
+}
- Membership* memb = channel->GetUser(user);
+void ModuleDelayJoin::RevealUser(User* user, Channel* chan)
+{
+ Membership* memb = chan->GetUser(user);
if (!memb || !unjoined.set(memb, 0))
return;
/* Display the join to everyone else (the user who joined got it earlier) */
- channel->WriteAllExceptSender(user, false, 0, "JOIN %s", channel->name.c_str());
-
- std::string ms = memb->modes;
- for(unsigned int i=0; i < memb->modes.length(); i++)
- ms.append(" ").append(user->nick);
-
- if (ms.length() > 0)
- channel->WriteAllExceptSender(user, false, 0, "MODE %s +%s", channel->name.c_str(), ms.c_str());
+ CUList except_list;
+ except_list.insert(user);
+ ClientProtocol::Events::Join joinevent(memb);
+ chan->Write(joinevent, 0, except_list);
}
/* make the user visible if he receives any mode change */
@@ -182,9 +215,7 @@ ModResult ModuleDelayJoin::OnRawMode(User* user, Channel* channel, ModeHandler*
if (!dest)
return MOD_RES_PASSTHRU;
- Membership* memb = channel->GetUser(dest);
- if (memb && unjoined.set(memb, 0))
- channel->WriteAllExceptSender(dest, false, 0, "JOIN %s", channel->name.c_str());
+ RevealUser(dest, channel);
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/m_hostcycle.cpp b/src/modules/m_hostcycle.cpp
index 0f7405dcc..a3c81df6e 100644
--- a/src/modules/m_hostcycle.cpp
+++ b/src/modules/m_hostcycle.cpp
@@ -24,13 +24,16 @@
class ModuleHostCycle : public Module
{
Cap::Reference chghostcap;
+ const std::string quitmsghost;
+ const std::string quitmsgident;
/** Send fake quit/join/mode messages for host or ident cycle.
*/
- void DoHostCycle(User* user, const std::string& newident, const std::string& newhost, const char* quitmsg)
+ void DoHostCycle(User* user, const std::string& newident, const std::string& newhost, const std::string& reason)
{
- // GetFullHost() returns the original data at the time this function is called
- const std::string quitline = ":" + user->GetFullHost() + " QUIT :" + quitmsg;
+ // The user has the original ident/host at the time this function is called
+ ClientProtocol::Messages::Quit quitmsg(user, reason);
+ ClientProtocol::Event quitevent(ServerInstance->GetRFCEvents().quit, quitmsg);
already_sent_t silent_id = ServerInstance->Users.NextAlreadySentId();
already_sent_t seen_id = ServerInstance->Users.NextAlreadySentId();
@@ -50,7 +53,7 @@ class ModuleHostCycle : public Module
if (i->second)
{
u->already_sent = seen_id;
- u->Write(quitline);
+ u->Send(quitevent);
}
else
{
@@ -65,17 +68,8 @@ class ModuleHostCycle : public Module
{
Membership* memb = *i;
Channel* c = memb->chan;
- const std::string joinline = ":" + newfullhost + " JOIN " + c->name;
- std::string modeline;
- if (!memb->modes.empty())
- {
- modeline = ":" + (ServerInstance->Config->CycleHostsFromUser ? newfullhost : ServerInstance->Config->ServerName)
- + " MODE " + c->name + " +" + memb->modes;
-
- for (size_t j = 0; j < memb->modes.length(); j++)
- modeline.append(" ").append(user->nick);
- }
+ ClientProtocol::Events::Join joinevent(memb, newfullhost);
const Channel::MemberMap& ulist = c->GetUsers();
for (Channel::MemberMap::const_iterator j = ulist.begin(); j != ulist.end(); ++j)
@@ -90,13 +84,11 @@ class ModuleHostCycle : public Module
if (u->already_sent != seen_id)
{
- u->Write(quitline);
+ u->Send(quitevent);
u->already_sent = seen_id;
}
- u->Write(joinline);
- if (!memb->modes.empty())
- u->Write(modeline);
+ u->Send(joinevent);
}
}
}
@@ -104,17 +96,19 @@ class ModuleHostCycle : public Module
public:
ModuleHostCycle()
: chghostcap(this, "chghost")
+ , quitmsghost("Changing host")
+ , quitmsgident("Changing ident")
{
}
void OnChangeIdent(User* user, const std::string& newident) CXX11_OVERRIDE
{
- DoHostCycle(user, newident, user->GetDisplayedHost(), "Changing ident");
+ DoHostCycle(user, newident, user->GetDisplayedHost(), quitmsgident);
}
void OnChangeHost(User* user, const std::string& newhost) CXX11_OVERRIDE
{
- DoHostCycle(user, user->ident, newhost, "Changing host");
+ DoHostCycle(user, user->ident, newhost, quitmsghost);
}
Version GetVersion() CXX11_OVERRIDE
diff --git a/src/modules/m_ircv3.cpp b/src/modules/m_ircv3.cpp
index 92e8a0881..14b1cf8a1 100644
--- a/src/modules/m_ircv3.cpp
+++ b/src/modules/m_ircv3.cpp
@@ -22,24 +22,110 @@
#include "modules/cap.h"
#include "modules/ircv3.h"
+class AwayMessage : public ClientProtocol::Message
+{
+ public:
+ AwayMessage(User* user)
+ : ClientProtocol::Message("AWAY", user)
+ {
+ SetParams(user, user->awaymsg);
+ }
+
+ AwayMessage()
+ : ClientProtocol::Message("AWAY")
+ {
+ }
+
+ void SetParams(User* user, const std::string& awaymsg)
+ {
+ // Going away: 1 parameter which is the away reason
+ // Back from away: no parameter
+ if (!awaymsg.empty())
+ PushParam(awaymsg);
+ }
+};
+
+class JoinHook : public ClientProtocol::EventHook
+{
+ ClientProtocol::Events::Join extendedjoinmsg;
+
+ public:
+ const std::string asterisk;
+ ClientProtocol::EventProvider awayprotoev;
+ AwayMessage awaymsg;
+ Cap::Capability extendedjoincap;
+ Cap::Capability awaycap;
+
+ JoinHook(Module* mod)
+ : ClientProtocol::EventHook(mod, "JOIN")
+ , asterisk(1, '*')
+ , awayprotoev(mod, "AWAY")
+ , extendedjoincap(mod, "extended-join")
+ , awaycap(mod, "away-notify")
+ {
+ }
+
+ void OnEventInit(const ClientProtocol::Event& ev) CXX11_OVERRIDE
+ {
+ const ClientProtocol::Events::Join& join = static_cast<const ClientProtocol::Events::Join&>(ev);
+
+ // An extended join has two extra parameters:
+ // First the account name of the joining user or an asterisk if the user is not logged in.
+ // The second parameter is the realname of the joining user.
+
+ Membership* const memb = join.GetMember();
+ const std::string* account = &asterisk;
+ const AccountExtItem* const accountext = GetAccountExtItem();
+ if (accountext)
+ {
+ const std::string* accountname = accountext->get(memb->user);
+ if (accountname)
+ account = accountname;
+ }
+
+ extendedjoinmsg.ClearParams();
+ extendedjoinmsg.SetSource(join);
+ extendedjoinmsg.PushParamRef(memb->chan->name);
+ extendedjoinmsg.PushParamRef(*account);
+ extendedjoinmsg.PushParamRef(memb->user->GetRealName());
+
+ awaymsg.ClearParams();
+ if ((memb->user->IsAway()) && (awaycap.IsActive()))
+ {
+ awaymsg.SetSource(join);
+ awaymsg.SetParams(memb->user, memb->user->awaymsg);
+ }
+ }
+
+ ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) CXX11_OVERRIDE
+ {
+ if (extendedjoincap.get(user))
+ messagelist.front() = &extendedjoinmsg;
+
+ if ((!awaymsg.GetParams().empty()) && (awaycap.get(user)))
+ messagelist.push_back(&awaymsg);
+
+ return MOD_RES_PASSTHRU;
+ }
+};
+
class ModuleIRCv3
: public Module
, public AccountEventListener
, public Away::EventListener
{
Cap::Capability cap_accountnotify;
- Cap::Capability cap_awaynotify;
- Cap::Capability cap_extendedjoin;
+ JoinHook joinhook;
- CUList last_excepts;
+ ClientProtocol::EventProvider accountprotoev;
public:
ModuleIRCv3()
: AccountEventListener(this)
, Away::EventListener(this)
, cap_accountnotify(this, "account-notify")
- , cap_awaynotify(this, "away-notify")
- , cap_extendedjoin(this, "extended-join")
+ , joinhook(this)
+ , accountprotoev(this, "ACCOUNT")
{
}
@@ -47,141 +133,41 @@ class ModuleIRCv3
{
ConfigTag* conf = ServerInstance->Config->ConfValue("ircv3");
cap_accountnotify.SetActive(conf->getBool("accountnotify", true));
- cap_awaynotify.SetActive(conf->getBool("awaynotify", true));
- cap_extendedjoin.SetActive(conf->getBool("extendedjoin", true));
+ joinhook.awaycap.SetActive(conf->getBool("awaynotify", true));
+ joinhook.extendedjoincap.SetActive(conf->getBool("extendedjoin", true));
}
void OnAccountChange(User* user, const std::string& newaccount) CXX11_OVERRIDE
{
- // :nick!user@host ACCOUNT account
- // or
- // :nick!user@host ACCOUNT *
- std::string line = ":" + user->GetFullHost() + " ACCOUNT ";
- if (newaccount.empty())
- line += "*";
- else
- line += newaccount;
-
- IRCv3::WriteNeighborsWithCap(user, line, cap_accountnotify);
- }
-
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) CXX11_OVERRIDE
- {
- // Remember who is not going to see the JOIN because of other modules
- if ((cap_awaynotify.IsActive()) && (memb->user->IsAway()))
- last_excepts = excepts;
-
- if (!cap_extendedjoin.IsActive())
- return;
-
- /*
- * Send extended joins to clients who have the extended-join capability.
- * An extended join looks like this:
- *
- * :nick!user@host JOIN #chan account :realname
- *
- * account is the joining user's account if he's logged in, otherwise it's an asterisk (*).
- */
-
- std::string line;
- std::string mode;
-
- const Channel::MemberMap& userlist = memb->chan->GetUsers();
- for (Channel::MemberMap::const_iterator it = userlist.begin(); it != userlist.end(); ++it)
- {
- // Send the extended join line if the current member is local, has the extended-join cap and isn't excepted
- User* member = IS_LOCAL(it->first);
- if ((member) && (cap_extendedjoin.get(member)) && (excepts.find(member) == excepts.end()))
- {
- // Construct the lines we're going to send if we haven't constructed them already
- if (line.empty())
- {
- bool has_account = false;
- line = ":" + memb->user->GetFullHost() + " JOIN " + memb->chan->name + " ";
- const AccountExtItem* accountext = GetAccountExtItem();
- if (accountext)
- {
- std::string* accountname;
- accountname = accountext->get(memb->user);
- if (accountname)
- {
- line += *accountname;
- has_account = true;
- }
- }
-
- if (!has_account)
- line += "*";
-
- line += " :" + memb->user->GetRealName();
-
- // If the joining user received privileges from another module then we must send them as well,
- // since silencing the normal join means the MODE will be silenced as well
- if (!memb->modes.empty())
- {
- const std::string& modefrom = ServerInstance->Config->CycleHostsFromUser ? memb->user->GetFullHost() : ServerInstance->Config->ServerName;
- mode = ":" + modefrom + " MODE " + memb->chan->name + " +" + memb->modes;
-
- for (unsigned int i = 0; i < memb->modes.length(); i++)
- mode += " " + memb->user->nick;
- }
- }
-
- // Write the JOIN and the MODE, if any
- member->Write(line);
- if ((!mode.empty()) && (member != memb->user))
- member->Write(mode);
-
- // Prevent the core from sending the JOIN and MODE to this user
- excepts.insert(it->first);
- }
- }
+ // Logged in: 1 parameter which is the account name
+ // Logged out: 1 parameter which is a "*"
+ ClientProtocol::Message msg("ACCOUNT", user);
+ const std::string& param = (newaccount.empty() ? joinhook.asterisk : newaccount);
+ msg.PushParamRef(param);
+ ClientProtocol::Event accountevent(accountprotoev, msg);
+ IRCv3::WriteNeighborsWithCap(user, accountevent, cap_accountnotify);
}
void OnUserAway(User* user) CXX11_OVERRIDE
{
- if (!cap_awaynotify.IsActive())
+ if (!joinhook.awaycap.IsActive())
return;
// Going away: n!u@h AWAY :reason
- const std::string line = ":" + user->GetFullHost() + " AWAY :" + user->awaymsg;
- IRCv3::WriteNeighborsWithCap(user, line, cap_awaynotify);
+ AwayMessage msg(user);
+ ClientProtocol::Event awayevent(joinhook.awayprotoev, msg);
+ IRCv3::WriteNeighborsWithCap(user, awayevent, joinhook.awaycap);
}
void OnUserBack(User* user) CXX11_OVERRIDE
{
- if (!cap_awaynotify.IsActive())
+ if (!joinhook.awaycap.IsActive())
return;
// Back from away: n!u@h AWAY
- const std::string line = ":" + user->GetFullHost() + " AWAY";
- IRCv3::WriteNeighborsWithCap(user, line, cap_awaynotify);
- }
-
- void OnPostJoin(Membership *memb) CXX11_OVERRIDE
- {
- if ((!cap_awaynotify.IsActive()) || (!memb->user->IsAway()))
- return;
-
- std::string line = ":" + memb->user->GetFullHost() + " AWAY :" + memb->user->awaymsg;
-
- const Channel::MemberMap& userlist = memb->chan->GetUsers();
- for (Channel::MemberMap::const_iterator it = userlist.begin(); it != userlist.end(); ++it)
- {
- // Send the away notify line if the current member is local, has the away-notify cap and isn't excepted
- User* member = IS_LOCAL(it->first);
- if ((member) && (cap_awaynotify.get(member)) && (last_excepts.find(member) == last_excepts.end()) && (it->second != memb))
- {
- member->Write(line);
- }
- }
-
- last_excepts.clear();
- }
-
- void Prioritize() CXX11_OVERRIDE
- {
- ServerInstance->Modules->SetPriority(this, I_OnUserJoin, PRIORITY_LAST);
+ AwayMessage msg(user);
+ ClientProtocol::Event awayevent(joinhook.awayprotoev, msg);
+ IRCv3::WriteNeighborsWithCap(user, awayevent, joinhook.awaycap);
}
Version GetVersion() CXX11_OVERRIDE
diff --git a/src/modules/m_ircv3_capnotify.cpp b/src/modules/m_ircv3_capnotify.cpp
index 93c30df12..757b0858f 100644
--- a/src/modules/m_ircv3_capnotify.cpp
+++ b/src/modules/m_ircv3_capnotify.cpp
@@ -46,19 +46,53 @@ class CapNotify : public Cap::Capability
}
};
+class CapNotifyMessage : public Cap::MessageBase
+{
+ public:
+ CapNotifyMessage(bool add, const std::string& capname)
+ : Cap::MessageBase((add ? "NEW" : "DEL"))
+ {
+ PushParamRef(capname);
+ }
+};
+
+class CapNotifyValueMessage : public Cap::MessageBase
+{
+ std::string s;
+ const std::string::size_type pos;
+
+ public:
+ CapNotifyValueMessage(const std::string& capname)
+ : Cap::MessageBase("NEW")
+ , s(capname)
+ , pos(s.size()+1)
+ {
+ s.push_back('=');
+ PushParamRef(s);
+ }
+
+ void SetCapValue(const std::string& capvalue)
+ {
+ s.erase(pos);
+ s.append(capvalue);
+ InvalidateCache();
+ }
+};
+
class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public ReloadModule::EventListener
{
CapNotify capnotify;
std::string reloadedmod;
std::vector<std::string> reloadedcaps;
+ ClientProtocol::EventProvider protoev;
void Send(const std::string& capname, Cap::Capability* cap, bool add)
{
- std::string msg = (add ? "NEW :" : "DEL :");
- msg.append(capname);
- std::string msgwithval = msg;
- msgwithval.push_back('=');
- std::string::size_type msgpos = msgwithval.size();
+ CapNotifyMessage msg(add, capname);
+ CapNotifyValueMessage msgwithval(capname);
+
+ ClientProtocol::Event event(protoev, msg);
+ ClientProtocol::Event eventwithval(protoev, msgwithval);
const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
@@ -73,13 +107,14 @@ class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public Re
const std::string* capvalue = cap->GetValue(user);
if ((capvalue) && (!capvalue->empty()))
{
- msgwithval.append(*capvalue);
- user->WriteCommand("CAP", msgwithval);
- msgwithval.erase(msgpos);
+ msgwithval.SetUser(user);
+ msgwithval.SetCapValue(*capvalue);
+ user->Send(eventwithval);
continue;
}
}
- user->WriteCommand("CAP", msg);
+ msg.SetUser(user);
+ user->Send(event);
}
}
@@ -88,6 +123,7 @@ class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public Re
: Cap::EventListener(this)
, ReloadModule::EventListener(this)
, capnotify(this)
+ , protoev(this, "CAP_NOTIFY")
{
}
diff --git a/src/modules/m_ircv3_chghost.cpp b/src/modules/m_ircv3_chghost.cpp
index 0a9e055b4..aa53612cb 100644
--- a/src/modules/m_ircv3_chghost.cpp
+++ b/src/modules/m_ircv3_chghost.cpp
@@ -24,17 +24,21 @@
class ModuleIRCv3ChgHost : public Module
{
Cap::Capability cap;
+ ClientProtocol::EventProvider protoevprov;
void DoChgHost(User* user, const std::string& ident, const std::string& host)
{
- std::string line(1, ':');
- line.append(user->GetFullHost()).append(" CHGHOST ").append(ident).append(1, ' ').append(host);
- IRCv3::WriteNeighborsWithCap(user, line, cap);
+ ClientProtocol::Message msg("CHGHOST", user);
+ msg.PushParamRef(ident);
+ msg.PushParamRef(host);
+ ClientProtocol::Event protoev(protoevprov, msg);
+ IRCv3::WriteNeighborsWithCap(user, protoev, cap);
}
public:
ModuleIRCv3ChgHost()
: cap(this, "chghost")
+ , protoevprov(this, "CHGHOST")
{
}
diff --git a/src/modules/m_ircv3_echomessage.cpp b/src/modules/m_ircv3_echomessage.cpp
index 056b02194..702552ea7 100644
--- a/src/modules/m_ircv3_echomessage.cpp
+++ b/src/modules/m_ircv3_echomessage.cpp
@@ -21,8 +21,6 @@
#include "inspircd.h"
#include "modules/cap.h"
-static const char* MessageTypeStringSp[] = { "PRIVMSG ", "NOTICE " };
-
class ModuleIRCv3EchoMessage : public Module
{
Cap::Capability cap;
@@ -38,27 +36,31 @@ class ModuleIRCv3EchoMessage : public Module
if (!cap.get(user))
return;
- std::string msg = MessageTypeStringSp[details.type];
+ // Caps are only set on local users
+ LocalUser* const localuser = static_cast<LocalUser*>(user);
+
+ const std::string& text = details.echooriginal ? details.originaltext : details.text;
if (target.type == MessageTarget::TYPE_USER)
{
User* destuser = target.Get<User>();
- msg.append(destuser->nick);
+ ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, destuser, text, details.type);
+ privmsg.AddTags(details.tags_in);
+ localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg);
}
else if (target.type == MessageTarget::TYPE_CHANNEL)
{
- if (target.status)
- msg.push_back(target.status);
-
Channel* chan = target.Get<Channel>();
- msg.append(chan->name);
+ ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, chan, text, details.type, target.status);
+ privmsg.AddTags(details.tags_in);
+ localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg);
}
else
{
const std::string* servername = target.Get<std::string>();
- msg.append(*servername);
+ ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, *servername, text, details.type);
+ privmsg.AddTags(details.tags_in);
+ localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg);
}
- msg.append(" :").append(details.echooriginal ? details.originaltext : details.text);
- user->WriteFrom(user, msg);
}
void OnUserMessageBlocked(User* user, const MessageTarget& target, const MessageDetails& details) CXX11_OVERRIDE
diff --git a/src/modules/m_ircv3_invitenotify.cpp b/src/modules/m_ircv3_invitenotify.cpp
index 3783ff33c..bcb6f51d5 100644
--- a/src/modules/m_ircv3_invitenotify.cpp
+++ b/src/modules/m_ircv3_invitenotify.cpp
@@ -32,8 +32,8 @@ class ModuleIRCv3InviteNotify : public Module
void OnUserInvite(User* source, User* dest, Channel* chan, time_t expiry, unsigned int notifyrank, CUList& notifyexcepts) CXX11_OVERRIDE
{
- std::string msg = "INVITE ";
- msg.append(dest->nick).append(1, ' ').append(chan->name);
+ ClientProtocol::Messages::Invite invitemsg(source, dest, chan);
+ ClientProtocol::Event inviteevent(ServerInstance->GetRFCEvents().invite, invitemsg);
const Channel::MemberMap& users = chan->GetUsers();
for (Channel::MemberMap::const_iterator i = users.begin(); i != users.end(); ++i)
{
@@ -47,8 +47,10 @@ class ModuleIRCv3InviteNotify : public Module
if (memb->getRank() < notifyrank)
continue;
+ // Caps are only set on local users
+ LocalUser* const localuser = static_cast<LocalUser*>(user);
// Send and add the user to the exceptions so they won't get the NOTICE invite announcement message
- user->WriteFrom(source, msg);
+ localuser->Send(inviteevent);
notifyexcepts.insert(user);
}
}
diff --git a/src/modules/m_knock.cpp b/src/modules/m_knock.cpp
index a0a8455a8..1b66e01a4 100644
--- a/src/modules/m_knock.cpp
+++ b/src/modules/m_knock.cpp
@@ -81,7 +81,13 @@ class CommandKnock : public Command
c->WriteNotice(InspIRCd::Format("User %s is KNOCKing on %s (%s)", user->nick.c_str(), c->name.c_str(), parameters[1].c_str()));
if (sendnumeric)
- c->WriteChannelWithServ(ServerInstance->Config->ServerName, "710 %s %s %s :is KNOCKing: %s", c->name.c_str(), c->name.c_str(), user->GetFullHost().c_str(), parameters[1].c_str());
+ {
+ Numeric::Numeric numeric(710);
+ numeric.push(c->name).push(user->GetFullHost()).push("is KNOCKing: " + parameters[1]);
+
+ ClientProtocol::Messages::Numeric numericmsg(numeric, c->name);
+ c->Write(ServerInstance->GetRFCEvents().numeric, numericmsg);
+ }
user->WriteNotice("KNOCKing on " + c->name);
return CMD_SUCCESS;
diff --git a/src/modules/m_ldapoper.cpp b/src/modules/m_ldapoper.cpp
index 094b37744..cde5b00d7 100644
--- a/src/modules/m_ldapoper.cpp
+++ b/src/modules/m_ldapoper.cpp
@@ -48,7 +48,8 @@ class LDAPOperBase : public LDAPInterface
CommandBase::Params params;
params.push_back(opername);
params.push_back(password);
- oper_command->Handle(user, params);
+ ClientProtocol::TagMap tags;
+ oper_command->Handle(user, CommandBase::Params(params, tags));
}
void Fallback()
diff --git a/src/modules/m_passforward.cpp b/src/modules/m_passforward.cpp
index e3f8624fc..08d3533cd 100644
--- a/src/modules/m_passforward.cpp
+++ b/src/modules/m_passforward.cpp
@@ -91,8 +91,8 @@ class ModulePassForward : public Module
}
std::string tmp;
- FormatStr(tmp,forwardmsg, user);
- user->WriteServ(tmp);
+ FormatStr(tmp, forwardmsg, user);
+ ServerInstance->Parser.ProcessBuffer(user, tmp);
tmp.clear();
FormatStr(tmp,forwardcmd, user);
diff --git a/src/modules/m_samode.cpp b/src/modules/m_samode.cpp
index 195b767ab..8f28a7e9c 100644
--- a/src/modules/m_samode.cpp
+++ b/src/modules/m_samode.cpp
@@ -26,6 +26,8 @@
*/
class CommandSamode : public Command
{
+ bool logged;
+
public:
bool active;
CommandSamode(Module* Creator) : Command(Creator,"SAMODE", 2)
@@ -55,24 +57,29 @@ class CommandSamode : public Command
Modes::ChangeList emptychangelist;
ServerInstance->Modes->ProcessSingle(ServerInstance->FakeClient, NULL, ServerInstance->FakeClient, emptychangelist);
+ logged = false;
this->active = true;
- CmdResult result = ServerInstance->Parser.CallHandler("MODE", parameters, user);
+ ServerInstance->Parser.CallHandler("MODE", parameters, user);
this->active = false;
- if (result == CMD_SUCCESS)
+ if (!logged)
{
- // If lastparse is empty and the MODE command handler returned CMD_SUCCESS then
- // the client queried the list of a listmode (e.g. /SAMODE #chan b), which was
- // handled internally by the MODE command handler.
+ // If we haven't logged anything yet then the client queried the list of a listmode
+ // (e.g. /SAMODE #chan b), which was handled internally by the MODE command handler.
//
- // Viewing the modes of a user or a channel can also result in CMD_SUCCESS, but
+ // Viewing the modes of a user or a channel could also result in this, but
// that is not possible with /SAMODE because we require at least 2 parameters.
- const std::string& lastparse = ServerInstance->Modes.GetLastParse();
- ServerInstance->SNO->WriteGlobalSno('a', user->nick + " used SAMODE: " + (lastparse.empty() ? stdalgo::string::join(parameters) : lastparse));
+ LogUsage(user, stdalgo::string::join(parameters));
}
return CMD_SUCCESS;
}
+
+ void LogUsage(const User* user, const std::string& text)
+ {
+ logged = true;
+ ServerInstance->SNO->WriteGlobalSno('a', user->nick + " used SAMODE: " + text);
+ }
};
class ModuleSaMode : public Module
@@ -96,6 +103,25 @@ class ModuleSaMode : public Module
return MOD_RES_PASSTHRU;
}
+ void OnMode(User* user, User* destuser, Channel* destchan, const Modes::ChangeList& modes, ModeParser::ModeProcessFlag processflags) CXX11_OVERRIDE
+ {
+ if (!cmd.active)
+ return;
+
+ std::string logtext = (destuser ? destuser->nick : destchan->name);
+ logtext.push_back(' ');
+ logtext += ClientProtocol::Messages::Mode::ToModeLetters(modes);
+
+ for (Modes::ChangeList::List::const_iterator i = modes.getlist().begin(); i != modes.getlist().end(); ++i)
+ {
+ const Modes::Change& item = *i;
+ if (!item.param.empty())
+ logtext.append(1, ' ').append(item.param);
+ }
+
+ cmd.LogUsage(user, logtext);
+ }
+
void Prioritize() CXX11_OVERRIDE
{
Module *override = ServerInstance->Modules->Find("m_override.so");
diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp
index d37e1c90f..480f8f6db 100644
--- a/src/modules/m_sasl.cpp
+++ b/src/modules/m_sasl.cpp
@@ -145,7 +145,7 @@ static Events::ModuleEventProvider* saslevprov;
static void SendSASL(LocalUser* user, const std::string& agent, char mode, const std::vector<std::string>& parameters)
{
- CommandBase::Params params(parameters.size() + 3);
+ CommandBase::Params params;
params.push_back(user->uuid);
params.push_back(agent);
params.push_back(ConvToStr(mode));
@@ -157,6 +157,8 @@ static void SendSASL(LocalUser* user, const std::string& agent, char mode, const
}
}
+static ClientProtocol::EventProvider* g_protoev;
+
/**
* Tracks SASL authentication state like charybdis does. --nenolod
*/
@@ -223,7 +225,15 @@ class SaslAuthenticator
return this->state;
if (msg[2] == "C")
- this->user->Write("AUTHENTICATE %s", msg[3].c_str());
+ {
+ ClientProtocol::Message authmsg("AUTHENTICATE");
+ authmsg.PushParamRef(msg[3]);
+
+ ClientProtocol::Event authevent(*g_protoev, authmsg);
+ LocalUser* const localuser = IS_LOCAL(user);
+ if (localuser)
+ localuser->Send(authevent);
+ }
else if (msg[2] == "D")
{
this->state = SASL_DONE;
@@ -377,6 +387,7 @@ class ModuleSASL : public Module
CommandAuthenticate auth;
CommandSASL sasl;
Events::ModuleEventProvider sasleventprov;
+ ClientProtocol::EventProvider protoev;
public:
ModuleSASL()
@@ -386,8 +397,10 @@ class ModuleSASL : public Module
, auth(this, authExt, cap)
, sasl(this, authExt)
, sasleventprov(this, "event/sasl")
+ , protoev(this, auth.name)
{
saslevprov = &sasleventprov;
+ g_protoev = &protoev;
}
void init() CXX11_OVERRIDE
diff --git a/src/modules/m_showfile.cpp b/src/modules/m_showfile.cpp
index 565aaf78b..99c545140 100644
--- a/src/modules/m_showfile.cpp
+++ b/src/modules/m_showfile.cpp
@@ -63,13 +63,14 @@ class CommandShowFile : public Command
user->WriteRemoteNumeric(endnumeric, endtext.c_str());
}
- else
+ else if (IS_LOCAL(user))
{
- const char* msgcmd = (method == SF_MSG ? "PRIVMSG" : "NOTICE");
+ LocalUser* const localuser = IS_LOCAL(user);
for (file_cache::const_iterator i = contents.begin(); i != contents.end(); ++i)
{
const std::string& line = *i;
- user->WriteCommand(msgcmd, ":" + line);
+ ClientProtocol::Messages::Privmsg msg(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, localuser, line, ((method == SF_MSG) ? MSG_PRIVMSG : MSG_NOTICE));
+ localuser->Send(ServerInstance->GetRFCEvents().privmsg, msg);
}
}
return CMD_SUCCESS;
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index 3c9089115..0ff180a83 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -731,7 +731,7 @@ void ModuleSpanningTree::OnUserBack(User* user)
CommandAway::Builder(user).Broadcast();
}
-void ModuleSpanningTree::OnMode(User* source, User* u, Channel* c, const Modes::ChangeList& modes, ModeParser::ModeProcessFlag processflags, const std::string& output_mode)
+void ModuleSpanningTree::OnMode(User* source, User* u, Channel* c, const Modes::ChangeList& modes, ModeParser::ModeProcessFlag processflags)
{
if (processflags & ModeParser::MODE_LOCALONLY)
return;
@@ -743,7 +743,7 @@ void ModuleSpanningTree::OnMode(User* source, User* u, Channel* c, const Modes::
CmdBuilder params(source, "MODE");
params.push(u->uuid);
- params.push(output_mode);
+ params.push(ClientProtocol::Messages::Mode::ToModeLetters(modes));
params.push_raw(Translate::ModeChangeListToParams(modes.getlist()));
params.Broadcast();
}
@@ -752,7 +752,7 @@ void ModuleSpanningTree::OnMode(User* source, User* u, Channel* c, const Modes::
CmdBuilder params(source, "FMODE");
params.push(c->name);
params.push_int(c->age);
- params.push(output_mode);
+ params.push(ClientProtocol::Messages::Mode::ToModeLetters(modes));
params.push_raw(Translate::ModeChangeListToParams(modes.getlist()));
params.Broadcast();
}
diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h
index 4a65f1c37..60f819e9c 100644
--- a/src/modules/m_spanningtree/main.h
+++ b/src/modules/m_spanningtree/main.h
@@ -172,7 +172,7 @@ class ModuleSpanningTree
void OnLoadModule(Module* mod) CXX11_OVERRIDE;
void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
ModResult OnAcceptConnection(int newsock, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE;
- void OnMode(User* source, User* u, Channel* c, const Modes::ChangeList& modes, ModeParser::ModeProcessFlag processflags, const std::string& output_mode) CXX11_OVERRIDE;
+ void OnMode(User* source, User* u, Channel* c, const Modes::ChangeList& modes, ModeParser::ModeProcessFlag processflags) CXX11_OVERRIDE;
CullResult cull() CXX11_OVERRIDE;
~ModuleSpanningTree();
Version GetVersion() CXX11_OVERRIDE;
diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index 3bc1fc71a..513fa6dbf 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -343,7 +343,8 @@ void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command,
res = scmd->Handle(who, params);
else
{
- res = cmd->Handle(who, params);
+ ClientProtocol::TagMap tags;
+ res = cmd->Handle(who, CommandBase::Params(params, tags));
if (res == CMD_INVALID)
throw ProtocolException("Error in command handler");
}
diff --git a/src/modules/m_sqloper.cpp b/src/modules/m_sqloper.cpp
index 2b298f662..da538caef 100644
--- a/src/modules/m_sqloper.cpp
+++ b/src/modules/m_sqloper.cpp
@@ -143,7 +143,8 @@ class OperQuery : public SQL::Query
return;
// Now handle /OPER.
- oper_command->Handle(user, params);
+ ClientProtocol::TagMap tags;
+ oper_command->Handle(user, CommandBase::Params(params, tags));
}
else
{
diff --git a/src/modules/m_timedbans.cpp b/src/modules/m_timedbans.cpp
index ffb84a44f..058028f61 100644
--- a/src/modules/m_timedbans.cpp
+++ b/src/modules/m_timedbans.cpp
@@ -113,7 +113,6 @@ class CommandTban : public Command
return CMD_FAILURE;
}
- CUList tmp;
T.mask = mask;
T.expire = expire + (IS_REMOTE(user) ? 5 : 0);
T.chan = channel;
@@ -124,7 +123,8 @@ class CommandTban : public Command
PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h');
char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@';
- channel->WriteAllExcept(ServerInstance->FakeClient, true, pfxchar, tmp, "NOTICE %s :%s", channel->name.c_str(), addban.c_str());
+ ClientProtocol::Messages::Privmsg notice(ServerInstance->FakeClient, channel, addban, MSG_NOTICE);
+ channel->Write(ServerInstance->GetRFCEvents().privmsg, notice, pfxchar);
ServerInstance->PI->SendChannelNotice(channel, pfxchar, addban);
return CMD_SUCCESS;
}
@@ -210,13 +210,13 @@ class ModuleTimedBans : public Module
std::string mask = i->mask;
Channel* cr = i->chan;
{
- CUList empty;
const std::string expiry = "*** Timed ban on " + cr->name + " expired.";
// If halfop is loaded, send notice to halfops and above, otherwise send to ops and above
PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h');
char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@';
- cr->WriteAllExcept(ServerInstance->FakeClient, true, pfxchar, empty, "NOTICE %s :%s", cr->name.c_str(), expiry.c_str());
+ ClientProtocol::Messages::Privmsg notice(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, cr, expiry, MSG_NOTICE);
+ cr->Write(ServerInstance->GetRFCEvents().privmsg, notice, pfxchar);
ServerInstance->PI->SendChannelNotice(cr, pfxchar, expiry);
Modes::ChangeList setban;