summaryrefslogtreecommitdiff
path: root/modules/nickserv/main
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2015-12-14 16:52:24 -0500
committerAdam <Adam@anope.org>2015-12-14 16:52:24 -0500
commit6302f980fe6dad83aab7d2dc1046dadea5ffd939 (patch)
tree4c27d33f55fc32ce34827977932dac4b3e5ceedd /modules/nickserv/main
parent64dac60071fab652745a6e7a06cf6b7bdbbd3625 (diff)
New source tree structure for modules. From commands/cs_access => chanserv/access etc.
Diffstat (limited to 'modules/nickserv/main')
-rw-r--r--modules/nickserv/main/CMakeLists.txt1
-rw-r--r--modules/nickserv/main/account.cpp129
-rw-r--r--modules/nickserv/main/account.h35
-rw-r--r--modules/nickserv/main/accounttype.cpp42
-rw-r--r--modules/nickserv/main/accounttype.h23
-rw-r--r--modules/nickserv/main/identifyrequest.cpp51
-rw-r--r--modules/nickserv/main/identifyrequest.h13
-rw-r--r--modules/nickserv/main/mode.cpp23
-rw-r--r--modules/nickserv/main/mode.h14
-rw-r--r--modules/nickserv/main/modetype.h14
-rw-r--r--modules/nickserv/main/nick.cpp192
-rw-r--r--modules/nickserv/main/nick.h46
-rw-r--r--modules/nickserv/main/nickserv.cpp686
-rw-r--r--modules/nickserv/main/nicktype.cpp45
-rw-r--r--modules/nickserv/main/nicktype.h32
15 files changed, 1346 insertions, 0 deletions
diff --git a/modules/nickserv/main/CMakeLists.txt b/modules/nickserv/main/CMakeLists.txt
new file mode 100644
index 000000000..781f0ef1f
--- /dev/null
+++ b/modules/nickserv/main/CMakeLists.txt
@@ -0,0 +1 @@
+build_subdir(${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/modules/nickserv/main/account.cpp b/modules/nickserv/main/account.cpp
new file mode 100644
index 000000000..85adf1a33
--- /dev/null
+++ b/modules/nickserv/main/account.cpp
@@ -0,0 +1,129 @@
+/*
+ *
+ * (C) 2003-2014 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ */
+
+#include "module.h"
+#include "accounttype.h"
+#include "modules/ns_access.h"
+
+AccountImpl::~AccountImpl()
+{
+ NickServ::nickcore_map& map = NickServ::service->GetAccountMap();
+ map.erase(this->GetDisplay());
+}
+
+void AccountImpl::Delete()
+{
+ Event::OnDelCore(&Event::DelCore::OnDelCore, this);
+
+ for (unsigned i = users.size(); i > 0; --i)
+ users[i - 1]->Logout();
+
+ return Serialize::Object::Delete();
+}
+
+Anope::string AccountImpl::GetDisplay()
+{
+ return Get<Anope::string>(&AccountType::display);
+}
+
+void AccountImpl::SetDisplay(const Anope::string &disp)
+{
+ Set(&AccountType::display, disp);
+}
+
+Anope::string AccountImpl::GetPassword()
+{
+ return Get(&AccountType::pass);
+}
+
+void AccountImpl::SetPassword(const Anope::string &pass)
+{
+ Set(&AccountType::pass, pass);
+}
+
+Anope::string AccountImpl::GetEmail()
+{
+ return Get(&AccountType::email);
+}
+
+void AccountImpl::SetEmail(const Anope::string &email)
+{
+ Set(&AccountType::email, email);
+}
+
+Anope::string AccountImpl::GetLanguage()
+{
+ return Get(&AccountType::language);
+}
+
+void AccountImpl::SetLanguage(const Anope::string &lang)
+{
+ Set(&AccountType::language, lang);
+}
+
+MemoServ::MemoInfo *AccountImpl::GetMemos()
+{
+ return GetRef<MemoServ::MemoInfo *>(MemoServ::memoinfo);
+}
+
+void AccountImpl::SetDisplay(NickServ::Nick *na)
+{
+ if (na->GetAccount() != this || na->GetNick() == this->GetDisplay())
+ return;
+
+ Event::OnChangeCoreDisplay(&Event::ChangeCoreDisplay::OnChangeCoreDisplay, this, na->GetNick());
+
+ NickServ::nickcore_map& map = NickServ::service->GetAccountMap();
+
+ /* Remove the core from the list */
+ map.erase(this->GetDisplay());
+
+ this->SetDisplay(na->GetNick());
+
+ NickServ::Account* &nc = map[this->GetDisplay()];
+ if (nc)
+ Log(LOG_DEBUG) << "Duplicate account " << this->GetDisplay() << " in nickcore table?";
+
+ nc = this;
+}
+
+bool AccountImpl::IsServicesOper() const
+{
+ return this->o != NULL;
+}
+
+bool AccountImpl::IsOnAccess(User *u)
+{
+ Anope::string buf = u->GetIdent() + "@" + u->host, buf2, buf3;
+ if (!u->vhost.empty())
+ buf2 = u->GetIdent() + "@" + u->vhost;
+ if (!u->GetCloakedHost().empty())
+ buf3 = u->GetIdent() + "@" + u->GetCloakedHost();
+
+ for (NickAccess *access : GetRefs<NickAccess *>(nsaccess))
+ {
+ Anope::string a = access->GetMask();
+ if (Anope::Match(buf, a) || (!buf2.empty() && Anope::Match(buf2, a)) || (!buf3.empty() && Anope::Match(buf3, a)))
+ return true;
+ }
+ return false;
+}
+
+unsigned int AccountImpl::GetChannelCount()
+{
+ unsigned int i = 0;
+ for (ChanServ::Channel *c : GetRefs<ChanServ::Channel *>(ChanServ::channel))
+ if (c->GetFounder() == this)
+ ++i;
+ return i;
+}
+
diff --git a/modules/nickserv/main/account.h b/modules/nickserv/main/account.h
new file mode 100644
index 000000000..584548563
--- /dev/null
+++ b/modules/nickserv/main/account.h
@@ -0,0 +1,35 @@
+#include "modules/nickserv.h"
+
+class AccountImpl : public NickServ::Account
+{
+ public:
+ AccountImpl(Serialize::TypeBase *type) : NickServ::Account(type) { }
+ AccountImpl(Serialize::TypeBase *type, Serialize::ID id) : NickServ::Account(type, id) { }
+ ~AccountImpl();
+ void Delete() override;
+
+ Anope::string GetDisplay() override;
+ void SetDisplay(const Anope::string &) override;
+
+ Anope::string GetPassword() override;
+ void SetPassword(const Anope::string &) override;
+
+ Anope::string GetEmail() override;
+ void SetEmail(const Anope::string &) override;
+
+ Anope::string GetLanguage() override;
+ void SetLanguage(const Anope::string &) override;
+
+ MemoServ::MemoInfo *GetMemos() override;
+
+ void SetDisplay(NickServ::Nick *na) override;
+ bool IsServicesOper() const override;
+ /*void AddAccess(const Anope::string &entry) override;
+ Anope::string GetAccess(unsigned entry) const override;
+ unsigned GetAccessCount() const override;
+ bool FindAccess(const Anope::string &entry) override;
+ void EraseAccess(const Anope::string &entry) override;
+ void ClearAccess() override;*/
+ bool IsOnAccess(User *u) override;
+ unsigned int GetChannelCount() override;
+};
diff --git a/modules/nickserv/main/accounttype.cpp b/modules/nickserv/main/accounttype.cpp
new file mode 100644
index 000000000..3dad436b4
--- /dev/null
+++ b/modules/nickserv/main/accounttype.cpp
@@ -0,0 +1,42 @@
+#include "module.h"
+#include "accounttype.h"
+//#include "account.h"
+
+AccountType::AccountType(Module *me) : Serialize::Type<AccountImpl>(me, "NickCore")
+ , display(this, "display")
+ , pass(this, "pass")
+ , email(this, "email")
+ , language(this, "language")
+{
+
+}
+
+void AccountType::Display::SetField(AccountImpl *acc, const Anope::string &disp)
+{
+ NickServ::nickcore_map& map = NickServ::service->GetAccountMap();
+
+ if (!acc->GetDisplay().empty())
+ map.erase(acc->GetDisplay());
+
+ Serialize::Field<AccountImpl, Anope::string>::SetField(acc, disp);
+
+ if (!disp.empty())
+ map[disp] = acc;
+
+ acc->o = Oper::Find(disp);
+}
+
+NickServ::Account *AccountType::FindAccount(const Anope::string &acc)
+{
+ Serialize::ID id;
+ EventReturn result = Event::OnSerialize(&Event::SerializeEvents::OnSerializeFind, this, &this->display, acc, id);
+ if (result == EVENT_ALLOW)
+ return RequireID(id);
+
+ NickServ::nickcore_map &map = NickServ::service->GetAccountMap();
+ auto it = map.find(acc);
+ if (it != map.end())
+ return it->second;
+ return nullptr;
+}
+
diff --git a/modules/nickserv/main/accounttype.h b/modules/nickserv/main/accounttype.h
new file mode 100644
index 000000000..792629877
--- /dev/null
+++ b/modules/nickserv/main/accounttype.h
@@ -0,0 +1,23 @@
+#include "account.h"
+
+class AccountType : public Serialize::Type<AccountImpl>
+{
+ public:
+ /* Name of the account */
+ struct Display : Serialize::Field<AccountImpl, Anope::string>
+ {
+ using Serialize::Field<AccountImpl, Anope::string>::Field;
+
+ void SetField(AccountImpl *s, const Anope::string &) override;
+ } display;
+ /* User password in form of hashm:data */
+ Serialize::Field<AccountImpl, Anope::string> pass;
+ Serialize::Field<AccountImpl, Anope::string> email;
+ /* Locale name of the language of the user. Empty means default language */
+ Serialize::Field<AccountImpl, Anope::string> language;
+
+
+ AccountType(Module *);
+
+ NickServ::Account *FindAccount(const Anope::string &nick);
+};
diff --git a/modules/nickserv/main/identifyrequest.cpp b/modules/nickserv/main/identifyrequest.cpp
new file mode 100644
index 000000000..4fc2f9989
--- /dev/null
+++ b/modules/nickserv/main/identifyrequest.cpp
@@ -0,0 +1,51 @@
+#include "identifyrequest.h"
+
+IdentifyRequestImpl::IdentifyRequestImpl(NickServ::IdentifyRequestListener *li, Module *o, const Anope::string &acc, const Anope::string &pass) : NickServ::IdentifyRequest(li, o, acc, pass)
+{
+ std::set<NickServ::IdentifyRequest *> &requests = NickServ::service->GetIdentifyRequests();
+ requests.insert(this);
+}
+
+IdentifyRequestImpl::~IdentifyRequestImpl()
+{
+ std::set<NickServ::IdentifyRequest *> &requests = NickServ::service->GetIdentifyRequests();
+ requests.erase(this);
+ delete l;
+}
+
+void IdentifyRequestImpl::Hold(Module *m)
+{
+ holds.insert(m);
+}
+
+void IdentifyRequestImpl::Release(Module *m)
+{
+ holds.erase(m);
+ if (holds.empty() && dispatched)
+ {
+ if (!success)
+ l->OnFail(this);
+ delete this;
+ }
+}
+
+void IdentifyRequestImpl::Success(Module *m)
+{
+ if (!success)
+ {
+ l->OnSuccess(this);
+ success = true;
+ }
+}
+
+void IdentifyRequestImpl::Dispatch()
+{
+ if (holds.empty())
+ {
+ if (!success)
+ l->OnFail(this);
+ delete this;
+ }
+ else
+ dispatched = true;
+}
diff --git a/modules/nickserv/main/identifyrequest.h b/modules/nickserv/main/identifyrequest.h
new file mode 100644
index 000000000..e74d3129e
--- /dev/null
+++ b/modules/nickserv/main/identifyrequest.h
@@ -0,0 +1,13 @@
+#include "modules/nickserv.h"
+
+class IdentifyRequestImpl : public NickServ::IdentifyRequest
+{
+ public:
+ IdentifyRequestImpl(NickServ::IdentifyRequestListener *, Module *o, const Anope::string &acc, const Anope::string &pass);
+ virtual ~IdentifyRequestImpl();
+
+ void Hold(Module *m) override;
+ void Release(Module *m) override;
+ void Success(Module *m) override;
+ void Dispatch() override;
+};
diff --git a/modules/nickserv/main/mode.cpp b/modules/nickserv/main/mode.cpp
new file mode 100644
index 000000000..61fe551c1
--- /dev/null
+++ b/modules/nickserv/main/mode.cpp
@@ -0,0 +1,23 @@
+#include "modules/nickserv.h"
+#include "modetype.h"
+
+NickServ::Account *ModeImpl::GetAccount()
+{
+ return Get(&NSModeType::account);
+}
+
+void ModeImpl::SetAccount(NickServ::Account *a)
+{
+ Set(&NSModeType::account, a);
+}
+
+Anope::string ModeImpl::GetMode()
+{
+ return Get(&NSModeType::mode);
+}
+
+void ModeImpl::SetMode(const Anope::string &m)
+{
+ Set(&NSModeType::mode, m);
+}
+
diff --git a/modules/nickserv/main/mode.h b/modules/nickserv/main/mode.h
new file mode 100644
index 000000000..9fc4c331e
--- /dev/null
+++ b/modules/nickserv/main/mode.h
@@ -0,0 +1,14 @@
+
+class ModeImpl : public NickServ::Mode
+{
+ public:
+ ModeImpl(Serialize::TypeBase *type) : NickServ::Mode(type) { }
+ ModeImpl(Serialize::TypeBase *type, Serialize::ID id) : NickServ::Mode(type, id) { }
+
+ NickServ::Account *GetAccount() override;
+ void SetAccount(NickServ::Account *) override;
+
+ Anope::string GetMode() override;
+ void SetMode(const Anope::string &) override;
+};
+
diff --git a/modules/nickserv/main/modetype.h b/modules/nickserv/main/modetype.h
new file mode 100644
index 000000000..0c4aefecc
--- /dev/null
+++ b/modules/nickserv/main/modetype.h
@@ -0,0 +1,14 @@
+#include "mode.h"
+
+class NSModeType : public Serialize::Type<ModeImpl>
+{
+ public:
+ Serialize::ObjectField<ModeImpl, NickServ::Account *> account;
+ Serialize::Field<ModeImpl, Anope::string> mode;
+
+ NSModeType(Module *creator) : Serialize::Type<ModeImpl>(creator, "NSKeepMode")
+ , account(this, "account", true)
+ , mode(this, "mode")
+ {
+ }
+};
diff --git a/modules/nickserv/main/nick.cpp b/modules/nickserv/main/nick.cpp
new file mode 100644
index 000000000..0ac55ff93
--- /dev/null
+++ b/modules/nickserv/main/nick.cpp
@@ -0,0 +1,192 @@
+/*
+ *
+ * (C) 2003-2014 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ */
+
+#include "module.h"
+#include "nicktype.h"
+
+NickImpl::~NickImpl()
+{
+ /* Remove us from the aliases list */
+ NickServ::nickalias_map &map = NickServ::service->GetNickMap();
+ map.erase(GetNick());
+}
+
+void NickImpl::Delete()
+{
+ Event::OnDelNick(&Event::DelNick::OnDelNick, this);
+
+ if (this->GetAccount())
+ {
+ /* Next: see if our core is still useful. */
+ std::vector<NickServ::Nick *> aliases = this->GetAccount()->GetRefs<NickServ::Nick *>(NickServ::nick);
+
+ auto it = std::find(aliases.begin(), aliases.end(), this);
+ if (it != aliases.end())
+ aliases.erase(it);
+
+ if (aliases.empty())
+ {
+ /* just me */
+ this->GetAccount()->Delete();
+ }
+ else
+ {
+ /* Display updating stuff */
+ if (GetNick().equals_ci(this->GetAccount()->GetDisplay()))
+ this->GetAccount()->SetDisplay(aliases[0]);
+ }
+ }
+
+ return Serialize::Object::Delete();
+}
+
+Anope::string NickImpl::GetNick()
+{
+ return Get<Anope::string>(&NickType::nick);
+}
+
+void NickImpl::SetNick(const Anope::string &nick)
+{
+ Set(&NickType::nick, nick);
+}
+
+Anope::string NickImpl::GetLastQuit()
+{
+ return Get(&NickType::last_quit);
+}
+
+void NickImpl::SetLastQuit(const Anope::string &lq)
+{
+ Set(&NickType::last_quit, lq);
+}
+
+Anope::string NickImpl::GetLastRealname()
+{
+ return Get(&NickType::last_realname);
+}
+
+void NickImpl::SetLastRealname(const Anope::string &lr)
+{
+ Set(&NickType::last_realname, lr);
+}
+
+Anope::string NickImpl::GetLastUsermask()
+{
+ return Get(&NickType::last_usermask);
+}
+
+void NickImpl::SetLastUsermask(const Anope::string &lu)
+{
+ Set(&NickType::last_usermask, lu);
+}
+
+Anope::string NickImpl::GetLastRealhost()
+{
+ return Get(&NickType::last_realhost);
+}
+
+void NickImpl::SetLastRealhost(const Anope::string &lr)
+{
+ Set(&NickType::last_realhost, lr);
+}
+
+time_t NickImpl::GetTimeRegistered()
+{
+ return Get(&NickType::time_registered);
+}
+
+void NickImpl::SetTimeRegistered(const time_t &tr)
+{
+ Set(&NickType::time_registered, tr);
+}
+
+time_t NickImpl::GetLastSeen()
+{
+ return Get(&NickType::last_seen);
+}
+
+void NickImpl::SetLastSeen(const time_t &ls)
+{
+ Set(&NickType::last_seen, ls);
+}
+
+NickServ::Account *NickImpl::GetAccount()
+{
+ return Get(&NickType::nc);
+}
+
+void NickImpl::SetAccount(NickServ::Account *acc)
+{
+ Set(&NickType::nc, acc);
+}
+
+void NickImpl::SetVhost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created)
+{
+ Set(&NickType::vhost_ident, ident);
+ Set(&NickType::vhost_host, host);
+ Set(&NickType::vhost_creator, creator);
+ Set(&NickType::vhost_created, created);
+}
+
+void NickImpl::RemoveVhost()
+{
+ Anope::string e;
+ Set(&NickType::vhost_ident, e);
+ Set(&NickType::vhost_host, e);
+ Set(&NickType::vhost_creator, e);
+ Set(&NickType::vhost_created, 0);
+}
+
+bool NickImpl::HasVhost()
+{
+ return !GetVhostHost().empty();
+}
+
+Anope::string NickImpl::GetVhostIdent()
+{
+ return Get(&NickType::vhost_ident);
+}
+
+void NickImpl::SetVhostIdent(const Anope::string &i)
+{
+ Set(&NickType::vhost_ident, i);
+}
+
+Anope::string NickImpl::GetVhostHost()
+{
+ return Get(&NickType::vhost_host);
+}
+
+void NickImpl::SetVhostHost(const Anope::string &h)
+{
+ Set(&NickType::vhost_host, h);
+}
+
+Anope::string NickImpl::GetVhostCreator()
+{
+ return Get(&NickType::vhost_creator);
+}
+
+void NickImpl::SetVhostCreator(const Anope::string &c)
+{
+ Set(&NickType::vhost_creator, c);
+}
+
+time_t NickImpl::GetVhostCreated()
+{
+ return Get(&NickType::vhost_created);
+}
+
+void NickImpl::SetVhostCreated(const time_t &cr)
+{
+ Set(&NickType::vhost_created, cr);
+}
diff --git a/modules/nickserv/main/nick.h b/modules/nickserv/main/nick.h
new file mode 100644
index 000000000..043d7c052
--- /dev/null
+++ b/modules/nickserv/main/nick.h
@@ -0,0 +1,46 @@
+
+class NickImpl : public NickServ::Nick
+{
+ public:
+ NickImpl(Serialize::TypeBase *type) : NickServ::Nick(type) { }
+ NickImpl(Serialize::TypeBase *type, Serialize::ID id) : NickServ::Nick(type, id) { }
+ ~NickImpl();
+ void Delete() override;
+
+ Anope::string GetNick() override;
+ void SetNick(const Anope::string &) override;
+
+ Anope::string GetLastQuit() override;
+ void SetLastQuit(const Anope::string &) override;
+
+ Anope::string GetLastRealname() override;
+ void SetLastRealname(const Anope::string &) override;
+
+ Anope::string GetLastUsermask() override;
+ void SetLastUsermask(const Anope::string &) override;
+
+ Anope::string GetLastRealhost() override;
+ void SetLastRealhost(const Anope::string &) override;
+
+ time_t GetTimeRegistered() override;
+ void SetTimeRegistered(const time_t &) override;
+
+ time_t GetLastSeen() override;
+ void SetLastSeen(const time_t &) override;
+
+ NickServ::Account *GetAccount() override;
+ void SetAccount(NickServ::Account *acc) override;
+
+ void SetVhost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created = Anope::CurTime) override;
+ void RemoveVhost() override;
+ bool HasVhost() override;
+
+ Anope::string GetVhostIdent() override;
+ void SetVhostIdent(const Anope::string &) override;
+ Anope::string GetVhostHost() override;
+ void SetVhostHost(const Anope::string &) override;
+ Anope::string GetVhostCreator() override;
+ void SetVhostCreator(const Anope::string &) override;
+ time_t GetVhostCreated() override;
+ void SetVhostCreated(const time_t &) override;
+};
diff --git a/modules/nickserv/main/nickserv.cpp b/modules/nickserv/main/nickserv.cpp
new file mode 100644
index 000000000..26f1457cc
--- /dev/null
+++ b/modules/nickserv/main/nickserv.cpp
@@ -0,0 +1,686 @@
+/* NickServ core functions
+ *
+ * (C) 2003-2014 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ */
+
+#include "module.h"
+#include "modules/ns_info.h"
+#include "modules/ns_group.h"
+#include "modules/ns_update.h"
+#include "modules/help.h"
+#include "modules/nickserv.h"
+#include "identifyrequest.h"
+#include "nicktype.h"
+#include "accounttype.h"
+#include "modetype.h"
+
+class NickServCollide;
+static std::set<NickServCollide *> collides;
+
+/** Timer for colliding nicks to force people off of nicknames
+ */
+class NickServCollide : public Timer
+{
+ NickServ::NickServService *service;
+ Reference<User> u;
+ time_t ts;
+ Reference<NickServ::Nick> na;
+
+ public:
+ NickServCollide(Module *me, NickServ::NickServService *nss, User *user, NickServ::Nick *nick, time_t delay) : Timer(me, delay), service(nss), u(user), ts(user->timestamp), na(nick)
+ {
+ collides.insert(this);
+ }
+
+ ~NickServCollide()
+ {
+ collides.erase(this);
+ }
+
+ NickServ::Nick *GetNick()
+ {
+ return na;
+ }
+
+ User *GetUser()
+ {
+ return u;
+ }
+
+ void Tick(time_t t) override
+ {
+ if (!u || !na)
+ return;
+ /* If they identified or don't exist anymore, don't kill them. */
+ if (u->Account() == na->GetAccount() || u->timestamp > ts)
+ return;
+
+ service->Collide(u, na);
+ }
+};
+
+/** Timer for removing HELD status from nicks.
+ */
+class NickServHeld : public Timer
+{
+ Reference<NickServ::Nick> na;
+ Anope::string nick;
+ public:
+ NickServHeld(Module *me, NickServ::Nick *n, long l) : Timer(me, l), na(n), nick(na->GetNick())
+ {
+ n->SetS<bool>("HELD", true);
+ }
+
+ void Tick(time_t)
+ {
+ if (na)
+ na->UnsetS<bool>("HELD");
+ }
+};
+
+class NickServRelease;
+static Anope::map<NickServRelease *> NickServReleases;
+
+/** Timer for releasing nicks to be available for use
+ */
+class NickServRelease : public User, public Timer
+{
+ Anope::string nick;
+
+ public:
+ NickServRelease(Module *me, NickServ::Nick *na, time_t delay) : User(na->GetNick(), Config->GetModule("nickserv")->Get<Anope::string>("enforceruser", "user"),
+ Config->GetModule("nickserv")->Get<Anope::string>("enforcerhost", "services.localhost.net"), "", "", Me, "Services Enforcer", Anope::CurTime, "", IRCD->UID_Retrieve(), NULL), Timer(me, delay), nick(na->GetNick())
+ {
+ /* Erase the current release timer and use the new one */
+ Anope::map<NickServRelease *>::iterator nit = NickServReleases.find(this->nick);
+ if (nit != NickServReleases.end())
+ {
+ IRCD->SendQuit(nit->second, "");
+ delete nit->second;
+ }
+
+ NickServReleases.insert(std::make_pair(this->nick, this));
+
+ IRCD->SendClientIntroduction(this);
+ }
+
+ ~NickServRelease()
+ {
+ IRCD->SendQuit(this, "");
+ NickServReleases.erase(this->nick);
+ }
+
+ void Tick(time_t t) override { }
+};
+
+class NickServCore : public Module, public NickServ::NickServService
+ , public EventHook<Event::Shutdown>
+ , public EventHook<Event::Restart>
+ , public EventHook<Event::UserLogin>
+ , public EventHook<Event::DelNick>
+ , public EventHook<Event::DelCore>
+ , public EventHook<Event::ChangeCoreDisplay>
+ , public EventHook<Event::NickIdentify>
+ , public EventHook<Event::NickGroup>
+ , public EventHook<Event::NickUpdate>
+ , public EventHook<Event::UserConnect>
+ , public EventHook<Event::PostUserLogoff>
+ , public EventHook<Event::ServerSync>
+ , public EventHook<Event::UserNickChange>
+ , public EventHook<Event::UserModeSet>
+ , public EventHook<Event::Help>
+ , public EventHook<Event::ExpireTick>
+ , public EventHook<Event::NickInfo>
+ , public EventHook<Event::ModuleUnload>
+ , public EventHook<Event::NickCoreCreate>
+ , public EventHook<Event::UserQuit>
+{
+ Reference<ServiceBot> NickServ;
+ std::vector<Anope::string> defaults;
+ ExtensibleItem<bool> held, collided;
+ EventHandlers<NickServ::Event::PreNickExpire> onprenickexpire;
+ EventHandlers<NickServ::Event::NickExpire> onnickexpire;
+ EventHandlers<NickServ::Event::NickRegister> onnickregister;
+ EventHandlers<NickServ::Event::NickValidate> onnickvalidate;
+ std::set<NickServ::IdentifyRequest *> identifyrequests;
+ NickServ::nickalias_map NickList;
+ NickServ::nickcore_map AccountList;
+ NickType nick_type;
+ AccountType account_type;
+ NSModeType mode_type;
+
+ void OnCancel(User *u, NickServ::Nick *na)
+ {
+ if (collided.HasExt(na))
+ {
+ collided.Unset(na);
+
+ new NickServHeld(this, na, Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
+
+ if (IRCD->CanSVSHold)
+ IRCD->SendSVSHold(na->GetNick(), Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
+ else
+ new NickServRelease(this, na, Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
+ }
+ }
+
+ public:
+ NickServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR)
+ , NickServ::NickServService(this)
+ , held(this, "HELD")
+ , collided(this, "COLLIDED")
+ , onprenickexpire(this)
+ , onnickexpire(this)
+ , onnickregister(this)
+ , onnickvalidate(this)
+ , nick_type(this)
+ , account_type(this)
+ , mode_type(this)
+ {
+ }
+
+ ~NickServCore()
+ {
+ OnShutdown();
+ }
+
+ void OnShutdown() override
+ {
+ /* On shutdown, restart, or mod unload, remove all of our holds for nicks (svshold or qlines)
+ * because some IRCds do not allow us to have these automatically expire
+ */
+ for (NickServ::Nick *na : nick_type.List<NickServ::Nick *>())
+ this->Release(na);
+ }
+
+ void OnRestart() override
+ {
+ OnShutdown();
+ }
+
+ void Validate(User *u) override
+ {
+ NickServ::Nick *na = NickServ::FindNick(u->nick);
+ if (!na)
+ return;
+
+ EventReturn MOD_RESULT = this->onnickvalidate(&NickServ::Event::NickValidate::OnNickValidate, u, na);
+ if (MOD_RESULT == EVENT_STOP)
+ {
+ this->Collide(u, na);
+ return;
+ }
+ else if (MOD_RESULT == EVENT_ALLOW)
+ return;
+
+ if (!na->GetAccount()->HasFieldS("NS_SECURE") && u->IsRecognized())
+ {
+ na->SetLastSeen(Anope::CurTime);
+ na->SetLastUsermask(u->GetIdent() + "@" + u->GetDisplayedHost());
+ na->SetLastRealname(u->realname);
+ return;
+ }
+
+ if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
+ return;
+
+ bool on_access = u->IsRecognized(false);
+
+ if (on_access || !na->GetAccount()->HasFieldS("KILL_IMMED"))
+ {
+ if (na->GetAccount()->HasFieldS("NS_SECURE"))
+ u->SendMessage(*NickServ, _("This nickname is registered and protected. If this is your nickname, type \002{0}{1} IDENTIFY \037password\037\002. Otherwise, please choose a different nickname."), Config->StrictPrivmsg, NickServ->nick); // XXX
+ else
+ u->SendMessage(*NickServ, _("This nickname is owned by someone else. If this is your nickname, type \002{0}{1} IDENTIFY \037password\037\002. Otherwise, please choose a different nickname."), Config->StrictPrivmsg, NickServ->nick); // XXX
+ }
+ if (na->GetAccount()->HasFieldS("KILLPROTECT") && !on_access)
+ {
+ if (na->GetAccount()->HasFieldS("KILL_IMMED"))
+ {
+ u->SendMessage(*NickServ, _("This nickname has been registered; you may not use it."));
+ this->Collide(u, na);
+ }
+ else if (na->GetAccount()->HasFieldS("KILL_QUICK"))
+ {
+ time_t killquick = Config->GetModule("nickserv")->Get<time_t>("killquick", "20s");
+ u->SendMessage(*NickServ, _("If you do not change within %s, I will change your nick."), Anope::Duration(killquick, u->Account()).c_str());
+ new NickServCollide(this, this, u, na, killquick);
+ }
+ else
+ {
+ time_t kill = Config->GetModule("nickserv")->Get<time_t>("kill", "60s");
+ u->SendMessage(*NickServ, _("If you do not change within %s, I will change your nick."), Anope::Duration(kill, u->Account()).c_str());
+ new NickServCollide(this, this, u, na, kill);
+ }
+ }
+
+ }
+
+ void OnUserLogin(User *u) override
+ {
+ NickServ::Nick *na = NickServ::FindNick(u->nick);
+ if (na && na->GetAccount() == u->Account() && !Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && !na->GetAccount()->HasFieldS("UNCONFIRMED"))
+ u->SetMode(NickServ, "REGISTERED");
+
+ const Anope::string &modesonid = Config->GetModule(this)->Get<Anope::string>("modesonid");
+ if (!modesonid.empty())
+ u->SetModes(NickServ, "%s", modesonid.c_str());
+ }
+
+ void Collide(User *u, NickServ::Nick *na) override
+ {
+ if (na)
+ collided.Set(na, true);
+
+ if (IRCD->CanSVSNick)
+ {
+ unsigned nicklen = Config->GetBlock("networkinfo")->Get<unsigned>("nicklen");
+ const Anope::string &guestprefix = Config->GetModule("nickserv")->Get<Anope::string>("guestnickprefix", "Guest");
+
+ Anope::string guestnick;
+
+ int i = 0;
+ do
+ {
+ guestnick = guestprefix + stringify(static_cast<uint16_t>(rand()));
+ if (guestnick.length() > nicklen)
+ guestnick = guestnick.substr(0, nicklen);
+ }
+ while (User::Find(guestnick) && i++ < 10);
+
+ if (i == 11)
+ u->Kill(*NickServ, "Services nickname-enforcer kill");
+ else
+ {
+ u->SendMessage(*NickServ, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str());
+ IRCD->SendForceNickChange(u, guestnick, Anope::CurTime);
+ }
+ }
+ else
+ u->Kill(*NickServ, "Services nickname-enforcer kill");
+ }
+
+ void Release(NickServ::Nick *na) override
+ {
+ if (held.HasExt(na))
+ {
+ if (IRCD->CanSVSHold)
+ IRCD->SendSVSHoldDel(na->GetNick());
+ else
+ {
+ User *u = User::Find(na->GetNick());
+ if (u && u->server == Me)
+ {
+ u->Quit();
+ }
+ }
+
+ held.Unset(na);
+ }
+ collided.Unset(na); /* clear pending collide */
+ }
+
+ NickServ::IdentifyRequest *CreateIdentifyRequest(NickServ::IdentifyRequestListener *l, Module *o, const Anope::string &acc, const Anope::string &pass) override
+ {
+ return new IdentifyRequestImpl(l, o, acc, pass);
+ }
+
+ std::set<NickServ::IdentifyRequest *>& GetIdentifyRequests() override
+ {
+ return identifyrequests;
+ }
+
+ std::vector<NickServ::Nick *> GetNickList() override
+ {
+ return nick_type.List<NickServ::Nick *>();
+ }
+
+ NickServ::nickalias_map& GetNickMap() override
+ {
+ return NickList;
+ }
+
+ std::vector<NickServ::Account *> GetAccountList() override
+ {
+ return account_type.List<NickServ::Account *>();
+ }
+
+ NickServ::nickcore_map& GetAccountMap() override
+ {
+ return AccountList;
+ }
+
+ NickServ::Nick *FindNick(const Anope::string &nick) override
+ {
+ return nick_type.FindNick(nick);
+ }
+
+ NickServ::Account *FindAccount(const Anope::string &acc) override
+ {
+ return account_type.FindAccount(acc);
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ const Anope::string &nsnick = conf->GetModule(this)->Get<Anope::string>("client");
+
+ if (nsnick.empty())
+ throw ConfigException(Module::name + ": <client> must be defined");
+
+ ServiceBot *bi = ServiceBot::Find(nsnick, true);
+ if (!bi)