-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
*
- * InspIRCd: (C) 2002-2007 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
+ * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+ * Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
+ * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ * Copyright (C) 2005-2007 Craig Edwards <craigedwards@brainbox.cc>
*
- * This program is free but copyrighted software; see
- * the file COPYING for details.
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
*
- * ---------------------------------------------------
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __COMMAND_PARSE_H
-#define __COMMAND_PARSE_H
-
-#include <string>
-#include "users.h"
-#include "ctables.h"
-#include "typedefs.h"
-
-/** Required forward declaration
- */
-class InspIRCd;
-/** A list of dll/so files containing the command handlers for the core
- */
-typedef std::map<std::string, void*> SharedObjectList;
+#pragma once
/** This class handles command management and parsing.
* It allows you to add and remove commands from the map,
* call command handlers by name, and chop up comma seperated
* parameters into multiple calls.
*/
-class CoreExport CommandParser : public classbase
+class CoreExport CommandParser
{
- private:
- /** The creator of this class
- */
- InspIRCd* ServerInstance;
-
- /** Parameter buffer
- */
- std::vector<std::string> para;
-
- /** Process a parameter string into a list of items
- * @param command_p The output list of items
- * @param parameters The input string
- * @return The number of parameters parsed into command_p
- */
- int ProcessParameters(char **command_p,char *parameters);
+ public:
+ typedef TR1NS::unordered_map<std::string, Command*> CommandMap;
+ private:
/** Process a command from a user.
* @param user The user to parse the command for
* @param cmd The command string to process
*/
- void ProcessCommand(userrec *user, std::string &cmd);
-
- /** Insert the default RFC1459 commands into the command hash.
- */
- void SetupCommandTable();
-
- /** Finds the init_command symbol in a .so file
- * @param v A function pointer to be initialized
- * @param h A valid shared object handle
- * @return True if the symbol could be found
- */
- bool FindSym(void** v, void* h);
+ void ProcessCommand(LocalUser* user, std::string& cmd);
- /** A list of core-implemented modes and their shared object handles
+ /** Command list, a hash_map of command names to Command*
*/
- SharedObjectList RFCCommands;
-
- /** Load a command from a shared object on disk.
- * @param name The shared object to load (without path)
- */
- void LoadCommand(const char* name);
-
- /** Removes a command if the sources match. Used as a helper for
- * safe hash_map delete while iter in RemoveCommands(const char* source).
- */
- void RemoveCommand(nspace::hash_map<std::string,command_t*>::iterator safei, const char* source);
-
+ CommandMap cmdlist;
public:
- /** Command list, a hash_map of command names to command_t*
- */
- command_table cmdlist;
-
- /** Reload a core command.
- * This will only reload commands implemented by the core,
- * to reload a modular command, you must reload that module.
- * @param cmd The command to reload. This will cause the shared
- * object which implements this command to be closed, and then reloaded.
- * @return True if the command was reloaded, false if it could not be found
- * or another error occured
+ /** Default constructor.
*/
- bool ReloadCommand(const char* cmd);
+ CommandParser();
- /** Default constructor.
- * @param Instance The creator of this class
+ /** Get a command name -> Command* map containing all client to server commands
+ * @return A map of command handlers keyed by command names
*/
- CommandParser(InspIRCd* Instance);
+ const CommandMap& GetCommands() const { return cmdlist; }
/** Calls the handler for a given command.
* @param commandname The command to find. This should be in uppercase.
- * @param parameters Parameter list as an array of array of char (that's not a typo).
- * @param pcnt The number of items in the parameters list
+ * @param parameters Parameter list
* @param user The user to call the handler on behalf of
+ * @param cmd If non-NULL and the command was executed it is set to the command handler,
+ * otherwise it isn't written to.
* @return This method will return CMD_SUCCESS if the command handler was found and called,
* and the command completeld successfully. It will return CMD_FAILURE if the command handler was found
* and called, but the command did not complete successfully, and it will return CMD_INVALID if the
* command simply did not exist at all or the wrong number of parameters were given, or the user
* was not privilaged enough to execute the command.
*/
- CmdResult CallHandler(const std::string &commandname,const char** parameters, int pcnt, userrec *user);
+ CmdResult CallHandler(const std::string& commandname, const std::vector<std::string>& parameters, User* user, Command** cmd = NULL);
/** Get the handler function for a command.
* @param commandname The command required. Always use uppercase for this parameter.
* @return a pointer to the command handler, or NULL
*/
- command_t* GetHandler(const std::string &commandname);
-
- /** This function returns true if a command is valid with the given number of parameters and user.
- * @param commandname The command name to check
- * @param pcnt The parameter count
- * @param user The user to check against
- * @return If the user given has permission to execute the command, and the parameter count is
- * equal to or greater than the minimum number of parameters to the given command, then this
- * function will return true, otherwise it will return false.
- */
- bool IsValidCommand(const std::string &commandname, int pcnt, userrec * user);
-
- /** LoopCall is used to call a command classes handler repeatedly based on the contents of a comma seperated list.
- * There are two overriden versions of this method, one of which takes two potential lists and the other takes one.
- * We need a version which takes two potential lists for JOIN, because a JOIN may contain two lists of items at once,
+ Command* GetHandler(const std::string &commandname);
+
+ /** LoopCall is used to call a command handler repeatedly based on the contents of a comma seperated list.
+ * There are two ways to call this method, either with one potential list or with two potential lists.
+ * We need to handle two potential lists for JOIN, because a JOIN may contain two lists of items at once:
* the channel names and their keys as follows:
*
- * JOIN #chan1,#chan2,#chan3 key1,,key3
+ * JOIN \#chan1,\#chan2,\#chan3 key1,,key3
*
- * Therefore, we need to deal with both lists concurrently. The first instance of this method does that by creating
- * two instances of irc::commasepstream and reading them both together until the first runs out of tokens.
- * The second version is much simpler and just has the one stream to read, and is used in NAMES, WHOIS, PRIVMSG etc.
- * Both will only parse until they reach ServerInstance->Config->MaxTargets number of targets, to stop abuse via spam.
+ * Therefore, we need to deal with both lists concurrently. If there are two lists then the method reads
+ * them both together until the first runs out of tokens.
+ * With one list it is much simpler, and is used in NAMES, WHOIS, PRIVMSG etc.
*
- * @param user The user who sent the command
- * @param CommandObj the command object to call for each parameter in the list
- * @param parameters Parameter list as an array of array of char (that's not a typo).
- * @param The number of items in the parameters list
- * @param splithere The first parameter index to split as a comma seperated list
- * @param extra The second parameter index to split as a comma seperated list
- * @return This function will return 1 when there are no more parameters to process. When this occurs, its
- * caller should return without doing anything, otherwise it should continue into its main section of code.
- */
- int LoopCall(userrec* user, command_t* CommandObj, const char** parameters, int pcnt, unsigned int splithere, unsigned int extra);
-
- /** LoopCall is used to call a command classes handler repeatedly based on the contents of a comma seperated list.
- * There are two overriden versions of this method, one of which takes two potential lists and the other takes one.
- * We need a version which takes two potential lists for JOIN, because a JOIN may contain two lists of items at once,
- * the channel names and their keys as follows:
+ * If there is only one list and there are duplicates in it, then the command handler is only called for
+ * unique items. Entries are compared using "irc comparision" (see irc::string).
+ * If the usemax parameter is true (the default) the function only parses until it reaches
+ * ServerInstance->Config->MaxTargets number of targets, to stop abuse via spam.
*
- * JOIN #chan1,#chan2,#chan3 key1,,key3
+ * The OnPostCommand hook is executed for each item after it has been processed by the handler, with the
+ * original line parameter being empty (to indicate that the command in that form was created by this function).
+ * This only applies if the user executing the command is local.
*
- * Therefore, we need to deal with both lists concurrently. The first instance of this method does that by creating
- * two instances of irc::commasepstream and reading them both together until the first runs out of tokens.
- * The second version is much simpler and just has the one stream to read, and is used in NAMES, WHOIS, PRIVMSG etc.
- * Both will only parse until they reach ServerInstance->Config->MaxTargets number of targets, to stop abuse via spam.
+ * If there are two lists and the second list runs out of tokens before the first list then parameters[extra]
+ * will be an EMPTY string when Handle() is called for the remaining tokens in the first list, even if it is
+ * in the middle of parameters[]! Moreover, empty tokens in the second list are allowed, and those will also
+ * result in the appropiate entry being empty in parameters[].
+ * This is different than what command handlers usually expect; the command parser only allows an empty param
+ * as the last item in the vector.
*
* @param user The user who sent the command
- * @param CommandObj the command object to call for each parameter in the list
- * @param parameters Parameter list as an array of array of char (that's not a typo).
- * @param The number of items in the parameters list
+ * @param handler The command handler to call for each parameter in the list
+ * @param parameters Parameter list as a vector of strings
* @param splithere The first parameter index to split as a comma seperated list
- * @param extra The second parameter index to split as a comma seperated list
- * @return This function will return 1 when there are no more parameters to process. When this occurs, its
- * caller should return without doing anything, otherwise it should continue into its main section of code.
+ * @param extra The second parameter index to split as a comma seperated list, or -1 (the default) if there is only one list
+ * @param usemax True to limit the command to MaxTargets targets (default), or false to process all tokens
+ * @return This function returns true when it identified a list in the given parameter and finished calling the
+ * command handler for each entry on the list. When this occurs, the caller should return without doing anything,
+ * otherwise it should continue into its main section of code.
*/
- int LoopCall(userrec* user, command_t* CommandObj, const char** parameters, int pcnt, unsigned int splithere);
+ static bool LoopCall(User* user, Command* handler, const std::vector<std::string>& parameters, unsigned int splithere, int extra = -1, bool usemax = true);
/** Take a raw input buffer from a recvq, and process it on behalf of a user.
* @param buffer The buffer line to process
* @param user The user to whom this line belongs
*/
- void ProcessBuffer(std::string &buffer,userrec *user);
-
- /** Remove all commands relating to module 'source'.
- * @param source A module name which has introduced new commands
- * @return True This function returns true if commands were removed
- */
- bool RemoveCommands(const char* source);
+ void ProcessBuffer(std::string &buffer,LocalUser *user);
/** Add a new command to the commands hash
- * @param f The new command_t to add to the list
- * @param so_handle The handle to the shared object where the command can be found.
- * Only core commands loaded via cmd_*.so files should set this parameter to anything
- * meaningful. Module authors should leave this parameter at its default of NULL.
+ * @param f The new Command to add to the list
* @return True if the command was added
*/
- bool CreateCommand(command_t *f, void* so_handle = NULL);
-};
+ bool AddCommand(Command *f);
-/** Command handler class for the RELOAD command.
- * A command cant really reload itself, so this has to be in here.
- */
-class cmd_reload : public command_t
-{
- public:
- /** Standard constructor
+ /** Removes a command.
*/
- cmd_reload (InspIRCd* Instance) : command_t(Instance,"RELOAD",'o',1) { syntax = "<core-command>"; }
- /** Handle RELOAD
+ void RemoveCommand(Command* x);
+
+ /** Translate a single item based on the TranslationType given.
+ * @param to The translation type to use for the process
+ * @param item The input string
+ * @param dest The output string. The translation result will be appended to this string
+ * @param custom_translator Used to translate the parameter if the translation type is TR_CUSTOM, if NULL, TR_CUSTOM will act like TR_TEXT
+ * @param paramnumber The index of the parameter we are translating.
+ */
+ static void TranslateSingleParam(TranslateType to, const std::string& item, std::string& dest, CommandBase* custom_translator = NULL, unsigned int paramnumber = 0);
+
+ /** Translate nicknames in a list of strings into UIDs, based on the TranslateTypes given.
+ * @param to The translation types to use for the process. If this list is too short, TR_TEXT is assumed for the rest.
+ * @param source The strings to translate
+ * @param prefix_final True if the final source argument should have a colon prepended (if it could contain a space)
+ * @param custom_translator Used to translate the parameter if the translation type is TR_CUSTOM, if NULL, TR_CUSTOM will act like TR_TEXT
+ * @return dest The output string
*/
- CmdResult Handle(const char** parameters, int pcnt, userrec *user);
+ static std::string TranslateUIDs(const std::vector<TranslateType>& to, const std::vector<std::string>& source, bool prefix_final = false, CommandBase* custom_translator = NULL);
};
/** A lookup table of values for multiplier characters used by
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 86400, 1, 1, 1, 3600,
1, 1, 1, 1, 60, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 604800, 1, 31536000, 1, 1, 1, 1, 1, 1, 1, 1,
+ 604800, 1, 31557600, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 86400, 1, 1, 1, 3600, 1, 1, 1, 1, 60,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 604800, 1, 31536000,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 604800, 1, 31557600,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
-
-#endif
-