diff --git a/include/ircd/globular.h b/include/ircd/globular.h index be7b845f6..e0335cb95 100644 --- a/include/ircd/globular.h +++ b/include/ircd/globular.h @@ -42,20 +42,11 @@ struct ircd::globular_iequals /// than globular_equals. Case insensitive. struct ircd::globular_imatch { - string_view expr; + string_view a; - template - bool operator()(A&& a) const noexcept - { - const globular_iequals globular_iequals - { - expr, std::forward(a) - }; + bool operator()(const string_view &b) const noexcept; - return bool(globular_iequals); - } - - globular_imatch(const string_view &expr = {}) - :expr{expr} + globular_imatch(const string_view &expr) + :a{expr} {} }; diff --git a/ircd/globular.cc b/ircd/globular.cc index bfd68def2..9d5351cba 100644 --- a/ircd/globular.cc +++ b/ircd/globular.cc @@ -53,3 +53,35 @@ const noexcept return iequals(a.substr(ap), b.substr(bp)); } + +bool +ircd::globular_imatch::operator()(const string_view &b) +const noexcept +{ + size_t ap(0), bp(0); + while(ap < a.size() && bp < b.size()) + { + const auto ca(tolower(a.at(ap))), cb(tolower(b.at(bp))); + const auto globa(ca == '*'); + const auto wilda(ca == '?'); + + if(!globa && !wilda && ca != cb) + return false; + + if(globa && ap + 1 >= a.size()) + break; + + if(globa && cb == tolower(a.at(ap + 1))) + ap += 2; + + if(!globa) + ++ap; + + ++bp; + } + + if(bp < b.size() && !a.empty() && a.back() == '*') + return true; + + return iequals(a.substr(ap), b.substr(bp)); +} diff --git a/modules/m_command.cc b/modules/m_command.cc index 53ae601d6..ab26821ec 100644 --- a/modules/m_command.cc +++ b/modules/m_command.cc @@ -446,7 +446,7 @@ command__read(const mutable_buffer &buf, // for_each returns true if it didn't break from the loop, which means // no match and skip actions for this room. - if(match.expr != "*") + if(match.a != "*") if(room_tags.for_each(without_match)) return;