1
0
mirror of https://github.com/anope/anope.git synced 2026-06-25 12:16:39 +02:00
Files
anope/src/nickalias.cpp
T
2025-11-12 19:49:59 +00:00

259 lines
6.4 KiB
C++

// Anope IRC Services <https://www.anope.org/>
//
// Copyright (C) 2003-2025 Anope Contributors
//
// Anope is free software. You can use, modify, and/or distribute it under the
// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt
// for the complete terms of this license and docs/AUTHORS.txt for a list of
// contributors.
//
// Based on the original code of Epona by Lara
// Based on the original code of Services by Andy Church
//
// SPDX-License-Identifier: GPL-2.0-only
#include "services.h"
#include "account.h"
#include "modules.h"
#include "opertype.h"
#include "protocol.h"
#include "users.h"
#include "servers.h"
#include "config.h"
Serialize::Checker<nickalias_map> NickAliasList(NICKALIAS_TYPE);
NickAlias::NickAlias(const Anope::string &nickname, NickCore *nickcore)
: Serializable(NICKALIAS_TYPE)
, nick(nickname)
, nc(nickcore)
{
if (nickname.empty())
throw CoreException("Empty nick passed to NickAlias constructor");
else if (!nickcore)
throw CoreException("Empty nickcore passed to NickAlias constructor");
nickcore->aliases->push_back(this);
if (this->nick.equals_ci(nickcore->display))
nickcore->na = this;
if (!NickAliasList->insert_or_assign(this->nick, this).second)
Log(LOG_DEBUG) << "Duplicate nick " << this->nick << " in NickAlias table";
if (this->nc->o == NULL)
{
Oper *o = Oper::Find(this->nick);
if (o == NULL)
o = Oper::Find(this->nc->display);
nickcore->o = o;
if (this->nc->o != NULL)
Log() << "Tied oper " << this->nc->display << " to type " << this->nc->o->ot->GetName();
}
}
NickAlias::~NickAlias()
{
FOREACH_MOD(OnDelNick, (this));
UnsetExtensibles();
/* Accept nicks that have no core, because of database load functions */
if (this->nc)
{
/* Next: see if our core is still useful. */
std::vector<NickAlias *>::iterator it = std::find(this->nc->aliases->begin(), this->nc->aliases->end(), this);
if (it != this->nc->aliases->end())
this->nc->aliases->erase(it);
if (this->nc->aliases->empty())
{
delete this->nc;
this->nc = NULL;
}
else
{
/* Display updating stuff */
if (this->nc->na == this)
this->nc->SetDisplay(nullptr);
}
}
/* Remove us from the aliases list */
NickAliasList->erase(this->nick);
}
void NickAlias::SetVHost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created)
{
this->vhost_ident = ident;
this->vhost_host = host;
this->vhost_creator = creator;
this->vhost_created = created;
}
void NickAlias::RemoveVHost()
{
this->vhost_ident.clear();
this->vhost_host.clear();
this->vhost_creator.clear();
this->vhost_created = 0;
}
bool NickAlias::HasVHost() const
{
return !this->vhost_host.empty();
}
const Anope::string &NickAlias::GetVHostIdent() const
{
return this->vhost_ident;
}
const Anope::string &NickAlias::GetVHostHost() const
{
return this->vhost_host;
}
Anope::string NickAlias::GetVHostMask() const
{
if (this->GetVHostIdent().empty())
return this->GetVHostHost();
return this->GetVHostIdent() + "@" + this->GetVHostHost();
}
const Anope::string &NickAlias::GetVHostCreator() const
{
return this->vhost_creator;
}
time_t NickAlias::GetVHostCreated() const
{
return this->vhost_created;
}
void NickAlias::UpdateSeen(User *u)
{
this->last_seen = Anope::CurTime;
this->last_userhost = u->GetIdent() + "@" + u->GetDisplayedHost();
this->last_userhost_real = u->GetIdent() + "@" + u->host;
}
NickAlias *NickAlias::Find(const Anope::string &nick)
{
nickalias_map::const_iterator it = NickAliasList->find(nick);
if (it != NickAliasList->end())
{
it->second->QueueUpdate();
return it->second;
}
return NULL;
}
NickAlias *NickAlias::FindId(uint64_t uid)
{
const auto *nc = NickCore::FindId(uid);
return nc ? nc->na : nullptr;
}
NickAlias::Type::Type()
: Serialize::Type(NICKALIAS_TYPE)
{
}
void NickAlias::Type::Serialize(Serializable *obj, Serialize::Data &data) const
{
const auto *na = static_cast<const NickAlias *>(obj);
data.Store("nick", na->nick);
data.Store("last_quit", na->last_quit);
data.Store("last_userhost", na->last_userhost);
data.Store("last_userhost_real", na->last_userhost_real);
data.Store("registered", na->registered);
data.Store("last_seen", na->last_seen);
data.Store("ncid", na->nc->GetId());
if (na->HasVHost())
{
data.Store("vhost_ident", na->GetVHostIdent());
data.Store("vhost_host", na->GetVHostHost());
data.Store("vhost_creator", na->GetVHostCreator());
data.Store("vhost_time", na->GetVHostCreated());
}
Extensible::ExtensibleSerialize(na, na, data);
}
Serializable *NickAlias::Type::Unserialize(Serializable *obj, Serialize::Data &data) const
{
Anope::string snc, snick;
uint64_t sncid = 0;
data["nc"] >> snc; // Deprecated 2.0 field
data["ncid"] >> sncid;
data["nick"] >> snick;
auto *core = sncid ? NickCore::FindId(sncid) : NickCore::Find(snc);
if (core == NULL)
return NULL;
NickAlias *na;
if (obj)
na = anope_dynamic_static_cast<NickAlias *>(obj);
else
na = new NickAlias(snick, core);
if (na->nc != core)
{
std::vector<NickAlias *>::iterator it = std::find(na->nc->aliases->begin(), na->nc->aliases->end(), na);
if (it != na->nc->aliases->end())
na->nc->aliases->erase(it);
if (na->nc->aliases->empty())
delete na->nc;
if (na->nc->na == na)
na->nc->SetDisplay(nullptr);
na->nc = core;
core->aliases->push_back(na);
}
data["last_quit"] >> na->last_quit;
data["last_userhost"] >> na->last_userhost;
data["last_userhost_real"] >> na->last_userhost_real;
data["registered"] >> na->registered;
data["last_seen"] >> na->last_seen;
Anope::string vhost_ident, vhost_host, vhost_creator;
time_t vhost_time;
data["vhost_ident"] >> vhost_ident;
data["vhost_host"] >> vhost_host;
data["vhost_creator"] >> vhost_creator;
data["vhost_time"] >> vhost_time;
na->SetVHost(vhost_ident, vhost_host, vhost_creator, vhost_time);
Extensible::ExtensibleUnserialize(na, na, data);
// Begin 1.9 compatibility.
bool b;
b = false;
data["extensible:NO_EXPIRE"] >> b;
if (b)
na->Extend<bool>("NS_NO_EXPIRE");
// End 1.9 compatibility.
// Begin 2.0 compatibility.
if (na->last_userhost.empty())
data["last_usermask"] >> na->last_userhost;
if (na->last_userhost_real.empty())
data["last_realhost"] >> na->last_userhost_real;
if (na->registered == Anope::CurTime)
data["time_registered"] >> na->registered;
if (na->registered < na->nc->registered)
na->nc->registered = na->registered;
// End 2.0 compatibility.
return na;
}