summaryrefslogtreecommitdiff
path: root/src/users.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/users.cpp')
-rw-r--r--src/users.cpp201
1 files changed, 115 insertions, 86 deletions
diff --git a/src/users.cpp b/src/users.cpp
index 9169da2b7..9b370ea06 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -40,7 +40,6 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
quit = false;
server = NULL;
invalid_pw_count = invalid_pw_time = lastmemosend = lastnickreg = lastmail = 0;
- on_access = false;
this->nick = snick;
this->ident = sident;
@@ -50,7 +49,7 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
this->server = sserver;
this->realname = srealname;
this->timestamp = this->signon = ts;
- this->SetModesInternal(sserver, "%s", smodes.c_str());
+ this->SetModesInternal(sserver, smodes);
this->uid = suid;
this->super_admin = false;
this->nc = NULL;
@@ -93,7 +92,7 @@ static void CollideKill(User *target, const Anope::string &reason)
else
{
// Be sure my user is really dead
- IRCD->SendQuit(target, "%s", reason.c_str());
+ IRCD->SendQuit(target, reason);
// Reintroduce my client
if (BotInfo *bi = dynamic_cast<BotInfo *>(target))
@@ -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, NickCore *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
@@ -153,14 +152,14 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts)
else
{
NickAlias *old_na = NickAlias::Find(this->nick);
- if (old_na && (this->IsIdentified(true) || this->IsRecognized()))
+ if (old_na && this->IsIdentified(true))
old_na->last_seen = Anope::CurTime;
UserListByNick.erase(this->nick);
this->nick = newnick;
- User* &other = UserListByNick[this->nick];
+ User *&other = UserListByNick[this->nick];
if (other)
{
CollideKill(this, "Nick collision");
@@ -169,11 +168,7 @@ 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())
{
na->last_seen = Anope::CurTime;
@@ -282,7 +277,7 @@ void User::SetRealname(const Anope::string &srealname)
this->realname = srealname;
NickAlias *na = NickAlias::Find(this->nick);
- if (na && (this->IsIdentified(true) || this->IsRecognized()))
+ if (na && this->IsIdentified(true))
na->last_realname = srealname;
Log(this, "realname") << "changed realname to " << srealname;
@@ -332,26 +327,37 @@ void User::SendMessage(BotInfo *source, const char *fmt, ...)
va_end(args);
}
-void User::SendMessage(BotInfo *source, const Anope::string &msg)
+namespace
{
- const char *translated_message = Language::Translate(this, msg.c_str());
-
- /* Send privmsg instead of notice if:
- * - UsePrivmsg is enabled
- * - 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")));
- sepstream sep(translated_message, '\n', true);
- for (Anope::string tok; sep.GetToken(tok);)
+ void SendMessageInternal(BotInfo *source, User *target, const Anope::string &msg, const Anope::map<Anope::string> &tags)
{
- if (send_privmsg)
- IRCD->SendPrivmsg(source, this->GetUID(), "%s", tok.c_str());
- else
- IRCD->SendNotice(source, this->GetUID(), "%s", tok.c_str());
+ const char *translated_message = Language::Translate(target, msg.c_str());
+
+ sepstream sep(translated_message, '\n', true);
+ for (Anope::string tok; sep.GetToken(tok);)
+ {
+ if (target->ShouldPrivmsg())
+ IRCD->SendPrivmsg(source, target->GetUID(), tok, tags);
+ else
+ IRCD->SendNotice(source, target->GetUID(), tok, tags);
+ }
}
}
+void User::SendMessage(BotInfo *source, const Anope::string &msg)
+{
+ SendMessageInternal(source, this, msg, {});
+}
+
+void User::SendMessage(CommandSource &source, const Anope::string &msg)
+{
+ Anope::map<Anope::string> tags;
+ if (!source.msgid.empty())
+ tags["+draft/reply"] = source.msgid;
+
+ SendMessageInternal(*source.service, this, msg, tags);
+}
+
void User::Identify(NickAlias *na)
{
if (this->nick.equals_ci(na->nick))
@@ -372,7 +378,7 @@ void User::Identify(NickAlias *na)
{
if (!this->nc->o->ot->modes.empty())
{
- this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str());
+ this->SetModes(NULL, this->nc->o->ot->modes);
this->SendMessage(NULL, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str());
UserMode *um = ModeManager::FindUserModeByName("OPER");
if (um && !this->HasMode("OPER") && this->nc->o->ot->modes.find(um->mchar) != Anope::string::npos)
@@ -382,7 +388,7 @@ void User::Identify(NickAlias *na)
{
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);
+ IRCD->SendVHost(this, "", this->nc->o->vhost);
}
}
}
@@ -424,6 +430,11 @@ NickCore *User::Account() const
return this->nc;
}
+NickAlias *User::AccountNick() const
+{
+ return this->nc ? this->nc->na : nullptr;
+}
+
bool User::IsIdentified(bool check_nick) const
{
if (check_nick && this->nc)
@@ -432,56 +443,58 @@ bool User::IsIdentified(bool check_nick) const
return na && *na->nc == *this->nc;
}
- return this->nc ? true : false;
+ return this->nc;
}
-bool User::IsRecognized(bool check_secure) const
+bool User::IsSecurelyConnected() const
{
- if (check_secure && on_access)
- {
- const NickAlias *na = NickAlias::Find(this->nick);
-
- if (!na || na->nc->HasExt("NS_SECURE"))
- return false;
- }
-
- return on_access;
+ return HasMode("SSL") || HasExt("ssl");
}
bool User::IsServicesOper()
{
if (!this->nc || !this->nc->IsServicesOper())
- // No opertype.
- return false;
- else if (this->nc->o->require_oper && !this->HasMode("OPER"))
- return false;
- else if (!this->nc->o->certfp.empty() && this->fingerprint != this->nc->o->certfp)
- // Certfp mismatch
- return false;
- else if (!this->nc->o->hosts.empty())
+ return false; // Account isn't a services oper.
+
+ auto *oper = this->nc->o;
+ if (oper->require_oper && !this->HasMode("OPER"))
+ return false; // User isn't an ircd oper.
+
+ if (!oper->certfp.empty())
+ {
+ bool match = false;
+ for (const auto &certfp : oper->certfp)
+ {
+ if (this->fingerprint == certfp)
+ {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ return false; // Wrong TLS fingerprint.
+ }
+
+ if (!oper->hosts.empty())
{
bool match = false;
Anope::string match_host = this->GetIdent() + "@" + this->host;
Anope::string match_ip = this->GetIdent() + "@" + this->ip.addr();
- for (unsigned i = 0; i < this->nc->o->hosts.size(); ++i)
+ for (const auto &userhost : oper->hosts)
{
- const Anope::string &userhost = this->nc->o->hosts[i];
if (Anope::Match(match_host, userhost) || Anope::Match(match_ip, userhost))
{
match = true;
break;
}
}
- if (match == false)
- return false;
+ if (!match)
+ return false; // Wrong user@host/ip.
}
EventReturn MOD_RESULT;
FOREACH_RESULT(IsServicesOper, MOD_RESULT, (this));
- if (MOD_RESULT == EVENT_STOP)
- return false;
-
- return true;
+ return MOD_RESULT != EVENT_STOP;
}
bool User::HasCommand(const Anope::string &command)
@@ -504,11 +517,7 @@ void User::UpdateHost()
return;
NickAlias *na = NickAlias::Find(this->nick);
- on_access = false;
- if (na)
- on_access = na->nc->IsOnAccess(this);
-
- if (na && (this->IsIdentified(true) || this->IsRecognized()))
+ if (na && this->IsIdentified(true))
{
Anope::string last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost();
Anope::string last_realhost = this->GetIdent() + "@" + this->host;
@@ -539,7 +548,7 @@ void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anop
{
if (!this->nc->o->ot->modes.empty())
{
- this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str());
+ this->SetModes(NULL, this->nc->o->ot->modes);
this->SendMessage(NULL, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str());
UserMode *oper = ModeManager::FindUserModeByName("OPER");
if (oper && !this->HasMode("OPER") && this->nc->o->ot->modes.find(oper->mchar) != Anope::string::npos)
@@ -549,7 +558,7 @@ void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anop
{
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);
+ IRCD->SendVHost(this, "", this->nc->o->vhost);
}
}
}
@@ -616,19 +625,24 @@ void User::SetModes(BotInfo *bi, const char *umodes, ...)
{
char buf[BUFSIZE] = "";
va_list args;
- Anope::string modebuf, sbuf;
- int add = -1;
va_start(args, umodes);
vsnprintf(buf, BUFSIZE - 1, umodes, args);
va_end(args);
- spacesepstream sep(buf);
+ SetModes(bi, Anope::string(buf));
+}
+
+void User::SetModes(BotInfo *bi, const Anope::string &umodes)
+{
+ Anope::string modebuf, sbuf;
+ int add = -1;
+ spacesepstream sep(umodes);
sep.GetToken(modebuf);
- for (unsigned i = 0, end = modebuf.length(); i < end; ++i)
+ for (auto mode : modebuf)
{
UserMode *um;
- switch (modebuf[i])
+ switch (mode)
{
case '+':
add = 1;
@@ -639,7 +653,7 @@ void User::SetModes(BotInfo *bi, const char *umodes, ...)
default:
if (add == -1)
continue;
- um = ModeManager::FindUserModeByChar(modebuf[i]);
+ um = ModeManager::FindUserModeByChar(mode);
if (!um)
continue;
}
@@ -660,22 +674,27 @@ void User::SetModesInternal(const MessageSource &source, const char *umodes, ...
{
char buf[BUFSIZE] = "";
va_list args;
- Anope::string modebuf, sbuf;
- int add = -1;
va_start(args, umodes);
vsnprintf(buf, BUFSIZE - 1, umodes, args);
va_end(args);
- if (this->server && this->server->IsSynced() && Anope::string(buf) != "+")
- Log(this, "mode") << "changes modes to " << buf;
+ SetModesInternal(source, Anope::string(buf));
+}
+
+void User::SetModesInternal(const MessageSource &source, const Anope::string &umodes)
+{
+ if (this->server && this->server->IsSynced() && Anope::string(umodes) != "+")
+ Log(this, "mode") << "changes modes to " << umodes;
- spacesepstream sep(buf);
+ int add = -1;
+ Anope::string modebuf;
+ spacesepstream sep(umodes);
sep.GetToken(modebuf);
- for (unsigned i = 0, end = modebuf.length(); i < end; ++i)
+ for (auto mode : modebuf)
{
UserMode *um;
- switch (modebuf[i])
+ switch (mode)
{
case '+':
add = 1;
@@ -686,13 +705,14 @@ void User::SetModesInternal(const MessageSource &source, const char *umodes, ...
default:
if (add == -1)
continue;
- um = ModeManager::FindUserModeByChar(modebuf[i]);
+ um = ModeManager::FindUserModeByChar(mode);
if (!um)
continue;
}
if (add)
{
+ Anope::string sbuf;
if (um->type == MODE_PARAM && sep.GetToken(sbuf))
this->SetModeInternal(source, um, sbuf);
else
@@ -707,16 +727,16 @@ Anope::string User::GetModes() const
{
Anope::string m, params;
- for (ModeList::const_iterator it = this->modes.begin(), it_end = this->modes.end(); it != it_end; ++it)
+ for (const auto &[mode, value] : this->modes)
{
- UserMode *um = ModeManager::FindUserModeByName(it->first);
+ UserMode *um = ModeManager::FindUserModeByName(mode);
if (um == NULL)
continue;
m += um->mchar;
- if (!it->second.empty())
- params += " " + it->second;
+ if (!value.empty())
+ params += " " + value;
}
return m + params;
@@ -744,7 +764,7 @@ void User::Kill(const MessageSource &source, const Anope::string &reason)
{
Anope::string real_reason = source.GetName() + " (" + reason + ")";
- IRCD->SendSVSKill(source, this, "%s", real_reason.c_str());
+ IRCD->SendSVSKill(source, this, real_reason);
}
void User::KillInternal(const MessageSource &source, const Anope::string &reason)
@@ -810,14 +830,14 @@ Anope::string User::Mask() const
bool User::BadPassword()
{
- if (!Config->GetBlock("options")->Get<int>("badpasslimit"))
+ if (!Config->GetBlock("options")->Get<unsigned int>("badpasslimit"))
return false;
if (Config->GetBlock("options")->Get<time_t>("badpasstimeout") > 0 && this->invalid_pw_time > 0 && this->invalid_pw_time < Anope::CurTime - Config->GetBlock("options")->Get<time_t>("badpasstimeout"))
this->invalid_pw_count = 0;
++this->invalid_pw_count;
this->invalid_pw_time = Anope::CurTime;
- if (this->invalid_pw_count >= Config->GetBlock("options")->Get<int>("badpasslimit"))
+ if (this->invalid_pw_count >= Config->GetBlock("options")->Get<unsigned int>("badpasslimit"))
{
this->Kill(Me, "Too many invalid passwords");
return true;
@@ -826,7 +846,16 @@ bool User::BadPassword()
return false;
}
-User* User::Find(const Anope::string &name, bool nick_only)
+bool User::ShouldPrivmsg() const
+{
+ // Send a PRIVMSG instead of a NOTICE if:
+ // 1. options:useprivmsg is enabled.
+ // 2. The user is not registered and msg is in nickserv:defaults.
+ // 3. The user is registered and has set /ns set message on.
+ return Config->UsePrivmsg && ((!nc && Config->DefPrivmsg) || (nc && nc->HasExt("MSG")));
+}
+
+User *User::Find(const Anope::string &name, bool nick_only)
{
if (!nick_only && IRCD && IRCD->RequiresID)
{
@@ -847,7 +876,7 @@ User* User::Find(const Anope::string &name, bool nick_only)
void User::QuitUsers()
{
- for (std::list<User *>::iterator it = quitting_users.begin(), it_end = quitting_users.end(); it != it_end; ++it)
- delete *it;
+ for (const auto *quitting_user : quitting_users)
+ delete quitting_user;
quitting_users.clear();
}