diff --git a/include/modes.h b/include/modes.h index fa46f7276..4b008978c 100644 --- a/include/modes.h +++ b/include/modes.h @@ -442,16 +442,17 @@ public: /** Constructor * @param mode What mode this host is for, can be empty for unknown/no mode - * @param host A full or partial nick!ident@host/cidr#real name mask + * @param mask A full or partial nick!ident@host/cidr#real name mask + * @Param real Whether to allow a real name in the mask. */ - Entry(const Anope::string &mode, const Anope::string &host); + Entry(const Anope::string &mode, const Anope::string &mask, bool real = true); /** Get the banned mask for this entry * @return The mask */ Anope::string GetMask() const; - Anope::string GetNUHMask() const; + Anope::string GetCleanMask() const; /** Check if this entry matches a user * @param u The user diff --git a/modules/chanserv/cs_access.cpp b/modules/chanserv/cs_access.cpp index 8993cbc03..8d6d773a7 100644 --- a/modules/chanserv/cs_access.cpp +++ b/modules/chanserv/cs_access.cpp @@ -226,7 +226,7 @@ private: else { // Normalize the entry mask. - mask = Entry("", mask).GetNUHMask(); + mask = Entry("", mask).GetCleanMask(); } } } diff --git a/modules/chanserv/cs_flags.cpp b/modules/chanserv/cs_flags.cpp index 7b19087df..470ef9680 100644 --- a/modules/chanserv/cs_flags.cpp +++ b/modules/chanserv/cs_flags.cpp @@ -153,7 +153,7 @@ class CommandCSFlags final else { // Normalize the entry mask. - mask = Entry("", mask).GetNUHMask(); + mask = Entry("", mask).GetCleanMask(); } } } diff --git a/modules/chanserv/cs_xop.cpp b/modules/chanserv/cs_xop.cpp index e785eacac..53fb7a5f4 100644 --- a/modules/chanserv/cs_xop.cpp +++ b/modules/chanserv/cs_xop.cpp @@ -201,7 +201,7 @@ private: else { // Normalize the entry mask. - mask = Entry("", mask).GetNUHMask(); + mask = Entry("", mask).GetCleanMask(); } } } diff --git a/modules/protocol/inspircd.cpp b/modules/protocol/inspircd.cpp index cbc822942..11a85daa4 100644 --- a/modules/protocol/inspircd.cpp +++ b/modules/protocol/inspircd.cpp @@ -788,7 +788,7 @@ namespace InspIRCdExtBan bool Matches(User *u, const Entry *e) override { - return Entry(this->name, e->GetMask()).Matches(u); + return Entry(this->name, e->GetMask(), false).Matches(u); } }; @@ -898,7 +898,7 @@ namespace InspIRCdExtBan bool Matches(User *u, const Entry *e) override { - return !u->Account() && Entry(this->base, e->GetMask()).Matches(u); + return !u->Account() && Entry(this->base, e->GetMask(), false).Matches(u); } }; diff --git a/modules/protocol/unrealircd.cpp b/modules/protocol/unrealircd.cpp index d32b6686b..728a77f83 100644 --- a/modules/protocol/unrealircd.cpp +++ b/modules/protocol/unrealircd.cpp @@ -564,7 +564,7 @@ namespace UnrealExtBan bool Matches(User *u, const Entry *e) override { - return Entry(this->base, e->GetMask()).Matches(u); + return Entry(this->base, e->GetMask(), false).Matches(u); } }; @@ -646,7 +646,7 @@ namespace UnrealExtBan /* strip down the time (~t:1234:) and call other matchers */ auto real_mask = e->GetMask(); real_mask = real_mask.substr(real_mask.find(":") + 1); - return Entry("BAN", real_mask).Matches(u); + return Entry("BAN", real_mask, false).Matches(u); } }; diff --git a/src/modes.cpp b/src/modes.cpp index 17e424701..61a66a314 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -673,42 +673,49 @@ void ModeManager::StackerDel(Mode *m) } } -Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh) +Entry::Entry(const Anope::string &n, const Anope::string &m, bool r) + : name(n) + , mask(m) { - Anope::string n, u, h; - - size_t at = fh.find('@'); - if (at != Anope::string::npos) + const auto first_sep = this->mask.find_first_of("!@"); + if (first_sep == Anope::string::npos) { - this->host = fh.substr(at + 1); + if (this->mask.find_first_of(".:") == Anope::string::npos) + this->nick = this->mask; + else + this->host = this->mask; + } + else if (this->mask[first_sep] == '!') + { + this->nick = this->mask.substr(0, first_sep); - const Anope::string &nu = fh.substr(0, at); - - size_t ex = nu.find('!'); - if (ex != Anope::string::npos) + const auto second_sep = this->mask.find('@'); + if (second_sep == Anope::string::npos) + this->user = this->mask.substr(first_sep + 1); + else { - this->user = nu.substr(ex + 1); - this->nick = nu.substr(0, ex); + this->user = this->mask.substr(first_sep + 1, second_sep - first_sep - 1); + this->host = this->mask.substr(second_sep + 1); } - else - this->user = nu; } - else + else if (this->mask[first_sep] == '@') { - if (fh.find('.') != Anope::string::npos || fh.find(':') != Anope::string::npos) - this->host = fh; - else - this->nick = fh; + this->user = this->mask.substr(0, first_sep); + this->host = this->mask.substr(first_sep + 1); } - at = this->host.find('#'); - if (at != Anope::string::npos) + // If the mask can have a realname then extract that. + if (r) { - this->real = this->host.substr(at + 1); - this->host = this->host.substr(0, at); + const auto real_sep = this->host.find('#'); + if (real_sep != Anope::string::npos) + { + this->real = this->host.substr(real_sep + 1); + this->host.erase(real_sep); + } } - /* If the mask is all *'s it will match anything, so just clear it */ + // If the mask is all *'s it will match anything, so just clear it. if (this->nick.find_first_not_of("*") == Anope::string::npos) this->nick.clear(); @@ -719,22 +726,19 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh this->host.clear(); else { - /* Host might be a CIDR range */ - size_t sl = this->host.find_last_of('/'); - if (sl != Anope::string::npos) + // Host might be a CIDR range. + const auto cidr_sep = this->host.find_last_of('/'); + if (cidr_sep != Anope::string::npos) { - const Anope::string &cidr_ip = this->host.substr(0, sl), - &cidr_range = this->host.substr(sl + 1); + sockaddrs cidr_addr(this->host.substr(0, cidr_sep)); + const auto cidr_range = this->host.substr(cidr_sep + 1); - sockaddrs addr(cidr_ip); - auto range = Anope::TryConvert(cidr_range); - if (addr.valid() && range.has_value()) + const auto range = Anope::TryConvert(cidr_range); + if (cidr_addr.valid() && range.has_value()) { this->cidr_len = range.value(); - this->host = cidr_ip; - this->family = addr.family(); - - Log(LOG_DEBUG) << "Ban " << mask << " has cidr " << this->cidr_len; + this->family = cidr_addr.family(); + this->host = cidr_addr.addr(); } } } @@ -748,26 +752,38 @@ Anope::string Entry::GetMask() const return this->mask; } -Anope::string Entry::GetNUHMask() const +Anope::string Entry::GetCleanMask() const { - Anope::string n = nick.empty() ? "*" : nick, - u = user.empty() ? "*" : user, - h = host.empty() ? "*" : host, - r = real.empty() ? "" : "#" + real, - c; + Anope::string cmask; + cmask.append(this->nick.empty() ? "*" : this->nick); + cmask.push_back('!'); + cmask.append(this->user.empty() ? "*" : this->user); + cmask.push_back('@'); + cmask.append(this->host.empty() ? "*" : this->host); + switch (family) { case AF_INET: - if (cidr_len <= 32) - c = "/" + Anope::ToString(cidr_len); + { + if (cidr_len < 32) + cmask.append("/").append(Anope::ToString(cidr_len)); break; + } case AF_INET6: - if (cidr_len <= 128) - c = "/" + Anope::ToString(cidr_len); + { + if (cidr_len < 128) + cmask.append("/").append(Anope::ToString(cidr_len)); break; + } } - return n + "!" + u + "@" + h + c + r; + if (!this->real.empty()) + { + cmask.push_back('#'); + cmask.append(this->real); + } + + return cmask; } bool Entry::Matches(User *u, bool full) const diff --git a/src/protocol.cpp b/src/protocol.cpp index 1aa2a0bf4..69eba97ba 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -389,7 +389,7 @@ Anope::string IRCDProto::NormalizeMask(const Anope::string &mask) { if (IsExtbanValid(mask)) return mask; - return Entry("", mask).GetNUHMask(); + return Entry("", mask).GetCleanMask(); } void IRCDProto::SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map &tags)