summaryrefslogtreecommitdiff
path: root/modules/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'modules/protocol')
-rw-r--r--modules/protocol/bahamut.cpp4
-rw-r--r--modules/protocol/hybrid.cpp24
-rw-r--r--modules/protocol/inspircd20.cpp221
-rw-r--r--modules/protocol/ngircd.cpp2
-rw-r--r--modules/protocol/plexus.cpp6
-rw-r--r--modules/protocol/ratbox.cpp2
-rw-r--r--modules/protocol/unreal.cpp131
7 files changed, 307 insertions, 83 deletions
diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp
index a67f4dc0d..5649dbbbe 100644
--- a/modules/protocol/bahamut.cpp
+++ b/modules/protocol/bahamut.cpp
@@ -16,7 +16,7 @@ class ChannelModeFlood : public ChannelModeParam
public:
ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
- bool IsValid(const Anope::string &value) const override
+ bool IsValid(Anope::string &value) const override
{
try
{
@@ -175,7 +175,7 @@ class BahamutIRCdProto : public IRCDProto
if (uc != NULL)
uc->status.Clear();
- BotInfo *setter = BotInfo::Find(user->nick);
+ BotInfo *setter = BotInfo::Find(user->GetUID());
for (size_t i = 0; i < cs.Modes().length(); ++i)
c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
diff --git a/modules/protocol/hybrid.cpp b/modules/protocol/hybrid.cpp
index 116f56a84..eb774d541 100644
--- a/modules/protocol/hybrid.cpp
+++ b/modules/protocol/hybrid.cpp
@@ -1,7 +1,7 @@
/* ircd-hybrid-8 protocol module
*
* (C) 2003-2014 Anope Team
- * (C) 2012-2013 by the Hybrid Development Team
+ * (C) 2012-2014 ircd-hybrid development team
*
* Please read COPYING and README for further details.
*
@@ -40,10 +40,11 @@ class HybridProto : public IRCDProto
{
DefaultPseudoclientModes = "+oi";
CanSVSNick = true;
+ CanSVSHold = true;
+ CanSVSJoin = true;
CanSNLine = true;
CanSQLine = true;
CanSZLine = true;
- CanSVSHold = true;
CanCertFP = true;
CanSetVHost = true;
RequiresID = true;
@@ -174,9 +175,9 @@ class HybridProto : public IRCDProto
void SendServer(const Server *server) override
{
if (server == Me)
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :" << server->GetDescription();
+ UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() + 1 << " :" << server->GetDescription();
else
- UplinkSocket::Message(Me) << "SID " << server->GetName() << " " << server->GetHops() << " " << server->GetSID() << " :" << server->GetDescription();
+ UplinkSocket::Message(Me) << "SID " << server->GetName() << " " << server->GetHops() + 1 << " " << server->GetSID() << " :" << server->GetDescription();
}
void SendConnect() override
@@ -254,6 +255,19 @@ class HybridProto : public IRCDProto
UplinkSocket::Message(Me) << "SVSNICK " << u->nick << " " << newnick << " " << when;
}
+ void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &) override
+ {
+ UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan;
+ }
+
+ void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) override
+ {
+ if (!param.empty())
+ UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param;
+ else
+ UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan;
+ }
+
void SendSVSHold(const Anope::string &nick, time_t t) override
{
XLine x(nick, Me->GetName(), Anope::CurTime + t, "Being held for registered user");
@@ -611,7 +625,7 @@ class ProtoHybrid : public Module
ModeManager::AddUserMode(new UserModeOperOnly("CALLERID", 'g'));
ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l'));
- ModeManager::AddUserMode(new UserMode("OPER", 'o'));
+ ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o'));
ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r'));
ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's'));
ModeManager::AddUserMode(new UserMode("WALLOPS", 'w'));
diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp
index 1981b3cc5..b25d4d5cb 100644
--- a/modules/protocol/inspircd20.cpp
+++ b/modules/protocol/inspircd20.cpp
@@ -434,25 +434,61 @@ class InspIRCd20Proto : public IRCDProto
}
};
-class InspIRCdExtBan : public ChannelModeList
+class InspIRCdExtBan : public ChannelModeVirtual<ChannelModeList>
{
+ char ext;
+
public:
- InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { }
+ InspIRCdExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
+ , ext(extban)
+ {
+ }
+
+ ChannelMode *Wrap(Anope::string &param) override
+ {
+ param = Anope::string(ext) + ":" + param;
+ return ChannelModeVirtual<ChannelModeList>::Wrap(param);
+ }
- bool Matches(User *u, const Entry *e) override
+ ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) override
{
- const Anope::string &mask = e->GetMask();
+ if (cm->type != MODE_LIST || param.length() < 3 || param[0] != ext || param[1] != ':')
+ return cm;
- if (mask.find("m:") == 0 || mask.find("N:") == 0)
+ param = param.substr(2);
+ return this;
+ }
+};
+
+namespace InspIRCdExtban
+{
+ class EntryMatcher : public InspIRCdExtBan
+ {
+ public:
+ EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
{
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
- Entry en(this->name, real_mask);
- if (en.Matches(u))
- return true;
+ return Entry(this->name, real_mask).Matches(u);
+ }
+ };
+
+ class ChannelMatcher : public InspIRCdExtBan
+ {
+ public:
+ ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
+ {
}
- else if (mask.find("j:") == 0)
+
+ bool Matches(User *u, const Entry *e) override
{
+ const Anope::string &mask = e->GetMask();
+
Anope::string channel = mask.substr(3);
ChannelMode *cm = NULL;
@@ -473,46 +509,94 @@ class InspIRCdExtBan : public ChannelModeList
if (cm == NULL || uc->status.HasMode(cm->mchar))
return true;
}
- }
- else if (mask.find("R:") == 0)
- {
- Anope::string real_mask = mask.substr(2);
- if (u->IsIdentified() && real_mask.equals_ci(u->Account()->display))
- return true;
+ return false;
}
- else if (mask.find("r:") == 0)
- {
- Anope::string real_mask = mask.substr(2);
+ };
- if (Anope::Match(u->realname, real_mask))
- return true;
- }
- else if (mask.find("s:") == 0)
+ class AccountMatcher : public InspIRCdExtBan
+ {
+ public:
+ AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
{
+ const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(2);
- if (Anope::Match(u->server->GetName(), real_mask))
- return true;
+ return u->IsIdentified() && real_mask.equals_ci(u->Account()->display);
}
- else if (mask.find("z:") == 0)
+ };
+
+ class RealnameMatcher : public InspIRCdExtBan
+ {
+ public:
+ RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ const Anope::string &mask = e->GetMask();
+ Anope::string real_mask = mask.substr(2);
+ return Anope::Match(u->realname, real_mask);
+ }
+ };
+
+ class ServerMatcher : public InspIRCdExtBan
+ {
+ public:
+ ServerMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ const Anope::string &mask = e->GetMask();
+ Anope::string real_mask = mask.substr(2);
+ return Anope::Match(u->server->GetName(), real_mask);
+ }
+ };
+
+ class FinerprintMatcher : public InspIRCdExtBan
+ {
+ public:
+ FinerprintMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ const Anope::string &mask = e->GetMask();
+ Anope::string real_mask = mask.substr(2);
+ return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
+ }
+ };
+
+ class UnidentifiedMatcher : public InspIRCdExtBan
+ {
+ public:
+ UnidentifiedMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
{
- Anope::string real_mask = mask.substr(2);
-
- if (!u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask))
- return true;
}
- return false;
- }
-};
+ bool Matches(User *u, const Entry *e) override
+ {
+ const Anope::string &mask = e->GetMask();
+ Anope::string real_mask = mask.substr(2);
+ return !u->Account() && Entry("BAN", real_mask).Matches(u);
+ }
+ };
+}
class ColonDelimitedParamMode : public ChannelModeParam
{
public:
ColonDelimitedParamMode(const Anope::string &modename, char modeChar) : ChannelModeParam(modename, modeChar, true) { }
- bool IsValid(const Anope::string &value) const override
+ bool IsValid(Anope::string &value) const override
{
return IsValid(value, false);
}
@@ -561,7 +645,7 @@ class SimpleNumberParamMode : public ChannelModeParam
public:
SimpleNumberParamMode(const Anope::string &modename, char modeChar) : ChannelModeParam(modename, modeChar, true) { }
- bool IsValid(const Anope::string &value) const override
+ bool IsValid(Anope::string &value) const override
{
if (value.empty())
return false; // empty param is never valid
@@ -586,11 +670,12 @@ class ChannelModeFlood : public ColonDelimitedParamMode
public:
ChannelModeFlood(char modeChar) : ColonDelimitedParamMode("FLOOD", modeChar) { }
- bool IsValid(const Anope::string &value) const override
+ bool IsValid(Anope::string &value) const override
{
// The parameter of this mode is a bit different, it may begin with a '*',
// ignore it if that's the case
- return ((!value.empty()) && (ColonDelimitedParamMode::IsValid(value[0] == '*' ? value.substr(1) : value)));
+ Anope::string v = value[0] == '*' ? value.substr(1) : value;
+ return ((!value.empty()) && (ColonDelimitedParamMode::IsValid(v)));
}
};
@@ -599,7 +684,7 @@ class ChannelModeHistory : public ColonDelimitedParamMode
public:
ChannelModeHistory(char modeChar) : ColonDelimitedParamMode("HISTORY", modeChar) { }
- bool IsValid(const Anope::string &value) const override
+ bool IsValid(Anope::string &value) const override
{
return (ColonDelimitedParamMode::IsValid(value, true));
}
@@ -610,7 +695,7 @@ class ChannelModeRedirect : public ChannelModeParam
public:
ChannelModeRedirect(char modeChar) : ChannelModeParam("REDIRECT", modeChar, true) { }
- bool IsValid(const Anope::string &value) const override
+ bool IsValid(Anope::string &value) const override
{
// The parameter of this mode is a channel, and channel names start with '#'
return ((!value.empty()) && (value[0] == '#'));
@@ -661,17 +746,26 @@ struct IRCDMessageCapab : Message::Capab
if (modename.equals_cs("admin"))
cm = new ChannelModeStatus("PROTECT", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 3);
else if (modename.equals_cs("allowinvite"))
+ {
cm = new ChannelMode("ALLINVITE", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("INVITEBAN", "BAN", 'A'));
+ }
else if (modename.equals_cs("auditorium"))
cm = new ChannelMode("AUDITORIUM", modechar[0]);
else if (modename.equals_cs("ban"))
- cm = new InspIRCdExtBan("BAN", modechar[0]);
+ cm = new ChannelModeList("BAN", modechar[0]);
else if (modename.equals_cs("banexception"))
- cm = new InspIRCdExtBan("EXCEPT", 'e');
+ cm = new ChannelModeList("EXCEPT", modechar[0]);
else if (modename.equals_cs("blockcaps"))
+ {
cm = new ChannelMode("BLOCKCAPS", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("BLOCKCAPSBAN", "BAN", 'B'));
+ }
else if (modename.equals_cs("blockcolor"))
+ {
cm = new ChannelMode("BLOCKCOLOR", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("BLOCKCOLORBAN", "BAN", 'c'));
+ }
else if (modename.equals_cs("c_registered"))
cm = new ChannelModeNoone("REGISTERED", modechar[0]);
else if (modename.equals_cs("censor"))
@@ -691,7 +785,7 @@ struct IRCDMessageCapab : Message::Capab
else if (modename.equals_cs("history"))
cm = new ChannelModeHistory(modechar[0]);
else if (modename.equals_cs("invex"))
- cm = new InspIRCdExtBan("INVITEOVERRIDE", 'I');
+ cm = new ChannelModeList("INVITEOVERRIDE", modechar[0]);
else if (modename.equals_cs("inviteonly"))
cm = new ChannelMode("INVITE", modechar[0]);
else if (modename.equals_cs("joinflood"))
@@ -707,17 +801,29 @@ struct IRCDMessageCapab : Message::Capab
else if (modename.equals_cs("nickflood"))
cm = new ColonDelimitedParamMode("NICKFLOOD", modechar[0]);
else if (modename.equals_cs("noctcp"))
+ {
cm = new ChannelMode("NOCTCP", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NOCTCPBAN", "BAN", 'C'));
+ }
else if (modename.equals_cs("noextmsg"))
cm = new ChannelMode("NOEXTERNAL", modechar[0]);
else if (modename.equals_cs("nokick"))
+ {
cm = new ChannelMode("NOKICK", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NOKICKBAN", "BAN", 'Q'));
+ }
else if (modename.equals_cs("noknock"))
cm = new ChannelMode("NOKNOCK", modechar[0]);
else if (modename.equals_cs("nonick"))
+ {
cm = new ChannelMode("NONICK", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NONICKBAN", "BAN", 'N'));
+ }
else if (modename.equals_cs("nonotice"))
+ {
cm = new ChannelMode("NONOTICE", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NONOTICEBAN", "BAN", 'T'));
+ }
else if (modename.equals_cs("op"))
cm = new ChannelModeStatus("OP", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 2);
else if (modename.equals_cs("operonly"))
@@ -735,9 +841,15 @@ struct IRCDMessageCapab : Message::Capab
else if (modename.equals_cs("secret"))
cm = new ChannelMode("SECRET", modechar[0]);
else if (modename.equals_cs("sslonly"))
+ {
cm = new ChannelMode("SSL", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::FinerprintMatcher("SSLBAN", "BAN", 'z'));
+ }
else if (modename.equals_cs("stripcolor"))
+ {
cm = new ChannelMode("STRIPCOLOR", modechar[0]);
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("STRIPCOLORBAN", "BAN", 'S'));
+ }
else if (modename.equals_cs("topiclock"))
cm = new ChannelMode("TOPIC", modechar[0]);
else if (modename.equals_cs("voice"))
@@ -838,11 +950,25 @@ struct IRCDMessageCapab : Message::Capab
while (ssep.GetToken(module))
{
if (module.equals_cs("m_services_account.so"))
+ {
Servers::Capab.insert("SERVICES");
+ ModeManager::AddChannelMode(new InspIRCdExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'R'));
+ ModeManager::AddChannelMode(new InspIRCdExtban::UnidentifiedMatcher("UNREGISTEREDBAN", "BAN", 'U'));
+ }
else if (module.equals_cs("m_chghost.so"))
Servers::Capab.insert("CHGHOST");
else if (module.equals_cs("m_chgident.so"))
Servers::Capab.insert("CHGIDENT");
+ else if (module == "m_channelban.so")
+ ModeManager::AddChannelMode(new InspIRCdExtban::ChannelMatcher("CHANNELBAN", "BAN", 'j'));
+ else if (module == "m_gecosban.so")
+ ModeManager::AddChannelMode(new InspIRCdExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
+ else if (module == "m_nopartmessage.so")
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("PARTMESSAGEBAN", "BAN", 'p'));
+ else if (module == "m_serverban.so")
+ ModeManager::AddChannelMode(new InspIRCdExtban::ServerMatcher("SERVERBAN", "BAN", 's'));
+ else if (module == "m_muteban.so")
+ ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("QUIET", "BAN", 'm'));
}
}
else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
@@ -934,6 +1060,8 @@ struct IRCDMessageCapab : Message::Capab
ModeManager::RebuildStatusModes();
}
+ else if (capab == "GLOBOPS=1")
+ Servers::Capab.insert("GLOBOPS");
}
}
else if (params[0].equals_cs("END"))
@@ -1431,6 +1559,7 @@ class ProtoInspIRCd20 : public Module
, public EventHook<Event::DelChan>
, public EventHook<Event::MLockEvents>
, public EventHook<Event::SetChannelOption>
+ , public EventHook<Event::ChannelModeUnset>
{
InspIRCd20Proto ircd_proto;
ExtensibleItem<bool> ssl;
@@ -1486,6 +1615,7 @@ class ProtoInspIRCd20 : public Module
, EventHook<Event::DelChan>("OnDelChan")
, EventHook<Event::MLockEvents>("MLock")
, EventHook<Event::SetChannelOption>("OnSetChannelOption")
+ , EventHook<Event::ChannelModeUnset>("OnChannelModeUnset")
, ircd_proto(this)
, ssl(this, "ssl")
, message_away(this)
@@ -1604,6 +1734,15 @@ class ProtoInspIRCd20 : public Module
return EVENT_CONTINUE;
}
+
+ EventReturn OnChannelModeUnset(Channel *c, const MessageSource &setter, ChannelMode *mode, const Anope::string &param) override
+ {
+ if ((setter.GetUser() && setter.GetUser()->server == Me) || setter.GetServer() == Me || !setter.GetServer())
+ if (mode->name == "OPERPREFIX")
+ c->SetMode(c->ci->WhoSends(), mode, param, false);
+
+ return EVENT_CONTINUE;
+ }
};
MODULE_INIT(ProtoInspIRCd20)
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
index 5832da62f..dc875cdbb 100644
--- a/modules/protocol/ngircd.cpp
+++ b/modules/protocol/ngircd.cpp
@@ -101,7 +101,7 @@ class ngIRCdProto : public IRCDProto
if (uc != NULL)
uc->status.Clear();
- BotInfo *setter = BotInfo::Find(user->nick);
+ BotInfo *setter = BotInfo::Find(user->GetUID());
for (size_t i = 0; i < cs.Modes().length(); ++i)
c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp
index 6e2930757..a804202b3 100644
--- a/modules/protocol/plexus.cpp
+++ b/modules/protocol/plexus.cpp
@@ -67,7 +67,7 @@ class PlexusProto : public IRCDProto
if (uc != NULL)
uc->status.Clear();
- BotInfo *setter = BotInfo::Find(user->nick);
+ BotInfo *setter = BotInfo::Find(user->GetUID());
for (size_t i = 0; i < cs.Modes().length(); ++i)
c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
@@ -333,10 +333,10 @@ class ProtoPlexus : public Module
ModeManager::AddUserMode(new UserMode("CALLERID", 'g'));
ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l'));
- ModeManager::AddUserMode(new UserMode("OPER", 'o'));
+ ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o'));
ModeManager::AddUserMode(new UserModeOperOnly("NETADMIN", 'N'));
ModeManager::AddUserMode(new UserMode("PRIV", 'p'));
- ModeManager::AddUserMode(new UserMode("ROUTING", 'q'));
+ ModeManager::AddUserMode(new UserModeOperOnly("ROUTING", 'q'));
ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r'));
ModeManager::AddUserMode(new UserMode("REGPRIV", 'R'));
ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's'));
diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp
index 8a88e74a3..a0d2cf9a2 100644
--- a/modules/protocol/ratbox.cpp
+++ b/modules/protocol/ratbox.cpp
@@ -253,7 +253,7 @@ class ProtoRatbox : public Module
// k = skill?
ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l'));
// n = nchange
- ModeManager::AddUserMode(new UserMode("OPER", 'o'));
+ ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o'));
// r = rej
ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's'));
ModeManager::AddUserMode(new UserModeNoone("PROTECTED", 'S'));
diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp
index 606f22270..721ba50c3 100644
--- a/modules/protocol/unreal.cpp
+++ b/modules/protocol/unreal.cpp
@@ -167,7 +167,7 @@ class UnrealIRCdProto : public IRCDProto
if (uc != NULL)
uc->status.Clear();
- BotInfo *setter = BotInfo::Find(user->nick);
+ BotInfo *setter = BotInfo::Find(user->GetUID());
for (size_t i = 0; i < cs.Modes().length(); ++i)
c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
@@ -415,17 +415,44 @@ class UnrealIRCdProto : public IRCDProto
}
};
-class UnrealExtBan : public ChannelModeList
+class UnrealExtBan : public ChannelModeVirtual<ChannelModeList>
{
+ char ext;
+
public:
- UnrealExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { }
+ UnrealExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
+ , ext(extban)
+ {
+ }
+
+ ChannelMode *Wrap(Anope::string &param) override
+ {
+ param = "~" + Anope::string(ext) + ":" + param;
+ return ChannelModeVirtual<ChannelModeList>::Wrap(param);
+ }
- bool Matches(User *u, const Entry *e) override
+ ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) override
{
- const Anope::string &mask = e->GetMask();
+ if (cm->type != MODE_LIST || param.length() < 4 || param[0] != '~' || param[1] != ext || param[2] != ':')
+ return cm;
- if (mask.find("~c:") == 0)
+ param = param.substr(3);
+ return this;
+ }
+};
+
+namespace UnrealExtban
+{
+ class ChannelMatcher : public UnrealExtBan
+ {
+ public:
+ ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
{
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ const Anope::string &mask = e->GetMask();
Anope::string channel = mask.substr(3);
ChannelMode *cm = NULL;
@@ -446,38 +473,73 @@ class UnrealExtBan : public ChannelModeList
if (cm == NULL || uc->status.HasMode(cm->mchar))
return true;
}
+
+ return false;
}
- else if (mask.find("~j:") == 0 || mask.find("~n:") == 0 || mask.find("~q:") == 0)
+ };
+
+ class EntryMatcher : public UnrealExtBan
+ {
+ public:
+ EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
{
+ const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
- Entry en(this->name, real_mask);
- if (en.Matches(u))
- return true;
+ return Entry(this->name, real_mask).Matches(u);
}
- else if (mask.find("~r:") == 0)
+ };
+
+ class RealnameMatcher : public UnrealExtBan
+ {
+ public:
+ RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
{
+ const Anope::string &mask = e->GetMask();
Anope::string real_mask = mask.substr(3);
- if (Anope::Match(u->realname, real_mask))
- return true;
+ return Anope::Match(u->realname, real_mask);
}
- else if (mask.find("~R:") == 0)
+ };
+
+ class RegisteredMatcher : public UnrealExtBan
+ {
+ public:
+ RegisteredMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
{
- if (u->HasMode("REGISTERED") && mask.equals_ci(u->nick))
- return true;
+ const Anope::string &mask = e->GetMask();
+ return u->HasMode("REGISTERED") && mask.equals_ci(u->nick);
}
- else if (mask.find("~a:") == 0)
- {
- Anope::string real_mask = mask.substr(3);
+ };
- if (u->Account() && Anope::Match(u->Account()->display, real_mask))
- return true;
- }
+ class AccountMatcher : public UnrealExtBan
+ {
+ public:
+ AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ {
+ }
- return false;
- }
-};
+ bool Matches(User *u, const Entry *e) override
+ {
+ const Anope::string &mask = e->GetMask();
+ Anope::string real_mask = mask.substr(3);
+
+ return u->Account() && Anope::Match(u->Account()->display, real_mask);
+ }
+ };
+}
class ChannelModeFlood : public ChannelModeParam
{
@@ -485,7 +547,7 @@ class ChannelModeFlood : public ChannelModeParam
ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
/* Borrowed part of this check from UnrealIRCd */
- bool IsValid(const Anope::string &value) const override
+ bool IsValid(Anope::string &value) const override
{
if (value.empty())
return false;
@@ -565,13 +627,21 @@ struct IRCDMessageCapab : Message::Capab
switch (modebuf[t])
{
case 'b':
- ModeManager::AddChannelMode(new UnrealExtBan("BAN", 'b'));
+ ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
+
+ ModeManager::AddChannelMode(new UnrealExtban::ChannelMatcher("CHANNELBAN", "BAN", 'c'));
+ ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("JOINBAN", "BAN", 'j'));
+ ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("NONICKBAN", "BAN", 'n'));
+ ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("QUIET", "BAN", 'q'));
+ ModeManager::AddChannelMode(new UnrealExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
+ ModeManager::AddChannelMode(new UnrealExtban::RegisteredMatcher("REGISTEREDBAN", "BAN", 'R'));
+ ModeManager::AddChannelMode(new UnrealExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'a'));
continue;
case 'e':
- ModeManager::AddChannelMode(new UnrealExtBan("EXCEPT", 'e'));
+ ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
continue;
case 'I':
- ModeManager::AddChannelMode(new UnrealExtBan("INVITEOVERRIDE", 'I'));
+ ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I'));
continue;
default:
ModeManager::AddChannelMode(new ChannelModeList("", modebuf[t]));
@@ -1105,7 +1175,7 @@ class ProtoUnreal : public Module
Message::Invite message_invite;
Message::Join message_join;
Message::Kick message_kick;
- Message::Kill message_kill;
+ Message::Kill message_kill, message_svskill;
Message::MOTD message_motd;
Message::Notice message_notice;
Message::Part message_part;
@@ -1199,6 +1269,7 @@ class ProtoUnreal : public Module
, message_quit(this)
, message_squit(this)
, message_stats(this)
+ , message_svskill(this, "SVSKILL")
, message_time(this)
, message_version(this)
, message_whois(this)