diff options
author | Adam <Adam@anope.org> | 2012-06-18 05:04:30 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-06-18 05:04:30 -0400 |
commit | 2dec8e767a70def4b9b04a96ae4f75e4d1013038 (patch) | |
tree | 36f5b551ff359a578e17d5e7d2f486970d759a7b /src | |
parent | 873d4287de57f7f9caa23cb2c9265d1ad2804aba (diff) |
Allow userless command sources
Diffstat (limited to 'src')
-rw-r--r-- | src/bots.cpp | 86 | ||||
-rw-r--r-- | src/command.cpp | 167 | ||||
-rw-r--r-- | src/logger.cpp | 38 | ||||
-rw-r--r-- | src/mail.cpp | 37 | ||||
-rw-r--r-- | src/misc.cpp | 6 | ||||
-rw-r--r-- | src/users.cpp | 7 |
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)) |