summaryrefslogtreecommitdiff
path: root/src/commands
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-16 22:42:36 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-16 22:42:36 +0000
commit3841c4b04a96389a4661535d12d5215a621d8736 (patch)
tree62098e63cc622d9889a9ed205a1c4487c8c20c84 /src/commands
parent558a44bf47370b68b14d0837bfae13c651ecf5c4 (diff)
Attempt to revert r11734
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11735 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/cmd_admin.cpp58
-rw-r--r--src/commands/cmd_away.cpp79
-rw-r--r--src/commands/cmd_clearcache.cpp55
-rw-r--r--src/commands/cmd_commands.cpp65
-rw-r--r--src/commands/cmd_connect.cpp48
-rw-r--r--src/commands/cmd_die.cpp74
-rw-r--r--src/commands/cmd_eline.cpp125
-rw-r--r--src/commands/cmd_gline.cpp111
-rw-r--r--src/commands/cmd_info.cpp91
-rw-r--r--src/commands/cmd_invite.cpp131
-rw-r--r--src/commands/cmd_ison.cpp108
-rw-r--r--src/commands/cmd_join.cpp78
-rw-r--r--src/commands/cmd_kick.cpp86
-rw-r--r--src/commands/cmd_kill.cpp131
-rw-r--r--src/commands/cmd_kline.cpp110
-rw-r--r--src/commands/cmd_links.cpp56
-rw-r--r--src/commands/cmd_list.cpp98
-rw-r--r--src/commands/cmd_loadmodule.cpp54
-rw-r--r--src/commands/cmd_lusers.cpp67
-rw-r--r--src/commands/cmd_map.cpp44
-rw-r--r--src/commands/cmd_mode.cpp55
-rw-r--r--src/commands/cmd_modules.cpp78
-rw-r--r--src/commands/cmd_motd.cpp58
-rw-r--r--src/commands/cmd_names.cpp80
-rw-r--r--src/commands/cmd_nick.cpp214
-rw-r--r--src/commands/cmd_notice.cpp203
-rw-r--r--src/commands/cmd_oper.cpp170
-rw-r--r--src/commands/cmd_part.cpp77
-rw-r--r--src/commands/cmd_pass.cpp56
-rw-r--r--src/commands/cmd_ping.cpp42
-rw-r--r--src/commands/cmd_pong.cpp43
-rw-r--r--src/commands/cmd_privmsg.cpp220
-rw-r--r--src/commands/cmd_qline.cpp86
-rw-r--r--src/commands/cmd_quit.cpp68
-rw-r--r--src/commands/cmd_rehash.cpp109
-rw-r--r--src/commands/cmd_reloadmodule.cpp56
-rw-r--r--src/commands/cmd_restart.cpp60
-rw-r--r--src/commands/cmd_rules.cpp56
-rw-r--r--src/commands/cmd_server.cpp49
-rw-r--r--src/commands/cmd_squit.cpp48
-rw-r--r--src/commands/cmd_stats.cpp68
-rw-r--r--src/commands/cmd_time.cpp65
-rw-r--r--src/commands/cmd_topic.cpp79
-rw-r--r--src/commands/cmd_unloadmodule.cpp58
-rw-r--r--src/commands/cmd_user.cpp83
-rw-r--r--src/commands/cmd_userhost.cpp93
-rw-r--r--src/commands/cmd_version.cpp56
-rw-r--r--src/commands/cmd_wallops.cpp56
-rw-r--r--src/commands/cmd_who.cpp403
-rw-r--r--src/commands/cmd_whois.cpp90
-rw-r--r--src/commands/cmd_whowas.cpp344
-rw-r--r--src/commands/cmd_zline.cpp106
52 files changed, 4998 insertions, 0 deletions
diff --git a/src/commands/cmd_admin.cpp b/src/commands/cmd_admin.cpp
new file mode 100644
index 000000000..1f2641e67
--- /dev/null
+++ b/src/commands/cmd_admin.cpp
@@ -0,0 +1,58 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_ADMIN_H__
+#define __CMD_ADMIN_H__
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /ADMIN. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandAdmin : public Command
+{
+ public:
+ /** Constructor for admin.
+ */
+ CommandAdmin(Module* parent) : Command(parent,"ADMIN",0,0) { syntax = "[<servername>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+
+/** Handle /ADMIN
+ */
+CmdResult CommandAdmin::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ user->WriteNumeric(RPL_ADMINME, "%s :Administrative info for %s",user->nick.c_str(),ServerInstance->Config->ServerName);
+ if (*ServerInstance->Config->AdminName)
+ user->WriteNumeric(RPL_ADMINLOC1, "%s :Name - %s",user->nick.c_str(),ServerInstance->Config->AdminName);
+ user->WriteNumeric(RPL_ADMINLOC2, "%s :Nickname - %s",user->nick.c_str(),ServerInstance->Config->AdminNick);
+ user->WriteNumeric(RPL_ADMINEMAIL, "%s :E-Mail - %s",user->nick.c_str(),ServerInstance->Config->AdminEmail);
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandAdmin)
diff --git a/src/commands/cmd_away.cpp b/src/commands/cmd_away.cpp
new file mode 100644
index 000000000..d93f74559
--- /dev/null
+++ b/src/commands/cmd_away.cpp
@@ -0,0 +1,79 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_AWAY_H__
+#define __CMD_AWAY_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /AWAY. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandAway : public Command
+{
+ public:
+ /** Constructor for away.
+ */
+ CommandAway ( Module* parent) : Command(parent,"AWAY",0,0) { syntax = "[<message>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /AWAY
+ */
+CmdResult CommandAway::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ ModResult MOD_RESULT;
+
+ if ((parameters.size()) && (!parameters[0].empty()))
+ {
+ FIRST_MOD_RESULT(ServerInstance, OnSetAway, MOD_RESULT, (user, parameters[0]));
+
+ if (MOD_RESULT == MOD_RES_DENY && IS_LOCAL(user))
+ return CMD_FAILURE;
+
+ user->awaytime = ServerInstance->Time();
+ user->awaymsg.assign(parameters[0], 0, ServerInstance->Config->Limits.MaxAway);
+
+ user->WriteNumeric(RPL_NOWAWAY, "%s :You have been marked as being away",user->nick.c_str());
+ }
+ else
+ {
+ FIRST_MOD_RESULT(ServerInstance, OnSetAway, MOD_RESULT, (user, ""));
+
+ if (MOD_RESULT == MOD_RES_DENY && IS_LOCAL(user))
+ return CMD_FAILURE;
+
+ user->awaymsg.clear();
+ user->WriteNumeric(RPL_UNAWAY, "%s :You are no longer marked as being away",user->nick.c_str());
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandAway)
diff --git a/src/commands/cmd_clearcache.cpp b/src/commands/cmd_clearcache.cpp
new file mode 100644
index 000000000..2334e597c
--- /dev/null
+++ b/src/commands/cmd_clearcache.cpp
@@ -0,0 +1,55 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_ADMIN_H__
+#define __CMD_ADMIN_H__
+
+#include "users.h"
+#include "channels.h"
+#include "ctables.h"
+
+/** Handle /ADMIN. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandClearcache : public Command
+{
+ public:
+ /** Constructor for clearcache.
+ */
+ CommandClearcache ( Module* parent) : Command(parent,"CLEARCACHE",0) { flags_needed = 'o'; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /CLEARCACHE
+ */
+CmdResult CommandClearcache::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ int n = ServerInstance->Res->ClearCache();
+ user->WriteServ("NOTICE %s :*** Cleared DNS cache of %d items.", user->nick.c_str(), n);
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandClearcache)
diff --git a/src/commands/cmd_commands.cpp b/src/commands/cmd_commands.cpp
new file mode 100644
index 000000000..63b4b24fb
--- /dev/null
+++ b/src/commands/cmd_commands.cpp
@@ -0,0 +1,65 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_COMMANDS_H__
+#define __CMD_COMMANDS_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /COMMANDS. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandCommands : public Command
+{
+ public:
+ /** Constructor for commands.
+ */
+ CommandCommands ( Module* parent) : Command(parent,"COMMANDS",0,0) { }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /COMMANDS
+ */
+CmdResult CommandCommands::Handle (const std::vector<std::string>&, User *user)
+{
+ for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++)
+ {
+ Module* src = i->second->creator;
+ user->WriteNumeric(RPL_COMMANDS, "%s :%s %s %d %d",
+ user->nick.c_str(),
+ i->second->command.c_str(),
+ src ? src->ModuleSourceFile.c_str() : "<core>",
+ i->second->min_params,
+ i->second->Penalty);
+ }
+ user->WriteNumeric(RPL_COMMANDSEND, "%s :End of COMMANDS list",user->nick.c_str());
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandCommands)
diff --git a/src/commands/cmd_connect.cpp b/src/commands/cmd_connect.cpp
new file mode 100644
index 000000000..65cc4bd6b
--- /dev/null
+++ b/src/commands/cmd_connect.cpp
@@ -0,0 +1,48 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /CONNECT. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandConnect : public Command
+{
+ public:
+ /** Constructor for connect.
+ */
+ CommandConnect ( Module* parent) : Command(parent,"CONNECT",1) { flags_needed = 'o'; syntax = "<servername> [<remote-server>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+/*
+ * This is handled by the server linking module, if necessary. Do not remove this stub.
+ */
+
+/** Handle /CONNECT
+ */
+CmdResult CommandConnect::Handle (const std::vector<std::string>&, User *user)
+{
+ user->WriteServ( "NOTICE %s :Look into loading a linking module (like m_spanningtree) if you want this to do anything useful.", user->nick.c_str());
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandConnect)
diff --git a/src/commands/cmd_die.cpp b/src/commands/cmd_die.cpp
new file mode 100644
index 000000000..658240de8
--- /dev/null
+++ b/src/commands/cmd_die.cpp
@@ -0,0 +1,74 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_DIE_H__
+#define __CMD_DIE_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /DIE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandDie : public Command
+{
+ public:
+ /** Constructor for die.
+ */
+ CommandDie ( Module* parent) : Command(parent,"DIE",1) { flags_needed = 'o'; syntax = "<password>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+#include "exitcodes.h"
+
+/** Handle /DIE
+ */
+CmdResult CommandDie::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ if (!ServerInstance->PassCompare(user, ServerInstance->Config->diepass, parameters[0].c_str(), ServerInstance->Config->powerhash))
+ {
+ {
+ std::string diebuf = std::string("*** DIE command from ") + user->nick + "!" + user->ident + "@" + user->dhost + ". Terminating in " + ConvToStr(ServerInstance->Config->DieDelay) + " seconds.";
+ ServerInstance->Logs->Log("COMMAND",SPARSE, diebuf);
+ ServerInstance->SendError(diebuf);
+ }
+
+ if (ServerInstance->Config->DieDelay)
+ sleep(ServerInstance->Config->DieDelay);
+
+ ServerInstance->Exit(EXIT_STATUS_DIE);
+ }
+ else
+ {
+ ServerInstance->Logs->Log("COMMAND",SPARSE, "Failed /DIE command from %s!%s@%s", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
+ ServerInstance->SNO->WriteGlobalSno('a', "Failed DIE Command from %s!%s@%s.",user->nick.c_str(),user->ident.c_str(),user->host.c_str());
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandDie)
diff --git a/src/commands/cmd_eline.cpp b/src/commands/cmd_eline.cpp
new file mode 100644
index 000000000..7845fa2f1
--- /dev/null
+++ b/src/commands/cmd_eline.cpp
@@ -0,0 +1,125 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#ifndef __CMD_ELINE_H__
+#define __CMD_ELINE_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /ELINE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandEline : public Command
+{
+ public:
+ /** Constructor for eline.
+ */
+ CommandEline ( Module* parent) : Command(parent,"ELINE",1,3) { flags_needed = 'o'; syntax = "<ident@host> [<duration> :<reason>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /ELINE
+ */
+CmdResult CommandEline::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string target = parameters[0];
+
+ if (parameters.size() >= 3)
+ {
+ IdentHostPair ih;
+ User* find = ServerInstance->FindNick(target.c_str());
+ if (find)
+ {
+ ih.first = "*";
+ ih.second = find->GetIPString();
+ target = std::string("*@") + find->GetIPString();
+ }
+ else
+ ih = ServerInstance->XLines->IdentSplit(target.c_str());
+
+ if (ih.first.empty())
+ {
+ user->WriteServ("NOTICE %s :*** Target not found", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
+ return CMD_FAILURE;
+
+ long duration = ServerInstance->Duration(parameters[1].c_str());
+
+ ELine* el = new ELine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
+ if (ServerInstance->XLines->AddLine(el, user))
+ {
+ if (!duration)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent E-line for %s: %s", user->nick.c_str(), target.c_str(), parameters[2].c_str());
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed E-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(),
+ ServerInstance->TimeString(c_requires_crap).c_str(), parameters[2].c_str());
+ }
+ }
+ else
+ {
+ delete el;
+ user->WriteServ("NOTICE %s :*** E-Line for %s already exists",user->nick.c_str(),target.c_str());
+ }
+ }
+ else
+ {
+ if (ServerInstance->XLines->DelLine(target.c_str(), "E", user))
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s removed E-line on %s",user->nick.c_str(),target.c_str());
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** E-Line %s not found in list, try /stats e.",user->nick.c_str(),target.c_str());
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandEline)
diff --git a/src/commands/cmd_gline.cpp b/src/commands/cmd_gline.cpp
new file mode 100644
index 000000000..ad3067428
--- /dev/null
+++ b/src/commands/cmd_gline.cpp
@@ -0,0 +1,111 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+
+/** Handle /GLINE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandGline : public Command
+{
+ public:
+ /** Constructor for gline.
+ */
+ CommandGline (Module* parent) : Command(parent,"GLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = "<ident@host> [<duration> :<reason>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+/** Handle /GLINE
+ */
+CmdResult CommandGline::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string target = parameters[0];
+
+ if (parameters.size() >= 3)
+ {
+ IdentHostPair ih;
+ User* find = ServerInstance->FindNick(target.c_str());
+ if (find)
+ {
+ ih.first = "*";
+ ih.second = find->GetIPString();
+ target = std::string("*@") + find->GetIPString();
+ }
+ else
+ ih = ServerInstance->XLines->IdentSplit(target.c_str());
+
+ if (ih.first.empty())
+ {
+ user->WriteServ("NOTICE %s :*** Target not found", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
+ return CMD_FAILURE;
+
+ else if (target.find('!') != std::string::npos)
+ {
+ user->WriteServ("NOTICE %s :*** G-Line cannot operate on nick!user@host masks",user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ long duration = ServerInstance->Duration(parameters[1].c_str());
+ GLine* gl = new GLine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
+ if (ServerInstance->XLines->AddLine(gl, user))
+ {
+ if (!duration)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent G-line for %s: %s",user->nick.c_str(),target.c_str(), parameters[2].c_str());
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed G-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(),
+ ServerInstance->TimeString(c_requires_crap).c_str(), parameters[2].c_str());
+ }
+
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
+ {
+ delete gl;
+ user->WriteServ("NOTICE %s :*** G-Line for %s already exists",user->nick.c_str(),target.c_str());
+ }
+
+ }
+ else
+ {
+ if (ServerInstance->XLines->DelLine(target.c_str(),"G",user))
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s removed G-line on %s",user->nick.c_str(),target.c_str());
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** G-line %s not found in list, try /stats g.",user->nick.c_str(),target.c_str());
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandGline)
diff --git a/src/commands/cmd_info.cpp b/src/commands/cmd_info.cpp
new file mode 100644
index 000000000..f239b9f78
--- /dev/null
+++ b/src/commands/cmd_info.cpp
@@ -0,0 +1,91 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_INFO_H__
+#define __CMD_INFO_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /INFO. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandInfo : public Command
+{
+ public:
+ /** Constructor for info.
+ */
+ CommandInfo ( Module* parent) : Command(parent,"INFO",0,0) { syntax = "[<servermask>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /INFO
+ */
+CmdResult CommandInfo::Handle (const std::vector<std::string>&, User *user)
+{
+ user->WriteNumeric(RPL_INFO, "%s : -/\\- \2InspIRCd\2 -\\/-", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : November 2002 - Present", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : ", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s :\2Core Developers\2:", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Craig Edwards, Brain, <brain@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Craig McLure, Craig, <craig@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Robin Burchell, w00t, <w00t@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Oliver Lupton, Om, <om@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : John Brooks, Special, <special@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Dennis Friis, peavey, <peavey@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Thomas Stagner, aquanight, <aquanight@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Uli Schlachter, psychon, <psychon@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Matt Smith, dz, <dz@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Daniel De Graaf danieldg, <danieldg@inspircd.org>", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : ", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s :\2Regular Contributors\2:", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Majic MacGyver Namegduf Ankit", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Phoenix Taros", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : ", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s :\2Other Contributors\2:", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : dmb Zaba skenmy GreenReaper", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Dan Jason satmd owine", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Adremelech John2 jilles HiroP", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : eggy Bricker AnMaster djGrrr", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : nenolod Quension praetorian pippijn", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : ", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s :\2Former Contributors\2:", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : CC jamie typobox43 Burlex (win32)", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Stskeeps ThaPrince BuildSmart Thunderhacker", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Skip LeaChim", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : ", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s :\2Thanks To\2:", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : searchirc.com irc-junkie.org Brik", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : ", user->nick.c_str());
+ user->WriteNumeric(RPL_INFO, "%s : Best experienced with: \2An IRC client\2", user->nick.c_str());
+ FOREACH_MOD(I_OnInfo,OnInfo(user));
+ user->WriteNumeric(RPL_ENDOFINFO, "%s :End of /INFO list", user->nick.c_str());
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandInfo)
diff --git a/src/commands/cmd_invite.cpp b/src/commands/cmd_invite.cpp
new file mode 100644
index 000000000..89437e252
--- /dev/null
+++ b/src/commands/cmd_invite.cpp
@@ -0,0 +1,131 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /INVITE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandInvite : public Command
+{
+ public:
+ /** Constructor for invite.
+ */
+ CommandInvite ( Module* parent) : Command(parent,"INVITE", 0, 0) { Penalty = 4; syntax = "[<nick> <channel>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+/** Handle /INVITE
+ */
+CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ ModResult MOD_RESULT;
+
+ if (parameters.size() == 2 || parameters.size() == 3)
+ {
+ User* u = ServerInstance->FindNick(parameters[0]);
+ Channel* c = ServerInstance->FindChan(parameters[1]);
+ time_t timeout = 0;
+ if (parameters.size() == 3)
+ {
+ if (IS_LOCAL(user))
+ timeout = ServerInstance->Time() + ServerInstance->Duration(parameters[2]);
+ else
+ timeout = ConvToInt(parameters[2]);
+ }
+
+ if ((!c) || (!u))
+ {
+ user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), c ? parameters[0].c_str() : parameters[1].c_str());
+ return CMD_FAILURE;
+ }
+
+ if (c->HasUser(u))
+ {
+ user->WriteNumeric(ERR_USERONCHANNEL, "%s %s %s :is already on channel",user->nick.c_str(),u->nick.c_str(),c->name.c_str());
+ return CMD_FAILURE;
+ }
+
+ if ((IS_LOCAL(user)) && (!c->HasUser(user)))
+ {
+ user->WriteNumeric(ERR_NOTONCHANNEL, "%s %s :You're not on that channel!",user->nick.c_str(), c->name.c_str());
+ return CMD_FAILURE;
+ }
+
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreInvite, MOD_RESULT, (user,u,c,timeout));
+
+ if (MOD_RESULT == MOD_RES_DENY)
+ {
+ return CMD_FAILURE;
+ }
+ else if (MOD_RESULT == MOD_RES_PASSTHRU)
+ {
+ if (IS_LOCAL(user))
+ {
+ int rank = c->GetPrefixValue(user);
+ if (rank < HALFOP_VALUE)
+ {
+ user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must be a channel %soperator",
+ user->nick.c_str(), c->name.c_str(), rank >= HALFOP_VALUE ? "" : "half-");
+ return CMD_FAILURE;
+ }
+ }
+ }
+
+ u->InviteTo(c->name.c_str(), timeout);
+ u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str());
+ user->WriteNumeric(RPL_INVITING, "%s %s %s",user->nick.c_str(),u->nick.c_str(),c->name.c_str());
+ switch (ServerInstance->Config->AnnounceInvites)
+ {
+ case ServerConfig::INVITE_ANNOUNCE_ALL:
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :*** %s invited %s into the channel", c->name.c_str(), user->nick.c_str(), u->nick.c_str());
+ break;
+ case ServerConfig::INVITE_ANNOUNCE_OPS:
+ c->WriteAllExceptSender(user, true, '@', "NOTICE %s :*** %s invited %s into the channel", c->name.c_str(), user->nick.c_str(), u->nick.c_str());
+ break;
+ case ServerConfig::INVITE_ANNOUNCE_DYNAMIC:
+ if (c->IsModeSet('i'))
+ c->WriteAllExceptSender(user, true, '@', "NOTICE %s :*** %s invited %s into the channel", c->name.c_str(), user->nick.c_str(), u->nick.c_str());
+ else
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :*** %s invited %s into the channel", c->name.c_str(), user->nick.c_str(), u->nick.c_str());
+ break;
+ default:
+ /* Nobody */
+ break;
+ }
+ FOREACH_MOD(I_OnUserInvite,OnUserInvite(user,u,c,timeout));
+ }
+ else
+ {
+ // pinched from ircu - invite with not enough parameters shows channels
+ // youve been invited to but haven't joined yet.
+ InvitedList* il = user->GetInviteList();
+ for (InvitedList::iterator i = il->begin(); i != il->end(); i++)
+ {
+ user->WriteNumeric(RPL_INVITELIST, "%s :%s",user->nick.c_str(),i->first.c_str());
+ }
+ user->WriteNumeric(RPL_ENDOFINVITELIST, "%s :End of INVITE list",user->nick.c_str());
+ }
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandInvite)
diff --git a/src/commands/cmd_ison.cpp b/src/commands/cmd_ison.cpp
new file mode 100644
index 000000000..ca7639b58
--- /dev/null
+++ b/src/commands/cmd_ison.cpp
@@ -0,0 +1,108 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_ISON_H__
+#define __CMD_ISON_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /ISON. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandIson : public Command
+{
+ public:
+ /** Constructor for ison.
+ */
+ CommandIson ( Module* parent) : Command(parent,"ISON",0,0) { syntax = "<nick> {nick}"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /ISON
+ */
+CmdResult CommandIson::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::map<User*,User*> ison_already;
+ User *u;
+ std::string reply = std::string("303 ") + user->nick + " :";
+
+ for (unsigned int i = 0; i < parameters.size(); i++)
+ {
+ u = ServerInstance->FindNick(parameters[i]);
+ if (ison_already.find(u) != ison_already.end())
+ continue;
+
+ if (u)
+ {
+ reply.append(u->nick).append(" ");
+ if (reply.length() > 450)
+ {
+ user->WriteServ(reply);
+ reply = std::string("303 ") + user->nick + " :";
+ }
+ ison_already[u] = u;
+ }
+ else
+ {
+ if ((i == parameters.size() - 1) && (parameters[i].find(' ') != std::string::npos))
+ {
+ /* Its a space seperated list of nicks (RFC1459 says to support this)
+ */
+ irc::spacesepstream list(parameters[i]);
+ std::string item;
+
+ while (list.GetToken(item))
+ {
+ u = ServerInstance->FindNick(item);
+ if (ison_already.find(u) != ison_already.end())
+ continue;
+
+ if (u)
+ {
+ reply.append(u->nick).append(" ");
+ if (reply.length() > 450)
+ {
+ user->WriteServ(reply);
+ reply = std::string("303 ") + user->nick + " :";
+ }
+ ison_already[u] = u;
+ }
+ }
+ }
+ }
+ }
+
+ if (!reply.empty())
+ user->WriteServ(reply);
+
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandIson)
diff --git a/src/commands/cmd_join.cpp b/src/commands/cmd_join.cpp
new file mode 100644
index 000000000..73cae4746
--- /dev/null
+++ b/src/commands/cmd_join.cpp
@@ -0,0 +1,78 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_JOIN_H__
+#define __CMD_JOIN_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /JOIN. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandJoin : public Command
+{
+ public:
+ /** Constructor for join.
+ */
+ CommandJoin ( Module* parent) : Command(parent,"JOIN", 1, 2) { syntax = "<channel>{,<channel>} {<key>{,<key>}}"; Penalty = 2; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /JOIN
+ */
+CmdResult CommandJoin::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ if (parameters.size() > 1)
+ {
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0, 1))
+ return CMD_SUCCESS;
+
+ if (ServerInstance->IsChannel(parameters[0].c_str(), ServerInstance->Config->Limits.ChanMax))
+ {
+ Channel::JoinUser(ServerInstance, user, parameters[0].c_str(), false, parameters[1].c_str(), false);
+ return CMD_SUCCESS;
+ }
+ }
+ else
+ {
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ return CMD_SUCCESS;
+
+ if (ServerInstance->IsChannel(parameters[0].c_str(), ServerInstance->Config->Limits.ChanMax))
+ {
+ Channel::JoinUser(ServerInstance, user, parameters[0].c_str(), false, "", false);
+ return CMD_SUCCESS;
+ }
+ }
+
+ user->WriteNumeric(ERR_NOSUCHCHANNEL, "%s %s :Invalid channel name",user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+}
+
+COMMAND_INIT(CommandJoin)
diff --git a/src/commands/cmd_kick.cpp b/src/commands/cmd_kick.cpp
new file mode 100644
index 000000000..d07d53836
--- /dev/null
+++ b/src/commands/cmd_kick.cpp
@@ -0,0 +1,86 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_KICK_H__
+#define __CMD_KICK_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /KICK. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandKick : public Command
+{
+ public:
+ /** Constructor for kick.
+ */
+ CommandKick ( Module* parent) : Command(parent,"KICK",2,3) { syntax = "<channel> <nick>{,<nick>} [<reason>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /KICK
+ */
+CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string reason;
+ Channel* c = ServerInstance->FindChan(parameters[0]);
+ User* u = ServerInstance->FindNick(parameters[1]);
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 1))
+ return CMD_SUCCESS;
+
+ if (!u || !c)
+ {
+ user->WriteServ( "401 %s %s :No such nick/channel", user->nick.c_str(), u ? parameters[0].c_str() : parameters[1].c_str());
+ return CMD_FAILURE;
+ }
+
+ if ((IS_LOCAL(user)) && (!c->HasUser(user)) && (!ServerInstance->ULine(user->server)))
+ {
+ user->WriteServ( "442 %s %s :You're not on that channel!", user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
+ if (parameters.size() > 2)
+ {
+ reason.assign(parameters[2], 0, ServerInstance->Config->Limits.MaxKick);
+ }
+ else
+ {
+ reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick);
+ }
+
+ if (!c->KickUser(user, u, reason.c_str()))
+ /* Nobody left here, delete the Channel */
+ delete c;
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandKick)
diff --git a/src/commands/cmd_kill.cpp b/src/commands/cmd_kill.cpp
new file mode 100644
index 000000000..1001d4c8a
--- /dev/null
+++ b/src/commands/cmd_kill.cpp
@@ -0,0 +1,131 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /KILL. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandKill : public Command
+{
+ public:
+ /** Constructor for kill.
+ */
+ CommandKill ( Module* parent) : Command(parent,"KILL",2,2) { flags_needed = 'o'; syntax = "<nickname> <reason>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+/** Handle /KILL
+ */
+CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ /* Allow comma seperated lists of users for /KILL (thanks w00t) */
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ return CMD_SUCCESS;
+
+ User *u = ServerInstance->FindNick(parameters[0]);
+ char killreason[MAXBUF];
+ ModResult MOD_RESULT;
+
+ if (u)
+ {
+ /*
+ * Here, we need to decide how to munge kill messages. Whether to hide killer, what to show opers, etc.
+ * We only do this when the command is being issued LOCALLY, for remote KILL, we just copy the message we got.
+ *
+ * This conditional is so that we only append the "Killed (" prefix ONCE. If killer is remote, then the kill
+ * just gets processed and passed on, otherwise, if they are local, it gets prefixed. Makes sense :-) -- w00t
+ */
+ if (IS_LOCAL(user))
+ {
+ /*
+ * Moved this event inside the IS_LOCAL check also, we don't want half the network killing a user
+ * and the other half not. This would be a bad thing. ;p -- w00t
+ */
+ FIRST_MOD_RESULT(ServerInstance, OnKill, MOD_RESULT, (user, u, parameters[1]));
+
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+
+ if (*ServerInstance->Config->HideKillsServer)
+ {
+ // hidekills is on, use it
+ snprintf(killreason, ServerInstance->Config->Limits.MaxQuit, "Killed (%s (%s))", ServerInstance->Config->HideKillsServer, parameters[1].c_str());
+ }
+ else
+ {
+ // hidekills is off, do nothing
+ snprintf(killreason, ServerInstance->Config->Limits.MaxQuit, "Killed (%s (%s))", user->nick.c_str(), parameters[1].c_str());
+ }
+ }
+ else
+ {
+ /* Leave it alone, remote server has already formatted it */
+ strlcpy(killreason, parameters[1].c_str(), ServerInstance->Config->Limits.MaxQuit);
+ }
+
+ /*
+ * Now we need to decide whether or not to send a local or remote snotice. Currently this checking is a little flawed.
+ * No time to fix it right now, so left a note. -- w00t
+ */
+ if (!IS_LOCAL(u))
+ {
+ // remote kill
+ ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s!%s@%s (%s)", user->nick.c_str(), u->nick.c_str(), u->ident.c_str(), u->host.c_str(), parameters[1].c_str());
+ FOREACH_MOD(I_OnRemoteKill, OnRemoteKill(user, u, killreason, killreason));
+ }
+ else
+ {
+ // local kill
+ /*
+ * XXX - this isn't entirely correct, servers A - B - C, oper on A, client on C. Oper kills client, A and B will get remote kill
+ * snotices, C will get a local kill snotice. this isn't accurate, and needs fixing at some stage. -- w00t
+ */
+ ServerInstance->SNO->WriteToSnoMask('k',"Local Kill by %s: %s!%s@%s (%s)", user->nick.c_str(), u->nick.c_str(), u->ident.c_str(), u->host.c_str(), parameters[1].c_str());
+ ServerInstance->Logs->Log("KILL",DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick.c_str(), ServerInstance->Config->ServerName, user->dhost.c_str(), user->nick.c_str(), parameters[1].c_str());
+ /* Bug #419, make sure this message can only occur once even in the case of multiple KILL messages crossing the network, and change to show
+ * hidekillsserver as source if possible
+ */
+ if (!u->quitting)
+ {
+ u->Write(":%s KILL %s :%s!%s!%s (%s)", *ServerInstance->Config->HideKillsServer ? ServerInstance->Config->HideKillsServer : user->GetFullHost().c_str(),
+ u->nick.c_str(),
+ ServerInstance->Config->ServerName,
+ user->dhost.c_str(),
+ *ServerInstance->Config->HideKillsServer ? ServerInstance->Config->HideKillsServer : user->nick.c_str(),
+ parameters[1].c_str());
+ }
+ }
+
+ // send the quit out
+ ServerInstance->Users->QuitUser(u, killreason);
+ }
+ else
+ {
+ user->WriteServ( "401 %s %s :No such nick/channel", user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandKill)
diff --git a/src/commands/cmd_kline.cpp b/src/commands/cmd_kline.cpp
new file mode 100644
index 000000000..3ec2461b4
--- /dev/null
+++ b/src/commands/cmd_kline.cpp
@@ -0,0 +1,110 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+
+/** Handle /KLINE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandKline : public Command
+{
+ public:
+ /** Constructor for kline.
+ */
+ CommandKline ( Module* parent) : Command(parent,"KLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = "<ident@host> [<duration> :<reason>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+/** Handle /KLINE
+ */
+CmdResult CommandKline::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string target = parameters[0];
+
+ if (parameters.size() >= 3)
+ {
+ IdentHostPair ih;
+ User* find = ServerInstance->FindNick(target.c_str());
+ if (find)
+ {
+ ih.first = "*";
+ ih.second = find->GetIPString();
+ target = std::string("*@") + find->GetIPString();
+ }
+ else
+ ih = ServerInstance->XLines->IdentSplit(target.c_str());
+
+ if (ih.first.empty())
+ {
+ user->WriteServ("NOTICE %s :*** Target not found", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
+ return CMD_FAILURE;
+
+ if (target.find('!') != std::string::npos)
+ {
+ user->WriteServ("NOTICE %s :*** K-Line cannot operate on nick!user@host masks",user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ long duration = ServerInstance->Duration(parameters[1].c_str());
+ KLine* kl = new KLine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
+ if (ServerInstance->XLines->AddLine(kl,user))
+ {
+ if (!duration)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent K-line for %s: %s",user->nick.c_str(),target.c_str(), parameters[2].c_str());
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed K-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(),
+ ServerInstance->TimeString(c_requires_crap).c_str(), parameters[2].c_str());
+ }
+
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
+ {
+ delete kl;
+ user->WriteServ("NOTICE %s :*** K-Line for %s already exists",user->nick.c_str(),target.c_str());
+ }
+ }
+ else
+ {
+ if (ServerInstance->XLines->DelLine(target.c_str(),"K",user))
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s removed K-line on %s",user->nick.c_str(),target.c_str());
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** K-Line %s not found in list, try /stats k.",user->nick.c_str(),target.c_str());
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandKline)
diff --git a/src/commands/cmd_links.cpp b/src/commands/cmd_links.cpp
new file mode 100644
index 000000000..d722fa65d
--- /dev/null
+++ b/src/commands/cmd_links.cpp
@@ -0,0 +1,56 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_LINKS_H__
+#define __CMD_LINKS_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /LINKS. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandLinks : public Command
+{
+ public:
+ /** Constructor for links.
+ */
+ CommandLinks ( Module* parent) : Command(parent,"LINKS",0,0) { }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /LINKS
+ */
+CmdResult CommandLinks::Handle (const std::vector<std::string>&, User *user)
+{
+ user->WriteNumeric(364, "%s %s %s :0 %s",user->nick.c_str(),ServerInstance->Config->ServerName,ServerInstance->Config->ServerName,ServerInstance->Config->ServerDesc);
+ user->WriteNumeric(365, "%s * :End of /LINKS list.",user->nick.c_str());
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandLinks)
diff --git a/src/commands/cmd_list.cpp b/src/commands/cmd_list.cpp
new file mode 100644
index 000000000..b7023072b
--- /dev/null
+++ b/src/commands/cmd_list.cpp
@@ -0,0 +1,98 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /LIST. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandList : public Command
+{
+ public:
+ /** Constructor for list.
+ */
+ CommandList ( Module* parent) : Command(parent,"LIST", 0, 0) { Penalty = 5; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+/** Handle /LIST
+ */
+CmdResult CommandList::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ int minusers = 0, maxusers = 0;
+
+ user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str());
+
+ /* Work around mIRC suckyness. YOU SUCK, KHALED! */
+ if (parameters.size() == 1)
+ {
+ if (parameters[0][0] == '<')
+ {
+ maxusers = atoi((parameters[0].c_str())+1);
+ }
+ else if (parameters[0][0] == '>')
+ {
+ minusers = atoi((parameters[0].c_str())+1);
+ }
+ }
+
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
+ {
+ // attempt to match a glob pattern
+ long users = i->second->GetUserCounter();
+
+ bool too_few = (minusers && (users <= minusers));
+ bool too_many = (maxusers && (users >= maxusers));
+
+ if (too_many || too_few)
+ continue;
+
+ if (parameters.size() && (parameters[0][0] != '<' && parameters[0][0] != '>'))
+ {
+ if (!InspIRCd::Match(i->second->name, parameters[0]) && !InspIRCd::Match(i->second->topic, parameters[0]))
+ continue;
+ }
+
+ // if the channel is not private/secret, OR the user is on the channel anyway
+ bool n = (i->second->HasUser(user) || user->HasPrivPermission("channels/auspex"));
+
+ if (!n && i->second->IsModeSet('p'))
+ {
+ /* Channel is +p and user is outside/not privileged */
+ user->WriteNumeric(322, "%s * %ld :",user->nick.c_str(), users);
+ }
+ else
+ {
+ if (n || !i->second->IsModeSet('s'))
+ {
+ /* User is in the channel/privileged, channel is not +s */
+ user->WriteNumeric(322, "%s %s %ld :[+%s] %s",user->nick.c_str(),i->second->name.c_str(),users,i->second->ChanModes(n),i->second->topic.c_str());
+ }
+ }
+ }
+ user->WriteNumeric(323, "%s :End of channel list.",user->nick.c_str());
+
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandList)
diff --git a/src/commands/cmd_loadmodule.cpp b/src/commands/cmd_loadmodule.cpp
new file mode 100644
index 000000000..d4cda20ab
--- /dev/null
+++ b/src/commands/cmd_loadmodule.cpp
@@ -0,0 +1,54 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /LOADMODULE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandLoadmodule : public Command
+{
+ public:
+ /** Constructor for loadmodule.
+ */
+ CommandLoadmodule ( Module* parent) : Command(parent,"LOADMODULE",1,1) { flags_needed='o'; syntax = "<modulename>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+/** Handle /LOADMODULE
+ */
+CmdResult CommandLoadmodule::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ if (ServerInstance->Modules->Load(parameters[0].c_str()))
+ {
+ ServerInstance->SNO->WriteToSnoMask('a', "NEW MODULE: %s loaded %s",user->nick.c_str(), parameters[0].c_str());
+ user->WriteNumeric(975, "%s %s :Module successfully loaded.",user->nick.c_str(), parameters[0].c_str());
+ return CMD_SUCCESS;
+ }
+ else
+ {
+ user->WriteNumeric(974, "%s %s :%s",user->nick.c_str(), parameters[0].c_str(), ServerInstance->Modules->LastError().c_str());
+ return CMD_FAILURE;
+ }
+}
+
+COMMAND_INIT(CommandLoadmodule)
diff --git a/src/commands/cmd_lusers.cpp b/src/commands/cmd_lusers.cpp
new file mode 100644
index 000000000..a79466ae4
--- /dev/null
+++ b/src/commands/cmd_lusers.cpp
@@ -0,0 +1,67 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_LUSERS_H__
+#define __CMD_LUSERS_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /LUSERS. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandLusers : public Command
+{
+ public:
+ /** Constructor for lusers.
+ */
+ CommandLusers ( Module* parent) : Command(parent,"LUSERS",0,0) { }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /LUSERS
+ */
+CmdResult CommandLusers::Handle (const std::vector<std::string>&, User *user)
+{
+ // this lusers command shows one server at all times because
+ // a protocol module must override it to show those stats.
+ user->WriteNumeric(251, "%s :There are %d users and %d invisible on 1 server",user->nick.c_str(),ServerInstance->Users->UserCount()-ServerInstance->Users->ModeCount('i'),ServerInstance->Users->ModeCount('i'));
+ if (ServerInstance->Users->OperCount())
+ user->WriteNumeric(252, "%s %d :operator(s) online",user->nick.c_str(),ServerInstance->Users->OperCount());
+ if (ServerInstance->Users->UnregisteredUserCount())
+ user->WriteNumeric(253, "%s %d :unknown connections",user->nick.c_str(),ServerInstance->Users->UnregisteredUserCount());
+ if (ServerInstance->ChannelCount())
+ user->WriteNumeric(254, "%s %ld :channels formed",user->nick.c_str(),ServerInstance->ChannelCount());
+ if (ServerInstance->Users->LocalUserCount())
+ user->WriteNumeric(255, "%s :I have %d clients and 0 servers",user->nick.c_str(),ServerInstance->Users->LocalUserCount());
+
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandLusers)
diff --git a/src/commands/cmd_map.cpp b/src/commands/cmd_map.cpp
new file mode 100644
index 000000000..edc8aa124
--- /dev/null
+++ b/src/commands/cmd_map.cpp
@@ -0,0 +1,44 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+class CommandMap : public Command
+{
+ public:
+ /** Constructor for map.
+ */
+ CommandMap ( Module* parent) : Command(parent,"MAP",0,0) { Penalty=2; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+/** Handle /MAP
+ */
+CmdResult CommandMap::Handle (const std::vector<std::string>&, User *user)
+{
+ // as with /LUSERS this does nothing without a linking
+ // module to override its behaviour and display something
+ // better.
+ user->WriteNumeric(006, "%s :%s",user->nick.c_str(),ServerInstance->Config->ServerName);
+ user->WriteNumeric(007, "%s :End of /MAP",user->nick.c_str());
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandMap)
diff --git a/src/commands/cmd_mode.cpp b/src/commands/cmd_mode.cpp
new file mode 100644
index 000000000..3cfc58263
--- /dev/null
+++ b/src/commands/cmd_mode.cpp
@@ -0,0 +1,55 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_ADMIN_H__
+#define __CMD_ADMIN_H__
+
+#include "users.h"
+#include "channels.h"
+#include "ctables.h"
+
+/** Handle /MODE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandMode : public Command
+{
+ public:
+ /** Constructor for mode.
+ */
+ CommandMode ( Module* parent) : Command(parent,"MODE",1) { syntax = "<target> <modes> {<mode-parameters>}"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /MODE
+ */
+CmdResult CommandMode::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ ServerInstance->Modes->Process(parameters, user, false);
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandMode)
diff --git a/src/commands/cmd_modules.cpp b/src/commands/cmd_modules.cpp
new file mode 100644
index 000000000..599eb611b
--- /dev/null
+++ b/src/commands/cmd_modules.cpp
@@ -0,0 +1,78 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_MODULES_H__
+#define __CMD_MODULES_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /MODULES. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandModules : public Command
+{
+ public:
+ /** Constructor for modules.
+ */
+ CommandModules ( Module* parent) : Command(parent,"MODULES",0,0) { syntax = "[debug]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /MODULES
+ */
+CmdResult CommandModules::Handle (const std::vector<std::string>&, User *user)
+{
+ std::vector<std::string> module_names = ServerInstance->Modules->GetAllModuleNames(0);
+
+ for (unsigned int i = 0; i < module_names.size(); i++)
+ {
+ Module* m = ServerInstance->Modules->Find(module_names[i]);
+ Version V = m->GetVersion();
+
+ if (user->HasPrivPermission("servers/auspex"))
+ {
+ std::string flags("Svsc");
+ int pos = 0;
+ for (int mult = 1; mult <= VF_SERVICEPROVIDER; mult *= 2, ++pos)
+ if (!(V.Flags & mult))
+ flags[pos] = '-';
+
+ user->WriteNumeric(702, "%s :0x%08lx %s %s :%s", user->nick.c_str(), (unsigned long)m, module_names[i].c_str(), flags.c_str(), V.version.c_str());
+ }
+ else
+ {
+ user->WriteNumeric(702, "%s :%s",user->nick.c_str(), module_names[i].c_str());
+ }
+ }
+ user->WriteNumeric(703, "%s :End of MODULES list",user->nick.c_str());
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandModules)
diff --git a/src/commands/cmd_motd.cpp b/src/commands/cmd_motd.cpp
new file mode 100644
index 000000000..0e0785e93
--- /dev/null
+++ b/src/commands/cmd_motd.cpp
@@ -0,0 +1,58 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_MOTD_H__
+#define __CMD_MOTD_H__
+
+// include the common header files
+
+#include <string>
+#include <vector>
+#include "inspircd.h"
+#include "users.h"
+#include "channels.h"
+
+/** Handle /MOTD. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandMotd : public Command
+{
+ public:
+ /** Constructor for motd.
+ */
+ CommandMotd ( Module* parent) : Command(parent,"MOTD",0,1) { syntax = "[<servername>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /MOTD
+ */
+CmdResult CommandMotd::Handle (const std::vector<std::string>&, User *user)
+{
+ user->ShowMOTD();
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandMotd)
diff --git a/src/commands/cmd_names.cpp b/src/commands/cmd_names.cpp
new file mode 100644
index 000000000..537c477c8
--- /dev/null
+++ b/src/commands/cmd_names.cpp
@@ -0,0 +1,80 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_NAMES_H__
+#define __CMD_NAMES_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /NAMES. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandNames : public Command
+{
+ public:
+ /** Constructor for names.
+ */
+ CommandNames ( Module* parent) : Command(parent,"NAMES",0,0) { syntax = "{<channel>{,<channel>}}"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+/** Handle /NAMES
+ */
+CmdResult CommandNames::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ Channel* c;
+
+ if (!parameters.size())
+ {
+ user->WriteNumeric(366, "%s * :End of /NAMES list.",user->nick.c_str());
+ return CMD_SUCCESS;
+ }
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ return CMD_SUCCESS;
+
+ c = ServerInstance->FindChan(parameters[0]);
+ if (c)
+ {
+ if ((c->IsModeSet('s')) && (!c->HasUser(user)))
+ {
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), c->name.c_str());
+ return CMD_FAILURE;
+ }
+ c->UserList(user);
+ }
+ else
+ {
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandNames)
diff --git a/src/commands/cmd_nick.cpp b/src/commands/cmd_nick.cpp
new file mode 100644
index 000000000..99b8348ab
--- /dev/null
+++ b/src/commands/cmd_nick.cpp
@@ -0,0 +1,214 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+
+/** Handle /NICK. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandNick : public Command
+{
+ public:
+ /** Constructor for nick.
+ */
+ CommandNick ( Module* parent) : Command(parent,"NICK", 1, 1) { works_before_reg = true; syntax = "<newnick>"; Penalty = 3; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+/** Handle nick changes from users.
+ * NOTE: If you are used to ircds based on ircd2.8, and are looking
+ * for the client introduction code in here, youre in the wrong place.
+ * You need to look in the spanningtree module for this!
+ */
+CmdResult CommandNick::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string oldnick;
+
+ if (parameters[0].empty())
+ {
+ /* We cant put blanks in the parameters, so for this (extremely rare) issue we just put '*' here. */
+ user->WriteNumeric(432, "%s * :Erroneous Nickname", user->nick.empty() ? user->nick.c_str() : "*");
+ return CMD_FAILURE;
+ }
+
+ if (((!ServerInstance->IsNick(parameters[0].c_str(), ServerInstance->Config->Limits.NickMax))) && (IS_LOCAL(user)))
+ {
+ if (!User::NICKForced.get(user))
+ {
+ if (parameters[0] == "0")
+ {
+ // Special case, Fake a /nick UIDHERE. Useful for evading "ERR: NICK IN USE" on connect etc.
+ std::vector<std::string> p2;
+ p2.push_back(user->uuid);
+ User::NICKForced.set(user, 1);
+ this->Handle(p2, user);
+ User::NICKForced.set(user, 0);
+ return CMD_SUCCESS;
+ }
+
+ user->WriteNumeric(432, "%s %s :Erroneous Nickname", user->nick.c_str(),parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ }
+
+ if (assign(user->nick) == parameters[0])
+ {
+ /* If its exactly the same, even case, dont do anything. */
+ if (parameters[0] == user->nick)
+ {
+ return CMD_SUCCESS;
+ }
+
+ /* Its a change of case. People insisted that they should be
+ * able to do silly things like this even though the RFC says
+ * the nick AAA is the same as the nick aaa.
+ */
+ oldnick.assign(user->nick, 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
+ ModResult MOD_RESULT;
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreNick, MOD_RESULT, (user,parameters[0]));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+ if (user->registered == REG_ALL)
+ user->WriteCommon("NICK %s",parameters[0].c_str());
+ user->nick.assign(parameters[0], 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
+ user->InvalidateCache();
+ FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick));
+ return CMD_SUCCESS;
+ }
+ else
+ {
+ /*
+ * Don't check Q:Lines if it's a server-enforced change, just on the off-chance some fucking *moron*
+ * tries to Q:Line SIDs, also, this means we just get our way period, as it really should be.
+ * Thanks Kein for finding this. -- w00t
+ *
+ * Also don't check Q:Lines for remote nickchanges, they should have our Q:Lines anyway to enforce themselves.
+ * -- w00t
+ */
+ if (!IS_LOCAL(user))
+ {
+ XLine* mq = ServerInstance->XLines->MatchesLine("Q",parameters[0]);
+ if (mq)
+ {
+ if (user->registered == REG_ALL)
+ {
+ ServerInstance->SNO->WriteGlobalSno('a', "Q-Lined nickname %s from %s!%s@%s: %s",
+ parameters[0].c_str(), user->nick.c_str(), user->ident.c_str(), user->host.c_str(), mq->reason.c_str());
+ }
+ user->WriteNumeric(432, "%s %s :Invalid nickname: %s",user->nick.c_str(), parameters[0].c_str(), mq->reason.c_str());
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->Config->RestrictBannedUsers)
+ {
+ for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++)
+ {
+ Channel *chan = *i;
+ if (chan->GetPrefixValue(user) < VOICE_VALUE && chan->IsBanned(user))
+ {
+ user->WriteNumeric(404, "%s %s :Cannot send to channel (you're banned)", user->nick.c_str(), chan->name.c_str());
+ return CMD_FAILURE;
+ }
+ }
+ }
+ }
+
+ /*
+ * Uh oh.. if the nickname is in use, and it's not in use by the person using it (doh) --
+ * then we have a potential collide. Check whether someone else is camping on the nick
+ * (i.e. connect -> send NICK, don't send USER.) If they are camping, force-change the
+ * camper to their UID, and allow the incoming nick change.
+ *
+ * If the guy using the nick is already using it, tell the incoming nick change to gtfo,
+ * because the nick is already (rightfully) in use. -- w00t
+ */
+ User* InUse = ServerInstance->FindNickOnly(parameters[0]);
+ if (InUse && (InUse != user))
+ {
+ if (InUse->registered != REG_ALL)
+ {
+ /* force the camper to their UUID, and ask them to re-send a NICK. */
+ InUse->WriteTo(InUse, "NICK %s", InUse->uuid.c_str());
+ InUse->WriteNumeric(433, "%s %s :Nickname overruled.", InUse->nick.c_str(), InUse->nick.c_str());
+ InUse->UpdateNickHash(InUse->uuid.c_str());
+ InUse->nick.assign(InUse->uuid, 0, IS_LOCAL(InUse) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
+ InUse->InvalidateCache();
+ InUse->registered &= ~REG_NICK;
+ }
+ else
+ {
+ /* No camping, tell the incoming user to stop trying to change nick ;p */
+ user->WriteNumeric(433, "%s %s :Nickname is already in use.", user->registered >= REG_NICK ? user->nick.c_str() : "*", parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ }
+ }
+
+
+ ModResult MOD_RESULT;
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreNick, MOD_RESULT, (user, parameters[0]));
+ if (MOD_RESULT == MOD_RES_DENY)
+ // if a module returns true, the nick change is silently forbidden.
+ return CMD_FAILURE;
+
+ if (user->registered == REG_ALL)
+ user->WriteCommon("NICK %s", parameters[0].c_str());
+
+ oldnick.assign(user->nick, 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
+
+ /* change the nick of the user in the users_hash */
+ user = user->UpdateNickHash(parameters[0].c_str());
+
+ /* actually change the nick within the record */
+ if (!user)
+ return CMD_FAILURE;
+
+ user->nick.assign(parameters[0], 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF);
+ user->InvalidateCache();
+
+ if (user->registered < REG_NICKUSER)
+ {
+ user->registered = (user->registered | REG_NICK);
+ if (user->registered == REG_NICKUSER)
+ {
+ /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
+ FIRST_MOD_RESULT(ServerInstance, OnUserRegister, MOD_RESULT, (user));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+
+ // return early to not penalize new users
+ return CMD_SUCCESS;
+ }
+ }
+
+ if (user->registered == REG_ALL)
+ {
+ user->IncreasePenalty(10);
+ FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user, oldnick));
+ }
+
+ return CMD_SUCCESS;
+
+}
+
+
+COMMAND_INIT(CommandNick)
diff --git a/src/commands/cmd_notice.cpp b/src/commands/cmd_notice.cpp
new file mode 100644
index 000000000..ced17072f
--- /dev/null
+++ b/src/commands/cmd_notice.cpp
@@ -0,0 +1,203 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+/** Handle /NOTICE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandNotice : public Command
+{
+ public:
+ /** Constructor for notice.
+ */
+ CommandNotice ( Module* parent) : Command(parent,"NOTICE",2,2) { syntax = "<target>{,<target>} <message>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+CmdResult CommandNotice::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ User *dest;
+ Channel *chan;
+
+ CUList exempt_list;
+
+ user->idle_lastmsg = ServerInstance->Time();
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ return CMD_SUCCESS;
+ if (parameters[0][0] == '$')
+ {
+ if (!user->HasPrivPermission("users/mass-message"))
+ return CMD_SUCCESS;
+
+ ModResult MOD_RESULT;
+ std::string temp = parameters[1];
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreNotice, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+ const char* text = temp.c_str();
+ const char* servermask = (parameters[0].c_str()) + 1;
+
+ FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
+ if (InspIRCd::Match(ServerInstance->Config->ServerName,servermask, NULL))
+ {
+ user->SendAll("NOTICE", "%s", text);
+ }
+ FOREACH_MOD(I_OnUserNotice,OnUserNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
+ return CMD_SUCCESS;
+ }
+ char status = 0;
+ const char* target = parameters[0].c_str();
+
+ if (ServerInstance->Modes->FindPrefix(*target))
+ {
+ status = *target;
+ target++;
+ }
+ if (*target == '#')
+ {
+ chan = ServerInstance->FindChan(target);
+
+ exempt_list.insert(user);
+
+ if (chan)
+ {
+ if (IS_LOCAL(user))
+ {
+ if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
+ {
+ user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
+ return CMD_FAILURE;
+ }
+ if ((chan->IsModeSet('m')) && (chan->GetPrefixValue(user) < VOICE_VALUE))
+ {
+ user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
+ return CMD_FAILURE;
+ }
+ }
+ ModResult MOD_RESULT;
+
+ std::string temp = parameters[1];
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreNotice, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status, exempt_list));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+
+ const char* text = temp.c_str();
+
+ if (temp.empty())
+ {
+ user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,exempt_list));
+
+ if (status)
+ {
+ if (ServerInstance->Config->UndernetMsgPrefix)
+ {
+ chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%c %s", status, chan->name.c_str(), status, text);
+ }
+ else
+ {
+ chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%s", status, chan->name.c_str(), text);
+ }
+ }
+ else
+ {
+ chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name.c_str(), text);
+ }
+
+ FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,text,status,exempt_list));
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), target);
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+ }
+
+ const char* destnick = parameters[0].c_str();
+
+ if (IS_LOCAL(user))
+ {
+ const char* targetserver = strchr(destnick, '@');
+
+ if (targetserver)
+ {
+ std::string nickonly;
+
+ nickonly.assign(destnick, 0, targetserver - destnick);
+ dest = ServerInstance->FindNickOnly(nickonly);
+ if (dest && strcasecmp(dest->server, targetserver + 1))
+ {
+ /* Incorrect server for user */
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ }
+ else
+ dest = ServerInstance->FindNickOnly(destnick);
+ }
+ else
+ dest = ServerInstance->FindNick(destnick);
+
+ if (dest)
+ {
+ if (parameters[1].empty())
+ {
+ user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ ModResult MOD_RESULT;
+ std::string temp = parameters[1];
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreNotice, MOD_RESULT, (user,dest,TYPE_USER,temp,0,exempt_list));
+ if (MOD_RESULT == MOD_RES_DENY) {
+ return CMD_FAILURE;
+ }
+ const char* text = temp.c_str();
+
+ FOREACH_MOD(I_OnText,OnText(user,dest,TYPE_USER,text,0,exempt_list));
+
+ if (IS_LOCAL(dest))
+ {
+ // direct write, same server
+ user->WriteTo(dest, "NOTICE %s :%s", dest->nick.c_str(), text);
+ }
+
+ FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,text,0,exempt_list));
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+
+}
+
+COMMAND_INIT(CommandNotice)
diff --git a/src/commands/cmd_oper.cpp b/src/commands/cmd_oper.cpp
new file mode 100644
index 000000000..da53d2b1a
--- /dev/null
+++ b/src/commands/cmd_oper.cpp
@@ -0,0 +1,170 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "hashcomp.h"
+
+bool OneOfMatches(const char* host, const char* ip, const char* hostlist);
+
+/** Handle /OPER. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandOper : public Command
+{
+ public:
+ /** Constructor for oper.
+ */
+ CommandOper ( Module* parent) : Command(parent,"OPER",2,2) { syntax = "<username> <password>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+bool OneOfMatches(const char* host, const char* ip, const char* hostlist)
+{
+ std::stringstream hl(hostlist);
+ std::string xhost;
+ while (hl >> xhost)
+ {
+ if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+CmdResult CommandOper::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ char LoginName[MAXBUF];
+ char Password[MAXBUF];
+ char OperType[MAXBUF];
+ char TypeName[MAXBUF];
+ char HostName[MAXBUF];
+ char ClassName[MAXBUF];
+ char TheHost[MAXBUF];
+ char TheIP[MAXBUF];
+ char HashType[MAXBUF];
+ int j;
+ bool found = false;
+ bool type_invalid = false;
+
+ bool match_login = false;
+ bool match_pass = false;
+ bool match_hosts = false;
+
+ snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(),user->host.c_str());
+ snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString());
+
+ for (int i = 0; i < ServerInstance->Config->ConfValueEnum("oper"); i++)
+ {
+ ServerInstance->Config->ConfValue("oper", "name", i, LoginName, MAXBUF);
+ ServerInstance->Config->ConfValue("oper", "password", i, Password, MAXBUF);
+ ServerInstance->Config->ConfValue("oper", "type", i, OperType, MAXBUF);
+ ServerInstance->Config->ConfValue("oper", "host", i, HostName, MAXBUF);
+ ServerInstance->Config->ConfValue("oper", "hash", i, HashType, MAXBUF);
+
+ match_login = (LoginName == parameters[0]);
+ match_pass = !ServerInstance->PassCompare(user, Password, parameters[1], HashType);
+ match_hosts = OneOfMatches(TheHost,TheIP,HostName);
+
+ if (match_login && match_pass && match_hosts)
+ {
+ type_invalid = true;
+ for (j =0; j < ServerInstance->Config->ConfValueEnum("type"); j++)
+ {
+ ServerInstance->Config->ConfValue("type", "name", j, TypeName, MAXBUF);
+ ServerInstance->Config->ConfValue("type", "class", j, ClassName, MAXBUF);
+
+ if (!strcmp(TypeName,OperType))
+ {
+ /* found this oper's opertype */
+ if (!ServerInstance->IsNick(TypeName, ServerInstance->Config->Limits.NickMax))
+ {
+ user->WriteNumeric(491, "%s :Invalid oper type (oper types must follow the same syntax as nicknames)",user->nick.c_str());
+ ServerInstance->SNO->WriteToSnoMask('o',"CONFIGURATION ERROR! Oper type '%s' contains invalid characters",OperType);
+ ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but oper type erroneous.", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
+ return CMD_FAILURE;
+ }
+ ServerInstance->Config->ConfValue("type","host", j, HostName, MAXBUF);
+ if (*HostName)
+ user->ChangeDisplayedHost(HostName);
+ if (*ClassName)
+ {
+ user->SetClass(ClassName);
+ user->CheckClass();
+ }
+ found = true;
+ type_invalid = false;
+ break;
+ }
+ }
+ }
+ if (match_login || found)
+ break;
+ }
+ if (found)
+ {
+ /* correct oper credentials */
+ user->Oper(OperType, LoginName);
+ }
+ else
+ {
+ char broadcast[MAXBUF];
+
+ if (!type_invalid)
+ {
+ std::string fields;
+ if (!match_login)
+ fields.append("login ");
+ else
+ {
+ if (!match_pass)
+ fields.append("password ");
+ if (!match_hosts)
+ fields.append("hosts");
+ }
+
+ // tell them they suck, and lag them up to help prevent brute-force attacks
+ user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str());
+ user->IncreasePenalty(10);
+
+ snprintf(broadcast, MAXBUF, "WARNING! Failed oper attempt by %s!%s@%s using login '%s': The following fields do not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
+ ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
+ ServerInstance->PI->SendSNONotice("o", std::string("OPER: ") + broadcast);
+
+ ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': The following fields did not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
+ return CMD_FAILURE;
+ }
+ else
+ {
+ user->WriteNumeric(491, "%s :Your oper block does not have a valid opertype associated with it",user->nick.c_str());
+
+ snprintf(broadcast, MAXBUF, "CONFIGURATION ERROR! Oper block '%s': missing OperType %s",parameters[0].c_str(),OperType);
+
+ ServerInstance->SNO->WriteToSnoMask('o', std::string(broadcast));
+
+ ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': credentials valid, but oper type nonexistent.", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandOper)
diff --git a/src/commands/cmd_part.cpp b/src/commands/cmd_part.cpp
new file mode 100644
index 000000000..e2e4e59a0
--- /dev/null
+++ b/src/commands/cmd_part.cpp
@@ -0,0 +1,77 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /PART. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandPart : public Command
+{
+ public:
+ /** Constructor for part.
+ */
+ CommandPart (Module* parent) : Command(parent,"PART", 1, 2) { Penalty = 5; syntax = "<channel>{,<channel>} [<reason>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandPart::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string reason;
+
+ if (IS_LOCAL(user))
+ {
+ if (*ServerInstance->Config->FixedPart)
+ reason = ServerInstance->Config->FixedPart;
+ else
+ {
+ if (parameters.size() > 1)
+ reason = ServerInstance->Config->PrefixPart + std::string(parameters[1]) + ServerInstance->Config->SuffixPart;
+ else
+ reason = "";
+ }
+ }
+ else
+ {
+ reason = parameters.size() > 1 ? parameters[1] : "";
+ }
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ return CMD_SUCCESS;
+
+ Channel* c = ServerInstance->FindChan(parameters[0]);
+
+ if (c)
+ {
+ if (!c->PartUser(user, reason))
+ /* Arse, who stole our channel! :/ */
+ delete c;
+ }
+ else
+ {
+ user->WriteServ( "401 %s %s :No such channel", user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandPart)
diff --git a/src/commands/cmd_pass.cpp b/src/commands/cmd_pass.cpp
new file mode 100644
index 000000000..6219118ee
--- /dev/null
+++ b/src/commands/cmd_pass.cpp
@@ -0,0 +1,56 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /PASS. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandPass : public Command
+{
+ public:
+ /** Constructor for pass.
+ */
+ CommandPass ( Module* parent) : Command(parent,"PASS",1,1) { works_before_reg = true; Penalty = 0; syntax = "<password>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+CmdResult CommandPass::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ // Check to make sure they havnt registered -- Fix by FCS
+ if (user->registered == REG_ALL)
+ {
+ user->WriteNumeric(ERR_ALREADYREGISTERED, "%s :You may not reregister",user->nick.c_str());
+ return CMD_FAILURE;
+ }
+ ConnectClass* a = user->GetClass();
+ if (!a)
+ return CMD_FAILURE;
+
+ user->password.assign(parameters[0], 0, 63);
+ if (!ServerInstance->PassCompare(user, a->pass.c_str(), parameters[0].c_str(), a->hash.c_str()))
+ user->haspassed = true;
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandPass)
diff --git a/src/commands/cmd_ping.cpp b/src/commands/cmd_ping.cpp
new file mode 100644
index 000000000..e7898921a
--- /dev/null
+++ b/src/commands/cmd_ping.cpp
@@ -0,0 +1,42 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /PING. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandPing : public Command
+{
+ public:
+ /** Constructor for ping.
+ */
+ CommandPing ( Module* parent) : Command(parent,"PING", 1, 2) { Penalty = 0; syntax = "<servername> [:<servername>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandPing::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ user->WriteServ("PONG %s :%s", ServerInstance->Config->ServerName, parameters[0].c_str());
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandPing)
diff --git a/src/commands/cmd_pong.cpp b/src/commands/cmd_pong.cpp
new file mode 100644
index 000000000..225be147a
--- /dev/null
+++ b/src/commands/cmd_pong.cpp
@@ -0,0 +1,43 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /PONG. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandPong : public Command
+{
+ public:
+ /** Constructor for pong.
+ */
+ CommandPong ( Module* parent) : Command(parent,"PONG", 0, 1) { Penalty = 0; syntax = "<ping-text>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandPong::Handle (const std::vector<std::string>&, User *user)
+{
+ // set the user as alive so they survive to next ping
+ user->lastping = 1;
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandPong)
diff --git a/src/commands/cmd_privmsg.cpp b/src/commands/cmd_privmsg.cpp
new file mode 100644
index 000000000..781ad8bac
--- /dev/null
+++ b/src/commands/cmd_privmsg.cpp
@@ -0,0 +1,220 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /PRIVMSG. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandPrivmsg : public Command
+{
+ public:
+ /** Constructor for privmsg.
+ */
+ CommandPrivmsg ( Module* parent) : Command(parent,"PRIVMSG",2,2) { syntax = "<target>{,<target>} <message>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandPrivmsg::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ User *dest;
+ Channel *chan;
+ CUList except_list;
+
+ user->idle_lastmsg = ServerInstance->Time();
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ return CMD_SUCCESS;
+
+ if (parameters[0][0] == '$')
+ {
+ if (!user->HasPrivPermission("users/mass-message"))
+ return CMD_SUCCESS;
+
+ ModResult MOD_RESULT;
+ std::string temp = parameters[1];
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreMessage, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, except_list));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+
+ const char* text = temp.c_str();
+ const char* servermask = (parameters[0].c_str()) + 1;
+
+ FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list));
+ if (InspIRCd::Match(ServerInstance->Config->ServerName, servermask, NULL))
+ {
+ user->SendAll("PRIVMSG", "%s", text);
+ }
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list));
+ return CMD_SUCCESS;
+ }
+ char status = 0;
+ const char* target = parameters[0].c_str();
+
+ if (ServerInstance->Modes->FindPrefix(*target))
+ {
+ status = *target;
+ target++;
+ }
+ if (*target == '#')
+ {
+ chan = ServerInstance->FindChan(target);
+
+ except_list.insert(user);
+
+ if (chan)
+ {
+ if (IS_LOCAL(user) && chan->GetPrefixValue(user) < VOICE_VALUE)
+ {
+ if (chan->IsModeSet('n') && !chan->HasUser(user))
+ {
+ user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
+ return CMD_FAILURE;
+ }
+
+ if (chan->IsModeSet('m'))
+ {
+ user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->Config->RestrictBannedUsers)
+ {
+ if (chan->IsBanned(user))
+ {
+ user->WriteNumeric(404, "%s %s :Cannot send to channel (you're banned)", user->nick.c_str(), chan->name.c_str());
+ return CMD_FAILURE;
+ }
+ }
+ }
+ ModResult MOD_RESULT;
+
+ std::string temp = parameters[1];
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreMessage, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status,except_list));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+
+ const char* text = temp.c_str();
+
+ /* Check again, a module may have zapped the input string */
+ if (temp.empty())
+ {
+ user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,except_list));
+
+ if (status)
+ {
+ if (ServerInstance->Config->UndernetMsgPrefix)
+ {
+ chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%c %s", status, chan->name.c_str(), status, text);
+ }
+ else
+ {
+ chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%s", status, chan->name.c_str(), text);
+ }
+ }
+ else
+ {
+ chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %s :%s", chan->name.c_str(), text);
+ }
+
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,text,status,except_list));
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteNumeric(401, "%s %s :No such nick/channel", user->nick.c_str(), target);
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+ }
+
+ const char* destnick = parameters[0].c_str();
+
+ if (IS_LOCAL(user))
+ {
+ const char* targetserver = strchr(destnick, '@');
+
+ if (targetserver)
+ {
+ std::string nickonly;
+
+ nickonly.assign(destnick, 0, targetserver - destnick);
+ dest = ServerInstance->FindNickOnly(nickonly);
+ if (dest && strcasecmp(dest->server, targetserver + 1))
+ {
+ /* Incorrect server for user */
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ }
+ else
+ dest = ServerInstance->FindNickOnly(destnick);
+ }
+ else
+ dest = ServerInstance->FindNick(destnick);
+
+ if (dest)
+ {
+ if (parameters[1].empty())
+ {
+ user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ if (IS_AWAY(dest))
+ {
+ /* auto respond with aweh msg */
+ user->WriteNumeric(301, "%s %s :%s", user->nick.c_str(), dest->nick.c_str(), dest->awaymsg.c_str());
+ }
+
+ ModResult MOD_RESULT;
+
+ std::string temp = parameters[1];
+ FIRST_MOD_RESULT(ServerInstance, OnUserPreMessage, MOD_RESULT, (user, dest, TYPE_USER, temp, 0, except_list));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+
+ const char* text = temp.c_str();
+
+ FOREACH_MOD(I_OnText,OnText(user, dest, TYPE_USER, text, 0, except_list));
+
+ if (IS_LOCAL(dest))
+ {
+ // direct write, same server
+ user->WriteTo(dest, "PRIVMSG %s :%s", dest->nick.c_str(), text);
+ }
+
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, dest, TYPE_USER, text, 0, except_list));
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandPrivmsg)
diff --git a/src/commands/cmd_qline.cpp b/src/commands/cmd_qline.cpp
new file mode 100644
index 000000000..ffe8c5ee6
--- /dev/null
+++ b/src/commands/cmd_qline.cpp
@@ -0,0 +1,86 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+
+/** Handle /QLINE. */
+class CommandQline : public Command
+{
+ public:
+ /** Constructor for qline.
+ */
+ CommandQline ( Module* parent) : Command(parent,"QLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = "<nick> [<duration> :<reason>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to the command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+CmdResult CommandQline::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ if (parameters.size() >= 3)
+ {
+ if (ServerInstance->NickMatchesEveryone(parameters[0],user))
+ return CMD_FAILURE;
+
+ if (parameters[0].find('@') != std::string::npos || parameters[0].find('!') != std::string::npos || parameters[0].find('.') != std::string::npos)
+ {
+ user->WriteServ("NOTICE %s :*** A Q-Line only bans a nick pattern, not a nick!user@host pattern.",user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ long duration = ServerInstance->Duration(parameters[1].c_str());
+ QLine* ql = new QLine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
+ if (ServerInstance->XLines->AddLine(ql,user))
+ {
+ if (!duration)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Q-line for %s: %s",user->nick.c_str(), parameters[0].c_str(), parameters[2].c_str());
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Q-line for %s, expires on %s: %s",user->nick.c_str(),parameters[0].c_str(),
+ ServerInstance->TimeString(c_requires_crap).c_str(), parameters[2].c_str());
+ }
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
+ {
+ delete ql;
+ user->WriteServ("NOTICE %s :*** Q-Line for %s already exists",user->nick.c_str(),parameters[0].c_str());
+ }
+ }
+ else
+ {
+ if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "Q", user))
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s removed Q-line on %s",user->nick.c_str(),parameters[0].c_str());
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** Q-Line %s not found in list, try /stats q.",user->nick.c_str(),parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandQline)
diff --git a/src/commands/cmd_quit.cpp b/src/commands/cmd_quit.cpp
new file mode 100644
index 000000000..d041fc031
--- /dev/null
+++ b/src/commands/cmd_quit.cpp
@@ -0,0 +1,68 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /QUIT. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandQuit : public Command
+{
+ public:
+ /** Constructor for quit.
+ */
+ CommandQuit ( Module* parent) : Command(parent,"QUIT",0,1) { works_before_reg = true; syntax = "[<message>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+CmdResult CommandQuit::Handle (const std::vector<std::string>& parameters, User *user)
+{
+
+ std::string quitmsg;
+
+ if (IS_LOCAL(user))
+ {
+ if (*ServerInstance->Config->FixedQuit)
+ quitmsg = ServerInstance->Config->FixedQuit;
+ else
+ quitmsg = parameters.size() ?
+ ServerInstance->Config->PrefixQuit + std::string(parameters[0]) + ServerInstance->Config->SuffixQuit
+ : "Client exited";
+ }
+ else
+ quitmsg = parameters.size() ? parameters[0] : "Client exited";
+
+ std::string* operquit = User::OperQuit.get(user);
+ if (operquit)
+ {
+ ServerInstance->Users->QuitUser(user, quitmsg, operquit->c_str());
+ }
+ else
+ {
+ ServerInstance->Users->QuitUser(user, quitmsg);
+ }
+
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandQuit)
diff --git a/src/commands/cmd_rehash.cpp b/src/commands/cmd_rehash.cpp
new file mode 100644
index 000000000..a689801aa
--- /dev/null
+++ b/src/commands/cmd_rehash.cpp
@@ -0,0 +1,109 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+/** Handle /REHASH. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandRehash : public Command
+{
+ public:
+ /** Constructor for rehash.
+ */
+ CommandRehash ( Module* parent) : Command(parent,"REHASH",0) { flags_needed = 'o'; Penalty = 2; syntax = "[<servermask>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandRehash::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string param = parameters.size() ? parameters[0] : "";
+
+ FOREACH_MOD(I_OnPreRehash,OnPreRehash(user, param));
+
+ if (param.empty())
+ {
+ // standard rehash of local server
+ }
+ else if (param.find_first_of("*.") != std::string::npos)
+ {
+ // rehash of servers by server name (with wildcard)
+ if (!InspIRCd::Match(ServerInstance->Config->ServerName, parameters[0]))
+ {
+ // Doesn't match us. PreRehash is already done, nothing left to do
+ return CMD_SUCCESS;
+ }
+ }
+ else
+ {
+ // parameterized rehash
+
+ // the leading "-" is optional; remove it if present.
+ if (param[0] == '-')
+ param = param.substr(1);
+
+ FOREACH_MOD(I_OnModuleRehash,OnModuleRehash(user, param));
+ return CMD_SUCCESS;
+ }
+
+ // Rehash for me. Try to start the rehash thread
+ if (!ServerInstance->ConfigThread)
+ {
+ std::string m = user->nick + " is rehashing config file " + ServerConfig::CleanFilename(ServerInstance->ConfigFileName) + " on " + ServerInstance->Config->ServerName;
+ ServerInstance->SNO->WriteGlobalSno('a', m);
+
+ if (IS_LOCAL(user))
+ user->WriteNumeric(RPL_REHASHING, "%s %s :Rehashing",
+ user->nick.c_str(),ServerConfig::CleanFilename(ServerInstance->ConfigFileName));
+ else
+ ServerInstance->PI->SendUserNotice(user, std::string("*** Rehashing server ") +
+ ServerConfig::CleanFilename(ServerInstance->ConfigFileName));
+
+ /* Don't do anything with the logs here -- logs are restarted
+ * after the config thread has completed.
+ */
+
+ ServerInstance->RehashUsersAndChans();
+ FOREACH_MOD(I_OnGarbageCollect, OnGarbageCollect());
+
+
+ ServerInstance->ConfigThread = new ConfigReaderThread(ServerInstance, user->uuid);
+ ServerInstance->Threads->Start(ServerInstance->ConfigThread);
+
+ return CMD_SUCCESS;
+ }
+ else
+ {
+ /*
+ * A rehash is already in progress! ahh shit.
+ * XXX, todo: we should find some way to kill runaway rehashes that are blocking, this is a major problem for unrealircd users
+ */
+ if (IS_LOCAL(user))
+ user->WriteServ("NOTICE %s :*** Could not rehash: A rehash is already in progress.", user->nick.c_str());
+ else
+ ServerInstance->PI->SendUserNotice(user, "*** Could not rehash: A rehash is already in progress.");
+
+ return CMD_FAILURE;
+ }
+}
+
+
+COMMAND_INIT(CommandRehash)
diff --git a/src/commands/cmd_reloadmodule.cpp b/src/commands/cmd_reloadmodule.cpp
new file mode 100644
index 000000000..3e3a3a617
--- /dev/null
+++ b/src/commands/cmd_reloadmodule.cpp
@@ -0,0 +1,56 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+class CommandReloadmodule : public Command
+{
+ public:
+ /** Constructor for reloadmodule.
+ */
+ CommandReloadmodule ( Module* parent) : Command( parent, "RELOADMODULE",1) { flags_needed = 'o'; syntax = "<modulename>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandReloadmodule::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ if (parameters[0] == "cmd_reloadmodule.so")
+ {
+ user->WriteNumeric(975, "%s %s :You cannot reload cmd_reloadmodule.so (unload and load it)",
+ user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->Modules->Unload(parameters[0].c_str()))
+ {
+ ServerInstance->SNO->WriteToSnoMask('a', "RELOAD MODULE: %s unloaded %s",user->nick.c_str(), parameters[0].c_str());
+ if (ServerInstance->Modules->Load(parameters[0].c_str()))
+ {
+ ServerInstance->SNO->WriteToSnoMask('a', "RELOAD MODULE: %s reloaded %s",user->nick.c_str(), parameters[0].c_str());
+ user->WriteNumeric(975, "%s %s :Module successfully reloaded.",user->nick.c_str(), parameters[0].c_str());
+ return CMD_SUCCESS;
+ }
+ }
+
+ ServerInstance->SNO->WriteToSnoMask('a', "RELOAD MODULE: %s unsuccessfully reloaded %s",user->nick.c_str(), parameters[0].c_str());
+ user->WriteNumeric(975, "%s %s :%s",user->nick.c_str(), parameters[0].c_str(), ServerInstance->Modules->LastError().c_str());
+ return CMD_FAILURE;
+}
+
+COMMAND_INIT(CommandReloadmodule)
diff --git a/src/commands/cmd_restart.cpp b/src/commands/cmd_restart.cpp
new file mode 100644
index 000000000..e83f3f381
--- /dev/null
+++ b/src/commands/cmd_restart.cpp
@@ -0,0 +1,60 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /RESTART
+ */
+class CommandRestart : public Command
+{
+ public:
+ /** Constructor for restart.
+ */
+ CommandRestart(Module* parent) : Command(parent,"RESTART",1,1) { flags_needed = 'o'; syntax = "<password>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandRestart::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ ServerInstance->Logs->Log("COMMAND",DEFAULT,"Restart: %s",user->nick.c_str());
+ if (!ServerInstance->PassCompare(user, ServerInstance->Config->restartpass, parameters[0].c_str(), ServerInstance->Config->powerhash))
+ {
+ ServerInstance->SNO->WriteGlobalSno('a', "RESTART command from %s!%s@%s, restarting server.", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
+
+ try
+ {
+ ServerInstance->Restart("Server restarting.");
+ }
+ catch (...)
+ {
+ /* We dont actually get here unless theres some fatal and unrecoverable error. */
+ exit(0);
+ }
+ }
+ else
+ {
+ ServerInstance->SNO->WriteGlobalSno('a', "Failed RESTART Command from %s!%s@%s.", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandRestart)
diff --git a/src/commands/cmd_rules.cpp b/src/commands/cmd_rules.cpp
new file mode 100644
index 000000000..3cc5c15f4
--- /dev/null
+++ b/src/commands/cmd_rules.cpp
@@ -0,0 +1,56 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_RULES_H__
+#define __CMD_RULES_H__
+
+// include the common header files
+
+#include <string>
+#include <vector>
+#include "inspircd.h"
+#include "users.h"
+#include "channels.h"
+
+/** Handle /RULES. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandRules : public Command
+{
+ public:
+ /** Constructor for rules.
+ */
+ CommandRules ( Module* parent) : Command(parent,"RULES",0,0) { syntax = "[<servername>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+CmdResult CommandRules::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ user->ShowRULES();
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandRules)
diff --git a/src/commands/cmd_server.cpp b/src/commands/cmd_server.cpp
new file mode 100644
index 000000000..e5a7622b8
--- /dev/null
+++ b/src/commands/cmd_server.cpp
@@ -0,0 +1,49 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /SERVER. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandServer : public Command
+{
+ public:
+ /** Constructor for server.
+ */
+ CommandServer ( Module* parent) : Command(parent,"SERVER") { works_before_reg = true;}
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandServer::Handle (const std::vector<std::string>&, User *user)
+{
+ if (user->registered == REG_ALL)
+ {
+ user->WriteNumeric(ERR_ALREADYREGISTERED, "%s :You are already registered. (Perhaps your IRC client does not have a /SERVER command).",user->nick.c_str());
+ }
+ else
+ {
+ user->WriteNumeric(ERR_NOTREGISTERED, "%s :You may not register as a server (servers have seperate ports from clients, change your config)",command.c_str());
+ }
+ return CMD_FAILURE;
+}
+
+COMMAND_INIT(CommandServer)
diff --git a/src/commands/cmd_squit.cpp b/src/commands/cmd_squit.cpp
new file mode 100644
index 000000000..f742dd964
--- /dev/null
+++ b/src/commands/cmd_squit.cpp
@@ -0,0 +1,48 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /SQUIT. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandSquit : public Command
+{
+ public:
+ /** Constructor for squit.
+ */
+ CommandSquit ( Module* parent) : Command(parent,"SQUIT",1,2) { flags_needed = 'o'; syntax = "<servername> [<reason>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+/*
+ * This is handled by the server linking module, if necessary. Do not remove this stub.
+ */
+
+
+CmdResult CommandSquit::Handle (const std::vector<std::string>&, User *user)
+{
+ user->WriteServ( "NOTICE %s :Look into loading a linking module (like m_spanningtree) if you want this to do anything useful.", user->nick.c_str());
+ return CMD_FAILURE;
+}
+
+COMMAND_INIT(CommandSquit)
diff --git a/src/commands/cmd_stats.cpp b/src/commands/cmd_stats.cpp
new file mode 100644
index 000000000..7ffa4a93c
--- /dev/null
+++ b/src/commands/cmd_stats.cpp
@@ -0,0 +1,68 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#ifndef WIN32
+ #include <sys/resource.h>
+ /* This is just to be completely certain that the change which fixed getrusage on RH7 doesn't break anything else -- Om */
+ #ifndef RUSAGE_SELF
+ #define RUSAGE_SELF 0
+ #endif
+#else
+ #include <psapi.h>
+ #include "inspircd_win32wrapper.h"
+ #pragma comment(lib, "psapi.lib")
+#endif
+
+#include "xline.h"
+
+/** Handle /STATS. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandStats : public Command
+{
+ public:
+ /** Constructor for stats.
+ */
+ CommandStats ( Module* parent) : Command(parent,"STATS",1,2) { syntax = "<stats-symbol> [<servername>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandStats::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ if (IS_LOCAL(user))
+ {
+ string_list values;
+ if (parameters[0].empty())
+ {
+ user->WriteNumeric(ERR_NEEDMOREPARAMS, "%s STATS :Not enough parameters.", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+ char search = parameters[0][0];
+ ServerInstance->DoStats(search, user, values);
+ for (size_t i = 0; i < values.size(); i++)
+ user->Write(":%s", values[i].c_str());
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandStats)
diff --git a/src/commands/cmd_time.cpp b/src/commands/cmd_time.cpp
new file mode 100644
index 000000000..8ff588c2d
--- /dev/null
+++ b/src/commands/cmd_time.cpp
@@ -0,0 +1,65 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_TIME_H__
+#define __CMD_TIME_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /TIME. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandTime : public Command
+{
+ public:
+ /** Constructor for time.
+ */
+ CommandTime ( Module* parent) : Command(parent,"TIME",0,0) { syntax = "[<servername>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+
+
+CmdResult CommandTime::Handle (const std::vector<std::string>&, User *user)
+{
+ struct tm* timeinfo;
+ time_t local = ServerInstance->Time();
+
+ timeinfo = localtime(&local);
+
+ char tms[26];
+ snprintf(tms,26,"%s",asctime(timeinfo));
+ tms[24] = 0;
+
+ user->WriteNumeric(RPL_TIME, "%s %s :%s",user->nick.c_str(),ServerInstance->Config->ServerName,tms);
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandTime)
diff --git a/src/commands/cmd_topic.cpp b/src/commands/cmd_topic.cpp
new file mode 100644
index 000000000..e0fa79d1c
--- /dev/null
+++ b/src/commands/cmd_topic.cpp
@@ -0,0 +1,79 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /TOPIC. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandTopic : public Command
+{
+ public:
+ /** Constructor for topic.
+ */
+ CommandTopic ( Module* parent) : Command(parent,"TOPIC",1, 2) { syntax = "<channel> [<topic>]"; Penalty = 2; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandTopic::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ Channel* c;
+
+ c = ServerInstance->FindChan(parameters[0]);
+ if (!c)
+ {
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
+ if (parameters.size() == 1)
+ {
+ if (c)
+ {
+ if ((c->IsModeSet('s')) && (!c->HasUser(user)))
+ {
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), c->name.c_str());
+ return CMD_FAILURE;
+ }
+
+ if (c->topic.length())
+ {
+ user->WriteNumeric(332, "%s %s :%s", user->nick.c_str(), c->name.c_str(), c->topic.c_str());
+ user->WriteNumeric(333, "%s %s %s %lu", user->nick.c_str(), c->name.c_str(), c->setby.c_str(), (unsigned long)c->topicset);
+ }
+ else
+ {
+ user->WriteNumeric(RPL_NOTOPICSET, "%s %s :No topic is set.", user->nick.c_str(), c->name.c_str());
+ }
+ }
+ return CMD_SUCCESS;
+ }
+ else if (parameters.size()>1)
+ {
+ std::string t = parameters[1]; // needed, in case a module wants to change it
+ c->SetTopic(user, t);
+ }
+
+ return CMD_SUCCESS;
+}
+
+
+COMMAND_INIT(CommandTopic)
diff --git a/src/commands/cmd_unloadmodule.cpp b/src/commands/cmd_unloadmodule.cpp
new file mode 100644
index 000000000..bdc516aac
--- /dev/null
+++ b/src/commands/cmd_unloadmodule.cpp
@@ -0,0 +1,58 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /UNLOADMODULE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandUnloadmodule : public Command
+{
+ public:
+ /** Constructor for unloadmodule.
+ */
+ CommandUnloadmodule ( Module* parent) : Command(parent,"UNLOADMODULE",1) { flags_needed = 'o'; syntax = "<modulename>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandUnloadmodule::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ if (parameters[0] == "cmd_unloadmodule.so" || parameters[0] == "cmd_loadmodule.so")
+ {
+ user->WriteNumeric(972, "%s %s :You cannot unload module loading commands!", user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->Modules->Unload(parameters[0].c_str()))
+ {
+ ServerInstance->SNO->WriteToSnoMask('a', "MODULE UNLOADED: %s unloaded %s", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNumeric(973, "%s %s :Module successfully unloaded.",user->nick.c_str(), parameters[0].c_str());
+ }
+ else
+ {
+ user->WriteNumeric(972, "%s %s :%s",user->nick.c_str(), parameters[0].c_str(), ServerInstance->Modules->LastError().c_str());
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandUnloadmodule)
diff --git a/src/commands/cmd_user.cpp b/src/commands/cmd_user.cpp
new file mode 100644
index 000000000..e2f81f33c
--- /dev/null
+++ b/src/commands/cmd_user.cpp
@@ -0,0 +1,83 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /USER. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandUser : public Command
+{
+ public:
+ /** Constructor for user.
+ */
+ CommandUser ( Module* parent) : Command(parent,"USER",4,4) { works_before_reg = true; Penalty = 0; syntax = "<username> <localhost> <remotehost> <GECOS>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandUser::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ /* A user may only send the USER command once */
+ if (!(user->registered & REG_USER))
+ {
+ if (!ServerInstance->IsIdent(parameters[0].c_str()))
+ {
+ /*
+ * RFC says we must use this numeric, so we do. Let's make it a little more nub friendly though. :)
+ * -- Craig, and then w00t.
+ */
+ user->WriteNumeric(461, "%s USER :Your username is not valid",user->nick.c_str());
+ return CMD_FAILURE;
+ }
+ else
+ {
+ /*
+ * The ident field is IDENTMAX+2 in size to account for +1 for the optional
+ * ~ character, and +1 for null termination, therefore we can safely use up to
+ * IDENTMAX here.
+ */
+ user->ChangeIdent(parameters[0].c_str());
+ user->fullname.assign(parameters[3].empty() ? std::string("No info") : parameters[3], 0, ServerInstance->Config->Limits.MaxGecos);
+ user->registered = (user->registered | REG_USER);
+ }
+ }
+ else
+ {
+ user->WriteNumeric(462, "%s :You may not reregister", user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ /* parameters 2 and 3 are local and remote hosts, and are ignored */
+ if (user->registered == REG_NICKUSER)
+ {
+ ModResult MOD_RESULT;
+
+ /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
+ FIRST_MOD_RESULT(ServerInstance, OnUserRegister, MOD_RESULT, (user));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return CMD_FAILURE;
+
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandUser)
diff --git a/src/commands/cmd_userhost.cpp b/src/commands/cmd_userhost.cpp
new file mode 100644
index 000000000..2833d56ba
--- /dev/null
+++ b/src/commands/cmd_userhost.cpp
@@ -0,0 +1,93 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_USERHOST_H__
+#define __CMD_USERHOST_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /USERHOST. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandUserhost : public Command
+{
+ public:
+ /** Constructor for userhost.
+ */
+ CommandUserhost ( Module* parent) : Command(parent,"USERHOST",0,1) { syntax = "<nick>{,<nick>}"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+CmdResult CommandUserhost::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string retbuf = std::string("302 ") + user->nick + " :";
+
+ for (unsigned int i = 0; i < parameters.size(); i++)
+ {
+ User *u = ServerInstance->FindNick(parameters[i]);
+
+ if ((u) && (u->registered == REG_ALL))
+ {
+ retbuf = retbuf + u->nick;
+
+ if (IS_OPER(u))
+ {
+ retbuf = retbuf + "*=";
+ }
+ else
+ {
+ retbuf = retbuf + "=";
+ }
+
+ if (IS_AWAY(u))
+ retbuf += "-";
+ else
+ retbuf += "+";
+
+ retbuf = retbuf + u->ident + "@";
+
+ if (user->HasPrivPermission("users/auspex"))
+ {
+ retbuf = retbuf + u->host;
+ }
+ else
+ {
+ retbuf = retbuf + u->dhost;
+ }
+
+ retbuf = retbuf + " ";
+ }
+ }
+
+ user->WriteServ(retbuf);
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandUserhost)
diff --git a/src/commands/cmd_version.cpp b/src/commands/cmd_version.cpp
new file mode 100644
index 000000000..bfe82d4d9
--- /dev/null
+++ b/src/commands/cmd_version.cpp
@@ -0,0 +1,56 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_VERSION_H__
+#define __CMD_VERSION_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /VERSION. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandVersion : public Command
+{
+ public:
+ /** Constructor for version.
+ */
+ CommandVersion ( Module* parent) : Command(parent,"VERSION",0,0) { syntax = "[<servername>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+
+
+CmdResult CommandVersion::Handle (const std::vector<std::string>&, User *user)
+{
+ user->WriteNumeric(RPL_VERSION, "%s :%s",user->nick.c_str(),ServerInstance->GetVersionString().c_str());
+ ServerInstance->Config->Send005(user);
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandVersion)
diff --git a/src/commands/cmd_wallops.cpp b/src/commands/cmd_wallops.cpp
new file mode 100644
index 000000000..7894419c1
--- /dev/null
+++ b/src/commands/cmd_wallops.cpp
@@ -0,0 +1,56 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+#ifndef __CMD_WALLOPS_H__
+#define __CMD_WALLOPS_H__
+
+// include the common header files
+
+#include "users.h"
+#include "channels.h"
+
+/** Handle /WALLOPS. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandWallops : public Command
+{
+ public:
+ /** Constructor for wallops.
+ */
+ CommandWallops ( Module* parent) : Command(parent,"WALLOPS",1,1) { flags_needed = 'o'; syntax = "<any-text>"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+#endif
+
+
+
+
+CmdResult CommandWallops::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ user->WriteWallOps(std::string(parameters[0]));
+ FOREACH_MOD(I_OnWallops,OnWallops(user,parameters[0]));
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandWallops)
diff --git a/src/commands/cmd_who.cpp b/src/commands/cmd_who.cpp
new file mode 100644
index 000000000..89ca60d02
--- /dev/null
+++ b/src/commands/cmd_who.cpp
@@ -0,0 +1,403 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /WHO. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandWho : public Command
+{
+ bool CanView(Channel* chan, User* user);
+ bool opt_viewopersonly;
+ bool opt_showrealhost;
+ bool opt_unlimit;
+ bool opt_realname;
+ bool opt_mode;
+ bool opt_ident;
+ bool opt_metadata;
+ bool opt_port;
+ bool opt_away;
+ bool opt_local;
+ bool opt_far;
+ bool opt_time;
+
+ public:
+ /** Constructor for who.
+ */
+ CommandWho ( Module* parent) : Command(parent,"WHO", 1) { Penalty = 2; syntax = "<server>|<nickname>|<channel>|<realname>|<host>|0 [ohurmMiaplf]"; }
+ void SendWhoLine(User* user, const std::string &initial, Channel* ch, User* u, std::vector<std::string> &whoresults);
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+ bool whomatch(User* cuser, User* user, const char* matchtext);
+};
+
+
+static const std::string star = "*";
+
+static const std::string& get_first_visible_channel(User *u)
+{
+ UCListIter i = u->chans.begin();
+ while (i != u->chans.end())
+ {
+ Channel* c = *i++;
+ if (!c->IsModeSet('s'))
+ return c->name;
+ }
+
+ return star;
+}
+
+bool CommandWho::whomatch(User* cuser, User* user, const char* matchtext)
+{
+ bool match = false;
+ bool positive = false;
+
+ if (user->registered != REG_ALL)
+ return false;
+
+ if (opt_local && !IS_LOCAL(user))
+ return false;
+ else if (opt_far && IS_LOCAL(user))
+ return false;
+
+ if (opt_mode)
+ {
+ for (const char* n = matchtext; *n; n++)
+ {
+ if (*n == '+')
+ {
+ positive = true;
+ continue;
+ }
+ else if (*n == '-')
+ {
+ positive = false;
+ continue;
+ }
+ if (user->IsModeSet(*n) != positive)
+ return false;
+ }
+ return true;
+ }
+ else
+ {
+ /*
+ * This was previously one awesome pile of ugly nested if, when really, it didn't need
+ * to be, since only one condition was ever checked, a chained if works just fine.
+ * -- w00t
+ */
+ if (opt_metadata)
+ match = user->GetExtList().find(matchtext) != user->GetExtList().end();
+ else if (opt_realname)
+ match = InspIRCd::Match(user->fullname, matchtext);
+ else if (opt_showrealhost)
+ match = InspIRCd::Match(user->host, matchtext, ascii_case_insensitive_map);
+ else if (opt_ident)
+ match = InspIRCd::Match(user->ident, matchtext, ascii_case_insensitive_map);
+ else if (opt_port)
+ {
+ irc::portparser portrange(matchtext, false);
+ long portno = -1;
+ while ((portno = portrange.GetToken()))
+ if (portno == user->GetServerPort())
+ {
+ match = true;
+ break;
+ }
+ }
+ else if (opt_away)
+ match = InspIRCd::Match(user->awaymsg, matchtext);
+ else if (opt_time)
+ {
+ long seconds = ServerInstance->Duration(matchtext);
+
+ // Okay, so time matching, we want all users connected `seconds' ago
+ if (user->age >= ServerInstance->Time() - seconds)
+ match = true;
+ }
+
+ /*
+ * Once the conditionals have been checked, only check dhost/nick/server
+ * if they didn't match this user -- and only match if we don't find a match.
+ *
+ * This should make things minutely faster, and again, less ugly.
+ * -- w00t
+ */
+ if (!match)
+ match = InspIRCd::Match(user->dhost, matchtext, ascii_case_insensitive_map);
+
+ if (!match)
+ match = InspIRCd::Match(user->nick, matchtext);
+
+ /* Don't allow server name matches if HideWhoisServer is enabled, unless the command user has the priv */
+ if (!match && (!*ServerInstance->Config->HideWhoisServer || cuser->HasPrivPermission("users/auspex")))
+ match = InspIRCd::Match(user->server, matchtext);
+
+ return match;
+ }
+}
+
+
+
+bool CommandWho::CanView(Channel* chan, User* user)
+{
+ if (!user || !chan)
+ return false;
+
+ /* Bug #383 - moved higher up the list, because if we are in the channel
+ * we can see all its users
+ */
+ if (chan->HasUser(user))
+ return true;
+ /* Opers see all */
+ if (user->HasPrivPermission("users/auspex"))
+ return true;
+ /* Cant see inside a +s or a +p channel unless we are a member (see above) */
+ else if (!chan->IsModeSet('s') && !chan->IsModeSet('p'))
+ return true;
+
+ return false;
+}
+
+void CommandWho::SendWhoLine(User* user, const std::string &initial, Channel* ch, User* u, std::vector<std::string> &whoresults)
+{
+ const std::string& lcn = get_first_visible_channel(u);
+ Channel* chlast = ServerInstance->FindChan(lcn);
+
+ std::string wholine = initial + (ch ? ch->name : lcn) + " " + u->ident + " " + (opt_showrealhost ? u->host : u->dhost) + " " +
+ ((*ServerInstance->Config->HideWhoisServer && !user->HasPrivPermission("servers/auspex")) ? ServerInstance->Config->HideWhoisServer : u->server) +
+ " " + u->nick + " ";
+
+ /* away? */
+ if (IS_AWAY(u))
+ {
+ wholine.append("G");
+ }
+ else
+ {
+ wholine.append("H");
+ }
+
+ /* oper? */
+ if (IS_OPER(u))
+ {
+ wholine.append("*");
+ }
+
+ wholine = wholine + (ch ? ch->GetPrefixChar(u) : (chlast ? chlast->GetPrefixChar(u) : "")) + " :0 " + u->fullname;
+
+ FOREACH_MOD(I_OnSendWhoLine, OnSendWhoLine(user, u, ch, wholine));
+
+ if (!wholine.empty())
+ whoresults.push_back(wholine);
+}
+
+CmdResult CommandWho::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ /*
+ * XXX - RFC says:
+ * The <name> passed to WHO is matched against users' host, server, real
+ * name and nickname
+ * Currently, we support WHO #chan, WHO nick, WHO 0, WHO *, and the addition of a 'o' flag, as per RFC.
+ */
+
+ /* WHO options */
+ opt_viewopersonly = false;
+ opt_showrealhost = false;
+ opt_unlimit = false;
+ opt_realname = false;
+ opt_mode = false;
+ opt_ident = false;
+ opt_metadata = false;
+ opt_port = false;
+ opt_away = false;
+ opt_local = false;
+ opt_far = false;
+ opt_time = false;
+
+ Channel *ch = NULL;
+ std::vector<std::string> whoresults;
+ std::string initial = "352 " + std::string(user->nick) + " ";
+
+ char matchtext[MAXBUF];
+ bool usingwildcards = false;
+
+ /* Change '0' into '*' so the wildcard matcher can grok it */
+ if (parameters[0] == "0")
+ strlcpy(matchtext, "*", MAXBUF);
+ else
+ strlcpy(matchtext, parameters[0].c_str(), MAXBUF);
+
+ for (const char* check = matchtext; *check; check++)
+ {
+ if (*check == '*' || *check == '?')
+ {
+ usingwildcards = true;
+ break;
+ }
+ }
+
+ if (ServerInstance->FindServerName(matchtext))
+ usingwildcards = true;
+
+ if (parameters.size() > 1)
+ {
+ /* Fix for bug #444, WHO flags count as a wildcard */
+ usingwildcards = true;
+
+ for (std::string::const_iterator iter = parameters[1].begin(); iter != parameters[1].end(); ++iter)
+ {
+ switch (*iter)
+ {
+ case 'o':
+ opt_viewopersonly = true;
+ break;
+ case 'h':
+ if (user->HasPrivPermission("users/auspex"))
+ opt_showrealhost = true;
+ break;
+ case 'u':
+ if (user->HasPrivPermission("users/auspex"))
+ opt_unlimit = true;
+ break;
+ case 'r':
+ opt_realname = true;
+ break;
+ case 'm':
+ if (user->HasPrivPermission("users/auspex"))
+ opt_mode = true;
+ break;
+ case 'M':
+ if (user->HasPrivPermission("users/auspex"))
+ opt_metadata = true;
+ break;
+ case 'i':
+ opt_ident = true;
+ break;
+ case 'p':
+ if (user->HasPrivPermission("users/auspex"))
+ opt_port = true;
+ break;
+ case 'a':
+ opt_away = true;
+ break;
+ case 'l':
+ if (user->HasPrivPermission("users/auspex") || !*ServerInstance->Config->HideWhoisServer)
+ opt_local = true;
+ break;
+ case 'f':
+ if (user->HasPrivPermission("users/auspex") || !*ServerInstance->Config->HideWhoisServer)
+ opt_far = true;
+ break;
+ case 't':
+ opt_time = true;
+ break;
+ }
+ }
+ }
+
+
+ /* who on a channel? */
+ ch = ServerInstance->FindChan(matchtext);
+
+ if (ch)
+ {
+ if (CanView(ch,user))
+ {
+ bool inside = ch->HasUser(user);
+
+ /* who on a channel. */
+ const UserMembList *cu = ch->GetUsers();
+
+ for (UserMembCIter i = cu->begin(); i != cu->end(); i++)
+ {
+ /* None of this applies if we WHO ourselves */
+ if (user != i->first)
+ {
+ /* opers only, please */
+ if (opt_viewopersonly && !IS_OPER(i->first))
+ continue;
+
+ /* If we're not inside the channel, hide +i users */
+ if (i->first->IsModeSet('i') && !inside && !user->HasPrivPermission("users/auspex"))
+ continue;
+ }
+
+ SendWhoLine(user, initial, ch, i->first, whoresults);
+ }
+ }
+ }
+ else
+ {
+ /* Match against wildcard of nick, server or host */
+ if (opt_viewopersonly)
+ {
+ /* Showing only opers */
+ for (std::list<User*>::iterator i = ServerInstance->Users->all_opers.begin(); i != ServerInstance->Users->all_opers.end(); i++)
+ {
+ User* oper = *i;
+
+ if (whomatch(user, oper, matchtext))
+ {
+ if (!user->SharesChannelWith(oper))
+ {
+ if (usingwildcards && (!oper->IsModeSet('i')) && (!user->HasPrivPermission("users/auspex")))
+ continue;
+ }
+
+ SendWhoLine(user, initial, NULL, oper, whoresults);
+ }
+ }
+ }
+ else
+ {
+ for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++)
+ {
+ if (whomatch(user, i->second, matchtext))
+ {
+ if (!user->SharesChannelWith(i->second))
+ {
+ if (usingwildcards && (i->second->IsModeSet('i')) && (!user->HasPrivPermission("users/auspex")))
+ continue;
+ }
+
+ SendWhoLine(user, initial, NULL, i->second, whoresults);
+ }
+ }
+ }
+ }
+ /* Send the results out */
+ if ((ServerInstance->Config->MaxWhoResults && (whoresults.size() <= (size_t)ServerInstance->Config->MaxWhoResults)) || opt_unlimit)
+ {
+ for (std::vector<std::string>::const_iterator n = whoresults.begin(); n != whoresults.end(); n++)
+ user->WriteServ(*n);
+ user->WriteNumeric(315, "%s %s :End of /WHO list.",user->nick.c_str(), *parameters[0].c_str() ? parameters[0].c_str() : "*");
+ return CMD_SUCCESS;
+ }
+ else
+ {
+ /* BZZT! Too many results. */
+ user->WriteNumeric(315, "%s %s :Too many results",user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+}
+
+COMMAND_INIT(CommandWho)
diff --git a/src/commands/cmd_whois.cpp b/src/commands/cmd_whois.cpp
new file mode 100644
index 000000000..972b0439e
--- /dev/null
+++ b/src/commands/cmd_whois.cpp
@@ -0,0 +1,90 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/** Handle /WHOIS. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandWhois : public Command
+{
+ public:
+ /** Constructor for whois.
+ */
+ CommandWhois ( Module* parent) : Command(parent,"WHOIS",1) { Penalty = 2; syntax = "<nick>{,<nick>}"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+
+CmdResult CommandWhois::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ User *dest;
+ int userindex = 0;
+ unsigned long idle = 0, signon = 0;
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
+ return CMD_SUCCESS;
+
+
+ /*
+ * If 2 paramters are specified (/whois nick nick), ignore the first one like spanningtree
+ * does, and use the second one, otherwise, use the only paramter. -- djGrrr
+ */
+ if (parameters.size() > 1)
+ userindex = 1;
+
+ if (IS_LOCAL(user))
+ dest = ServerInstance->FindNickOnly(parameters[userindex]);
+ else
+ dest = ServerInstance->FindNick(parameters[userindex]);
+
+ if (dest)
+ {
+ /*
+ * Okay. Umpteenth attempt at doing this, so let's re-comment...
+ * For local users (/w localuser), we show idletime if hidewhois is disabled
+ * For local users (/w localuser localuser), we always show idletime, hence parameters.size() > 1 check.
+ * For remote users (/w remoteuser), we do NOT show idletime
+ * For remote users (/w remoteuser remoteuser), spanningtree will handle calling do_whois, so we can ignore this case.
+ * Thanks to djGrrr for not being impatient while I have a crap day coding. :p -- w00t
+ */
+ if (IS_LOCAL(dest) && (!*ServerInstance->Config->HideWhoisServer || parameters.size() > 1))
+ {
+ idle = abs((long)((dest->idle_lastmsg)-ServerInstance->Time()));
+ signon = dest->signon;
+ }
+
+ ServerInstance->DoWhois(user,dest,signon,idle,parameters[userindex].c_str());
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), !parameters[userindex].empty() ? parameters[userindex].c_str() : "*");
+ user->WriteNumeric(318, "%s %s :End of /WHOIS list.",user->nick.c_str(), parameters[userindex].empty() ? parameters[userindex].c_str() : "*");
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
+
+
+
+COMMAND_INIT(CommandWhois)
diff --git a/src/commands/cmd_whowas.cpp b/src/commands/cmd_whowas.cpp
new file mode 100644
index 000000000..78a7e7544
--- /dev/null
+++ b/src/commands/cmd_whowas.cpp
@@ -0,0 +1,344 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_whowas.h"
+
+WhoWasMaintainTimer * timer;
+
+CommandWhowas::CommandWhowas( Module* parent) : Command(parent, "WHOWAS", 1)
+{
+ syntax = "<nick>{,<nick>}";
+ Penalty = 2;
+ timer = new WhoWasMaintainTimer(ServerInstance, 3600);
+ ServerInstance->Timers->AddTimer(timer);
+}
+
+CmdResult CommandWhowas::Handle (const std::vector<std::string>& parameters, User* user)
+{
+ /* if whowas disabled in config */
+ if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
+ {
+ user->WriteNumeric(421, "%s %s :This command has been disabled.",user->nick.c_str(),command.c_str());
+ return CMD_FAILURE;
+ }
+
+ whowas_users::iterator i = whowas.find(assign(parameters[0]));
+
+ if (i == whowas.end())
+ {
+ user->WriteNumeric(406, "%s %s :There was no such nickname",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNumeric(369, "%s %s :End of WHOWAS",user->nick.c_str(),parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ else
+ {
+ whowas_set* grp = i->second;
+ if (grp->size())
+ {
+ for (whowas_set::iterator ux = grp->begin(); ux != grp->end(); ux++)
+ {
+ WhoWasGroup* u = *ux;
+ time_t rawtime = u->signon;
+ tm *timeinfo;
+ char b[25];
+
+ timeinfo = localtime(&rawtime);
+
+ strncpy(b,asctime(timeinfo),24);
+ b[24] = 0;
+
+ user->WriteNumeric(314, "%s %s %s %s * :%s",user->nick.c_str(),parameters[0].c_str(),
+ u->ident.c_str(),u->dhost.c_str(),u->gecos.c_str());
+
+ if (user->HasPrivPermission("users/auspex"))
+ user->WriteNumeric(379, "%s %s :was connecting from *@%s",
+ user->nick.c_str(), parameters[0].c_str(), u->host.c_str());
+
+ if (*ServerInstance->Config->HideWhoisServer && !user->HasPrivPermission("servers/auspex"))
+ user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(),parameters[0].c_str(), ServerInstance->Config->HideWhoisServer, b);
+ else
+ user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(),parameters[0].c_str(), u->server, b);
+ }
+ }
+ else
+ {
+ user->WriteNumeric(406, "%s %s :There was no such nickname",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNumeric(369, "%s %s :End of WHOWAS",user->nick.c_str(),parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+ }
+
+ user->WriteNumeric(369, "%s %s :End of WHOWAS",user->nick.c_str(),parameters[0].c_str());
+ return CMD_SUCCESS;
+}
+
+std::string CommandWhowas::GetStats()
+{
+ int whowas_size = 0;
+ int whowas_bytes = 0;
+ whowas_users_fifo::iterator iter;
+ for (iter = whowas_fifo.begin(); iter != whowas_fifo.end(); iter++)
+ {
+ whowas_set* n = (whowas_set*)whowas.find(iter->second)->second;
+ if (n->size())
+ {
+ whowas_size += n->size();
+ whowas_bytes += (sizeof(whowas_set) + ( sizeof(WhoWasGroup) * n->size() ) );
+ }
+ }
+ stats.assign("Whowas(MAPSETS) " +ConvToStr(whowas_size)+" ("+ConvToStr(whowas_bytes)+" bytes)");
+ return stats;
+}
+
+void CommandWhowas::AddToWhoWas(User* user)
+{
+ /* if whowas disabled */
+ if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
+ {
+ return;
+ }
+
+ whowas_users::iterator iter = whowas.find(irc::string(user->nick.c_str()));
+
+ if (iter == whowas.end())
+ {
+ whowas_set* n = new whowas_set;
+ WhoWasGroup *a = new WhoWasGroup(user);
+ n->push_back(a);
+ whowas[user->nick.c_str()] = n;
+ whowas_fifo.push_back(std::make_pair(ServerInstance->Time(),user->nick.c_str()));
+
+ if ((int)(whowas.size()) > ServerInstance->Config->WhoWasMaxGroups)
+ {
+ whowas_users::iterator iter2 = whowas.find(whowas_fifo[0].second);
+ if (iter2 != whowas.end())
+ {
+ whowas_set* n2 = (whowas_set*)iter2->second;
+
+ if (n2->size())
+ {
+ while (n2->begin() != n2->end())
+ {
+ WhoWasGroup *a2 = *(n2->begin());
+ delete a2;
+ n2->pop_front();
+ }
+ }
+
+ delete n2;
+ whowas.erase(iter2);
+ }
+ whowas_fifo.pop_front();
+ }
+ }
+ else
+ {
+ whowas_set* group = (whowas_set*)iter->second;
+ WhoWasGroup *a = new WhoWasGroup(user);
+ group->push_back(a);
+
+ if ((int)(group->size()) > ServerInstance->Config->WhoWasGroupSize)
+ {
+ WhoWasGroup *a2 = (WhoWasGroup*)*(group->begin());
+ delete a2;
+ group->pop_front();
+ }
+ }
+}
+
+/* on rehash, refactor maps according to new conf values */
+void CommandWhowas::PruneWhoWas(time_t t)
+{
+ /* config values */
+ int groupsize = ServerInstance->Config->WhoWasGroupSize;
+ int maxgroups = ServerInstance->Config->WhoWasMaxGroups;
+ int maxkeep = ServerInstance->Config->WhoWasMaxKeep;
+
+ /* first cut the list to new size (maxgroups) and also prune entries that are timed out. */
+ whowas_users::iterator iter;
+ int fifosize;
+ while ((fifosize = (int)whowas_fifo.size()) > 0)
+ {
+ if (fifosize > maxgroups || whowas_fifo[0].first < t - maxkeep)
+ {
+ iter = whowas.find(whowas_fifo[0].second);
+
+ /* hopefully redundant integrity check, but added while debugging r6216 */
+ if (iter == whowas.end())
+ {
+ /* this should never happen, if it does maps are corrupt */
+ ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (1)");
+ return;
+ }
+
+ whowas_set* n = (whowas_set*)iter->second;
+
+ if (n->size())
+ {
+ while (n->begin() != n->end())
+ {
+ WhoWasGroup *a = *(n->begin());
+ delete a;
+ n->pop_front();
+ }
+ }
+
+ delete n;
+ whowas.erase(iter);
+ whowas_fifo.pop_front();
+ }
+ else
+ break;
+ }
+
+ /* Then cut the whowas sets to new size (groupsize) */
+ fifosize = (int)whowas_fifo.size();
+ for (int i = 0; i < fifosize; i++)
+ {
+ iter = whowas.find(whowas_fifo[0].second);
+ /* hopefully redundant integrity check, but added while debugging r6216 */
+ if (iter == whowas.end())
+ {
+ /* this should never happen, if it does maps are corrupt */
+ ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (2)");
+ return;
+ }
+ whowas_set* n = (whowas_set*)iter->second;
+ if (n->size())
+ {
+ int nickcount = n->size();
+ while (n->begin() != n->end() && nickcount > groupsize)
+ {
+ WhoWasGroup *a = *(n->begin());
+ delete a;
+ n->pop_front();
+ nickcount--;
+ }
+ }
+ }
+}
+
+/* call maintain once an hour to remove expired nicks */
+void CommandWhowas::MaintainWhoWas(time_t t)
+{
+ for (whowas_users::iterator iter = whowas.begin(); iter != whowas.end(); iter++)
+ {
+ whowas_set* n = (whowas_set*)iter->second;
+ if (n->size())
+ {
+ while ((n->begin() != n->end()) && ((*n->begin())->signon < t - ServerInstance->Config->WhoWasMaxKeep))
+ {
+ WhoWasGroup *a = *(n->begin());
+ delete a;
+ n->erase(n->begin());
+ }
+ }
+ }
+}
+
+CommandWhowas::~CommandWhowas()
+{
+ if (timer)
+ {
+ ServerInstance->Timers->DelTimer(timer);
+ }
+
+ whowas_users::iterator iter;
+ int fifosize;
+ while ((fifosize = (int)whowas_fifo.size()) > 0)
+ {
+ iter = whowas.find(whowas_fifo[0].second);
+
+ /* hopefully redundant integrity check, but added while debugging r6216 */
+ if (iter == whowas.end())
+ {
+ /* this should never happen, if it does maps are corrupt */
+ ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (3)");
+ return;
+ }
+
+ whowas_set* n = (whowas_set*)iter->second;
+
+ if (n->size())
+ {
+ while (n->begin() != n->end())
+ {
+ WhoWasGroup *a = *(n->begin());
+ delete a;
+ n->pop_front();
+ }
+ }
+
+ delete n;
+ whowas.erase(iter);
+ whowas_fifo.pop_front();
+ }
+}
+
+WhoWasGroup::WhoWasGroup(User* user) : host(user->host), dhost(user->dhost), ident(user->ident),
+ server(user->server), gecos(user->fullname), signon(user->signon)
+{
+}
+
+WhoWasGroup::~WhoWasGroup()
+{
+}
+
+/* every hour, run this function which removes all entries older than Config->WhoWasMaxKeep */
+void WhoWasMaintainTimer::Tick(time_t)
+{
+ Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so");
+ if (whowas)
+ {
+ WhowasRequest(whowas, whowas, WhowasRequest::WHOWAS_MAINTAIN).Send();
+ }
+}
+
+class ModuleWhoWas : public Module
+{
+ CommandWhowas cmd;
+ public:
+ ModuleWhoWas(InspIRCd *Me) : Module(Me), cmd(this)
+ {
+ ServerInstance->AddCommand(&cmd);
+ }
+
+ const char* OnRequest(Request* request)
+ {
+ WhowasRequest* req = static_cast<WhowasRequest*>(request);
+ switch (req->type)
+ {
+ case WhowasRequest::WHOWAS_ADD:
+ cmd.AddToWhoWas(req->user);
+ break;
+ case WhowasRequest::WHOWAS_STATS:
+ req->value = cmd.GetStats();
+ break;
+ case WhowasRequest::WHOWAS_PRUNE:
+ cmd.PruneWhoWas(ServerInstance->Time());
+ break;
+ case WhowasRequest::WHOWAS_MAINTAIN:
+ cmd.MaintainWhoWas(ServerInstance->Time());
+ break;
+ }
+ return NULL;
+ }
+
+ Version GetVersion()
+ {
+ return Version("WHOWAS Command", VF_VENDOR);
+ }
+};
+
+MODULE_INIT(ModuleWhoWas)
diff --git a/src/commands/cmd_zline.cpp b/src/commands/cmd_zline.cpp
new file mode 100644
index 000000000..e2cca7649
--- /dev/null
+++ b/src/commands/cmd_zline.cpp
@@ -0,0 +1,106 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+/** Handle /ZLINE. These command handlers can be reloaded by the core,
+ * and handle basic RFC1459 commands. Commands within modules work
+ * the same way, however, they can be fully unloaded, where these
+ * may not.
+ */
+class CommandZline : public Command
+{
+ public:
+ /** Constructor for zline.
+ */
+ CommandZline ( Module* parent) : Command(parent,"ZLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = "<ipmask> [<duration> :<reason>]"; }
+ /** Handle command.
+ * @param parameters The parameters to the comamnd
+ * @param pcnt The number of parameters passed to teh command
+ * @param user The user issuing the command
+ * @return A value from CmdResult to indicate command success or failure.
+ */
+ CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+};
+
+CmdResult CommandZline::Handle (const std::vector<std::string>& parameters, User *user)
+{
+ std::string target = parameters[0];
+
+ if (parameters.size() >= 3)
+ {
+ if (target.find('!') != std::string::npos)
+ {
+ user->WriteServ("NOTICE %s :*** You cannot include a nickname in a zline, a zline must ban only an IP mask",user->nick.c_str());
+ return CMD_FAILURE;
+ }
+
+ User *u = ServerInstance->FindNick(target.c_str());
+
+ if (u)
+ {
+ target = u->GetIPString();
+ }
+
+ const char* ipaddr = target.c_str();
+
+ if (strchr(ipaddr,'@'))
+ {
+ while (*ipaddr != '@')
+ ipaddr++;
+ ipaddr++;
+ }
+
+ if (ServerInstance->IPMatchesEveryone(ipaddr,user))
+ return CMD_FAILURE;
+
+ long duration = ServerInstance->Duration(parameters[1].c_str());
+
+ ZLine* zl = new ZLine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr);
+ if (ServerInstance->XLines->AddLine(zl,user))
+ {
+ if (!duration)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Z-line for %s: %s", user->nick.c_str(), ipaddr, parameters[2].c_str());
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Z-line for %s, expires on %s: %s",user->nick.c_str(),ipaddr,
+ ServerInstance->TimeString(c_requires_crap).c_str(), parameters[2].c_str());
+ }
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
+ {
+ delete zl;
+ user->WriteServ("NOTICE %s :*** Z-Line for %s already exists",user->nick.c_str(),ipaddr);
+ }
+ }
+ else
+ {
+ if (ServerInstance->XLines->DelLine(target.c_str(),"Z",user))
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s removed Z-line on %s",user->nick.c_str(),target.c_str());
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** Z-Line %s not found in list, try /stats Z.",user->nick.c_str(),target.c_str());
+ return CMD_FAILURE;
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+COMMAND_INIT(CommandZline)