00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "services.h"
00011 #include "commands.h"
00012 #include "users.h"
00013 #include "language.h"
00014 #include "config.h"
00015 #include "bots.h"
00016 #include "opertype.h"
00017 #include "access.h"
00018 #include "regchannel.h"
00019 #include "channels.h"
00020
00021 CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi) : nick(n), u(user), nc(core), reply(r),
00022 c(NULL), service(bi)
00023 {
00024 }
00025
00026 const Anope::string &CommandSource::GetNick() const
00027 {
00028 return this->nick;
00029 }
00030
00031 User *CommandSource::GetUser()
00032 {
00033 return this->u;
00034 }
00035
00036 NickCore *CommandSource::GetAccount()
00037 {
00038 return this->nc;
00039 }
00040
00041 AccessGroup CommandSource::AccessFor(ChannelInfo *ci)
00042 {
00043 if (this->u)
00044 return ci->AccessFor(this->u);
00045 else if (this->nc)
00046 return ci->AccessFor(this->nc);
00047 else
00048 return AccessGroup();
00049 }
00050
00051 bool CommandSource::IsFounder(ChannelInfo *ci)
00052 {
00053 if (this->u)
00054 return ::IsFounder(this->u, ci);
00055 else if (this->nc)
00056 return *this->nc == ci->GetFounder();
00057 return false;
00058 }
00059
00060 bool CommandSource::HasCommand(const Anope::string &cmd)
00061 {
00062 if (this->u)
00063 return this->u->HasCommand(cmd);
00064 else if (this->nc && this->nc->o)
00065 return this->nc->o->ot->HasCommand(cmd);
00066 return false;
00067 }
00068
00069 bool CommandSource::HasPriv(const Anope::string &cmd)
00070 {
00071 if (this->u)
00072 return this->u->HasPriv(cmd);
00073 else if (this->nc && this->nc->o)
00074 return this->nc->o->ot->HasPriv(cmd);
00075 return false;
00076 }
00077
00078 bool CommandSource::IsServicesOper()
00079 {
00080 if (this->u)
00081 return this->u->IsServicesOper();
00082 else if (this->nc)
00083 return this->nc->IsServicesOper();
00084 return false;
00085 }
00086
00087 bool CommandSource::IsOper()
00088 {
00089 if (this->u)
00090 return this->u->HasMode("OPER");
00091 else if (this->nc)
00092 return this->nc->IsServicesOper();
00093 return false;
00094 }
00095
00096 void CommandSource::Reply(const char *message, ...)
00097 {
00098 va_list args;
00099 char buf[4096];
00100
00101 const char *translated_message = Language::Translate(this->nc, message);
00102
00103 va_start(args, message);
00104 vsnprintf(buf, sizeof(buf), translated_message, args);
00105
00106 this->Reply(Anope::string(buf));
00107
00108 va_end(args);
00109 }
00110
00111 void CommandSource::Reply(const Anope::string &message)
00112 {
00113 const char *translated_message = Language::Translate(this->nc, message.c_str());
00114
00115 sepstream sep(translated_message, '\n');
00116 Anope::string tok;
00117 while (sep.GetToken(tok))
00118 this->reply->SendMessage(this->service, tok);
00119 }
00120
00121 Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t maxparams) : Service(o, "Command", sname), max_params(maxparams), min_params(minparams), module(owner)
00122 {
00123 allow_unregistered = require_user = false;
00124 }
00125
00126 Command::~Command()
00127 {
00128 }
00129
00130 void Command::SetDesc(const Anope::string &d)
00131 {
00132 this->desc = d;
00133 }
00134
00135 void Command::ClearSyntax()
00136 {
00137 this->syntax.clear();
00138 }
00139
00140 void Command::SetSyntax(const Anope::string &s)
00141 {
00142 this->syntax.push_back(s);
00143 }
00144
00145 void Command::SendSyntax(CommandSource &source)
00146 {
00147 if (!this->syntax.empty())
00148 {
00149 source.Reply(_("Syntax: \002%s %s\002"), source.command.c_str(), this->syntax[0].c_str());
00150 for (unsigned i = 1, j = this->syntax.size(); i < j; ++i)
00151 source.Reply(" \002%s %s\002", source.command.c_str(), this->syntax[i].c_str());
00152 }
00153 }
00154
00155 void Command::SendSyntax(CommandSource &source, const Anope::string &syn)
00156 {
00157 source.Reply(_("Syntax: \002%s %s\002"), source.command.c_str(), syn.c_str());
00158 source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), source.command.c_str());
00159 }
00160
00161 bool Command::AllowUnregistered() const
00162 {
00163 return this->allow_unregistered;
00164 }
00165
00166 void Command::AllowUnregistered(bool b)
00167 {
00168 this->allow_unregistered = b;
00169 }
00170
00171 bool Command::RequireUser() const
00172 {
00173 return this->require_user;
00174 }
00175
00176 void Command::RequireUser(bool b)
00177 {
00178 this->require_user = b;
00179 }
00180
00181 const Anope::string &Command::GetDesc() const
00182 {
00183 return this->desc;
00184 }
00185
00186 void Command::OnServHelp(CommandSource &source)
00187 {
00188 source.Reply(" %-14s %s", source.command.c_str(), Language::Translate(source.nc, this->GetDesc().c_str()));
00189 }
00190
00191 bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { return false; }
00192
00193 void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcommand)
00194 {
00195 this->SendSyntax(source);
00196 source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), source.command.c_str());
00197 }
00198
00199 void RunCommand(CommandSource &source, const Anope::string &message)
00200 {
00201 std::vector<Anope::string> params;
00202 spacesepstream(message).GetTokens(params);
00203 bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
00204
00205 CommandInfo::map::const_iterator it = source.service->commands.end();
00206 unsigned count = 0;
00207 for (unsigned max = params.size(); it == source.service->commands.end() && max > 0; --max)
00208 {
00209 Anope::string full_command;
00210 for (unsigned i = 0; i < max; ++i)
00211 full_command += " " + params[i];
00212 full_command.erase(full_command.begin());
00213
00214 ++count;
00215 it = source.service->commands.find(full_command);
00216 }
00217
00218 if (it == source.service->commands.end())
00219 {
00220 if (has_help)
00221 source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00222 else
00223 source.Reply(_("Unknown command \002%s\002."), message.c_str());
00224 return;
00225 }
00226
00227 const CommandInfo &info = it->second;
00228 ServiceReference<Command> c("Command", info.name);
00229 if (!c)
00230 {
00231 if (has_help)
00232 source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str());
00233 else
00234 source.Reply(_("Unknown command \002%s\002."), message.c_str());
00235 Log(source.service) << "Command " << it->first << " exists on me, but its service " << info.name << " was not found!";
00236 return;
00237 }
00238
00239 if (c->RequireUser() && !source.GetUser())
00240 return;
00241
00242
00243 if (!c->AllowUnregistered() && !source.nc)
00244 {
00245 source.Reply(NICK_IDENTIFY_REQUIRED);
00246 if (source.GetUser())
00247 Log(LOG_NORMAL, "access_denied", source.service) << "Access denied for unregistered user " << source.GetUser()->GetMask() << " with command " << c->name;
00248 return;
00249 }
00250
00251 for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i)
00252 params.erase(params.begin());
00253
00254 while (c->max_params > 0 && params.size() > c->max_params)
00255 {
00256 params[c->max_params - 1] += " " + params[c->max_params];
00257 params.erase(params.begin() + c->max_params);
00258 }
00259
00260 source.command = it->first;
00261 source.permission = info.permission;
00262
00263 EventReturn MOD_RESULT;
00264 FOREACH_RESULT(I_OnPreCommand, OnPreCommand(source, c, params));
00265 if (MOD_RESULT == EVENT_STOP)
00266 return;
00267
00268 if (params.size() < c->min_params)
00269 {
00270 c->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : "");
00271 return;
00272 }
00273
00274
00275 if (!info.permission.empty() && !source.HasCommand(info.permission))
00276 {
00277 source.Reply(ACCESS_DENIED);
00278 if (source.GetUser())
00279 Log(LOG_NORMAL, "access_denied", source.service) << "Access denied for user " << source.GetUser()->GetMask() << " with command " << c->name;
00280 return;
00281 }
00282
00283 Reference<NickCore> nc_reference(source.nc);
00284 c->Execute(source, params);
00285 if (!nc_reference)
00286 source.nc = NULL;
00287 FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params));
00288 }
00289