Anope IRC Services  Version 2.0
command.cpp
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
4  * Copyright (C) 2008-2014 Anope Team <team@anope.org>
5  *
6  * Please read COPYING and README for further details.
7  *
8  */
9 
10 #include "services.h"
11 #include "commands.h"
12 #include "users.h"
13 #include "language.h"
14 #include "config.h"
15 #include "bots.h"
16 #include "opertype.h"
17 #include "access.h"
18 #include "regchannel.h"
19 #include "channels.h"
20 
21 CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi) : nick(n), u(user), nc(core), reply(r),
22  c(NULL), service(bi)
23 {
24 }
25 
27 {
28  return this->nick;
29 }
30 
32 {
33  return this->u;
34 }
35 
37 {
38  return this->nc;
39 }
40 
42 {
43  if (this->u)
44  return ci->AccessFor(this->u);
45  else if (this->nc)
46  return ci->AccessFor(this->nc);
47  else
48  return AccessGroup();
49 }
50 
52 {
53  if (this->u)
54  return ::IsFounder(this->u, ci);
55  else if (this->nc)
56  return *this->nc == ci->GetFounder();
57  return false;
58 }
59 
61 {
62  if (this->u)
63  return this->u->HasCommand(cmd);
64  else if (this->nc && this->nc->o)
65  return this->nc->o->ot->HasCommand(cmd);
66  return false;
67 }
68 
70 {
71  if (this->u)
72  return this->u->HasPriv(cmd);
73  else if (this->nc && this->nc->o)
74  return this->nc->o->ot->HasPriv(cmd);
75  return false;
76 }
77 
79 {
80  if (this->u)
81  return this->u->IsServicesOper();
82  else if (this->nc)
83  return this->nc->IsServicesOper();
84  return false;
85 }
86 
88 {
89  if (this->u)
90  return this->u->HasMode("OPER");
91  else if (this->nc)
92  return this->nc->IsServicesOper();
93  return false;
94 }
95 
96 void CommandSource::Reply(const char *message, ...)
97 {
98  va_list args;
99  char buf[4096]; // Messages can be really big.
100 
101  const char *translated_message = Language::Translate(this->nc, message);
102 
103  va_start(args, message);
104  vsnprintf(buf, sizeof(buf), translated_message, args);
105 
106  this->Reply(Anope::string(buf));
107 
108  va_end(args);
109 }
110 
112 {
113  const char *translated_message = Language::Translate(this->nc, message.c_str());
114 
115  sepstream sep(translated_message, '\n', true);
116  Anope::string tok;
117  while (sep.GetToken(tok))
118  this->reply->SendMessage(this->service, tok);
119 }
120 
121 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)
122 {
124 }
125 
127 {
128 }
129 
131 {
132  this->desc = d;
133 }
134 
136 {
137  this->syntax.clear();
138 }
139 
141 {
142  this->syntax.push_back(s);
143 }
144 
146 {
147  Anope::string s = Language::Translate(source.GetAccount(), _("Syntax"));
148  if (!this->syntax.empty())
149  {
150  source.Reply("%s: \002%s %s\002", s.c_str(), source.command.c_str(), Language::Translate(source.GetAccount(), this->syntax[0].c_str()));
151  Anope::string spaces(s.length(), ' ');
152  for (unsigned i = 1, j = this->syntax.size(); i < j; ++i)
153  source.Reply("%s \002%s %s\002", spaces.c_str(), source.command.c_str(), Language::Translate(source.GetAccount(), this->syntax[i].c_str()));
154  }
155  else
156  source.Reply("%s: \002%s\002", s.c_str(), source.command.c_str());
157 }
158 
160 {
161  return this->allow_unregistered;
162 }
163 
165 {
166  this->allow_unregistered = b;
167 }
168 
170 {
171  return this->require_user;
172 }
173 
175 {
176  this->require_user = b;
177 }
178 
180 {
181  return this->desc;
182 }
183 
185 {
186  source.Reply(" %-14s %s", source.command.c_str(), Language::Translate(source.nc, this->GetDesc(source).c_str()));
187 }
188 
189 bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { return false; }
190 
191 void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcommand)
192 {
193  this->SendSyntax(source);
194  bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
195  if (has_help)
196  source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
197 }
198 
199 void Command::Run(CommandSource &source, const Anope::string &message)
200 {
201  std::vector<Anope::string> params;
202  spacesepstream(message).GetTokens(params);
203  bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
204 
205  CommandInfo::map::const_iterator it = source.service->commands.end();
206  unsigned count = 0;
207  for (unsigned max = params.size(); it == source.service->commands.end() && max > 0; --max)
208  {
209  Anope::string full_command;
210  for (unsigned i = 0; i < max; ++i)
211  full_command += " " + params[i];
212  full_command.erase(full_command.begin());
213 
214  ++count;
215  it = source.service->commands.find(full_command);
216  }
217 
218  if (it == source.service->commands.end())
219  {
220  if (has_help)
221  source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
222  else
223  source.Reply(_("Unknown command \002%s\002."), message.c_str());
224  return;
225  }
226 
227  const CommandInfo &info = it->second;
228  ServiceReference<Command> c("Command", info.name);
229  if (!c)
230  {
231  if (has_help)
232  source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
233  else
234  source.Reply(_("Unknown command \002%s\002."), message.c_str());
235  Log(source.service) << "Command " << it->first << " exists on me, but its service " << info.name << " was not found!";
236  return;
237  }
238 
239  if (c->RequireUser() && !source.GetUser())
240  return;
241 
242  // Command requires registered users only
243  if (!c->AllowUnregistered() && !source.nc)
244  {
246  if (source.GetUser())
247  Log(LOG_NORMAL, "access_denied_unreg", source.service) << "Access denied for unregistered user " << source.GetUser()->GetMask() << " with command " << it->first;
248  return;
249  }
250 
251  for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i)
252  params.erase(params.begin());
253 
254  while (c->max_params > 0 && params.size() > c->max_params)
255  {
256  params[c->max_params - 1] += " " + params[c->max_params];
257  params.erase(params.begin() + c->max_params);
258  }
259 
260  source.command = it->first;
261  source.permission = info.permission;
262 
263  EventReturn MOD_RESULT;
264  FOREACH_RESULT(OnPreCommand, MOD_RESULT, (source, c, params));
265  if (MOD_RESULT == EVENT_STOP)
266  return;
267 
268  if (params.size() < c->min_params)
269  {
270  c->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : "");
271  return;
272  }
273 
274  // If the command requires a permission, and they aren't registered or don't have the required perm, DENIED
275  if (!info.permission.empty() && !source.HasCommand(info.permission))
276  {
277  source.Reply(ACCESS_DENIED);
278  if (source.GetUser())
279  Log(LOG_NORMAL, "access_denied", source.service) << "Access denied for user " << source.GetUser()->GetMask() << " with command " << it->first;
280  return;
281  }
282 
283  c->Execute(source, params);
284  FOREACH_MOD(OnPostCommand, (source, c, params));
285 }
286 
288 {
289  bot = NULL;
290 
291  for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
292  {
293  BotInfo *bi = it->second;
294 
295  for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit)
296  {
297  const Anope::string &c_name = cit->first;
298  const CommandInfo &info = cit->second;
299 
300  if (info.name != command_service)
301  continue;
302 
303  bot = bi;
304  name = c_name;
305  return true;
306  }
307  }
308 
309  return false;
310 }
311 
Definition: bots.h:24
bool HasMode(const Anope::string &name) const
Definition: users.cpp:513
Anope::string permission
Definition: commands.h:34
Anope::string name
Definition: commands.h:32
virtual ~Command()
Definition: command.cpp:126
bool allow_unregistered
Definition: commands.h:97
Definition: hashcomp.h:84
bool HasCommand(const Anope::string &cmdstr)
Definition: users.cpp:480
#define NICK_IDENTIFY_REQUIRED
Definition: language.h:86
bool IsServicesOper()
Definition: command.cpp:78
void RequireUser(bool b)
Definition: command.cpp:174
#define ACCESS_DENIED
Definition: language.h:73
void AllowUnregistered(bool b)
Definition: command.cpp:164
CommandInfo::map commands
Definition: bots.h:33
virtual void Execute(CommandSource &source, const std::vector< Anope::string > &params)=0
static bool FindCommandFromService(const Anope::string &command_service, BotInfo *&bi, Anope::string &name)
Definition: command.cpp:287
void GetTokens(T &token)
Definition: anope.h:587
bool HasPriv(const Anope::string &privstr) const
Definition: opertype.cpp:81
Anope::string permission
Definition: commands.h:71
size_t max_params
Definition: commands.h:103
Definition: users.h:34
bool HasCommand(const Anope::string &cmd)
Definition: command.cpp:60
bool IsFounder(ChannelInfo *ci)
Definition: command.cpp:51
void ClearSyntax()
Definition: command.cpp:135
CoreExport bool IsFounder(const User *user, const ChannelInfo *ci)
Definition: regchannel.cpp:642
#define FOREACH_RESULT(ename, ret, args)
Definition: modules.h:95
void SetDesc(const Anope::string &d)
Definition: command.cpp:130
virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand)
Definition: command.cpp:189
size_t min_params
Definition: commands.h:105
virtual void SendMessage(BotInfo *source, const Anope::string &msg)=0
const Anope::string & GetNick() const
Definition: command.cpp:26
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *reply, BotInfo *bi)
Definition: command.cpp:21
iterator erase(const iterator &i)
Definition: anope.h:155
size_type length() const
Definition: anope.h:131
NickCore * GetFounder() const
Definition: regchannel.cpp:364
Definition: Config.cs:26
OperType * ot
Definition: opertype.h:23
virtual void OnSyntaxError(CommandSource &source, const Anope::string &subcommand)
Definition: command.cpp:191
Anope::string command
Definition: commands.h:69
void Reply(const char *message,...)
Definition: command.cpp:96
Reference< User > u
Definition: commands.h:58
CoreExport Serialize::Checker< botinfo_map > BotListByNick
bool HasPriv(const Anope::string &cmd)
Definition: command.cpp:69
Reference< BotInfo > service
Definition: commands.h:67
Anope::string GetMask() const
Definition: users.cpp:269
bool HasPriv(const Anope::string &privstr)
Definition: users.cpp:487
Oper * o
Definition: account.h:131
bool empty() const
Definition: anope.h:126
static void Run(CommandSource &source, const Anope::string &message)
Definition: command.cpp:199
#define MORE_INFO
Definition: language.h:67
Command(Module *owner, const Anope::string &sname, size_t min_params, size_t max_params=0)
Definition: command.cpp:121
EventReturn
Definition: modules.h:129
virtual const Anope::string GetDesc(CommandSource &source) const
Definition: command.cpp:179
CoreExport const char * Translate(const char *string)
Definition: language.cpp:59
bool AllowUnregistered() const
Definition: command.cpp:159
User * GetUser()
Definition: command.cpp:31
bool IsOper()
Definition: command.cpp:87
bool require_user
Definition: commands.h:99
void SetSyntax(const Anope::string &s)
Definition: command.cpp:140
AccessGroup AccessFor(const User *u)
Definition: regchannel.cpp:413
std::vector< Anope::string > syntax
Definition: commands.h:95
virtual void OnServHelp(CommandSource &source)
Definition: command.cpp:184
bool RequireUser() const
Definition: command.cpp:169
Anope::string nick
Definition: commands.h:56
Anope::string nick
Definition: users.h:62
AccessGroup AccessFor(ChannelInfo *ci)
Definition: command.cpp:41
Anope::string desc
Definition: commands.h:94
Anope::string name
Definition: access.cpp:22
Reference< NickCore > nc
Definition: commands.h:61
void SendSyntax(CommandSource &)
Definition: command.cpp:145
NickCore * GetAccount()
Definition: command.cpp:36
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
virtual bool IsServicesOper() const
Definition: nickcore.cpp:173
CommandReply * reply
Definition: commands.h:63
bool IsServicesOper()
Definition: users.cpp:451
bool HasCommand(const Anope::string &cmdstr) const
Definition: opertype.cpp:59
iterator begin()
Definition: anope.h:282
#define _(x)
Definition: services.h:50