diff options
Diffstat (limited to 'src/users.cpp')
-rw-r--r-- | src/users.cpp | 259 |
1 files changed, 138 insertions, 121 deletions
diff --git a/src/users.cpp b/src/users.cpp index 264f5ceba..3d4b7e1b7 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -1,18 +1,25 @@ -/* Routines to maintain a list of online users. +/* + * Anope IRC Services * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org + * Copyright (C) 2003-2016 Anope Team <team@anope.org> * - * Please read COPYING and README for further details. + * This file is part of Anope. Anope is free software; you can + * redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software + * Foundation, version 2. * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see see <http://www.gnu.org/licenses/>. */ #include "services.h" #include "modules.h" #include "users.h" -#include "account.h" #include "protocol.h" #include "servers.h" #include "channels.h" @@ -22,16 +29,17 @@ #include "language.h" #include "sockets.h" #include "uplink.h" +#include "event.h" +#include "modules/nickserv.h" -user_map UserListByNick, UserListByUID; +user_map UserListByNick; +uid_map UserListByUID; int OperCount = 0; -unsigned MaxUserCount = 0; -time_t MaxUserTime = 0; std::list<User *> User::quitting_users; -User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &uip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *account) : ip(uip) +User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &uip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickServ::Account *account) : ip(uip) { if (snick.empty() || sident.empty() || shost.empty()) throw CoreException("Bad args passed to User::User"); @@ -53,7 +61,6 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope: this->SetModesInternal(sserver, "%s", smodes.c_str()); this->uid = suid; this->super_admin = false; - this->nc = NULL; size_t old = UserListByNick.size(); UserListByNick[snick] = this; @@ -72,18 +79,10 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope: Log(this, "connect") << (!vhost.empty() && vhost != host ? "(" + vhost + ") " : "") << "(" << srealname << ") " << (!uip.empty() && uip != host ? "[" + uip + "] " : "") << "connected to the network (" << sserver->GetName() << ")"; } - if (UserListByNick.size() > MaxUserCount) - { - MaxUserCount = UserListByNick.size(); - MaxUserTime = Anope::CurTime; - if (sserver && sserver->IsSynced()) - Log(this, "maxusers") << "connected - new maximum user count: " << UserListByNick.size(); - } - bool exempt = false; if (server && server->IsULined()) exempt = true; - FOREACH_MOD(OnUserConnect, (this, exempt)); + EventManager::Get()->Dispatch(&Event::UserConnect::OnUserConnect, this, exempt); } static void CollideKill(User *target, const Anope::string &reason) @@ -96,7 +95,7 @@ static void CollideKill(User *target, const Anope::string &reason) IRCD->SendQuit(target, "%s", reason.c_str()); // Reintroduce my client - if (BotInfo *bi = dynamic_cast<BotInfo *>(target)) + if (ServiceBot *bi = dynamic_cast<ServiceBot *>(target)) bi->OnKill(); else target->Quit(reason); @@ -111,7 +110,7 @@ static void Collide(User *u, const Anope::string &id, const Anope::string &type) CollideKill(u, type); } -User* User::OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc) +User* User::OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickServ::Account *nc) { // How IRCds handle collisions varies a lot, for safety well just always kill both sides // With properly set qlines, this can almost never happen anyway @@ -141,7 +140,7 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts) /* Sanity check to make sure we don't segfault */ if (newnick.empty()) throw CoreException("User::ChangeNick() got a bad argument"); - + this->super_admin = false; Log(this, "nick") << "(" << this->realname << ") changed nick to " << newnick; @@ -152,10 +151,10 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts) this->nick = newnick; else { - NickAlias *old_na = NickAlias::Find(this->nick); + NickServ::Nick *old_na = NickServ::FindNick(this->nick); if (old_na && (this->IsIdentified(true) || this->IsRecognized())) - old_na->last_seen = Anope::CurTime; - + old_na->SetLastSeen(Anope::CurTime); + UserListByNick.erase(this->nick); this->nick = newnick; @@ -170,18 +169,23 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts) other = this; on_access = false; - NickAlias *na = NickAlias::Find(this->nick); - if (na) - on_access = na->nc->IsOnAccess(this); - - if (na && na->nc == this->Account()) + if (NickServ::service) { - na->last_seen = Anope::CurTime; - this->UpdateHost(); + NickServ::Nick *na = NickServ::service->FindNick(this->nick); + if (na) + { + on_access = na->GetAccount()->IsOnAccess(this); + + if (na->GetAccount() == this->Account()) + { + na->SetLastSeen(Anope::CurTime); + this->UpdateHost(); + } + } } } - FOREACH_MOD(OnUserNickChange, (this, old)); + EventManager::Get()->Dispatch(&Event::UserNickChange::OnUserNickChange, this, old); } void User::SetDisplayedHost(const Anope::string &shost) @@ -193,7 +197,7 @@ void User::SetDisplayedHost(const Anope::string &shost) Log(this, "host") << "changed vhost to " << shost; - FOREACH_MOD(OnSetDisplayedHost, (this)); + EventManager::Get()->Dispatch(&Event::SetDisplayedHost::OnSetDisplayedHost, this); this->UpdateHost(); } @@ -280,18 +284,18 @@ void User::SetRealname(const Anope::string &srealname) throw CoreException("realname empty in SetRealname"); this->realname = srealname; - NickAlias *na = NickAlias::Find(this->nick); + + //XXX event + NickServ::Nick *na = NickServ::FindNick(this->nick); if (na && (this->IsIdentified(true) || this->IsRecognized())) - na->last_realname = srealname; + na->SetLastRealname(srealname); Log(this, "realname") << "changed realname to " << srealname; } User::~User() { - UnsetExtensibles(); - if (this->server != NULL) { if (this->server->IsSynced()) @@ -299,7 +303,7 @@ User::~User() --this->server->users; } - FOREACH_MOD(OnPreUserLogoff, (this)); + EventManager::Get()->Dispatch(&Event::PreUserLogoff::OnPreUserLogoff, this); ModeManager::StackerDel(this); this->Logout(); @@ -314,25 +318,10 @@ User::~User() if (!this->uid.empty()) UserListByUID.erase(this->uid); - FOREACH_MOD(OnPostUserLogoff, (this)); + EventManager::Get()->Dispatch(&Event::PostUserLogoff::OnPostUserLogoff, this); } -void User::SendMessage(BotInfo *source, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - - const char *translated_message = Language::Translate(this, fmt); - - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, translated_message, args); - - this->SendMessage(source, Anope::string(buf)); - - va_end(args); -} - -void User::SendMessage(BotInfo *source, const Anope::string &msg) +void User::SendMessage(const MessageSource &source, const Anope::string &msg) { const char *translated_message = Language::Translate(this, msg.c_str()); @@ -341,54 +330,77 @@ void User::SendMessage(BotInfo *source, const Anope::string &msg) * - The user is not registered and NSDefMsg is enabled * - The user is registered and has set /ns set msg on */ - bool send_privmsg = Config->UsePrivmsg && ((!this->nc && Config->DefPrivmsg) || (this->nc && this->nc->HasExt("MSG"))); + bool send_privmsg = Config->UsePrivmsg && ((!this->nc && Config->DefPrivmsg) || (this->nc && this->nc->HasFieldS("MSG"))); sepstream sep(translated_message, '\n', true); for (Anope::string tok; sep.GetToken(tok);) { - if (send_privmsg) - IRCD->SendPrivmsg(source, this->GetUID(), "%s", tok.c_str()); - else - IRCD->SendNotice(source, this->GetUID(), "%s", tok.c_str()); + if (tok.empty()) + tok = " "; + spacesepstream ssep(tok, true); + Anope::string buf; + for (Anope::string word; ssep.GetToken(word);) + { + Anope::string add = buf.empty() ? word : " " + word; + if (buf.length() + add.length() > Config->LineWrap) + { + if (send_privmsg) + IRCD->SendPrivmsg(source, this->GetUID(), "%s", buf.c_str()); + else + IRCD->SendNotice(source, this->GetUID(), "%s", buf.c_str()); + buf.clear(); + add = word; + } + buf.append(add); + } + + if (!buf.empty()) + { + if (send_privmsg) + IRCD->SendPrivmsg(source, this->GetUID(), "%s", buf.c_str()); + else + IRCD->SendNotice(source, this->GetUID(), "%s", buf.c_str()); + } } } -void User::Identify(NickAlias *na) +void User::Identify(NickServ::Nick *na) { - if (this->nick.equals_ci(na->nick)) + if (this->nick.equals_ci(na->GetNick())) { - na->last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost(); - na->last_realhost = this->GetIdent() + "@" + this->host; - na->last_realname = this->realname; - na->last_seen = Anope::CurTime; + na->SetLastUsermask(this->GetIdent() + "@" + this->GetDisplayedHost()); + na->SetLastRealhost(this->GetIdent() + "@" + this->host); + na->SetLastRealname(this->realname); + na->SetLastSeen(Anope::CurTime); } IRCD->SendLogin(this, na); - this->Login(na->nc); + this->Login(na->GetAccount()); - FOREACH_MOD(OnNickIdentify, (this)); + EventManager::Get()->Dispatch(&Event::NickIdentify::OnNickIdentify, this); if (this->IsServicesOper()) { - if (!this->nc->o->ot->modes.empty()) + Anope::string m = this->nc->o->GetType()->modes; + if (!m.empty()) { - this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str()); - this->SendMessage(NULL, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str()); + this->SetModes(NULL, "%s", m.c_str()); + this->SendMessage(Me, "Changing your usermodes to \002{0}\002", m.c_str()); UserMode *um = ModeManager::FindUserModeByName("OPER"); - if (um && !this->HasMode("OPER") && this->nc->o->ot->modes.find(um->mchar) != Anope::string::npos) + if (um && !this->HasMode("OPER") && m.find(um->mchar) != Anope::string::npos) IRCD->SendOper(this); } - if (IRCD->CanSetVHost && !this->nc->o->vhost.empty()) + if (IRCD->CanSetVHost && !this->nc->o->GetVhost().empty()) { - this->SendMessage(NULL, "Changing your vhost to \002%s\002", this->nc->o->vhost.c_str()); - this->SetDisplayedHost(this->nc->o->vhost); - IRCD->SendVhost(this, "", this->nc->o->vhost); + this->SendMessage(Me, "Changing your vhost to \002{0}\002", this->nc->o->GetVhost()); + this->SetDisplayedHost(this->nc->o->GetVhost()); + IRCD->SendVhost(this, "", this->nc->o->GetVhost()); } } } -void User::Login(NickCore *core) +void User::Login(NickServ::Account *core) { if (!core || core == this->nc) return; @@ -400,26 +412,26 @@ void User::Login(NickCore *core) this->UpdateHost(); if (this->server->IsSynced()) - Log(this, "account") << "is now identified as " << this->nc->display; - - FOREACH_MOD(OnUserLogin, (this)); + Log(this, "account") << "is now identified as " << this->nc->GetDisplay(); + + EventManager::Get()->Dispatch(&Event::UserLogin::OnUserLogin, this); } void User::Logout() { if (!this->nc) return; - - Log(this, "account") << "is no longer identified as " << this->nc->display; - std::list<User *>::iterator it = std::find(this->nc->users.begin(), this->nc->users.end(), this); + Log(this, "account") << "is no longer identified as " << this->nc->GetDisplay(); + + auto it = std::find(this->nc->users.begin(), this->nc->users.end(), this); if (it != this->nc->users.end()) this->nc->users.erase(it); this->nc = NULL; } -NickCore *User::Account() const +NickServ::Account *User::Account() const { return this->nc; } @@ -428,8 +440,8 @@ bool User::IsIdentified(bool check_nick) const { if (check_nick && this->nc) { - NickAlias *na = NickAlias::Find(this->nick); - return na && *na->nc == *this->nc; + NickServ::Nick *na = NickServ::FindNick(nick); + return na && na->GetAccount() == *this->nc; } return this->nc ? true : false; @@ -439,9 +451,9 @@ bool User::IsRecognized(bool check_secure) const { if (check_secure && on_access) { - const NickAlias *na = NickAlias::Find(this->nick); + NickServ::Nick *na = NickServ::FindNick(nick); - if (!na || na->nc->HasExt("NS_SECURE")) + if (!na || na->GetAccount()->HasFieldS("NS_SECURE")) return false; } @@ -453,24 +465,27 @@ bool User::IsServicesOper() if (!this->nc || !this->nc->IsServicesOper()) // No opertype. return false; - else if (this->nc->o->require_oper && !this->HasMode("OPER")) + else if (this->nc->o->GetRequireOper() && !this->HasMode("OPER")) return false; - else if (!this->nc->o->certfp.empty() && this->fingerprint != this->nc->o->certfp) + else if (!this->nc->o->GetCertFP().empty() && this->fingerprint != this->nc->o->GetCertFP()) // Certfp mismatch return false; - else if (!this->nc->o->hosts.empty()) + else if (!this->nc->o->GetHost().empty()) { + std::vector<Anope::string> hosts; + spacesepstream(this->nc->o->GetHost()).GetTokens(hosts); + bool match = false; Anope::string match_host = this->GetIdent() + "@" + this->host; - for (unsigned i = 0; i < this->nc->o->hosts.size(); ++i) - if (Anope::Match(match_host, this->nc->o->hosts[i])) + for (Anope::string h : hosts) + if (Anope::Match(match_host, h)) match = true; if (match == false) return false; } EventReturn MOD_RESULT; - FOREACH_RESULT(IsServicesOper, MOD_RESULT, (this)); + MOD_RESULT = EventManager::Get()->Dispatch(&Event::IsServicesOperEvent::IsServicesOper, this); if (MOD_RESULT == EVENT_STOP) return false; @@ -480,14 +495,14 @@ bool User::IsServicesOper() bool User::HasCommand(const Anope::string &command) { if (this->IsServicesOper()) - return this->nc->o->ot->HasCommand(command); + return this->nc->o->GetType()->HasCommand(command); return false; } bool User::HasPriv(const Anope::string &priv) { if (this->IsServicesOper()) - return this->nc->o->ot->HasPriv(priv); + return this->nc->o->GetType()->HasPriv(priv); return false; } @@ -496,19 +511,20 @@ void User::UpdateHost() if (this->host.empty()) return; - NickAlias *na = NickAlias::Find(this->nick); + //XXX event + NickServ::Nick *na = NickServ::FindNick(this->nick); on_access = false; if (na) - on_access = na->nc->IsOnAccess(this); + on_access = na->GetAccount()->IsOnAccess(this); if (na && (this->IsIdentified(true) || this->IsRecognized())) { Anope::string last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost(); Anope::string last_realhost = this->GetIdent() + "@" + this->host; - na->last_usermask = last_usermask; - na->last_realhost = last_realhost; + na->SetLastUsermask(last_usermask); + na->SetLastRealhost(last_realhost); // This is called on signon, and if users are introduced with an account it won't update - na->last_realname = this->realname; + na->SetLastRealname(this->realname); } } @@ -530,19 +546,20 @@ void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anop if (this->IsServicesOper()) { - if (!this->nc->o->ot->modes.empty()) + Anope::string m = this->nc->o->GetType()->modes; + if (!m.empty()) { - this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str()); - this->SendMessage(NULL, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str()); + this->SetModes(NULL, "%s", m.c_str()); + this->SendMessage(Me, "Changing your usermodes to \002{0}\002", m); UserMode *oper = ModeManager::FindUserModeByName("OPER"); - if (oper && !this->HasMode("OPER") && this->nc->o->ot->modes.find(oper->mchar) != Anope::string::npos) + if (oper && !this->HasMode("OPER") && m.find(oper->mchar) != Anope::string::npos) IRCD->SendOper(this); } - if (IRCD->CanSetVHost && !this->nc->o->vhost.empty()) + if (IRCD->CanSetVHost && !this->nc->o->GetVhost().empty()) { - this->SendMessage(NULL, "Changing your vhost to \002%s\002", this->nc->o->vhost.c_str()); - this->SetDisplayedHost(this->nc->o->vhost); - IRCD->SendVhost(this, "", this->nc->o->vhost); + this->SendMessage(Me, "Changing your vhost to \002{0}\002", this->nc->o->GetVhost()); + this->SetDisplayedHost(this->nc->o->GetVhost()); + IRCD->SendVhost(this, "", this->nc->o->GetVhost()); } } } @@ -550,7 +567,7 @@ void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anop if (um->name == "CLOAK" || um->name == "VHOST") this->UpdateHost(); - FOREACH_MOD(OnUserModeSet, (source, this, um->name)); + EventManager::Get()->Dispatch(&Event::UserModeSet::OnUserModeSet, source, this, um->name); } void User::RemoveModeInternal(const MessageSource &source, UserMode *um) @@ -569,10 +586,10 @@ void User::RemoveModeInternal(const MessageSource &source, UserMode *um) this->UpdateHost(); } - FOREACH_MOD(OnUserModeUnset, (source, this, um->name)); + EventManager::Get()->Dispatch(&Event::UserModeUnset::OnUserModeUnset, source, this, um->name); } -void User::SetMode(BotInfo *bi, UserMode *um, const Anope::string ¶m) +void User::SetMode(ServiceBot *bi, UserMode *um, const Anope::string ¶m) { if (!um || HasMode(um->name)) return; @@ -581,12 +598,12 @@ void User::SetMode(BotInfo *bi, UserMode *um, const Anope::string ¶m) SetModeInternal(bi, um, param); } -void User::SetMode(BotInfo *bi, const Anope::string &uname, const Anope::string ¶m) +void User::SetMode(ServiceBot *bi, const Anope::string &uname, const Anope::string ¶m) { SetMode(bi, ModeManager::FindUserModeByName(uname), param); } -void User::RemoveMode(BotInfo *bi, UserMode *um, const Anope::string ¶m) +void User::RemoveMode(ServiceBot *bi, UserMode *um, const Anope::string ¶m) { if (!um || !HasMode(um->name)) return; @@ -595,12 +612,12 @@ void User::RemoveMode(BotInfo *bi, UserMode *um, const Anope::string ¶m) RemoveModeInternal(bi, um); } -void User::RemoveMode(BotInfo *bi, const Anope::string &name, const Anope::string ¶m) +void User::RemoveMode(ServiceBot *bi, const Anope::string &name, const Anope::string ¶m) { RemoveMode(bi, ModeManager::FindUserModeByName(name), param); } -void User::SetModes(BotInfo *bi, const char *umodes, ...) +void User::SetModes(ServiceBot *bi, const char *umodes, ...) { char buf[BUFSIZE] = ""; va_list args; @@ -756,7 +773,7 @@ void User::Quit(const Anope::string &reason) return; } - FOREACH_MOD(OnUserQuit, (this, reason)); + EventManager::Get()->Dispatch(&Event::UserQuit::OnUserQuit, this, reason); this->quit = true; quitting_users.push_back(this); @@ -818,7 +835,7 @@ User* User::Find(const Anope::string &name, bool nick_only) { if (!nick_only && IRCD->RequiresID) { - user_map::iterator it = UserListByUID.find(name); + uid_map::iterator it = UserListByUID.find(name); if (it != UserListByUID.end()) return it->second; |