diff options
author | Adam <Adam@anope.org> | 2013-03-15 12:27:08 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2013-03-15 12:27:08 -0500 |
commit | 1a0e6b0be3f901462d4376c882f1dc7304bedaf9 (patch) | |
tree | ff20ba105783b7c79a14a257f79cabb5f3d63d0d | |
parent | 81c89bb7080f17a4bdfd8912863285713e0822df (diff) |
Allow autokicking real names, extbans, and channels
-rw-r--r-- | include/modes.h | 4 | ||||
-rw-r--r-- | include/protocol.h | 1 | ||||
-rw-r--r-- | modules/commands/cs_akick.cpp | 91 | ||||
-rw-r--r-- | modules/protocol/inspircd12.cpp | 5 | ||||
-rw-r--r-- | modules/protocol/inspircd20.cpp | 1 | ||||
-rw-r--r-- | modules/protocol/unreal.cpp | 5 | ||||
-rw-r--r-- | src/modes.cpp | 33 |
7 files changed, 87 insertions, 53 deletions
diff --git a/include/modes.h b/include/modes.h index a9957e332..bb329b5b4 100644 --- a/include/modes.h +++ b/include/modes.h @@ -401,11 +401,11 @@ class CoreExport Entry Anope::string mask; public: unsigned short cidr_len; - Anope::string nick, user, host; + Anope::string nick, user, host, real; /** Constructor * @param mode What mode this host is for, can be empty for unknown/no mode - * @param host A full nick!ident@host/cidr mask + * @param host A full or poartial nick!ident@host/cidr#real name mask */ Entry(const Anope::string &mode, const Anope::string &host); diff --git a/include/protocol.h b/include/protocol.h index 385448662..9ff0167c9 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -222,6 +222,7 @@ class CoreExport IRCDProto : public Service virtual bool IsChannelValid(const Anope::string &); virtual bool IsIdentValid(const Anope::string &); virtual bool IsHostValid(const Anope::string &); + virtual bool IsExtbanValid(const Anope::string &) { return false; } }; class CoreExport MessageSource diff --git a/modules/commands/cs_akick.cpp b/modules/commands/cs_akick.cpp index b388620fc..a3133b8e9 100644 --- a/modules/commands/cs_akick.cpp +++ b/modules/commands/cs_akick.cpp @@ -13,39 +13,6 @@ #include "module.h" -static void split_usermask(const Anope::string &mask, Anope::string &nick, Anope::string &user, Anope::string &host) -{ - size_t ex = mask.find('!'), at = mask.find('@', ex == Anope::string::npos ? 0 : ex + 1); - if (ex == Anope::string::npos) - { - if (at == Anope::string::npos) - { - nick = mask; - user = host = "*"; - } - else - { - nick = "*"; - user = mask.substr(0, at); - host = mask.substr(at + 1); - } - } - else - { - nick = mask.substr(0, ex); - if (at == Anope::string::npos) - { - user = mask.substr(ex + 1); - host = "*"; - } - else - { - user = mask.substr(ex + 1, at - ex - 1); - host = mask.substr(at + 1); - } - } -} - class CommandCSAKick : public Command { void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) @@ -59,12 +26,45 @@ class CommandCSAKick : public Command if (reason.length() > Config->CSReasonMax) reason = reason.substr(0, Config->CSReasonMax); - if (!na) + if (IRCD->IsExtbanValid(mask)) + ; /* If this is an extban don't try to complete the mask */ + else if (IRCD->IsChannelValid(mask)) { - Anope::string nick, user, host; + /* Also don't try to complete the mask if this is a channel */ - split_usermask(mask, nick, user, host); - mask = nick + "!" + user + "@" + host; + if (mask.equals_ci(ci->name) && ci->HasExt("PEACE")) + { + source.Reply(ACCESS_DENIED); + return; + } + } + else if (!na) + { + /* If the mask contains a realname the reason must be prepended with a : */ + if (mask.find('#') != Anope::string::npos) + { + size_t r = reason.find(':'); + if (r != Anope::string::npos) + { + mask += " " + reason.substr(0, r); + mask.trim(); + reason = reason.substr(r + 1); + reason.trim(); + } + else + { + mask = mask + " " + reason; + reason.clear(); + } + } + + Entry e("", mask); + + mask = (e.nick.empty() ? "*" : e.nick) + "!" + + (e.user.empty() ? "*" : e.user) + "@" + + (e.host.empty() ? "*" : e.host); + if (!e.real.empty()) + mask += "#" + e.real; } else nc = na->nc; @@ -87,6 +87,9 @@ class CommandCSAKick : public Command /* Opers overriding get to bypass PEACE */ if (override) ; + /* These peace checks are only for masks */ + else if (IRCD->IsChannelValid(mask)) + ; /* Check whether target nick has equal/higher access * or whether the mask matches a user with higher/equal access - Viper */ else if (ci->HasExt("PEACE") && nc) @@ -526,22 +529,20 @@ class CSAKick : public Module bool kick = false; if (autokick->nc) + kick = autokick->nc == u->Account(); + else if (IRCD->IsChannelValid(autokick->mask)) { - if (autokick->nc == u->Account()) - kick = true; + Channel *c = Channel::Find(autokick->mask); + kick = c != NULL && c->FindUser(u); } else - { - Entry akick_mask("", autokick->mask); - if (akick_mask.Matches(u)) - kick = true; - } + kick = Entry("BAN", autokick->mask).Matches(u); if (kick) { Log(LOG_DEBUG_2) << u->nick << " matched akick " << (autokick->nc ? autokick->nc->display : autokick->mask); autokick->last_used = Anope::CurTime; - if (!autokick->nc) + if (!autokick->nc && autokick->mask.find('#') == Anope::string::npos) mask = autokick->mask; reason = autokick->reason.empty() ? Config->CSAutokickReason : autokick->reason; return EVENT_STOP; diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index 62886d311..1a7f338c1 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -374,6 +374,11 @@ class InspIRCd12Proto : public IRCDProto void SendOper(User *u) anope_override { } + + bool IsExtbanValid(const Anope::string &mask) anope_override + { + return mask.length() >= 3 && mask[1] == ':'; + } }; class InspIRCdExtBan : public ChannelModeList diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index cd2a1bbd4..632c60a3c 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -72,6 +72,7 @@ class InspIRCd20Proto : public IRCDProto void SendLogin(User *u) anope_override { insp12->SendLogin(u); } void SendLogout(User *u) anope_override { insp12->SendLogout(u); } void SendChannel(Channel *c) anope_override { insp12->SendChannel(c); } + bool IsExtbanValid(const Anope::string &mask) anope_override { return insp12->IsExtbanValid(mask); } }; class InspIRCdExtBan : public ChannelModeList diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index 3f1d33279..4bfc8e3fb 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -337,6 +337,11 @@ class UnrealIRCdProto : public IRCDProto return IRCDProto::IsChannelValid(chan); } + bool IsExtbanValid(const Anope::string &mask) anope_override + { + return mask.length() >= 4 && mask[0] == '~' && mask[2] == ':'; + } + void SendLogin(User *u) anope_override { if (!u->Account()) diff --git a/src/modes.cpp b/src/modes.cpp index b7c22dfc7..0eee41682 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -626,7 +626,19 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh this->user = nu; } else - this->host = fh; + { + if (fh.find('.') != Anope::string::npos || fh.find(':') != Anope::string::npos) + this->host = fh; + else + this->nick = fh; + } + + at = this->host.find('#'); + if (at != Anope::string::npos) + { + this->real = this->host.substr(at + 1); + this->host = this->host.substr(0, at); + } /* If the mask is all *'s it will match anything, so just clear it */ if (this->nick.find_first_not_of("*") == Anope::string::npos) @@ -667,6 +679,9 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh catch (const ConvertException &) { } } } + + if (this->real.find_first_not_of("*") == Anope::string::npos) + this->real.clear(); } const Anope::string Entry::GetMask() const @@ -677,12 +692,15 @@ const Anope::string Entry::GetMask() const bool Entry::Matches(const User *u, bool full) const { /* First check if this mode has defined any matches (usually for extbans). */ - ChannelMode *cm = ModeManager::FindChannelModeByName(this->name); - if (cm != NULL && cm->type == MODE_LIST) + if (IRCD->IsExtbanValid(this->mask)) { - ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm); - if (cml->Matches(u, this)) - return true; + ChannelMode *cm = ModeManager::FindChannelModeByName(this->name); + if (cm != NULL && cm->type == MODE_LIST) + { + ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm); + if (cml->Matches(u, this)) + return true; + } } /* If the user's displayed host is their real host, then we can do a full match without @@ -714,6 +732,9 @@ bool Entry::Matches(const User *u, bool full) const (!full || (!Anope::Match(u->host, this->host) && !Anope::Match(u->ip, this->host)))) ret = false; + if (!this->real.empty() && !Anope::Match(u->realname, this->real)) + ret = false; + return ret; } |