summaryrefslogtreecommitdiff
path: root/modules/nickserv/nickserv.cpp
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2024-11-24 23:56:57 +0000
committerSadie Powell <sadie@witchery.services>2024-11-25 00:08:30 +0000
commit7019b27e591e0f5ce3727993e02198ae070885e9 (patch)
tree7752a85bb31f4bce07f63c3364a9f8d6c903daa2 /modules/nickserv/nickserv.cpp
parent70227dc8823c0f9669e35dbf63593faaeef5410d (diff)
Rework how guest nicks work.
- Use the config setting as a string template instead of as a prefix. - Allow users of IRCds that have UIDs to use that as the guest nick. - Fall back to a UID before killing if a guest nick can not be found.
Diffstat (limited to 'modules/nickserv/nickserv.cpp')
-rw-r--r--modules/nickserv/nickserv.cpp63
1 files changed, 49 insertions, 14 deletions
diff --git a/modules/nickserv/nickserv.cpp b/modules/nickserv/nickserv.cpp
index 04dd2e1e2..1328ecea5 100644
--- a/modules/nickserv/nickserv.cpp
+++ b/modules/nickserv/nickserv.cpp
@@ -174,6 +174,24 @@ public:
OnShutdown();
}
+ bool IsGuestNick(const Anope::string &nick) const
+ {
+ const auto guestnick = Config->GetModule(this)->Get<Anope::string>("guestnick", "Guest####");
+ if (guestnick.empty())
+ return false; // No guest nick.
+
+ const auto minlen = std::min(nick.length(), guestnick.length());
+ for (size_t idx = 0; idx < minlen; ++idx)
+ {
+ if (guestnick[idx] == '#' && !isdigit(nick[idx]))
+ return false;
+
+ if (Anope::tolower(guestnick[idx]) != Anope::tolower(nick[idx]))
+ return false;
+ }
+ return true;
+ }
+
void Validate(User *u) override
{
NickAlias *na = NickAlias::Find(u->nick);
@@ -238,30 +256,47 @@ public:
if (IRCD->CanSVSNick)
{
- unsigned nicklen = IRCD->MaxNick;
- const Anope::string &guestprefix = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest");
-
+ auto guestnickok = false;
Anope::string guestnick;
+ for (auto i = 0; i < 10; ++i)
+ {
+ guestnick.clear();
+ for (auto guestnickchr : Config->GetModule(this)->Get<Anope::string>("guestnick", "Guest####").substr(0, IRCD->MaxNick))
+ {
+ if (guestnickchr == '#')
+ guestnick.append(Anope::ToString(abs(Anope::RandomNumber()) % 10));
+ else
+ guestnick.push_back(guestnickchr);
+ }
- int i = 0;
- do
+ // A guest nick is valid if it is non-empty and is not in use.
+ if (!guestnick.empty() && !User::Find(guestnick, true))
+ {
+ guestnickok = true;
+ break;
+ }
+ }
+
+ // If we can't find a guest nick and the IRCd supports
+ // uids then we should use that as the backup guest
+ // nickname.
+ if (!guestnickok && IRCD->RequiresID)
{
- guestnick = guestprefix + Anope::ToString(static_cast<uint16_t>(Anope::RandomNumber()));
- if (guestnick.length() > nicklen)
- guestnick = guestnick.substr(0, nicklen);
+ guestnickok = true;
+ guestnick = u->GetUID();
}
- while (User::Find(guestnick) && i++ < 10);
- if (i == 11)
- u->Kill(*NickServ, "Services nickname-enforcer kill");
- else
+ if (guestnickok)
{
u->SendMessage(*NickServ, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str());
IRCD->SendForceNickChange(u, guestnick, Anope::CurTime);
+ return;
}
}
- else
- u->Kill(*NickServ, "Services nickname-enforcer kill");
+
+ // We can't change the user's nickname or we can't find an
+ // acceptable guest nick, give them the boot.
+ u->Kill(*NickServ, "Enforcement of services protected nickname");
}
void Release(NickAlias *na) override