summaryrefslogtreecommitdiff
path: root/src/commands.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands.cpp')
-rw-r--r--src/commands.cpp196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/commands.cpp b/src/commands.cpp
new file mode 100644
index 000000000..71c4c986a
--- /dev/null
+++ b/src/commands.cpp
@@ -0,0 +1,196 @@
+/* Routines for looking up commands in a *Serv command list.
+ *
+ * (C) 2003-2010 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ *
+ */
+
+#include "services.h"
+#include "modules.h"
+#include "language.h"
+#include "hashcomp.h"
+
+Command *FindCommand(BotInfo *bi, const ci::string &name)
+{
+ if (!bi || bi->Commands.empty() || name.empty())
+ return NULL;
+
+ std::map<ci::string, Command *>::iterator it = bi->Commands.find(name);
+
+ if (it != bi->Commands.end())
+ return it->second;
+
+ return NULL;
+}
+
+void mod_run_cmd(BotInfo *bi, User *u, const ci::string &cmd)
+{
+ if (!bi || !u || cmd.empty())
+ return;
+
+ Command *c = FindCommand(bi, cmd);
+ int retVal = MOD_CONT;
+ ChannelInfo *ci;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(I_OnPreCommandRun, OnPreCommandRun(bi, u, cmd, c));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (!c)
+ {
+ notice_lang(bi->nick, u, UNKNOWN_COMMAND_HELP, cmd.c_str(), bi->nick.c_str());
+ return;
+ }
+
+ if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED))
+ {
+ // Command requires registered users only
+ if (!u->IsIdentified())
+ {
+ notice_lang(bi->nick, u, NICK_IDENTIFY_REQUIRED, Config.s_NickServ);
+ Alog() << "Access denied for unregistered user " << u->nick << " with service " << bi->nick << " and command " << cmd;
+ return;
+ }
+ }
+
+ std::vector<ci::string> params;
+ std::string curparam;
+ char *s = NULL;
+ while ((s = strtok(NULL, " ")))
+ {
+ // - 1 because params[0] corresponds with a maxparam of 1.
+ if (params.size() >= (c->MaxParams - 1))
+ {
+ curparam += s;
+ curparam += " ";
+ }
+ else
+ {
+ params.push_back(s);
+ }
+ }
+
+ if (!curparam.empty())
+ {
+ // Remove trailing space
+ curparam.erase(curparam.size() - 1, curparam.size());
+
+ // Add it
+ params.push_back(curparam.c_str());
+ }
+
+ if (params.size() < c->MinParams)
+ {
+ c->OnSyntaxError(u, !params.empty() ? params[params.size() - 1] : "");
+ return;
+ }
+
+ FOREACH_RESULT(I_OnPreCommand, OnPreCommand(u, c->service, c->name, params));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (params.size() > 0 && !c->HasFlag(CFLAG_STRIP_CHANNEL) && (bi == ChanServ || bi == BotServ))
+ {
+ if (ircdproto->IsChannelValid(params[0].c_str()))
+ {
+ if ((ci = cs_findchan(params[0].c_str())))
+ {
+ if ((ci->HasFlag(CI_FORBIDDEN)) && (!c->HasFlag(CFLAG_ALLOW_FORBIDDEN)))
+ {
+ notice_lang(bi->nick, u, CHAN_X_FORBIDDEN, ci->name.c_str());
+ Alog() << "Access denied for user " << u->nick << " with service " << bi->nick
+ << " and command " << cmd << " because of FORBIDDEN channel " << ci->name;
+ return;
+ }
+ else if ((ci->HasFlag(CI_SUSPENDED)) && (!c->HasFlag(CFLAG_ALLOW_SUSPENDED)))
+ {
+ notice_lang(bi->nick, u, CHAN_X_FORBIDDEN, ci->name.c_str());
+ Alog() << "Access denied for user " << u->nick << " with service " << bi->nick
+ <<" and command " << cmd << " because of SUSPENDED channel " << ci->name;
+ return;
+ }
+ }
+ else if (!c->HasFlag(CFLAG_ALLOW_UNREGISTEREDCHANNEL))
+ {
+ notice_lang(bi->nick, u, CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+ }
+ /* A user not giving a channel name for a param that should be a channel */
+ else
+ {
+ notice_lang(bi->nick, u, CHAN_X_INVALID, params[0].c_str());
+ return;
+ }
+ }
+
+ // If the command requires a permission, and they aren't registered or don't have the required perm, DENIED
+ if (!c->permission.empty())
+ {
+ if (!u->Account()->HasCommand(c->permission))
+ {
+ notice_lang(bi->nick, u, ACCESS_DENIED);
+ Alog() << "Access denied for user " << u->nick << " with service " << bi->nick << " and command " << cmd;
+ return;
+ }
+
+ }
+
+ retVal = c->Execute(u, params);
+
+ if (retVal == MOD_CONT)
+ {
+ FOREACH_MOD(I_OnPostCommand, OnPostCommand(u, c->service, c->name.c_str(), params));
+ }
+}
+
+/**
+ * Prints the help message for a given command.
+ * @param services Services Client
+ * @param u User Struct
+ * @param Command Hash Table
+ * @param cmd Command
+ * @return void
+ */
+void mod_help_cmd(BotInfo *bi, User *u, const ci::string &cmd)
+{
+ if (!bi || !u || cmd.empty())
+ return;
+
+ spacesepstream tokens(cmd);
+ ci::string token;
+ tokens.GetToken(token);
+
+ Command *c = FindCommand(bi, token);
+
+ ci::string subcommand = tokens.StreamEnd() ? "" : tokens.GetRemaining().c_str();
+
+ if (!c || !c->OnHelp(u, subcommand))
+ notice_lang(bi->nick, u, NO_HELP_AVAILABLE, cmd.c_str());
+ else
+ {
+ u->SendMessage(bi->nick, " ");
+
+ /* Inform the user what permission is required to use the command */
+ if (!c->permission.empty())
+ notice_lang(bi->nick, u, COMMAND_REQUIRES_PERM, c->permission.c_str());
+
+ /* User isn't identified and needs to be to use this command */
+ if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified())
+ notice_lang(bi->nick, u, COMMAND_IDENTIFY_REQUIRED);
+ /* User doesn't have the proper permission to use this command */
+ else if (!c->permission.empty() && (!u->Account() || (!u->Account()->HasCommand(c->permission))))
+ notice_lang(bi->nick, u, COMMAND_CANNOT_USE);
+ /* User can use this command */
+ else
+ notice_lang(bi->nick, u, COMMAND_CAN_USE);
+ }
+}
+