diff options
author | Adam <Adam@anope.org> | 2014-04-25 16:51:06 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2014-04-25 16:51:06 -0400 |
commit | 6a03eb69ebbe773f1d4139ff88d74ecdb2b0af4b (patch) | |
tree | d370fbc4a1dd55b72dbcda9f2aff24678d5626f3 /modules/protocol | |
parent | 4fa2a00bd595eb120e6acde5eb167759c2018e33 (diff) |
Add "virtual mode" support
This allows fully tracking extbans and other modes set by a different
underlying mode, such as InspIRCd's namedmodes
Add two configuration options to cs_ban to configure which mode is set
and whether or not to kick banned users.
Add default "mute" fantasy command to botserv.example.conf
Diffstat (limited to 'modules/protocol')
-rw-r--r-- | modules/protocol/inspircd20.cpp | 195 | ||||
-rw-r--r-- | modules/protocol/unreal.cpp | 124 |
2 files changed, 257 insertions, 62 deletions
diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index 4e88d01a8..1e439da30 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -77,25 +77,61 @@ class InspIRCd20Proto : public IRCDProto bool IsIdentValid(const Anope::string &ident) anope_override { return insp12->IsIdentValid(ident); } }; -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 ¶m) anope_override + { + param = Anope::string(ext) + ":" + param; + return ChannelModeVirtual<ChannelModeList>::Wrap(param); + } - bool Matches(User *u, const Entry *e) anope_override + ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) anope_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) anope_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) anope_override { + const Anope::string &mask = e->GetMask(); + Anope::string channel = mask.substr(3); ChannelMode *cm = NULL; @@ -116,39 +152,87 @@ 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) anope_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) - { - Anope::string real_mask = mask.substr(2); + }; - if (!u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask)) - return true; + 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) anope_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) anope_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) anope_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) + { } - return false; - } -}; + bool Matches(User *u, const Entry *e) anope_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 { @@ -304,17 +388,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")) @@ -334,7 +427,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")) @@ -350,17 +443,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")) @@ -378,9 +483,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")) @@ -481,11 +592,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) diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index d7bc8fa14..f444947f6 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -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 ¶m) anope_override + { + param = "~" + Anope::string(ext) + ":" + param; + return ChannelModeVirtual<ChannelModeList>::Wrap(param); + } - bool Matches(User *u, const Entry *e) anope_override + ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) anope_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) anope_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) anope_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) anope_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) anope_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) - { + }; + + class AccountMatcher : public UnrealExtBan + { + public: + AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c) + { + } + + bool Matches(User *u, const Entry *e) anope_override + { + const Anope::string &mask = e->GetMask(); Anope::string real_mask = mask.substr(3); - if (u->Account() && Anope::Match(u->Account()->display, real_mask)) - return true; - } - - return false; - } -}; + return u->Account() && Anope::Match(u->Account()->display, real_mask); + } + }; +} class ChannelModeFlood : public ChannelModeParam { @@ -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])); |