summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-06-18 05:04:30 -0400
committerAdam <Adam@anope.org>2012-06-18 05:04:30 -0400
commit2dec8e767a70def4b9b04a96ae4f75e4d1013038 (patch)
tree36f5b551ff359a578e17d5e7d2f486970d759a7b /src
parent873d4287de57f7f9caa23cb2c9265d1ad2804aba (diff)
Allow userless command sources
Diffstat (limited to 'src')
-rw-r--r--src/bots.cpp86
-rw-r--r--src/command.cpp167
-rw-r--r--src/logger.cpp38
-rw-r--r--src/mail.cpp37
-rw-r--r--src/misc.cpp6
-rw-r--r--src/users.cpp7
6 files changed, 224 insertions, 117 deletions
diff --git a/src/bots.cpp b/src/bots.cpp
index a4db8b5a3..85d6e0700 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -238,94 +238,12 @@ void BotInfo::OnMessage(User *u, const Anope::string &message)
if (this->commands.empty())
return;
- std::vector<Anope::string> params = BuildStringVector(message);
- bool has_help = this->commands.find("HELP") != this->commands.end();
-
- BotInfo::command_map::const_iterator it = this->commands.end();
- unsigned count = 0;
- for (unsigned max = params.size(); it == this->commands.end() && max > 0; --max)
- {
- Anope::string full_command;
- for (unsigned i = 0; i < max; ++i)
- full_command += " " + params[i];
- full_command.erase(full_command.begin());
-
- ++count;
- it = this->commands.find(full_command);
- }
-
- if (it == this->commands.end())
- {
- if (has_help)
- u->SendMessage(this, _("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), this->nick.c_str());
- else
- u->SendMessage(this, _("Unknown command \002%s\002."), message.c_str());
- return;
- }
-
- const CommandInfo &info = it->second;
- service_reference<Command> c("Command", info.name);
- if (!c)
- {
- if (has_help)
- u->SendMessage(this, _("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), this->nick.c_str());
- else
- u->SendMessage(this, _("Unknown command \002%s\002."), message.c_str());
- Log(this) << "Command " << it->first << " exists on me, but its service " << info.name << " was not found!";
- return;
- }
-
- // Command requires registered users only
- if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified())
- {
- u->SendMessage(this, NICK_IDENTIFY_REQUIRED);
- Log(LOG_NORMAL, "access_denied", this) << "Access denied for unregistered user " << u->GetMask() << " with command " << c->name;
- return;
- }
-
- for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i)
- params.erase(params.begin());
-
- while (c->MaxParams > 0 && params.size() > c->MaxParams)
- {
- params[c->MaxParams - 1] += " " + params[c->MaxParams];
- params.erase(params.begin() + c->MaxParams);
- }
-
- CommandSource source;
- source.u = u;
+ CommandSource source(u->nick, u, u->Account(), u);
source.c = NULL;
source.owner = this;
source.service = this;
- source.command = it->first;
- source.permission = info.permission;
- EventReturn MOD_RESULT;
- FOREACH_RESULT(I_OnPreCommand, OnPreCommand(source, c, params));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
-
- if (params.size() < c->MinParams)
- {
- c->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : "");
- return;
- }
-
- // If the command requires a permission, and they aren't registered or don't have the required perm, DENIED
- if (!info.permission.empty() && !u->HasCommand(info.permission))
- {
- u->SendMessage(this, ACCESS_DENIED);
- Log(LOG_NORMAL, "access_denied", this) << "Access denied for user " << u->GetMask() << " with command " << c->name;
- return;
- }
-
- dynamic_reference<User> user_reference(u);
- c->Execute(source, params);
- if (user_reference)
- {
- FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params));
- }
+ RunCommand(source, message);
}
/** Link a command name to a command in services
diff --git a/src/command.cpp b/src/command.cpp
index 309611a92..ae01ecda4 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -12,6 +12,78 @@
#include "language.h"
#include "config.h"
#include "bots.h"
+#include "opertype.h"
+#include "access.h"
+#include "regchannel.h"
+
+CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r) : nick(n), u(user), nc(core), reply(r)
+{
+}
+
+const Anope::string &CommandSource::GetNick() const
+{
+ return this->nick;
+}
+
+User *CommandSource::GetUser() const
+{
+ return this->u;
+}
+
+AccessGroup CommandSource::AccessFor(ChannelInfo *ci) const
+{
+ if (this->u)
+ return ci->AccessFor(this->u);
+ else if (this->nc)
+ return ci->AccessFor(this->nc);
+ else
+ return AccessGroup();
+}
+
+bool CommandSource::IsFounder(ChannelInfo *ci) const
+{
+ if (this->u)
+ return ::IsFounder(this->u, ci);
+ else if (this->nc)
+ return this->nc == ci->GetFounder();
+ return false;
+}
+
+bool CommandSource::HasCommand(const Anope::string &cmd)
+{
+ if (this->u)
+ return this->u->HasCommand(cmd);
+ else if (this->nc && this->nc->o)
+ return this->nc->o->ot->HasCommand(cmd);
+ return false;
+}
+
+bool CommandSource::HasPriv(const Anope::string &cmd)
+{
+ if (this->u)
+ return this->u->HasPriv(cmd);
+ else if (this->nc && this->nc->o)
+ return this->nc->o->ot->HasPriv(cmd);
+ return false;
+}
+
+bool CommandSource::IsServicesOper() const
+{
+ if (this->u)
+ return this->u->IsServicesOper();
+ else if (this->nc)
+ return this->nc->IsServicesOper();
+ return false;
+}
+
+bool CommandSource::IsOper() const
+{
+ if (this->u)
+ return this->u->HasMode(UMODE_OPER);
+ else if (this->nc)
+ return this->nc->IsServicesOper();
+ return false;
+}
void CommandSource::Reply(const char *message, ...)
{
@@ -35,7 +107,7 @@ void CommandSource::Reply(const Anope::string &message)
sepstream sep(translated_message, '\n');
Anope::string tok;
while (sep.GetToken(tok))
- u->SendMessage(this->service, tok);
+ this->reply->SendMessage(this->service, tok);
}
Command::Command(Module *o, const Anope::string &sname, size_t min_params, size_t max_params) : Service(o, "Command", sname), Flags<CommandFlag>(CommandFlagStrings), MaxParams(max_params), MinParams(min_params), module(owner)
@@ -84,7 +156,7 @@ const Anope::string &Command::GetDesc() const
void Command::OnServHelp(CommandSource &source)
{
- source.Reply(" %-14s %s", source.command.c_str(), translate(source.u, (this->GetDesc().c_str())));
+ source.Reply(" %-14s %s", source.command.c_str(), translate(source.nc, (this->GetDesc().c_str())));
}
bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { return false; }
@@ -95,3 +167,94 @@ void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcomma
source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str());
}
+void RunCommand(CommandSource &source, const Anope::string &message)
+{
+ std::vector<Anope::string> params = BuildStringVector(message);
+ bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
+
+ BotInfo::command_map::const_iterator it = source.service->commands.end();
+ unsigned count = 0;
+ for (unsigned max = params.size(); it == source.service->commands.end() && max > 0; --max)
+ {
+ Anope::string full_command;
+ for (unsigned i = 0; i < max; ++i)
+ full_command += " " + params[i];
+ full_command.erase(full_command.begin());
+
+ ++count;
+ it = source.service->commands.find(full_command);
+ }
+
+ if (it == source.service->commands.end())
+ {
+ if (has_help)
+ source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
+ else
+ source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ return;
+ }
+
+ const CommandInfo &info = it->second;
+ service_reference<Command> c("Command", info.name);
+ if (!c)
+ {
+ if (has_help)
+ source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
+ else
+ source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ Log(source.service) << "Command " << it->first << " exists on me, but its service " << info.name << " was not found!";
+ return;
+ }
+
+ // Command requires registered users only
+ if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !source.nc)
+ {
+ source.Reply(NICK_IDENTIFY_REQUIRED);
+ if (source.GetUser())
+ Log(LOG_NORMAL, "access_denied", source.service) << "Access denied for unregistered user " << source.GetUser()->GetMask() << " with command " << c->name;
+ return;
+ }
+
+ for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i)
+ params.erase(params.begin());
+
+ while (c->MaxParams > 0 && params.size() > c->MaxParams)
+ {
+ params[c->MaxParams - 1] += " " + params[c->MaxParams];
+ params.erase(params.begin() + c->MaxParams);
+ }
+
+ source.command = it->first;
+ source.permission = info.permission;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(I_OnPreCommand, OnPreCommand(source, c, params));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+
+ if (params.size() < c->MinParams)
+ {
+ c->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : "");
+ return;
+ }
+
+ // If the command requires a permission, and they aren't registered or don't have the required perm, DENIED
+ if (!info.permission.empty() && !source.HasCommand(info.permission))
+ {
+ source.Reply(ACCESS_DENIED);
+ if (source.GetUser())
+ Log(LOG_NORMAL, "access_denied", source.service) << "Access denied for user " << source.GetUser()->GetMask() << " with command " << c->name;
+ return;
+ }
+
+ bool had_u = source.GetUser(), had_nc = source.nc;
+ dynamic_reference<User> user_reference(source.GetUser());
+ dynamic_reference<NickCore> nc_reference(source.nc);
+ c->Execute(source, params);
+ if (had_u == user_reference && had_nc == nc_reference)
+ {
+ FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params));
+ }
+}
+
diff --git a/src/logger.cpp b/src/logger.cpp
index 1b7c48f78..d18b0731e 100644
--- a/src/logger.cpp
+++ b/src/logger.cpp
@@ -75,7 +75,7 @@ Anope::string LogFile::GetName() const
return this->filename;
}
-Log::Log(LogType type, const Anope::string &category, const BotInfo *b) : bi(b), u(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(type), Category(category)
+Log::Log(LogType type, const Anope::string &category, const BotInfo *b) : bi(b), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(type), Category(category)
{
if (!bi && Config)
bi = findbot(Config->Global);
@@ -83,9 +83,9 @@ Log::Log(LogType type, const Anope::string &category, const BotInfo *b) : bi(b),
this->Sources.push_back(bi->nick);
}
-Log::Log(LogType type, const User *_u, Command *_c, const ChannelInfo *_ci) : u(_u), c(_c), chan(NULL), ci(_ci), s(NULL), Type(type)
+Log::Log(LogType type, const CommandSource &source, Command *_c, const ChannelInfo *_ci) : u(source.GetUser()), nc(source.nc), c(_c), chan(NULL), ci(_ci), s(NULL), Type(type)
{
- if (!u || !c)
+ if (!c)
throw CoreException("Invalid pointers passed to Log::Log");
if (type != LOG_COMMAND && type != LOG_OVERRIDE && type != LOG_ADMIN)
@@ -100,13 +100,14 @@ Log::Log(LogType type, const User *_u, Command *_c, const ChannelInfo *_ci) : u(
this->Category = c->name;
if (this->bi)
this->Sources.push_back(this->bi->nick);
- this->Sources.push_back(u->nick);
+ if (u)
+ this->Sources.push_back(u->nick);
this->Sources.push_back(c->name);
if (ci)
this->Sources.push_back(ci->name);
}
-Log::Log(const User *_u, Channel *ch, const Anope::string &category) : bi(NULL), u(_u), c(NULL), chan(ch), ci(chan ? *chan->ci : NULL), s(NULL), Type(LOG_CHANNEL)
+Log::Log(const User *_u, Channel *ch, const Anope::string &category) : bi(NULL), u(_u), nc(NULL), c(NULL), chan(ch), ci(chan ? *chan->ci : NULL), s(NULL), Type(LOG_CHANNEL)
{
if (!chan)
throw CoreException("Invalid pointers passed to Log::Log");
@@ -121,7 +122,7 @@ Log::Log(const User *_u, Channel *ch, const Anope::string &category) : bi(NULL),
this->Sources.push_back(chan->name);
}
-Log::Log(const User *_u, const Anope::string &category, const BotInfo *_bi) : bi(_bi), u(_u), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(LOG_USER), Category(category)
+Log::Log(const User *_u, const Anope::string &category, const BotInfo *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(LOG_USER), Category(category)
{
if (!u)
throw CoreException("Invalid pointers passed to Log::Log");
@@ -133,7 +134,7 @@ Log::Log(const User *_u, const Anope::string &category, const BotInfo *_bi) : bi
this->Sources.push_back(u->nick);
}
-Log::Log(Server *serv, const Anope::string &category, const BotInfo *_bi) : bi(_bi), u(NULL), c(NULL), chan(NULL), ci(NULL), s(serv), Type(LOG_SERVER), Category(category)
+Log::Log(Server *serv, const Anope::string &category, const BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(serv), Type(LOG_SERVER), Category(category)
{
if (!s)
throw CoreException("Invalid pointer passed to Log::Log");
@@ -147,7 +148,7 @@ Log::Log(Server *serv, const Anope::string &category, const BotInfo *_bi) : bi(_
this->Sources.push_back(s->GetName());
}
-Log::Log(const BotInfo *b, const Anope::string &category) : bi(b), u(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(LOG_NORMAL), Category(category)
+Log::Log(const BotInfo *b, const Anope::string &category) : bi(b), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(LOG_NORMAL), Category(category)
{
if (!this->bi && Config)
this->bi = findbot(Config->Global);
@@ -179,36 +180,45 @@ Anope::string Log::BuildPrefix() const
{
case LOG_ADMIN:
{
- if (!this->c || !this->u)
+ if (!this->c && !(this->u || this->nc))
break;
buffer += "ADMIN: ";
size_t sl = this->c->name.find('/');
Anope::string cname = sl != Anope::string::npos ? this->c->name.substr(sl + 1) : this->c->name;
- buffer += this->u->GetMask() + " used " + cname + " ";
+ if (this->u)
+ buffer += this->u->GetMask() + " used " + cname + " ";
+ else if (this->nc)
+ buffer += this->nc->display + " used " + cname + " ";
if (this->ci)
buffer += "on " + this->ci->name + " ";
break;
}
case LOG_OVERRIDE:
{
- if (!this->c || !this->u)
+ if (!this->c && !(this->u || this->nc))
break;
buffer += "OVERRIDE: ";
size_t sl = this->c->name.find('/');
Anope::string cname = sl != Anope::string::npos ? this->c->name.substr(sl + 1) : this->c->name;
- buffer += this->u->GetMask() + " used " + cname + " ";
+ if (this->u)
+ buffer += this->u->GetMask() + " used " + cname + " ";
+ else if (this->nc)
+ buffer += this->nc->display + " used " + cname + " ";
if (this->ci)
buffer += "on " + this->ci->name + " ";
break;
}
case LOG_COMMAND:
{
- if (!this->c || !this->u)
+ if (!this->c || !(this->u || this->nc))
break;
buffer += "COMMAND: ";
size_t sl = this->c->name.find('/');
Anope::string cname = sl != Anope::string::npos ? this->c->name.substr(sl + 1) : this->c->name;
- buffer += this->u->GetMask() + " used " + cname + " ";
+ if (this->u)
+ buffer += this->u->GetMask() + " used " + cname + " ";
+ else if (this->nc)
+ buffer += this->nc->display + " used " + cname + " ";
if (this->ci)
buffer += "on " + this->ci->name + " ";
break;
diff --git a/src/mail.cpp b/src/mail.cpp
index aaf564bc6..0a9273ebc 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -53,24 +53,39 @@ void MailThread::Run()
bool Mail(User *u, NickCore *nc, const BotInfo *service, const Anope::string &subject, const Anope::string &message)
{
- if (!u || !nc || !service || subject.empty() || message.empty())
+ if (!nc || !service || subject.empty() || message.empty())
return false;
-
- if (!Config->UseMail)
- u->SendMessage(service, _("Services have been configured to not send mail."));
- else if (Anope::CurTime - u->lastmail < Config->MailDelay)
- u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), Config->MailDelay - (Anope::CurTime - u->lastmail));
- else if (nc->email.empty())
- u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->display.c_str());
- else
+
+ if (!u)
{
- u->lastmail = nc->lastmail = Anope::CurTime;
+ if (!Config->UseMail)
+ return false;
+ else if (nc->email.empty())
+ return false;
+
+ nc->lastmail = Anope::CurTime;
Thread *t = new MailThread(nc->display, nc->email, subject, message);
t->Start();
return true;
}
+ else
+ {
+ if (!Config->UseMail)
+ u->SendMessage(service, _("Services have been configured to not send mail."));
+ else if (Anope::CurTime - u->lastmail < Config->MailDelay)
+ u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), Config->MailDelay - (Anope::CurTime - u->lastmail));
+ else if (nc->email.empty())
+ u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->display.c_str());
+ else
+ {
+ u->lastmail = nc->lastmail = Anope::CurTime;
+ Thread *t = new MailThread(nc->display, nc->email, subject, message);
+ t->Start();
+ return true;
+ }
- return false;
+ return false;
+ }
}
bool Mail(NickCore *nc, const Anope::string &subject, const Anope::string &message)
diff --git a/src/misc.cpp b/src/misc.cpp
index e5ad71d45..41f1370a1 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -222,7 +222,7 @@ void ListFormatter::Process(std::vector<Anope::string> &buffer)
}
}
-InfoFormatter::InfoFormatter(User *u) : user(u), longest(0)
+InfoFormatter::InfoFormatter(NickCore *acc) : nc(acc), longest(0)
{
}
@@ -235,7 +235,7 @@ void InfoFormatter::Process(std::vector<Anope::string> &buffer)
Anope::string s;
for (unsigned i = it->first.length(); i < this->longest; ++i)
s += " ";
- s += Anope::string(translate(this->user, it->first.c_str())) + ": " + it->second;
+ s += Anope::string(translate(this->nc, it->first.c_str())) + ": " + it->second;
buffer.push_back(s);
}
@@ -360,7 +360,7 @@ Anope::string do_strftime(const time_t &t, const NickCore *nc, bool short_output
* @param seconds time in seconds
* @return buffer
*/
-Anope::string expire_left(NickCore *nc, time_t expires)
+Anope::string expire_left(const NickCore *nc, time_t expires)
{
if (!expires)
return translate(nc, NO_EXPIRE);
diff --git a/src/users.cpp b/src/users.cpp
index bbe26a11a..18bafd032 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -234,12 +234,13 @@ void User::SendMessage(const BotInfo *source, const char *fmt, ...)
va_start(args, fmt);
vsnprintf(buf, BUFSIZE - 1, translated_message, args);
- this->SendMessage(source, Anope::string(buf));
+ Anope::string m = buf;
+ this->SendMessage(source, buf);
va_end(args);
}
-void User::SendMessage(const BotInfo *source, Anope::string msg)
+void User::SendMessage(const BotInfo *source, const Anope::string &msg)
{
const char *translated_message = translate(this, msg.c_str());
@@ -472,7 +473,7 @@ bool User::IsRecognized(bool CheckSecure) const
*/
bool User::IsServicesOper()
{
- if (!this->nc || !this->nc->o)
+ if (!this->nc || !this->nc->IsServicesOper())
// No opertype.
return false;
else if (this->nc->o->require_oper && !this->HasMode(UMODE_OPER))