summaryrefslogtreecommitdiff
path: root/src/commands
diff options
context:
space:
mode:
authorw00t <w00t@e03df62e-2008-0410-955e-edbf42e46eb7>2007-10-22 14:13:48 +0000
committerw00t <w00t@e03df62e-2008-0410-955e-edbf42e46eb7>2007-10-22 14:13:48 +0000
commit5d5285f24b1fe306faa2a6d0565ba1cff0f17f11 (patch)
tree75ce78d3a653f5897b92623808bfdba516f6514f /src/commands
parent4cc6e5e14fdbde499481dbab5ab2ad1257b8af9c (diff)
Move cmd_*.cpp to src/commands/. Not done in the nicest of ways yet, but ah well :p
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@8299 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/cmd_admin.cpp33
-rw-r--r--src/commands/cmd_away.cpp39
-rw-r--r--src/commands/cmd_clearcache.cpp29
-rw-r--r--src/commands/cmd_commands.cpp37
-rw-r--r--src/commands/cmd_connect.cpp32
-rw-r--r--src/commands/cmd_die.cpp45
-rw-r--r--src/commands/cmd_eline.cpp74
-rw-r--r--src/commands/cmd_gline.cpp86
-rw-r--r--src/commands/cmd_info.cpp54
-rw-r--r--src/commands/cmd_invite.cpp111
-rw-r--r--src/commands/cmd_ison.cpp87
-rw-r--r--src/commands/cmd_join.cpp51
-rw-r--r--src/commands/cmd_kick.cpp56
-rw-r--r--src/commands/cmd_kill.cpp116
-rw-r--r--src/commands/cmd_kline.cpp85
-rw-r--r--src/commands/cmd_links.cpp29
-rw-r--r--src/commands/cmd_list.cpp84
-rw-r--r--src/commands/cmd_loadmodule.cpp37
-rw-r--r--src/commands/cmd_lusers.cpp40
-rw-r--r--src/commands/cmd_map.cpp33
-rw-r--r--src/commands/cmd_mode.cpp29
-rw-r--r--src/commands/cmd_modules.cpp72
-rw-r--r--src/commands/cmd_motd.cpp28
-rw-r--r--src/commands/cmd_names.cpp53
-rw-r--r--src/commands/cmd_nick.cpp169
-rw-r--r--src/commands/cmd_notice.cpp159
-rw-r--r--src/commands/cmd_oper.cpp159
-rw-r--r--src/commands/cmd_part.cpp42
-rw-r--r--src/commands/cmd_pass.cpp41
-rw-r--r--src/commands/cmd_ping.cpp26
-rw-r--r--src/commands/cmd_pong.cpp27
-rw-r--r--src/commands/cmd_privmsg.cpp165
-rw-r--r--src/commands/cmd_qline.cpp77
-rw-r--r--src/commands/cmd_quit.cpp45
-rw-r--r--src/commands/cmd_rehash.cpp54
-rw-r--r--src/commands/cmd_reloadmodule.cpp38
-rw-r--r--src/commands/cmd_restart.cpp47
-rw-r--r--src/commands/cmd_rules.cpp26
-rw-r--r--src/commands/cmd_server.cpp29
-rw-r--r--src/commands/cmd_squit.cpp31
-rw-r--r--src/commands/cmd_stats.cpp318
-rw-r--r--src/commands/cmd_time.cpp38
-rw-r--r--src/commands/cmd_topic.cpp115
-rw-r--r--src/commands/cmd_trace.cpp45
-rw-r--r--src/commands/cmd_unloadmodule.cpp38
-rw-r--r--src/commands/cmd_user.cpp67
-rw-r--r--src/commands/cmd_userhost.cpp62
-rw-r--r--src/commands/cmd_version.cpp29
-rw-r--r--src/commands/cmd_wallops.cpp29
-rw-r--r--src/commands/cmd_who.cpp346
-rw-r--r--src/commands/cmd_whois.cpp144
-rw-r--r--src/commands/cmd_whowas.cpp348
-rw-r--r--src/commands/cmd_zline.cpp77
53 files changed, 4131 insertions, 0 deletions
diff --git a/src/commands/cmd_admin.cpp b/src/commands/cmd_admin.cpp
new file mode 100644
index 000000000..0d704ba24
--- /dev/null
+++ b/src/commands/cmd_admin.cpp
@@ -0,0 +1,33 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_admin.h"
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandAdmin(Instance);
+}
+
+/** Handle /ADMIN
+ */
+CmdResult CommandAdmin::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->WriteServ("256 %s :Administrative info for %s",user->nick,ServerInstance->Config->ServerName);
+ if (*ServerInstance->Config->AdminName)
+ user->WriteServ("257 %s :Name - %s",user->nick,ServerInstance->Config->AdminName);
+ user->WriteServ("258 %s :Nickname - %s",user->nick,ServerInstance->Config->AdminNick);
+ user->WriteServ("259 %s :E-Mail - %s",user->nick,ServerInstance->Config->AdminEmail);
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_away.cpp b/src/commands/cmd_away.cpp
new file mode 100644
index 000000000..ce4628858
--- /dev/null
+++ b/src/commands/cmd_away.cpp
@@ -0,0 +1,39 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_away.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandAway(Instance);
+}
+
+/** Handle /AWAY
+ */
+CmdResult CommandAway::Handle (const char** parameters, int pcnt, User *user)
+{
+ if ((pcnt) && (*parameters[0]))
+ {
+ strlcpy(user->awaymsg,parameters[0],MAXAWAY);
+ user->WriteServ("306 %s :You have been marked as being away",user->nick);
+ FOREACH_MOD(I_OnSetAway,OnSetAway(user));
+ }
+ else
+ {
+ *user->awaymsg = 0;
+ user->WriteServ("305 %s :You are no longer marked as being away",user->nick);
+ FOREACH_MOD(I_OnCancelAway,OnCancelAway(user));
+ }
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_clearcache.cpp b/src/commands/cmd_clearcache.cpp
new file mode 100644
index 000000000..cbc796bba
--- /dev/null
+++ b/src/commands/cmd_clearcache.cpp
@@ -0,0 +1,29 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_clearcache.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandClearcache(Instance);
+}
+
+/** Handle /CLEARCACHE
+ */
+CmdResult CommandClearcache::Handle (const char** parameters, int pcnt, User *user)
+{
+ int n = ServerInstance->Res->ClearCache();
+ user->WriteServ("NOTICE %s :*** Cleared DNS cache of %d items.", user->nick, n);
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_commands.cpp b/src/commands/cmd_commands.cpp
new file mode 100644
index 000000000..68c5a8c78
--- /dev/null
+++ b/src/commands/cmd_commands.cpp
@@ -0,0 +1,37 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_commands.h"
+
+/** Handle /COMMANDS
+ */
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandCommands(Instance);
+}
+
+CmdResult CommandCommands::Handle (const char** parameters, int pcnt, User *user)
+{
+ for (Commandable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++)
+ {
+ user->WriteServ("902 %s :%s %s %d %d",
+ user->nick,
+ i->second->command.c_str(),
+ i->second->source.c_str(),
+ i->second->min_params,
+ i->second->Penalty);
+ }
+ user->WriteServ("903 %s :End of COMMANDS list",user->nick);
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_connect.cpp b/src/commands/cmd_connect.cpp
new file mode 100644
index 000000000..b44264123
--- /dev/null
+++ b/src/commands/cmd_connect.cpp
@@ -0,0 +1,32 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_connect.h"
+
+/*
+ * This is handled by the server linking module, if necessary. Do not remove this stub.
+ */
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandConnect(Instance);
+}
+
+/** Handle /CONNECT
+ */
+CmdResult CommandConnect::Handle (const char** parameters, int pcnt, 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);
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_die.cpp b/src/commands/cmd_die.cpp
new file mode 100644
index 000000000..4ef9e4301
--- /dev/null
+++ b/src/commands/cmd_die.cpp
@@ -0,0 +1,45 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_die.h"
+#include "exitcodes.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandDie(Instance);
+}
+
+/** Handle /DIE
+ */
+CmdResult CommandDie::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (!strcmp(parameters[0],ServerInstance->Config->diepass))
+ {
+ std::string diebuf = std::string("*** DIE command from ") + user->nick + "!" + user->ident + "@" + user->dhost + ". Terminating in " + ConvToStr(ServerInstance->Config->DieDelay) + " seconds.";
+ ServerInstance->Log(SPARSE, diebuf);
+ ServerInstance->SendError(diebuf);
+
+ if (ServerInstance->Config->DieDelay)
+ sleep(ServerInstance->Config->DieDelay);
+
+ ServerInstance->Exit(EXIT_STATUS_DIE);
+ }
+ else
+ {
+ ServerInstance->Log(SPARSE, "Failed /DIE command from %s!%s@%s", user->nick, user->ident, user->host);
+ ServerInstance->WriteOpers("*** Failed DIE Command from %s!%s@%s.",user->nick,user->ident,user->host);
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_eline.cpp b/src/commands/cmd_eline.cpp
new file mode 100644
index 000000000..bd9832c8a
--- /dev/null
+++ b/src/commands/cmd_eline.cpp
@@ -0,0 +1,74 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+#include "commands/cmd_eline.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandEline(Instance);
+}
+
+/** Handle /ELINE
+ */
+CmdResult CommandEline::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (pcnt >= 3)
+ {
+ IdentHostPair ih = ServerInstance->XLines->IdentSplit(parameters[0]);
+ if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
+ return CMD_FAILURE;
+
+ if (!strchr(parameters[0],'@'))
+ {
+ user->WriteServ("NOTICE %s :*** E-Line must contain a username, e.g. *@%s",user->nick,parameters[0]);
+ return CMD_FAILURE;
+ }
+
+ long duration = ServerInstance->Duration(parameters[1]);
+ if (ServerInstance->XLines->add_eline(duration,user->nick,parameters[2],parameters[0]))
+ {
+ FOREACH_MOD(I_OnAddELine,OnAddELine(duration, user, parameters[2], parameters[0]));
+
+ if (!duration)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent E-line for %s.",user->nick,parameters[0]);
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed E-line for %s, expires on %s",user->nick,parameters[0],
+ ServerInstance->TimeString(c_requires_crap).c_str());
+ }
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** E-Line for %s already exists",user->nick,parameters[0]);
+ }
+ }
+ else
+ {
+ if (ServerInstance->XLines->del_eline(parameters[0]))
+ {
+ FOREACH_MOD(I_OnDelELine,OnDelELine(user, parameters[0]));
+ ServerInstance->SNO->WriteToSnoMask('x',"%s Removed E-line on %s.",user->nick,parameters[0]);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** E-Line %s not found in list, try /stats e.",user->nick,parameters[0]);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_gline.cpp b/src/commands/cmd_gline.cpp
new file mode 100644
index 000000000..3845c23ee
--- /dev/null
+++ b/src/commands/cmd_gline.cpp
@@ -0,0 +1,86 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+#include "commands/cmd_gline.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandGline(Instance);
+}
+
+/** Handle /GLINE
+ */
+CmdResult CommandGline::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (pcnt >= 3)
+ {
+ IdentHostPair ih = ServerInstance->XLines->IdentSplit(parameters[0]);
+ if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
+ return CMD_FAILURE;
+
+ if (!strchr(parameters[0],'@'))
+ {
+ user->WriteServ("NOTICE %s :*** G-Line must contain a username, e.g. *@%s",user->nick,parameters[0]);
+ return CMD_FAILURE;
+ }
+ else if (strchr(parameters[0],'!'))
+ {
+ user->WriteServ("NOTICE %s :*** G-Line cannot contain a nickname!",user->nick);
+ return CMD_FAILURE;
+ }
+
+ long duration = ServerInstance->Duration(parameters[1]);
+ if (ServerInstance->XLines->add_gline(duration,user->nick,parameters[2],parameters[0]))
+ {
+ int to_apply = APPLY_GLINES;
+
+ FOREACH_MOD(I_OnAddGLine,OnAddGLine(duration, user, parameters[2], parameters[0]));
+
+ if (!duration)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent G-line for %s.",user->nick,parameters[0]);
+ to_apply |= APPLY_PERM_ONLY;
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed G-line for %s, expires on %s",user->nick,parameters[0],
+ ServerInstance->TimeString(c_requires_crap).c_str());
+ }
+
+ ServerInstance->XLines->apply_lines(to_apply);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** G-Line for %s already exists",user->nick,parameters[0]);
+ }
+
+ }
+ else
+ {
+ if (ServerInstance->XLines->del_gline(parameters[0]))
+ {
+ FOREACH_MOD(I_OnDelGLine,OnDelGLine(user, parameters[0]));
+ ServerInstance->SNO->WriteToSnoMask('x',"%s Removed G-line on %s.",user->nick,parameters[0]);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** G-line %s not found in list, try /stats g.",user->nick,parameters[0]);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_info.cpp b/src/commands/cmd_info.cpp
new file mode 100644
index 000000000..959f04a39
--- /dev/null
+++ b/src/commands/cmd_info.cpp
@@ -0,0 +1,54 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_info.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandInfo(Instance);
+}
+
+/** Handle /INFO
+ */
+CmdResult CommandInfo::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->WriteServ( "371 %s : -/\\- \2InspIRCd\2 -\\/-", user->nick);
+ user->WriteServ( "371 %s : November 2002 - Present", user->nick);
+ user->WriteServ( "371 %s : ", user->nick);
+ user->WriteServ( "371 %s :\2Core Developers\2:", user->nick);
+ user->WriteServ( "371 %s : Craig Edwards, Brain, <brain@inspircd.org>", user->nick);
+ user->WriteServ( "371 %s : Craig McLure, Craig, <craig@inspircd.org>", user->nick);
+ user->WriteServ( "371 %s : Robin Burchell, w00t, <w00t@inspircd.org>", user->nick);
+ user->WriteServ( "371 %s : Oliver Lupton, Om, <om@inspircd.org>", user->nick);
+ user->WriteServ( "371 %s : John Brooks, Special, <special@inspircd.org>", user->nick);
+ user->WriteServ( "371 %s : Pippijn van Steenhoven, pippijn, <pippijn@one09.net>", user->nick);
+ user->WriteServ( "371 %s : Dennis Friis, peavey, <peavey@inspircd.org>", user->nick);
+ user->WriteServ( "371 %s : Burlex, <burlex@inspircd.org>", user->nick);
+ user->WriteServ( "371 %s : ", user->nick);
+ user->WriteServ( "371 %s :\2Regular Contributors\2:", user->nick);
+ user->WriteServ( "371 %s : satmd nenolod BuildSmart HiroP", user->nick);
+ user->WriteServ( "371 %s : jilles Stskeeps eggy Trystan", user->nick);
+ user->WriteServ( "371 %s : Bricker danieldg DarkStorm Majic", user->nick);
+ user->WriteServ( "371 %s : ThaPrince Thunderhacker praetorian", user->nick);
+ user->WriteServ( "371 %s : searchirc.com irc-junkie.org", user->nick);
+ user->WriteServ( "371 %s : ", user->nick);
+ user->WriteServ( "371 %s :\2Other Contributors\2:", user->nick);
+ user->WriteServ( "371 %s : dmb CC skenmy LeaChim owine Adremelech", user->nick);
+ user->WriteServ( "371 %s : typobox43 jamie Jason", user->nick);
+ user->WriteServ( "371 %s : ", user->nick);
+ user->WriteServ( "371 %s : Best experienced with: \2An IRC client\2", user->nick);
+ FOREACH_MOD(I_OnInfo,OnInfo(user));
+ user->WriteServ( "374 %s :End of /INFO list", user->nick);
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_invite.cpp b/src/commands/cmd_invite.cpp
new file mode 100644
index 000000000..d5ce160ac
--- /dev/null
+++ b/src/commands/cmd_invite.cpp
@@ -0,0 +1,111 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_invite.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandInvite(Instance);
+}
+
+/** Handle /INVITE
+ */
+CmdResult CommandInvite::Handle (const char** parameters, int pcnt, User *user)
+{
+ int MOD_RESULT = 0;
+
+ if (pcnt == 2)
+ {
+ User* u = ServerInstance->FindNick(parameters[0]);
+ Channel* c = ServerInstance->FindChan(parameters[1]);
+
+ if ((!c) || (!u))
+ {
+ if (!c)
+ {
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[1]);
+ }
+ else
+ {
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ }
+
+ return CMD_FAILURE;
+ }
+
+ if ((c->IsModeSet('i')) && (IS_LOCAL(user)))
+ {
+ if (c->GetStatus(user) < STATUS_HOP)
+ {
+ user->WriteServ("482 %s %s :You must be a channel %soperator", user->nick, c->name, c->GetStatus(u) == STATUS_HOP ? "" : "half-");
+ return CMD_FAILURE;
+ }
+ }
+
+ if (c->HasUser(u))
+ {
+ user->WriteServ("443 %s %s %s :is already on channel",user->nick,u->nick,c->name);
+ return CMD_FAILURE;
+ }
+
+ if ((IS_LOCAL(user)) && (!c->HasUser(user)))
+ {
+ user->WriteServ("442 %s %s :You're not on that channel!",user->nick, c->name);
+ return CMD_FAILURE;
+ }
+
+ FOREACH_RESULT(I_OnUserPreInvite,OnUserPreInvite(user,u,c));
+
+ if (MOD_RESULT == 1)
+ {
+ return CMD_FAILURE;
+ }
+
+ u->InviteTo(c->name);
+ u->WriteFrom(user,"INVITE %s :%s",u->nick,c->name);
+ user->WriteServ("341 %s %s %s",user->nick,u->nick,c->name);
+ switch (ServerInstance->Config->AnnounceInvites)
+ {
+ case ServerConfig::INVITE_ANNOUNCE_ALL:
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :*** %s invited %s into the channel", c->name, user->nick, u->nick);
+ break;
+ case ServerConfig::INVITE_ANNOUNCE_OPS:
+ c->WriteAllExceptSender(user, true, '@', "NOTICE %s :*** %s invited %s into the channel", c->name, user->nick, u->nick);
+ break;
+ case ServerConfig::INVITE_ANNOUNCE_DYNAMIC:
+ if (c->IsModeSet('i'))
+ c->WriteAllExceptSender(user, true, '@', "NOTICE %s :*** %s invited %s into the channel", c->name, user->nick, u->nick);
+ else
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :*** %s invited %s into the channel", c->name, user->nick, u->nick);
+ break;
+ default:
+ /* Nobody */
+ break;
+ }
+ FOREACH_MOD(I_OnUserInvite,OnUserInvite(user,u,c));
+ }
+ 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->WriteServ("346 %s :%s",user->nick,i->c_str());
+ }
+ user->WriteServ("347 %s :End of INVITE list",user->nick);
+ }
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_ison.cpp b/src/commands/cmd_ison.cpp
new file mode 100644
index 000000000..9289dd014
--- /dev/null
+++ b/src/commands/cmd_ison.cpp
@@ -0,0 +1,87 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_ison.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandIson(Instance);
+}
+
+/** Handle /ISON
+ */
+CmdResult CommandIson::Handle (const char** parameters, int pcnt, User *user)
+{
+ std::map<User*,User*> ison_already;
+ User *u;
+ std::string reply = std::string("303 ") + user->nick + " :";
+
+ for (int i = 0; i < pcnt; i++)
+ {
+ u = ServerInstance->FindNick(parameters[i]);
+ if (ison_already.find(u) != ison_already.end())
+ continue;
+
+ if (u)
+ {
+ if (u->Visibility && !u->Visibility->VisibleTo(user))
+ continue;
+
+ 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 == pcnt-1) && (strchr(parameters[i],' ')))
+ {
+ /* 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)
+ {
+ if (u->Visibility && !u->Visibility->VisibleTo(user))
+ continue;
+
+ 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;
+}
+
diff --git a/src/commands/cmd_join.cpp b/src/commands/cmd_join.cpp
new file mode 100644
index 000000000..b5359397d
--- /dev/null
+++ b/src/commands/cmd_join.cpp
@@ -0,0 +1,51 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_join.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandJoin(Instance);
+}
+
+/** Handle /JOIN
+ */
+CmdResult CommandJoin::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (pcnt > 1)
+ {
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0, 1))
+ return CMD_SUCCESS;
+
+ if (ServerInstance->IsChannel(parameters[0]))
+ {
+ Channel::JoinUser(ServerInstance, user, parameters[0], false, parameters[1]);
+ return CMD_SUCCESS;
+ }
+ }
+ else
+ {
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0))
+ return CMD_SUCCESS;
+
+ if (ServerInstance->IsChannel(parameters[0]))
+ {
+ Channel::JoinUser(ServerInstance, user, parameters[0], false, "");
+ return CMD_SUCCESS;
+ }
+ }
+
+ user->WriteServ("403 %s %s :Invalid channel name",user->nick, parameters[0]);
+ return CMD_FAILURE;
+}
diff --git a/src/commands/cmd_kick.cpp b/src/commands/cmd_kick.cpp
new file mode 100644
index 000000000..c8b505ff0
--- /dev/null
+++ b/src/commands/cmd_kick.cpp
@@ -0,0 +1,56 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_kick.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandKick(Instance);
+}
+
+/** Handle /KICK
+ */
+CmdResult CommandKick::Handle (const char** parameters, int pcnt, User *user)
+{
+ char reason[MAXKICK];
+ Channel* c = ServerInstance->FindChan(parameters[0]);
+ User* u = ServerInstance->FindNick(parameters[1]);
+
+ if (!u || !c)
+ {
+ user->WriteServ( "401 %s %s :No such nick/channel", user->nick, u ? parameters[0] : parameters[1]);
+ 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, parameters[0]);
+ return CMD_FAILURE;
+ }
+
+ if (pcnt > 2)
+ {
+ strlcpy(reason, parameters[2], MAXKICK - 1);
+ }
+ else
+ {
+ strlcpy(reason, user->nick, MAXKICK - 1);
+ }
+
+ if (!c->KickUser(user, u, reason))
+ /* Nobody left here, delete the Channel */
+ delete c;
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_kill.cpp b/src/commands/cmd_kill.cpp
new file mode 100644
index 000000000..29ce56b5c
--- /dev/null
+++ b/src/commands/cmd_kill.cpp
@@ -0,0 +1,116 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_kill.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandKill(Instance);
+}
+
+/** Handle /KILL
+ */
+CmdResult CommandKill::Handle (const char** parameters, int pcnt, User *user)
+{
+ /* Allow comma seperated lists of users for /KILL (thanks w00t) */
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0))
+ return CMD_SUCCESS;
+
+ User *u = ServerInstance->FindNick(parameters[0]);
+ char killreason[MAXBUF];
+ int MOD_RESULT = 0;
+
+ 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
+ */
+ FOREACH_RESULT(I_OnKill, OnKill(user, u, parameters[1]));
+
+ if (MOD_RESULT)
+ return CMD_FAILURE;
+
+ if (*ServerInstance->Config->HideKillsServer)
+ {
+ // hidekills is on, use it
+ snprintf(killreason, MAXQUIT, "Killed (%s (%s))", ServerInstance->Config->HideKillsServer, parameters[1]);
+ }
+ else
+ {
+ // hidekills is off, do nothing
+ snprintf(killreason, MAXQUIT, "Killed (%s (%s))", user->nick, parameters[1]);
+ }
+ }
+ else
+ {
+ /* Leave it alone, remote server has already formatted it */
+ snprintf(killreason, MAXQUIT, "%s", parameters[1]);
+ }
+
+ /*
+ * 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, u->nick, u->ident, u->host, parameters[1]);
+ 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, u->nick, u->ident, u->host, parameters[1]);
+ ServerInstance->Log(DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick, ServerInstance->Config->ServerName, user->dhost, user->nick, parameters[1]);
+ /* 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->muted)
+ {
+ u->Write(":%s KILL %s :%s!%s!%s (%s)", *ServerInstance->Config->HideKillsServer ? ServerInstance->Config->HideKillsServer : user->GetFullHost(),
+ u->nick,
+ ServerInstance->Config->ServerName,
+ user->dhost,
+ *ServerInstance->Config->HideKillsServer ? ServerInstance->Config->HideKillsServer : user->nick,
+ parameters[1]);
+ u->muted = true;
+ }
+ }
+
+ // send the quit out
+ User::QuitUser(ServerInstance, u, killreason);
+ }
+ else
+ {
+ user->WriteServ( "401 %s %s :No such nick/channel", user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_kline.cpp b/src/commands/cmd_kline.cpp
new file mode 100644
index 000000000..5edb414ea
--- /dev/null
+++ b/src/commands/cmd_kline.cpp
@@ -0,0 +1,85 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+#include "commands/cmd_kline.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandKline(Instance);
+}
+
+/** Handle /KLINE
+ */
+CmdResult CommandKline::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (pcnt >= 3)
+ {
+ IdentHostPair ih = ServerInstance->XLines->IdentSplit(parameters[0]);
+ if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
+ return CMD_FAILURE;
+
+ if (!strchr(parameters[0],'@'))
+ {
+ user->WriteServ("NOTICE %s :*** K-Line must contain a username, e.g. *@%s",user->nick,parameters[0]);
+ return CMD_FAILURE;
+ }
+ else if (strchr(parameters[0],'!'))
+ {
+ user->WriteServ("NOTICE %s :*** K-Line cannot contain a nickname!",user->nick);
+ return CMD_FAILURE;
+ }
+
+ long duration = ServerInstance->Duration(parameters[1]);
+ if (ServerInstance->XLines->add_kline(duration,user->nick,parameters[2],parameters[0]))
+ {
+ int to_apply = APPLY_KLINES;
+
+ FOREACH_MOD(I_OnAddKLine,OnAddKLine(duration, user, parameters[2], parameters[0]));
+
+ if (!duration)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent K-line for %s.",user->nick,parameters[0]);
+ to_apply |= APPLY_PERM_ONLY;
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed K-line for %s, expires on %s",user->nick,parameters[0],
+ ServerInstance->TimeString(c_requires_crap).c_str());
+ }
+
+ ServerInstance->XLines->apply_lines(to_apply);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** K-Line for %s already exists",user->nick,parameters[0]);
+ }
+ }
+ else
+ {
+ if (ServerInstance->XLines->del_kline(parameters[0]))
+ {
+ FOREACH_MOD(I_OnDelKLine,OnDelKLine(user, parameters[0]));
+ ServerInstance->SNO->WriteToSnoMask('x',"%s Removed K-line on %s.",user->nick,parameters[0]);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** K-Line %s not found in list, try /stats k.",user->nick,parameters[0]);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_links.cpp b/src/commands/cmd_links.cpp
new file mode 100644
index 000000000..4c50b2684
--- /dev/null
+++ b/src/commands/cmd_links.cpp
@@ -0,0 +1,29 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_links.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandLinks(Instance);
+}
+
+/** Handle /LINKS
+ */
+CmdResult CommandLinks::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->WriteServ("364 %s %s %s :0 %s",user->nick,ServerInstance->Config->ServerName,ServerInstance->Config->ServerName,ServerInstance->Config->ServerDesc);
+ user->WriteServ("365 %s * :End of /LINKS list.",user->nick);
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_list.cpp b/src/commands/cmd_list.cpp
new file mode 100644
index 000000000..0e97d0db1
--- /dev/null
+++ b/src/commands/cmd_list.cpp
@@ -0,0 +1,84 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_list.h"
+#include "wildcard.h"
+
+/** Handle /LIST
+ */
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandList(Instance);
+}
+
+CmdResult CommandList::Handle (const char** parameters, int pcnt, User *user)
+{
+ int minusers = 0, maxusers = 0;
+
+ user->WriteServ("321 %s Channel :Users Name",user->nick);
+
+ /* Work around mIRC suckyness. YOU SUCK, KHALED! */
+ if (pcnt == 1)
+ {
+ if (*parameters[0] == '<')
+ {
+ maxusers = atoi(parameters[0]+1);
+ pcnt = 0;
+ }
+ else if (*parameters[0] == '>')
+ {
+ minusers = atoi(parameters[0]+1);
+ pcnt = 0;
+ }
+ }
+
+ 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 (pcnt)
+ {
+ if (!match(i->second->name, parameters[0]) && !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);
+ if ((i->second->IsModeSet('p')) && (!n))
+ {
+ if (users)
+ user->WriteServ("322 %s *",user->nick,i->second->name);
+ }
+ else
+ {
+ if (((!(i->second->IsModeSet('p'))) && (!(i->second->IsModeSet('s')))) || (n))
+ {
+ long users = i->second->GetUserCounter();
+ if (users)
+ user->WriteServ("322 %s %s %d :[+%s] %s",user->nick,i->second->name,users,i->second->ChanModes(n),i->second->topic);
+ }
+ }
+ }
+ user->WriteServ("323 %s :End of channel list.",user->nick);
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_loadmodule.cpp b/src/commands/cmd_loadmodule.cpp
new file mode 100644
index 000000000..c6f0a611c
--- /dev/null
+++ b/src/commands/cmd_loadmodule.cpp
@@ -0,0 +1,37 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_loadmodule.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandLoadmodule(Instance);
+}
+
+/** Handle /LOADMODULE
+ */
+CmdResult CommandLoadmodule::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (ServerInstance->Modules->Load(parameters[0]))
+ {
+ ServerInstance->WriteOpers("*** NEW MODULE: %s loaded %s",user->nick, parameters[0]);
+ user->WriteServ("975 %s %s :Module successfully loaded.",user->nick, parameters[0]);
+ return CMD_SUCCESS;
+ }
+ else
+ {
+ user->WriteServ("974 %s %s :Failed to load module: %s",user->nick, parameters[0], ServerInstance->Modules->LastError());
+ return CMD_FAILURE;
+ }
+}
diff --git a/src/commands/cmd_lusers.cpp b/src/commands/cmd_lusers.cpp
new file mode 100644
index 000000000..04f2906ac
--- /dev/null
+++ b/src/commands/cmd_lusers.cpp
@@ -0,0 +1,40 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_lusers.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandLusers(Instance);
+}
+
+/** Handle /LUSERS
+ */
+CmdResult CommandLusers::Handle (const char** parameters, int pcnt, User *user)
+{
+ // this lusers command shows one server at all times because
+ // a protocol module must override it to show those stats.
+ user->WriteServ("251 %s :There are %d users and %d invisible on 1 server",user->nick,ServerInstance->UserCount()-ServerInstance->InvisibleUserCount(),ServerInstance->InvisibleUserCount());
+ if (ServerInstance->OperCount())
+ user->WriteServ("252 %s %d :operator(s) online",user->nick,ServerInstance->OperCount());
+ if (ServerInstance->UnregisteredUserCount())
+ user->WriteServ("253 %s %d :unknown connections",user->nick,ServerInstance->UnregisteredUserCount());
+ if (ServerInstance->ChannelCount())
+ user->WriteServ("254 %s %d :channels formed",user->nick,ServerInstance->ChannelCount());
+ if (ServerInstance->LocalUserCount())
+ user->WriteServ("255 %s :I have %d clients and 0 servers",user->nick,ServerInstance->LocalUserCount());
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_map.cpp b/src/commands/cmd_map.cpp
new file mode 100644
index 000000000..7d391d275
--- /dev/null
+++ b/src/commands/cmd_map.cpp
@@ -0,0 +1,33 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_map.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandMap(Instance);
+}
+
+/** Handle /MAP
+ */
+CmdResult CommandMap::Handle (const char** parameters, int pcnt, User *user)
+{
+ // as with /LUSERS this does nothing without a linking
+ // module to override its behaviour and display something
+ // better.
+ user->WriteServ("006 %s :%s",user->nick,ServerInstance->Config->ServerName);
+ user->WriteServ("007 %s :End of /MAP",user->nick);
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_mode.cpp b/src/commands/cmd_mode.cpp
new file mode 100644
index 000000000..e0d3b4242
--- /dev/null
+++ b/src/commands/cmd_mode.cpp
@@ -0,0 +1,29 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_mode.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandMode(Instance);
+}
+
+/** Handle /MODE
+ */
+CmdResult CommandMode::Handle (const char** parameters, int pcnt, User *user)
+{
+ ServerInstance->Modes->Process(parameters, pcnt, user, false);
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_modules.cpp b/src/commands/cmd_modules.cpp
new file mode 100644
index 000000000..1ff8c1c75
--- /dev/null
+++ b/src/commands/cmd_modules.cpp
@@ -0,0 +1,72 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "wildcard.h"
+#include "commands/cmd_modules.h"
+
+char* itab[] = {
+ "OnUserConnect", "OnUserQuit", "OnUserDisconnect", "OnUserJoin", "OnUserPart", "OnRehash", "OnServerRaw",
+ "OnUserPreJoin", "OnUserPreKick", "OnUserKick", "OnOper", "OnInfo", "OnWhois", "OnUserPreInvite",
+ "OnUserInvite", "OnUserPreMessage", "OnUserPreNotice", "OnUserPreNick", "OnUserMessage", "OnUserNotice", "OnMode",
+ "OnGetServerDescription", "OnSyncUser", "OnSyncChannel", "OnSyncChannelMetaData", "OnSyncUserMetaData",
+ "OnDecodeMetaData", "ProtoSendMode", "ProtoSendMetaData", "OnWallops", "OnChangeHost", "OnChangeName", "OnAddGLine",
+ "OnAddZLine", "OnAddQLine", "OnAddKLine", "OnAddELine", "OnDelGLine", "OnDelZLine", "OnDelKLine", "OnDelELine", "OnDelQLine",
+ "OnCleanup", "OnUserPostNick", "OnAccessCheck", "On005Numeric", "OnKill", "OnRemoteKill", "OnLoadModule", "OnUnloadModule",
+ "OnBackgroundTimer", "OnSendList", "OnPreCommand", "OnCheckReady", "OnUserRegister", "OnCheckInvite",
+ "OnCheckKey", "OnCheckLimit", "OnCheckBan", "OnStats", "OnChangeLocalUserHost", "OnChangeLocalUserGecos", "OnLocalTopicChange",
+ "OnPostLocalTopicChange", "OnEvent", "OnRequest", "OnOperCompre", "OnGlobalOper", "OnPostConnect", "OnAddBan", "OnDelBan",
+ "OnRawSocketAccept", "OnRawSocketClose", "OnRawSocketWrite", "OnRawSocketRead", "OnChangeLocalUserGECOS", "OnUserRegister",
+ "OnOperCompare", "OnChannelDelete", "OnPostOper", "OnSyncOtherMetaData", "OnSetAway", "OnCancelAway", "OnNamesList",
+ "OnPostCommand", "OnPostJoin", "OnWhoisLine", "OnBuildExemptList", "OnRawSocketConnect", "OnGarbageCollect", NULL
+};
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandModules(Instance);
+}
+
+/** Handle /MODULES
+ */
+CmdResult CommandModules::Handle (const char** parameters, int pcnt, User *user)
+{
+ for (unsigned int i = 0; i < ServerInstance->Config->module_names.size(); i++)
+ {
+ Version V = ServerInstance->Modules->modules[i]->GetVersion();
+ char modulename[MAXBUF];
+ char flagstate[MAXBUF];
+ *flagstate = 0;
+ if (V.Flags & VF_STATIC)
+ strlcat(flagstate,", static",MAXBUF);
+ if (V.Flags & VF_VENDOR)
+ strlcat(flagstate,", vendor",MAXBUF);
+ if (V.Flags & VF_COMMON)
+ strlcat(flagstate,", common",MAXBUF);
+ if (V.Flags & VF_SERVICEPROVIDER)
+ strlcat(flagstate,", service provider",MAXBUF);
+ if (!flagstate[0])
+ strcpy(flagstate," <no flags>");
+ strlcpy(modulename,ServerInstance->Config->module_names[i].c_str(),256);
+ if (IS_OPER(user))
+ {
+ user->WriteServ("900 %s :0x%08lx %d.%d.%d.%d %s (%s)",user->nick,ServerInstance->Modules->modules[i],V.Major,V.Minor,V.Revision,V.Build,ServerConfig::CleanFilename(modulename),flagstate+2);
+ }
+ else
+ {
+ user->WriteServ("900 %s :%s",user->nick,ServerConfig::CleanFilename(modulename));
+ }
+ }
+ user->WriteServ("901 %s :End of MODULES list",user->nick);
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_motd.cpp b/src/commands/cmd_motd.cpp
new file mode 100644
index 000000000..8098b2007
--- /dev/null
+++ b/src/commands/cmd_motd.cpp
@@ -0,0 +1,28 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_motd.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandMotd(Instance);
+}
+
+/** Handle /MOTD
+ */
+CmdResult CommandMotd::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->ShowMOTD();
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_names.cpp b/src/commands/cmd_names.cpp
new file mode 100644
index 000000000..4049364a7
--- /dev/null
+++ b/src/commands/cmd_names.cpp
@@ -0,0 +1,53 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_names.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandNames(Instance);
+}
+
+/** Handle /NAMES
+ */
+CmdResult CommandNames::Handle (const char** parameters, int pcnt, User *user)
+{
+ Channel* c;
+
+ if (!pcnt)
+ {
+ user->WriteServ("366 %s * :End of /NAMES list.",user->nick);
+ return CMD_SUCCESS;
+ }
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0))
+ return CMD_SUCCESS;
+
+ c = ServerInstance->FindChan(parameters[0]);
+ if (c)
+ {
+ if ((c->IsModeSet('s')) && (!c->HasUser(user)))
+ {
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, c->name);
+ return CMD_FAILURE;
+ }
+ c->UserList(user);
+ }
+ else
+ {
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ }
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_nick.cpp b/src/commands/cmd_nick.cpp
new file mode 100644
index 000000000..52e562d02
--- /dev/null
+++ b/src/commands/cmd_nick.cpp
@@ -0,0 +1,169 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+#include "commands/cmd_nick.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandNick(Instance);
+}
+
+/** 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 char** parameters, int pcnt, User *user)
+{
+ char oldnick[NICKMAX];
+
+ if (!*parameters[0] || !*user->nick)
+ {
+ /* We cant put blanks in the parameters, so for this (extremely rare) issue we just put '*' here. */
+ user->WriteServ("432 %s * :Erroneous Nickname", *user->nick ? user->nick : "*");
+ return CMD_FAILURE;
+ }
+
+ if (irc::string(user->nick) == irc::string(parameters[0]))
+ {
+ /* If its exactly the same, even case, dont do anything. */
+ if (!strcmp(user->nick,parameters[0]))
+ 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.
+ */
+ strlcpy(oldnick, user->nick, NICKMAX - 1);
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user,parameters[0]));
+ if (MOD_RESULT)
+ return CMD_FAILURE;
+ if (user->registered == REG_ALL)
+ user->WriteCommon("NICK %s",parameters[0]);
+ strlcpy(user->nick, parameters[0], NICKMAX - 1);
+ user->InvalidateCache();
+ FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick));
+ return CMD_SUCCESS;
+ }
+ else
+ {
+ QLine* mq = ServerInstance->XLines->matches_qline(parameters[0]);
+ if (mq)
+ {
+ ServerInstance->SNO->WriteToSnoMask('x', "Q-Lined nickname %s from %s!%s@%s: %s", parameters[0], user->nick, user->ident, user->host, mq->reason);
+ user->WriteServ("432 %s %s :Invalid nickname: %s",user->nick,parameters[0], mq->reason);
+ 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) && ((ServerInstance->IsNick(parameters[0]) || allowinvalid)))
+ {
+ 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);
+ InUse->WriteServ("433 %s %s :Nickname overruled.", InUse->nick, InUse->nick);
+ InUse->UpdateNickHash(InUse->uuid);
+ strlcpy(InUse->nick, InUse->uuid, NICKMAX - 1);
+ InUse->InvalidateCache();
+ InUse->registered &= ~REG_NICK;
+ }
+ else
+ {
+ /* No camping, tell the incoming user to stop trying to change nick ;p */
+ user->WriteServ("433 %s %s :Nickname is already in use.", user->registered >= REG_NICK ? user->nick : "*", parameters[0]);
+ return CMD_FAILURE;
+ }
+ }
+ }
+ if (((!ServerInstance->IsNick(parameters[0]))) && (IS_LOCAL(user)))
+ {
+ if (!allowinvalid)
+ {
+ user->WriteServ("432 %s %s :Erroneous Nickname",user->nick,parameters[0]);
+ return CMD_FAILURE;
+ }
+ }
+
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user,parameters[0]));
+ if (MOD_RESULT)
+ // 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]);
+
+ strlcpy(oldnick, user->nick, NICKMAX - 1);
+
+ /* change the nick of the user in the users_hash */
+ user = user->UpdateNickHash(parameters[0]);
+
+ /* actually change the nick within the record */
+ if (!user)
+ return CMD_FAILURE;
+ if (!*user->nick)
+ return CMD_FAILURE;
+
+ strlcpy(user->nick, parameters[0], NICKMAX - 1);
+
+ user->InvalidateCache();
+
+ /* Update display nicks */
+ for (UCListIter v = user->chans.begin(); v != user->chans.end(); v++)
+ {
+ CUList* ulist = v->first->GetUsers();
+ CUList::iterator i = ulist->find(user);
+ if (i != ulist->end())
+ i->second = user->nick;
+ }
+
+ if (user->registered < REG_NICKUSER)
+ {
+ user->registered = (user->registered | REG_NICK);
+ }
+ else if (user->registered == REG_NICKUSER)
+ {
+ /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnUserRegister,OnUserRegister(user));
+ if (MOD_RESULT > 0)
+ return CMD_FAILURE;
+ }
+ else if (user->registered == REG_ALL)
+ {
+ FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick));
+ }
+
+ return CMD_SUCCESS;
+
+}
+
+CmdResult CommandNick::HandleInternal(const unsigned int id, const std::deque<classbase*> &parameters)
+{
+ allowinvalid = (id != 0);
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_notice.cpp b/src/commands/cmd_notice.cpp
new file mode 100644
index 000000000..9cc846dd8
--- /dev/null
+++ b/src/commands/cmd_notice.cpp
@@ -0,0 +1,159 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "wildcard.h"
+#include "commands/cmd_notice.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandNotice(Instance);
+}
+
+CmdResult CommandNotice::Handle (const char** parameters, int pcnt, User *user)
+{
+ User *dest;
+ Channel *chan;
+
+ CUList exempt_list;
+
+ user->idle_lastmsg = ServerInstance->Time();
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0))
+ return CMD_SUCCESS;
+ if ((parameters[0][0] == '$') && (IS_OPER(user) || ServerInstance->ULine(user->server)))
+ {
+ int MOD_RESULT = 0;
+ std::string temp = parameters[1];
+ FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user,(void*)parameters[0],TYPE_SERVER,temp,0,exempt_list));
+ if (MOD_RESULT)
+ return CMD_FAILURE;
+ parameters[1] = temp.c_str();
+ // notice to server mask
+ const char* servermask = parameters[0] + 1;
+ if (match(ServerInstance->Config->ServerName,servermask))
+ {
+ user->SendAll("NOTICE", "%s", parameters[1]);
+ }
+ FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,(void*)parameters[0],TYPE_SERVER,parameters[1],0,exempt_list));
+ return CMD_SUCCESS;
+ }
+ char status = 0;
+ if ((*parameters[0] == '@') || (*parameters[0] == '%') || (*parameters[0] == '+'))
+ {
+ status = *parameters[0];
+ parameters[0]++;
+ }
+ if (*parameters[0] == '#')
+ {
+ chan = ServerInstance->FindChan(parameters[0]);
+
+ exempt_list[user] = user->nick;
+
+ if (chan)
+ {
+ if (IS_LOCAL(user))
+ {
+ if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
+ {
+ user->WriteServ("404 %s %s :Cannot send to channel (no external messages)", user->nick, chan->name);
+ return CMD_FAILURE;
+ }
+ if ((chan->IsModeSet('m')) && (chan->GetStatus(user) < STATUS_VOICE))
+ {
+ user->WriteServ("404 %s %s :Cannot send to channel (+m)", user->nick, chan->name);
+ return CMD_FAILURE;
+ }
+ }
+ int MOD_RESULT = 0;
+
+ std::string temp = parameters[1];
+ FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user,chan,TYPE_CHANNEL,temp,status, exempt_list));
+ if (MOD_RESULT) {
+ return CMD_FAILURE;
+ }
+ parameters[1] = temp.c_str();
+
+ if (temp.empty())
+ {
+ user->WriteServ("412 %s :No text to send", user->nick);
+ return CMD_FAILURE;
+ }
+
+ if (status)
+ {
+ if (ServerInstance->Config->UndernetMsgPrefix)
+ {
+ chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%c %s", status, chan->name, status, parameters[1]);
+ }
+ else
+ {
+ chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%s", status, chan->name, parameters[1]);
+ }
+ }
+ else
+ {
+ chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name, parameters[1]);
+ }
+
+ FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,parameters[1],status,exempt_list));
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+ }
+
+ if (IS_LOCAL(user))
+ dest = ServerInstance->FindNickOnly(parameters[0]);
+ else
+ dest = ServerInstance->FindNick(parameters[0]);
+
+ if (dest)
+ {
+ if (!*parameters[1])
+ {
+ user->WriteServ("412 %s :No text to send", user->nick);
+ return CMD_FAILURE;
+ }
+
+ int MOD_RESULT = 0;
+ std::string temp = parameters[1];
+ FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user,dest,TYPE_USER,temp,0,exempt_list));
+ if (MOD_RESULT) {
+ return CMD_FAILURE;
+ }
+ parameters[1] = (char*)temp.c_str();
+
+ if (IS_LOCAL(dest))
+ {
+ // direct write, same server
+ user->WriteTo(dest, "NOTICE %s :%s", dest->nick, parameters[1]);
+ }
+
+ FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,parameters[1],0,exempt_list));
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+
+}
+
diff --git a/src/commands/cmd_oper.cpp b/src/commands/cmd_oper.cpp
new file mode 100644
index 000000000..bcb2991b7
--- /dev/null
+++ b/src/commands/cmd_oper.cpp
@@ -0,0 +1,159 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "wildcard.h"
+#include "commands/cmd_oper.h"
+#include "hashcomp.h"
+
+bool OneOfMatches(const char* host, const char* ip, const char* hostlist)
+{
+ std::stringstream hl(hostlist);
+ std::string xhost;
+ while (hl >> xhost)
+ {
+ if (match(host,xhost.c_str()) || match(ip,xhost.c_str(),true))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandOper(Instance);
+}
+
+CmdResult CommandOper::Handle (const char** parameters, int pcnt, 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];
+ 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,user->host);
+ snprintf(TheIP, MAXBUF,"%s@%s",user->ident,user->GetIPString());
+
+ for (int i = 0; i < ServerInstance->Config->ConfValueEnum(ServerInstance->Config->config_data, "oper"); i++)
+ {
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "name", i, LoginName, MAXBUF);
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "password", i, Password, MAXBUF);
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "type", i, OperType, MAXBUF);
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "host", i, HostName, MAXBUF);
+
+ match_login = !strcmp(LoginName,parameters[0]);
+ match_pass = !ServerInstance->OperPassCompare(Password,parameters[1], i);
+ match_hosts = OneOfMatches(TheHost,TheIP,HostName);
+
+ if (match_login && match_pass && match_hosts)
+ {
+ type_invalid = true;
+ for (j =0; j < ServerInstance->Config->ConfValueEnum(ServerInstance->Config->config_data, "type"); j++)
+ {
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "type", "name", j, TypeName, MAXBUF);
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "type", "class", j, ClassName, MAXBUF);
+
+ if (!strcmp(TypeName,OperType))
+ {
+ /* found this oper's opertype */
+ if (!ServerInstance->IsNick(TypeName))
+ {
+ user->WriteServ("491 %s :Invalid oper type (oper types must follow the same syntax as nicknames)",user->nick);
+ ServerInstance->SNO->WriteToSnoMask('o',"CONFIGURATION ERROR! Oper type '%s' contains invalid characters",OperType);
+ ServerInstance->Log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but oper type erroneous.",user->nick,user->ident,user->host);
+ return CMD_FAILURE;
+ }
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "type","host", j, HostName, MAXBUF);
+ if (*HostName)
+ user->ChangeDisplayedHost(HostName);
+ if (*ClassName)
+ user->CheckClass(ClassName);
+ found = true;
+ type_invalid = false;
+ break;
+ }
+ }
+ }
+ if (match_login || found)
+ break;
+ }
+ if (found)
+ {
+ /* correct oper credentials */
+ ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')",user->nick,user->ident,user->host,irc::Spacify(OperType),parameters[0]);
+ user->WriteServ("381 %s :You are now %s %s",user->nick, strchr("aeiouAEIOU", *OperType) ? "an" : "a", irc::Spacify(OperType));
+ if (!user->IsModeSet('o'))
+ user->Oper(OperType);
+ }
+ else
+ {
+ std::deque<std::string> n;
+ n.push_back("o");
+ 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->WriteServ("491 %s :Invalid oper credentials",user->nick);
+ 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,user->ident,user->host, parameters[0], fields.c_str());
+ ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
+ n.push_back(broadcast);
+ Event rmode2((char *)&n, NULL, "send_snoset");
+ rmode2.Send(ServerInstance);
+
+ ServerInstance->Log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': The following fields did not match: %s",user->nick,user->ident,user->host,parameters[0],fields.c_str());
+ return CMD_FAILURE;
+ }
+ else
+ {
+ user->WriteServ("491 %s :Your oper block does not have a valid opertype associated with it",user->nick);
+
+ snprintf(broadcast, MAXBUF, "CONFIGURATION ERROR! Oper block '%s': missing OperType %s",parameters[0],OperType);
+
+ ServerInstance->SNO->WriteToSnoMask('o', std::string(broadcast));
+ n.push_back(broadcast);
+ Event rmode2((char *)&n, NULL, "send_snoset");
+ rmode2.Send(ServerInstance);
+
+ ServerInstance->Log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': credentials valid, but oper type nonexistent.",user->nick,user->ident,user->host,parameters[0]);
+ return CMD_FAILURE;
+ }
+ }
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_part.cpp b/src/commands/cmd_part.cpp
new file mode 100644
index 000000000..46108eca2
--- /dev/null
+++ b/src/commands/cmd_part.cpp
@@ -0,0 +1,42 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_part.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandPart(Instance);
+}
+
+CmdResult CommandPart::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0))
+ return CMD_SUCCESS;
+
+ Channel* c = ServerInstance->FindChan(parameters[0]);
+
+ if (c)
+ {
+ if (!c->PartUser(user, pcnt > 1 ? parameters[1] : NULL))
+ /* Arse, who stole our channel! :/ */
+ delete c;
+ }
+ else
+ {
+ user->WriteServ( "401 %s %s :No such channel", user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_pass.cpp b/src/commands/cmd_pass.cpp
new file mode 100644
index 000000000..801d9923b
--- /dev/null
+++ b/src/commands/cmd_pass.cpp
@@ -0,0 +1,41 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_pass.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandPass(Instance);
+}
+
+CmdResult CommandPass::Handle (const char** parameters, int pcnt, User *user)
+{
+ // Check to make sure they havnt registered -- Fix by FCS
+ if (user->registered == REG_ALL)
+ {
+ user->WriteServ("462 %s :You may not reregister",user->nick);
+ return CMD_FAILURE;
+ }
+ ConnectClass* a = user->GetClass();
+ if (!a)
+ return CMD_FAILURE;
+
+ strlcpy(user->password,parameters[0],63);
+ if (a->GetPass() == parameters[0])
+ {
+ user->haspassed = true;
+ }
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_ping.cpp b/src/commands/cmd_ping.cpp
new file mode 100644
index 000000000..fb0b03829
--- /dev/null
+++ b/src/commands/cmd_ping.cpp
@@ -0,0 +1,26 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_ping.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandPing(Instance);
+}
+
+CmdResult CommandPing::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->WriteServ("PONG %s :%s",ServerInstance->Config->ServerName,parameters[0]);
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_pong.cpp b/src/commands/cmd_pong.cpp
new file mode 100644
index 000000000..e1927deab
--- /dev/null
+++ b/src/commands/cmd_pong.cpp
@@ -0,0 +1,27 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_pong.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandPong(Instance);
+}
+
+CmdResult CommandPong::Handle (const char** parameters, int pcnt, User *user)
+{
+ // set the user as alive so they survive to next ping
+ user->lastping = 1;
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_privmsg.cpp b/src/commands/cmd_privmsg.cpp
new file mode 100644
index 000000000..96aff8392
--- /dev/null
+++ b/src/commands/cmd_privmsg.cpp
@@ -0,0 +1,165 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "wildcard.h"
+#include "commands/cmd_privmsg.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandPrivmsg(Instance);
+}
+
+CmdResult CommandPrivmsg::Handle (const char** parameters, int pcnt, User *user)
+{
+ User *dest;
+ Channel *chan;
+ CUList except_list;
+
+ user->idle_lastmsg = ServerInstance->Time();
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0))
+ return CMD_SUCCESS;
+
+ if ((parameters[0][0] == '$') && (IS_OPER(user) || ServerInstance->ULine(user->server)))
+ {
+ int MOD_RESULT = 0;
+ std::string temp = parameters[1];
+ FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user,(void*)parameters[0],TYPE_SERVER,temp,0,except_list));
+ if (MOD_RESULT)
+ return CMD_FAILURE;
+ parameters[1] = temp.c_str();
+ // notice to server mask
+ const char* servermask = parameters[0] + 1;
+ if (match(ServerInstance->Config->ServerName,servermask))
+ {
+ user->SendAll("PRIVMSG", "%s", parameters[1]);
+ }
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,(void*)parameters[0],TYPE_SERVER,parameters[1],0,except_list));
+ return CMD_SUCCESS;
+ }
+ char status = 0;
+ if ((*parameters[0] == '@') || (*parameters[0] == '%') || (*parameters[0] == '+'))
+ {
+ status = *parameters[0];
+ parameters[0]++;
+ }
+ if (parameters[0][0] == '#')
+ {
+ chan = ServerInstance->FindChan(parameters[0]);
+
+ except_list[user] = user->nick;
+
+ if (chan)
+ {
+ if (IS_LOCAL(user))
+ {
+ if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
+ {
+ user->WriteServ("404 %s %s :Cannot send to channel (no external messages)", user->nick, chan->name);
+ return CMD_FAILURE;
+ }
+ if ((chan->IsModeSet('m')) && (chan->GetStatus(user) < STATUS_VOICE))
+ {
+ user->WriteServ("404 %s %s :Cannot send to channel (+m)", user->nick, chan->name);
+ return CMD_FAILURE;
+ }
+ }
+ int MOD_RESULT = 0;
+
+ std::string temp = parameters[1];
+ FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user,chan,TYPE_CHANNEL,temp,status,except_list));
+ if (MOD_RESULT) {
+ return CMD_FAILURE;
+ }
+ parameters[1] = temp.c_str();
+
+ /* Check again, a module may have zapped the input string */
+ if (temp.empty())
+ {
+ user->WriteServ("412 %s :No text to send", user->nick);
+ return CMD_FAILURE;
+ }
+
+ if (status)
+ {
+ if (ServerInstance->Config->UndernetMsgPrefix)
+ {
+ chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%c %s", status, chan->name, status, parameters[1]);
+ }
+ else
+ {
+ chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%s", status, chan->name, parameters[1]);
+ }
+ }
+ else
+ {
+ chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %s :%s", chan->name, parameters[1]);
+ }
+
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,parameters[1],status,except_list));
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+ }
+
+ if (IS_LOCAL(user))
+ dest = ServerInstance->FindNickOnly(parameters[0]);
+ else
+ dest = ServerInstance->FindNick(parameters[0]);
+
+ if (dest)
+ {
+ if (!*parameters[1])
+ {
+ user->WriteServ("412 %s :No text to send", user->nick);
+ return CMD_FAILURE;
+ }
+
+ if (IS_AWAY(dest))
+ {
+ /* auto respond with aweh msg */
+ user->WriteServ("301 %s %s :%s",user->nick,dest->nick,dest->awaymsg);
+ }
+
+ int MOD_RESULT = 0;
+
+ std::string temp = parameters[1];
+ FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user,dest,TYPE_USER,temp,0,except_list));
+ if (MOD_RESULT) {
+ return CMD_FAILURE;
+ }
+ parameters[1] = (char*)temp.c_str();
+
+ if (IS_LOCAL(dest))
+ {
+ // direct write, same server
+ user->WriteTo(dest, "PRIVMSG %s :%s", dest->nick, parameters[1]);
+ }
+
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,dest,TYPE_USER,parameters[1],0,except_list));
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_qline.cpp b/src/commands/cmd_qline.cpp
new file mode 100644
index 000000000..16927d234
--- /dev/null
+++ b/src/commands/cmd_qline.cpp
@@ -0,0 +1,77 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+#include "commands/cmd_qline.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandQline(Instance);
+}
+
+CmdResult CommandQline::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (pcnt >= 3)
+ {
+ if (ServerInstance->NickMatchesEveryone(parameters[0],user))
+ return CMD_FAILURE;
+
+ if (strchr(parameters[0],'@') || strchr(parameters[0],'!') || strchr(parameters[0],'.'))
+ {
+ user->WriteServ("NOTICE %s :*** A Q-Line only bans a nick pattern, not a nick!user@host pattern.",user->nick);
+ return CMD_FAILURE;
+ }
+
+ long duration = ServerInstance->Duration(parameters[1]);
+ if (ServerInstance->XLines->add_qline(duration,user->nick,parameters[2],parameters[0]))
+ {
+ int to_apply = APPLY_QLINES;
+ FOREACH_MOD(I_OnAddQLine,OnAddQLine(duration, user, parameters[2], parameters[0]));
+ if (!duration)
+ {
+ to_apply |= APPLY_PERM_ONLY;
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Q-line for %s.",user->nick,parameters[0]);
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Q-line for %s, expires on %s",user->nick,parameters[0],
+ ServerInstance->TimeString(c_requires_crap).c_str());
+ }
+ ServerInstance->XLines->apply_lines(to_apply);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** Q-Line for %s already exists",user->nick,parameters[0]);
+ }
+ }
+ else
+ {
+ if (ServerInstance->XLines->del_qline(parameters[0]))
+ {
+ FOREACH_MOD(I_OnDelQLine,OnDelQLine(user, parameters[0]));
+ ServerInstance->SNO->WriteToSnoMask('x',"%s Removed Q-line on %s.",user->nick,parameters[0]);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** Q-Line %s not found in list, try /stats q.",user->nick,parameters[0]);
+ return CMD_FAILURE;
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_quit.cpp b/src/commands/cmd_quit.cpp
new file mode 100644
index 000000000..c74f868ba
--- /dev/null
+++ b/src/commands/cmd_quit.cpp
@@ -0,0 +1,45 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_quit.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandQuit(Instance);
+}
+
+CmdResult CommandQuit::Handle (const char** parameters, int pcnt, User *user)
+{
+
+ std::string quitmsg;
+
+ if (IS_LOCAL(user))
+ {
+ if (*ServerInstance->Config->FixedQuit)
+ quitmsg = ServerInstance->Config->FixedQuit;
+ else
+ quitmsg = pcnt ?
+ ServerInstance->Config->PrefixQuit + std::string(parameters[0]) + ServerInstance->Config->SuffixQuit
+ : "Client exited";
+ }
+ else
+ quitmsg = pcnt ? parameters[0] : "Client exited";
+
+ User::QuitUser(ServerInstance, user, quitmsg);
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_rehash.cpp b/src/commands/cmd_rehash.cpp
new file mode 100644
index 000000000..2246c2f46
--- /dev/null
+++ b/src/commands/cmd_rehash.cpp
@@ -0,0 +1,54 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_rehash.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandRehash(Instance);
+}
+
+CmdResult CommandRehash::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->WriteServ("382 %s %s :Rehashing",user->nick,ServerConfig::CleanFilename(ServerInstance->ConfigFileName));
+ std::string parameter;
+ std::string old_disabled = ServerInstance->Config->DisabledCommands;
+ if (pcnt)
+ {
+ parameter = parameters[0];
+ }
+ else
+ {
+ ServerInstance->WriteOpers("*** %s is rehashing config file %s",user->nick,ServerConfig::CleanFilename(ServerInstance->ConfigFileName));
+ ServerInstance->CloseLog();
+ if (!ServerInstance->OpenLog(ServerInstance->Config->argv, ServerInstance->Config->argc))
+ user->WriteServ("*** NOTICE %s :ERROR: Could not open logfile %s: %s", user->nick, ServerInstance->Config->logpath.c_str(), strerror(errno));
+ ServerInstance->RehashUsersAndChans();
+ FOREACH_MOD(I_OnGarbageCollect, OnGarbageCollect());
+ ServerInstance->Config->Read(false,user);
+ ServerInstance->Res->Rehash();
+ ServerInstance->ResetMaxBans();
+ }
+ if (old_disabled != ServerInstance->Config->DisabledCommands)
+ InitializeDisabledCommands(ServerInstance->Config->DisabledCommands, ServerInstance);
+
+ FOREACH_MOD(I_OnRehash,OnRehash(user, parameter));
+
+ ServerInstance->BuildISupport();
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_reloadmodule.cpp b/src/commands/cmd_reloadmodule.cpp
new file mode 100644
index 000000000..5180807b2
--- /dev/null
+++ b/src/commands/cmd_reloadmodule.cpp
@@ -0,0 +1,38 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_reloadmodule.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandReloadmodule(Instance);
+}
+
+CmdResult CommandReloadmodule::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (ServerInstance->Modules->Unload(parameters[0]))
+ {
+ ServerInstance->WriteOpers("*** RELOAD MODULE: %s unloaded %s",user->nick, parameters[0]);
+ if (ServerInstance->Modules->Load(parameters[0]))
+ {
+ ServerInstance->WriteOpers("*** RELOAD MODULE: %s reloaded %s",user->nick, parameters[0]);
+ user->WriteServ("975 %s %s :Module successfully reloaded.",user->nick, parameters[0]);
+ return CMD_SUCCESS;
+ }
+ }
+
+ ServerInstance->WriteOpers("*** RELOAD MODULE: %s unsuccessfully reloaded %s",user->nick, parameters[0]);
+ user->WriteServ("975 %s %s :Module failed to reload.",user->nick, parameters[0]);
+ return CMD_FAILURE;
+}
diff --git a/src/commands/cmd_restart.cpp b/src/commands/cmd_restart.cpp
new file mode 100644
index 000000000..3f1ff13b8
--- /dev/null
+++ b/src/commands/cmd_restart.cpp
@@ -0,0 +1,47 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_restart.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandRestart(Instance);
+}
+
+CmdResult CommandRestart::Handle (const char** parameters, int pcnt, User *user)
+{
+ ServerInstance->Log(DEFAULT,"Restart: %s",user->nick);
+ if (!strcmp(parameters[0],ServerInstance->Config->restartpass))
+ {
+ ServerInstance->WriteOpers("*** RESTART command from %s!%s@%s, restarting server.",user->nick,user->ident,user->host);
+
+ try
+ {
+ ServerInstance->Restart("Server restarting.");
+ }
+ catch (...)
+ {
+ /* We dont actually get here unless theres some fatal and unrecoverable error. */
+ exit(0);
+ }
+ }
+ else
+ {
+ ServerInstance->WriteOpers("*** Failed RESTART Command from %s!%s@%s.",user->nick,user->ident,user->host);
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_rules.cpp b/src/commands/cmd_rules.cpp
new file mode 100644
index 000000000..f9009c9df
--- /dev/null
+++ b/src/commands/cmd_rules.cpp
@@ -0,0 +1,26 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_rules.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandRules(Instance);
+}
+
+CmdResult CommandRules::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->ShowRULES();
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_server.cpp b/src/commands/cmd_server.cpp
new file mode 100644
index 000000000..9e80cc386
--- /dev/null
+++ b/src/commands/cmd_server.cpp
@@ -0,0 +1,29 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_server.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandServer(Instance);
+}
+
+CmdResult CommandServer::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->WriteServ("666 %s :You cannot identify as a server, you are a USER. IRC Operators informed.",user->nick);
+ ServerInstance->WriteOpers("*** WARNING: %s attempted to issue a SERVER command and is registered as a user!",user->nick);
+ return CMD_FAILURE;
+}
diff --git a/src/commands/cmd_squit.cpp b/src/commands/cmd_squit.cpp
new file mode 100644
index 000000000..8f1cbf43d
--- /dev/null
+++ b/src/commands/cmd_squit.cpp
@@ -0,0 +1,31 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_squit.h"
+
+/*
+ * This is handled by the server linking module, if necessary. Do not remove this stub.
+ */
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandSquit(Instance);
+}
+
+CmdResult CommandSquit::Handle (const char** parameters, int pcnt, 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);
+ return CMD_FAILURE;
+}
diff --git a/src/commands/cmd_stats.cpp b/src/commands/cmd_stats.cpp
new file mode 100644
index 000000000..52172df06
--- /dev/null
+++ b/src/commands/cmd_stats.cpp
@@ -0,0 +1,318 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/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
+
+#endif
+#include "xline.h"
+#include "commands/cmd_stats.h"
+#include "commands/cmd_whowas.h"
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandStats(Instance);
+}
+
+CmdResult CommandStats::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (IS_LOCAL(user))
+ {
+ string_list values;
+ DoStats(this->ServerInstance, *parameters[0], user, values);
+ for (size_t i = 0; i < values.size(); i++)
+ user->Write(":%s", values[i].c_str());
+ }
+
+ return CMD_SUCCESS;
+}
+
+DllExport void DoStats(InspIRCd* ServerInstance, char statschar, User* user, string_list &results)
+{
+ std::string sn = ServerInstance->Config->ServerName;
+
+ if ((!*ServerInstance->Config->UserStats && !IS_OPER(user)) || (!IS_OPER(user) && !ServerInstance->ULine(user->server) && !strchr(ServerInstance->Config->UserStats,statschar)))
+ {
+ ServerInstance->SNO->WriteToSnoMask('t',
+ "%s '%c' denied for %s (%s@%s)",
+ (IS_LOCAL(user) ? "Stats" : "Remote stats"),
+ statschar, user->nick, user->ident, user->host);
+ results.push_back(sn + " 481 " + user->nick + " :Permission denied - STATS " + statschar + " is oper-only");
+ return;
+ }
+
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnStats,OnStats(statschar,user,results));
+ if (MOD_RESULT)
+ return;
+
+ switch (statschar)
+ {
+ /* stats p (show listening ports and registered clients on each) */
+ case 'p':
+ {
+ for (size_t i = 0; i < ServerInstance->Config->ports.size(); i++)
+ {
+ std::string ip = ServerInstance->Config->ports[i]->GetIP();
+ if (ip.empty())
+ ip.assign("*");
+
+ results.push_back(sn+" 249 "+user->nick+" :"+ ip + ":"+ConvToStr(ServerInstance->Config->ports[i]->GetPort())+" (client, " +
+ ServerInstance->Config->ports[i]->GetDescription() + ")");
+ }
+ }
+ break;
+
+ case 'n':
+ case 'c':
+ {
+ /* This stats symbol must be handled by a linking module */
+ }
+ break;
+
+ case 'i':
+ {
+ int idx = 0;
+ for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++)
+ {
+ results.push_back(sn+" 215 "+user->nick+" I NOMATCH * "+i->GetHost()+" "+ConvToStr(MAXCLIENTS)+" "+ConvToStr(idx)+" "+ServerInstance->Config->ServerName+" *");
+ idx++;
+ }
+ }
+ break;
+
+ case 'Y':
+ {
+ int idx = 0;
+ for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++)
+ {
+ results.push_back(sn+" 218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(i->GetPingTime())+" 0 "+ConvToStr(i->GetSendqMax())+" :"+
+ ConvToStr(i->GetFlood())+" "+ConvToStr(i->GetRegTimeout()));
+ idx++;
+ }
+ }
+ break;
+
+ case 'U':
+ {
+ char ulined[MAXBUF];
+ for (int i = 0; i < ServerInstance->Config->ConfValueEnum(ServerInstance->Config->config_data, "uline"); i++)
+ {
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "uline","server", i, ulined, MAXBUF);
+ results.push_back(sn+" 248 "+user->nick+" U "+std::string(ulined));
+ }
+ }
+ break;
+
+ case 'P':
+ {
+ int idx = 0;
+ for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
+ {
+ if (IS_OPER(i->second) && !ServerInstance->ULine(i->second->server))
+ {
+ results.push_back(sn+" 249 "+user->nick+" :"+i->second->nick+" ("+i->second->ident+"@"+i->second->dhost+") Idle: "+
+ (IS_LOCAL(i->second) ? ConvToStr(ServerInstance->Time() - i->second->idle_lastmsg) + " secs" : "unavailable"));
+ idx++;
+ }
+ }
+ results.push_back(sn+" 249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)");
+ }
+ break;
+
+ case 'k':
+ ServerInstance->XLines->stats_k(user,results);
+ break;
+
+ case 'g':
+ ServerInstance->XLines->stats_g(user,results);
+ break;
+
+ case 'q':
+ ServerInstance->XLines->stats_q(user,results);
+ break;
+
+ case 'Z':
+ ServerInstance->XLines->stats_z(user,results);
+ break;
+
+ case 'e':
+ ServerInstance->XLines->stats_e(user,results);
+ break;
+
+ /* stats m (list number of times each command has been used, plus bytecount) */
+ case 'm':
+ for (Commandable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++)
+ {
+ if (i->second->use_count)
+ {
+ /* RPL_STATSCOMMANDS */
+ results.push_back(sn+" 212 "+user->nick+" "+i->second->command+" "+ConvToStr(i->second->use_count)+" "+ConvToStr(i->second->total_bytes));
+ }
+ }
+ break;
+
+ /* stats z (debug and memory info) */
+ case 'z':
+ {
+ results.push_back(sn+" 240 "+user->nick+" :InspIRCd(CLASS) "+ConvToStr(sizeof(InspIRCd))+" bytes");
+ results.push_back(sn+" 249 "+user->nick+" :Users(HASH_MAP) "+ConvToStr(ServerInstance->clientlist->size())+" ("+ConvToStr(ServerInstance->clientlist->size()*sizeof(User))+" bytes)");
+ results.push_back(sn+" 249 "+user->nick+" :Channels(HASH_MAP) "+ConvToStr(ServerInstance->chanlist->size())+" ("+ConvToStr(ServerInstance->chanlist->size()*sizeof(Channel))+" bytes)");
+ results.push_back(sn+" 249 "+user->nick+" :Commands(VECTOR) "+ConvToStr(ServerInstance->Parser->cmdlist.size())+" ("+ConvToStr(ServerInstance->Parser->cmdlist.size()*sizeof(Command))+" bytes)");
+
+ if (!ServerInstance->Config->WhoWasGroupSize == 0 && !ServerInstance->Config->WhoWasMaxGroups == 0)
+ {
+ Command* whowas_command = ServerInstance->Parser->GetHandler("WHOWAS");
+ if (whowas_command)
+ {
+ std::deque<classbase*> params;
+ Extensible whowas_stats;
+ params.push_back(&whowas_stats);
+ whowas_command->HandleInternal(WHOWAS_STATS, params);
+ if (whowas_stats.GetExt("stats"))
+ {
+ char* stats;
+ whowas_stats.GetExt("stats", stats);
+ results.push_back(sn+" 249 "+user->nick+" :"+ConvToStr(stats));
+ }
+ }
+ }
+
+ results.push_back(sn+" 249 "+user->nick+" :MOTD(VECTOR) "+ConvToStr(ServerInstance->Config->MOTD.size())+", RULES(VECTOR) "+ConvToStr(ServerInstance->Config->RULES.size()));
+ results.push_back(sn+" 249 "+user->nick+" :Modules(VECTOR) "+ConvToStr(ServerInstance->Modules->modules.size())+" ("+ConvToStr(ServerInstance->Modules->modules.size()*sizeof(Module))+" bytes)");
+ results.push_back(sn+" 249 "+user->nick+" :ModuleHandles(VECTOR) "+ConvToStr(ServerInstance->Modules->handles.size())+" ("+ConvToStr(ServerInstance->Modules->handles.size()*sizeof(ircd_module))+" bytes)");
+
+#ifndef WIN32
+ /* Moved this down here so all the not-windows stuff (look w00tie, I didn't say win32!) is in one ifndef.
+ * Also cuts out some identical code in both branches of the ifndef. -- Om
+ */
+ rusage R;
+
+ /* Not sure why we were doing '0' with a RUSAGE_SELF comment rather than just using RUSAGE_SELF -- Om */
+ if (!getrusage(RUSAGE_SELF,&R)) /* RUSAGE_SELF */
+ {
+ results.push_back(sn+" 249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K");
+ results.push_back(sn+" 249 "+user->nick+" :Signals: "+ConvToStr(R.ru_nsignals));
+ results.push_back(sn+" 249 "+user->nick+" :Page faults: "+ConvToStr(R.ru_majflt));
+ results.push_back(sn+" 249 "+user->nick+" :Swaps: "+ConvToStr(R.ru_nswap));
+ results.push_back(sn+" 249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw));
+
+ timeval tv;
+ char percent[30];
+ gettimeofday(&tv, NULL);
+
+ float n_elapsed = ((tv.tv_sec - ServerInstance->stats->LastSampled.tv_sec) * 1000000 + tv.tv_usec - ServerInstance->stats->LastSampled.tv_usec);
+ float n_eaten = ((R.ru_utime.tv_sec - ServerInstance->stats->LastCPU.tv_sec) * 1000000 + R.ru_utime.tv_usec - ServerInstance->stats->LastCPU.tv_usec);
+ float per = (n_eaten / n_elapsed) * 100;
+
+ snprintf(percent, 30, "%03.5f%%", per);
+ results.push_back(sn+" 249 "+user->nick+" :CPU Usage: "+percent);
+ }
+#endif
+ }
+ break;
+
+ case 'T':
+ {
+ char buffer[MAXBUF];
+ results.push_back(sn+" 249 "+user->nick+" :accepts "+ConvToStr(ServerInstance->stats->statsAccept)+" refused "+ConvToStr(ServerInstance->stats->statsRefused));
+ results.push_back(sn+" 249 "+user->nick+" :unknown commands "+ConvToStr(ServerInstance->stats->statsUnknown));
+ results.push_back(sn+" 249 "+user->nick+" :nick collisions "+ConvToStr(ServerInstance->stats->statsCollisions));
+ results.push_back(sn+" 249 "+user->nick+" :dns requests "+ConvToStr(ServerInstance->stats->statsDnsGood+ServerInstance->stats->statsDnsBad)+" succeeded "+ConvToStr(ServerInstance->stats->statsDnsGood)+" failed "+ConvToStr(ServerInstance->stats->statsDnsBad));
+ results.push_back(sn+" 249 "+user->nick+" :connection count "+ConvToStr(ServerInstance->stats->statsConnects));
+ snprintf(buffer,MAXBUF," 249 %s :bytes sent %5.2fK recv %5.2fK",user->nick,ServerInstance->stats->statsSent / 1024,ServerInstance->stats->statsRecv / 1024);
+ results.push_back(sn+buffer);
+ }
+ break;
+
+ /* stats o */
+ case 'o':
+ for (int i = 0; i < ServerInstance->Config->ConfValueEnum(ServerInstance->Config->config_data, "oper"); i++)
+ {
+ char LoginName[MAXBUF];
+ char HostName[MAXBUF];
+ char OperType[MAXBUF];
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper","name", i, LoginName, MAXBUF);
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper","host", i, HostName, MAXBUF);
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper","type", i, OperType, MAXBUF);
+ results.push_back(sn+" 243 "+user->nick+" O "+HostName+" * "+LoginName+" "+OperType+" 0");
+ }
+ break;
+
+ /* stats l (show user I/O stats) */
+ case 'l':
+ results.push_back(sn+" 211 "+user->nick+" :nick[ident@host] sendq cmds_out bytes_out cmds_in bytes_in time_open");
+ for (std::vector<User*>::iterator n = ServerInstance->local_users.begin(); n != ServerInstance->local_users.end(); n++)
+ {
+ User* i = *n;
+ if (ServerInstance->IsNick(i->nick))
+ {
+ results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->sendq.length())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age));
+ }
+ }
+ break;
+
+ /* stats L (show user I/O stats with IP addresses) */
+ case 'L':
+ results.push_back(sn+" 211 "+user->nick+" :nick[ident@ip] sendq cmds_out bytes_out cmds_in bytes_in time_open");
+ for (std::vector<User*>::iterator n = ServerInstance->local_users.begin(); n != ServerInstance->local_users.end(); n++)
+ {
+ User* i = *n;
+ if (ServerInstance->IsNick(i->nick))
+ {
+ results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->sendq.length())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age));
+ }
+ }
+ break;
+
+ /* stats u (show server uptime) */
+ case 'u':
+ {
+ time_t current_time = 0;
+ current_time = ServerInstance->Time();
+ time_t server_uptime = current_time - ServerInstance->startup_time;
+ struct tm* stime;
+ stime = gmtime(&server_uptime);
+ /* i dont know who the hell would have an ircd running for over a year nonstop, but
+ * Craig suggested this, and it seemed a good idea so in it went */
+ if (stime->tm_year > 70)
+ {
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF," 242 %s :Server up %d years, %d days, %.2d:%.2d:%.2d",user->nick,(stime->tm_year-70),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec);
+ results.push_back(sn+buffer);
+ }
+ else
+ {
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF," 242 %s :Server up %d days, %.2d:%.2d:%.2d",user->nick,stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec);
+ results.push_back(sn+buffer);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ results.push_back(sn+" 219 "+user->nick+" "+statschar+" :End of /STATS report");
+ ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)",
+ (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick, user->ident, user->host);
+ return;
+}
diff --git a/src/commands/cmd_time.cpp b/src/commands/cmd_time.cpp
new file mode 100644
index 000000000..97f4eb5ae
--- /dev/null
+++ b/src/commands/cmd_time.cpp
@@ -0,0 +1,38 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_time.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandTime(Instance);
+}
+
+CmdResult CommandTime::Handle (const char** parameters, int pcnt, 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->WriteServ("391 %s %s :%s",user->nick,ServerInstance->Config->ServerName,tms);
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_topic.cpp b/src/commands/cmd_topic.cpp
new file mode 100644
index 000000000..e12fd64f9
--- /dev/null
+++ b/src/commands/cmd_topic.cpp
@@ -0,0 +1,115 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_topic.h"
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandTopic(Instance);
+}
+
+CmdResult CommandTopic::Handle (const char** parameters, int pcnt, User *user)
+{
+ Channel* Ptr;
+
+ if (pcnt == 1)
+ {
+ Ptr = ServerInstance->FindChan(parameters[0]);
+ if (Ptr)
+ {
+ if ((Ptr->IsModeSet('s')) && (!Ptr->HasUser(user)))
+ {
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, Ptr->name);
+ return CMD_FAILURE;
+ }
+ if (Ptr->topicset)
+ {
+ user->WriteServ("332 %s %s :%s", user->nick, Ptr->name, Ptr->topic);
+ user->WriteServ("333 %s %s %s %d", user->nick, Ptr->name, Ptr->setby, Ptr->topicset);
+ }
+ else
+ {
+ user->WriteServ("331 %s %s :No topic is set.", user->nick, Ptr->name);
+ }
+ }
+ else
+ {
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+ return CMD_SUCCESS;
+ }
+ else if (pcnt>1)
+ {
+ Ptr = ServerInstance->FindChan(parameters[0]);
+ if (Ptr)
+ {
+ if (IS_LOCAL(user))
+ {
+ if (!Ptr->HasUser(user))
+ {
+ user->WriteServ("442 %s %s :You're not on that channel!",user->nick, Ptr->name);
+ return CMD_FAILURE;
+ }
+ if ((Ptr->IsModeSet('t')) && (Ptr->GetStatus(user) < STATUS_HOP))
+ {
+ user->WriteServ("482 %s %s :You must be at least a half-operator to change the topic on this channel", user->nick, Ptr->name);
+ return CMD_FAILURE;
+ }
+ }
+
+ char topic[MAXTOPIC];
+
+ if (IS_LOCAL(user))
+ {
+ /* XXX: we need two string copies for a local topic, because we cant
+ * let a module see the topic as longer than it actually is
+ */
+ int MOD_RESULT = 0;
+
+ strlcpy(topic,parameters[1],MAXTOPIC-1);
+ FOREACH_RESULT(I_OnLocalTopicChange,OnLocalTopicChange(user,Ptr,topic));
+ if (MOD_RESULT)
+ return CMD_FAILURE;
+
+ strlcpy(Ptr->topic,topic,MAXTOPIC-1);
+ }
+ else
+ {
+ /* Sneaky shortcut, one string copy for a remote topic */
+ strlcpy(Ptr->topic, parameters[1], MAXTOPIC-1);
+ }
+
+ if (ServerInstance->Config->FullHostInTopic)
+ strlcpy(Ptr->setby,user->GetFullHost(),127);
+ else
+ strlcpy(Ptr->setby,user->nick,127);
+
+ Ptr->topicset = ServerInstance->Time();
+ Ptr->WriteChannel(user, "TOPIC %s :%s", Ptr->name, Ptr->topic);
+
+ if (IS_LOCAL(user))
+ /* We know 'topic' will contain valid data here */
+ FOREACH_MOD(I_OnPostLocalTopicChange,OnPostLocalTopicChange(user, Ptr, topic));
+ }
+ else
+ {
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+ }
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_trace.cpp b/src/commands/cmd_trace.cpp
new file mode 100644
index 000000000..d1e57ab00
--- /dev/null
+++ b/src/commands/cmd_trace.cpp
@@ -0,0 +1,45 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_trace.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandTrace(Instance);
+}
+
+/** XXX: This is crap. someone fix this when you have time, to be more useful.
+ */
+CmdResult CommandTrace::Handle (const char** parameters, int pcnt, User *user)
+{
+ for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
+ {
+ if (i->second->registered == REG_ALL)
+ {
+ if (IS_OPER(i->second))
+ {
+ user->WriteServ("205 %s :Oper 0 %s",user->nick,i->second->nick);
+ }
+ else
+ {
+ user->WriteServ("204 %s :User 0 %s",user->nick,i->second->nick);
+ }
+ }
+ else
+ {
+ user->WriteServ("203 %s :???? 0 [%s]",user->nick,i->second->host);
+ }
+ }
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_unloadmodule.cpp b/src/commands/cmd_unloadmodule.cpp
new file mode 100644
index 000000000..fc20d4895
--- /dev/null
+++ b/src/commands/cmd_unloadmodule.cpp
@@ -0,0 +1,38 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_unloadmodule.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandUnloadmodule(Instance);
+}
+
+CmdResult CommandUnloadmodule::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (ServerInstance->Modules->Unload(parameters[0]))
+ {
+ ServerInstance->WriteOpers("*** MODULE UNLOADED: %s unloaded %s", user->nick, parameters[0]);
+ user->WriteServ("973 %s %s :Module successfully unloaded.",user->nick, parameters[0]);
+ }
+ else
+ {
+ user->WriteServ("972 %s %s :Failed to unload module: %s",user->nick, parameters[0],ServerInstance->Modules->LastError());
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_user.cpp b/src/commands/cmd_user.cpp
new file mode 100644
index 000000000..0f64600e9
--- /dev/null
+++ b/src/commands/cmd_user.cpp
@@ -0,0 +1,67 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_user.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandUser(Instance);
+}
+
+CmdResult CommandUser::Handle (const char** parameters, int pcnt, User *user)
+{
+ /* A user may only send the USER command once */
+ if (!(user->registered & REG_USER))
+ {
+ if (!ServerInstance->IsIdent(parameters[0]))
+ {
+ /*
+ * 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->WriteServ("461 %s USER :Your username is not valid",user->nick);
+ 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.
+ */
+ strlcpy(user->ident, parameters[0], IDENTMAX);
+ strlcpy(user->fullname, *parameters[3] ? parameters[3] : "No info", MAXGECOS);
+ user->registered = (user->registered | REG_USER);
+ }
+ }
+ else
+ {
+ user->WriteServ("462 %s :You may not reregister",user->nick);
+ return CMD_FAILURE;
+ }
+
+ /* parameters 2 and 3 are local and remote hosts, and are ignored */
+ if (user->registered == REG_NICKUSER)
+ {
+ int MOD_RESULT = 0;
+
+ /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
+ FOREACH_RESULT(I_OnUserRegister,OnUserRegister(user));
+ if (MOD_RESULT > 0)
+ return CMD_FAILURE;
+
+ }
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_userhost.cpp b/src/commands/cmd_userhost.cpp
new file mode 100644
index 000000000..94f406c31
--- /dev/null
+++ b/src/commands/cmd_userhost.cpp
@@ -0,0 +1,62 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_userhost.h"
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandUserhost(Instance);
+}
+
+CmdResult CommandUserhost::Handle (const char** parameters, int pcnt, User *user)
+{
+ std::string retbuf = std::string("302 ") + user->nick + " :";
+
+
+ for (int i = 0; i < pcnt; 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 + "=+";
+ }
+
+ retbuf = retbuf + u->ident + "@";
+
+ if (IS_OPER(user))
+ {
+ retbuf = retbuf + u->host;
+ }
+ else
+ {
+ retbuf = retbuf + u->dhost;
+ }
+
+ retbuf = retbuf + " ";
+ }
+ }
+
+ user->WriteServ(retbuf);
+
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_version.cpp b/src/commands/cmd_version.cpp
new file mode 100644
index 000000000..19bb9e4af
--- /dev/null
+++ b/src/commands/cmd_version.cpp
@@ -0,0 +1,29 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_version.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandVersion(Instance);
+}
+
+CmdResult CommandVersion::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->WriteServ("351 %s :%s",user->nick,ServerInstance->GetVersionString().c_str());
+ ServerInstance->Config->Send005(user);
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_wallops.cpp b/src/commands/cmd_wallops.cpp
new file mode 100644
index 000000000..f2a4ddfd9
--- /dev/null
+++ b/src/commands/cmd_wallops.cpp
@@ -0,0 +1,29 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_wallops.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandWallops(Instance);
+}
+
+CmdResult CommandWallops::Handle (const char** parameters, int pcnt, User *user)
+{
+ user->WriteWallOps(std::string(parameters[0]));
+ FOREACH_MOD(I_OnWallops,OnWallops(user,parameters[0]));
+ return CMD_SUCCESS;
+}
diff --git a/src/commands/cmd_who.cpp b/src/commands/cmd_who.cpp
new file mode 100644
index 000000000..70fe78da1
--- /dev/null
+++ b/src/commands/cmd_who.cpp
@@ -0,0 +1,346 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "wildcard.h"
+#include "commands/cmd_who.h"
+
+static char *get_first_visible_channel(User *u)
+{
+ UCListIter i = u->chans.begin();
+ if (i != u->chans.end())
+ {
+ if (!i->first->IsModeSet('s'))
+ return i->first->name;
+ }
+
+ return "*";
+}
+
+bool CommandWho::whomatch(User* user, const char* matchtext)
+{
+ bool realhost = false;
+ bool realname = false;
+ bool positive = true;
+ bool metadata = false;
+ bool ident = false;
+ bool away = false;
+ bool port = false;
+ char* dummy = NULL;
+
+ 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
+ {
+
+ if (opt_metadata)
+ metadata = user->GetExt(matchtext, dummy);
+ else
+ {
+ if (opt_realname)
+ realname = match(user->fullname, matchtext);
+ else
+ {
+ if (opt_showrealhost)
+ realhost = match(user->host, matchtext);
+ else
+ {
+ if (opt_ident)
+ ident = match(user->ident, matchtext);
+ else
+ {
+ if (opt_port)
+ {
+ irc::portparser portrange(matchtext, false);
+ long portno = -1;
+ while ((portno = portrange.GetToken()))
+ if (portno == user->GetPort())
+ port = true;
+ }
+ else
+ {
+ if (opt_away)
+ away = match(user->awaymsg, matchtext);
+ }
+ }
+ }
+ }
+ }
+ return ((port) || (away) || (ident) || (metadata) || (realname) || (realhost) || (match(user->dhost, matchtext)) || (match(user->nick, matchtext)) || (match(user->server, matchtext)));
+ }
+}
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandWho(Instance);
+}
+
+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 (IS_OPER(user))
+ 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)
+{
+ std::string lcn = get_first_visible_channel(u);
+ Channel* chlast = ServerInstance->FindChan(lcn);
+
+ /* Not visible to this user */
+ if (u->Visibility && !u->Visibility->VisibleTo(user))
+ return;
+
+ std::string wholine = initial + (ch ? ch->name : lcn) + " " + u->ident + " " + (opt_showrealhost ? u->host : u->dhost) + " " +
+ ((*ServerInstance->Config->HideWhoisServer && !IS_OPER(user)) ? 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;
+ whoresults.push_back(wholine);
+}
+
+CmdResult CommandWho::Handle (const char** parameters, int pcnt, 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;
+
+ Channel *ch = NULL;
+ std::vector<std::string> whoresults;
+ std::string initial = "352 " + std::string(user->nick) + " ";
+
+ const char* matchtext = NULL;
+ bool usingwildcards = false;
+
+ /* Change '0' into '*' so the wildcard matcher can grok it */
+ matchtext = parameters[0];
+ if (!strcmp(matchtext,"0"))
+ matchtext = "*";
+
+ for (const char* check = matchtext; *check; check++)
+ {
+ if (*check == '*' || *check == '?')
+ {
+ usingwildcards = true;
+ break;
+ }
+ }
+
+ if (pcnt > 1)
+ {
+ /* parse flags */
+ const char *iter = parameters[1];
+
+ while (*iter)
+ {
+ switch (*iter)
+ {
+ case 'o':
+ opt_viewopersonly = true;
+ break;
+ case 'h':
+ if (IS_OPER(user))
+ opt_showrealhost = true;
+ break;
+ case 'u':
+ if (IS_OPER(user))
+ opt_unlimit = true;
+ break;
+ case 'r':
+ opt_realname = true;
+ break;
+ case 'm':
+ opt_mode = true;
+ break;
+ case 'M':
+ opt_metadata = true;
+ break;
+ case 'i':
+ opt_ident = true;
+ break;
+ case 'p':
+ opt_port = true;
+ break;
+ case 'a':
+ opt_away = true;
+ break;
+ case 'l':
+ opt_local = true;
+ break;
+ case 'f':
+ opt_far = true;
+ break;
+ }
+
+ *iter++;
+ }
+ }
+
+
+ /* who on a channel? */
+ ch = ServerInstance->FindChan(matchtext);
+
+ if (ch)
+ {
+ if (CanView(ch,user))
+ {
+ bool inside = ch->HasUser(user);
+
+ /* who on a channel. */
+ CUList *cu = ch->GetUsers();
+
+ for (CUList::iterator 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)
+ 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->all_opers.begin(); i != ServerInstance->all_opers.end(); i++)
+ {
+ User* oper = *i;
+
+ if (whomatch(oper, matchtext))
+ {
+ if (!user->SharesChannelWith(oper))
+ {
+ if (usingwildcards && (!oper->IsModeSet('i')) && (!IS_OPER(user)))
+ continue;
+ }
+
+ SendWhoLine(user, initial, NULL, oper, whoresults);
+ }
+ }
+ }
+ else
+ {
+ for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++)
+ {
+ if (whomatch(i->second, matchtext))
+ {
+ if (!user->SharesChannelWith(i->second))
+ {
+ if (usingwildcards && (i->second->IsModeSet('i')) && (!IS_OPER(user)))
+ 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->WriteServ("315 %s %s :End of /WHO list.",user->nick, *parameters[0] ? parameters[0] : "*");
+ return CMD_SUCCESS;
+ }
+ else
+ {
+ /* BZZT! Too many results. */
+ user->WriteServ("315 %s %s :Too many results",user->nick, parameters[0]);
+ return CMD_FAILURE;
+ }
+}
+
diff --git a/src/commands/cmd_whois.cpp b/src/commands/cmd_whois.cpp
new file mode 100644
index 000000000..45249a0f6
--- /dev/null
+++ b/src/commands/cmd_whois.cpp
@@ -0,0 +1,144 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_whois.h"
+#include "hashcomp.h"
+
+void do_whois(InspIRCd* ServerInstance, User* user, User* dest,unsigned long signon, unsigned long idle, const char* nick)
+{
+ if (dest->Visibility && !dest->Visibility->VisibleTo(user))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 401, "%s %s :No such nick/channel",user->nick, *nick ? nick : "*");
+ ServerInstance->SendWhoisLine(user, dest, 318, "%s %s :End of /WHOIS list.",user->nick, *nick ? nick : "*");
+ return;
+ }
+
+ if (dest->registered == REG_ALL)
+ {
+ ServerInstance->SendWhoisLine(user, dest, 311, "%s %s %s %s * :%s",user->nick, dest->nick, dest->ident, dest->dhost, dest->fullname);
+ if (user == dest || IS_OPER(user))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 378, "%s %s :is connecting from %s@%s %s", user->nick, dest->nick, dest->ident, dest->host, dest->GetIPString());
+ }
+
+ std::string cl = dest->ChannelList(user);
+
+ if (cl.length())
+ {
+ if (cl.length() > 400)
+ {
+ user->SplitChanList(dest,cl);
+ }
+ else
+ {
+ ServerInstance->SendWhoisLine(user, dest, 319, "%s %s :%s",user->nick, dest->nick, cl.c_str());
+ }
+ }
+ if (*ServerInstance->Config->HideWhoisServer && !IS_OPER(user))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 312, "%s %s %s :%s",user->nick, dest->nick, ServerInstance->Config->HideWhoisServer, ServerInstance->Config->Network);
+ }
+ else
+ {
+ ServerInstance->SendWhoisLine(user, dest, 312, "%s %s %s :%s",user->nick, dest->nick, dest->server, ServerInstance->GetServerDescription(dest->server).c_str());
+ }
+
+ if (IS_AWAY(dest))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 301, "%s %s :%s",user->nick, dest->nick, dest->awaymsg);
+ }
+
+ if (IS_OPER(dest))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 313, "%s %s :is %s %s on %s",user->nick, dest->nick, (strchr("AEIOUaeiou",*dest->oper) ? "an" : "a"),irc::Spacify(dest->oper), ServerInstance->Config->Network);
+ }
+
+ FOREACH_MOD(I_OnWhois,OnWhois(user,dest));
+
+ /*
+ * We only send these if we've been provided them. That is, if hidewhois is turned off, and user is local, or
+ * if remote whois is queried, too. This is to keep the user hidden, and also since you can't reliably tell remote time. -- w00t
+ */
+ if ((idle) || (signon))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 317, "%s %s %d %d :seconds idle, signon time",user->nick, dest->nick, idle, signon);
+ }
+
+ ServerInstance->SendWhoisLine(user, dest, 318, "%s %s :End of /WHOIS list.",user->nick, dest->nick);
+ }
+ else
+ {
+ ServerInstance->SendWhoisLine(user, dest, 401, "%s %s :No such nick/channel",user->nick, *nick ? nick : "*");
+ ServerInstance->SendWhoisLine(user, dest, 318, "%s %s :End of /WHOIS list.",user->nick, *nick ? nick : "*");
+ }
+}
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandWhois(Instance);
+}
+
+CmdResult CommandWhois::Handle (const char** parameters, int pcnt, User *user)
+{
+ User *dest;
+ int userindex = 0;
+ unsigned long idle = 0, signon = 0;
+
+ if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 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 (pcnt > 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 pcnt > 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 || pcnt > 1))
+ {
+ idle = abs((dest->idle_lastmsg)-ServerInstance->Time());
+ signon = dest->signon;
+ }
+
+ do_whois(this->ServerInstance, user,dest,signon,idle,parameters[userindex]);
+ }
+ else
+ {
+ /* no such nick/channel */
+ user->WriteServ("401 %s %s :No such nick/channel",user->nick, *parameters[userindex] ? parameters[userindex] : "*");
+ user->WriteServ("318 %s %s :End of /WHOIS list.",user->nick, *parameters[userindex] ? parameters[userindex] : "*");
+ return CMD_FAILURE;
+ }
+
+ return CMD_SUCCESS;
+}
+
diff --git a/src/commands/cmd_whowas.cpp b/src/commands/cmd_whowas.cpp
new file mode 100644
index 000000000..005a23489
--- /dev/null
+++ b/src/commands/cmd_whowas.cpp
@@ -0,0 +1,348 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "commands/cmd_whowas.h"
+
+WhoWasMaintainTimer * timer;
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandWhowas(Instance);
+}
+
+CommandWhowas::CommandWhowas(InspIRCd* Instance) : Command(Instance, "WHOWAS", 0, 1, false, 2)
+{
+ syntax = "<nick>{,<nick>}";
+ timer = new WhoWasMaintainTimer(Instance, 3600);
+ Instance->Timers->AddTimer(timer);
+}
+
+CmdResult CommandWhowas::Handle (const char** parameters, int pcnt, User* user)
+{
+ /* if whowas disabled in config */
+ if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
+ {
+ user->WriteServ("421 %s %s :This command has been disabled.",user->nick,command.c_str());
+ return CMD_FAILURE;
+ }
+
+ whowas_users::iterator i = whowas.find(parameters[0]);
+
+ if (i == whowas.end())
+ {
+ user->WriteServ("406 %s %s :There was no such nickname",user->nick,parameters[0]);
+ user->WriteServ("369 %s %s :End of WHOWAS",user->nick,parameters[0]);
+ 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[MAXBUF];
+
+ timeinfo = localtime(&rawtime);
+
+ /* XXX - 'b' could be only 25 chars long and then strlcpy() would terminate it for us too? */
+ strlcpy(b,asctime(timeinfo),MAXBUF);
+ b[24] = 0;
+
+ user->WriteServ("314 %s %s %s %s * :%s",user->nick,parameters[0],u->ident,u->dhost,u->gecos);
+
+ if (IS_OPER(user))
+ user->WriteServ("379 %s %s :was connecting from *@%s", user->nick, parameters[0], u->host);
+
+ if (*ServerInstance->Config->HideWhoisServer && !IS_OPER(user))
+ user->WriteServ("312 %s %s %s :%s",user->nick,parameters[0], ServerInstance->Config->HideWhoisServer, b);
+ else
+ user->WriteServ("312 %s %s %s :%s",user->nick,parameters[0], u->server, b);
+ }
+ }
+ else
+ {
+ user->WriteServ("406 %s %s :There was no such nickname",user->nick,parameters[0]);
+ user->WriteServ("369 %s %s :End of WHOWAS",user->nick,parameters[0]);
+ return CMD_FAILURE;
+ }
+ }
+
+ user->WriteServ("369 %s %s :End of WHOWAS",user->nick,parameters[0]);
+ return CMD_SUCCESS;
+}
+
+CmdResult CommandWhowas::HandleInternal(const unsigned int id, const std::deque<classbase*> &parameters)
+{
+ switch (id)
+ {
+ case WHOWAS_ADD:
+ AddToWhoWas((User*)parameters[0]);
+ break;
+
+ case WHOWAS_STATS:
+ GetStats((Extensible*)parameters[0]);
+ break;
+
+ case WHOWAS_PRUNE:
+ PruneWhoWas(ServerInstance->Time());
+ break;
+
+ case WHOWAS_MAINTAIN:
+ MaintainWhoWas(ServerInstance->Time());
+ break;
+
+ default:
+ break;
+ }
+ return CMD_SUCCESS;
+}
+
+void CommandWhowas::GetStats(Extensible* ext)
+{
+ 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)");
+ ext->Extend("stats", stats.c_str());
+}
+
+void CommandWhowas::AddToWhoWas(User* user)
+{
+ /* if whowas disabled */
+ if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
+ {
+ return;
+ }
+
+ whowas_users::iterator iter = whowas.find(user->nick);
+
+ if (iter == whowas.end())
+ {
+ whowas_set* n = new whowas_set;
+ WhoWasGroup *a = new WhoWasGroup(user);
+ n->push_back(a);
+ whowas[user->nick] = n;
+ whowas_fifo.push_back(std::make_pair(ServerInstance->Time(),user->nick));
+
+ if ((int)(whowas.size()) > ServerInstance->Config->WhoWasMaxGroups)
+ {
+ whowas_users::iterator iter = whowas.find(whowas_fifo[0].second);
+ if (iter != whowas.end())
+ {
+ 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
+ {
+ whowas_set* group = (whowas_set*)iter->second;
+ WhoWasGroup *a = new WhoWasGroup(user);
+ group->push_back(a);
+
+ if ((int)(group->size()) > ServerInstance->Config->WhoWasGroupSize)
+ {
+ WhoWasGroup *a = (WhoWasGroup*)*(group->begin());
+ delete a;
+ 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->Log(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->Log(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->Log(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(NULL), dhost(NULL), ident(NULL), server(NULL), gecos(NULL), signon(user->signon)
+{
+ this->host = strdup(user->host);
+ this->dhost = strdup(user->dhost);
+ this->ident = strdup(user->ident);
+ this->server = user->server;
+ this->gecos = strdup(user->fullname);
+}
+
+WhoWasGroup::~WhoWasGroup()
+{
+ if (host)
+ free(host);
+ if (dhost)
+ free(dhost);
+ if (ident)
+ free(ident);
+ if (gecos)
+ free(gecos);
+}
+
+/* every hour, run this function which removes all entries older than Config->WhoWasMaxKeep */
+void WhoWasMaintainTimer::Tick(time_t t)
+{
+ Command* whowas_command = ServerInstance->Parser->GetHandler("WHOWAS");
+ if (whowas_command)
+ {
+ std::deque<classbase*> params;
+ whowas_command->HandleInternal(WHOWAS_MAINTAIN, params);
+ }
+}
diff --git a/src/commands/cmd_zline.cpp b/src/commands/cmd_zline.cpp
new file mode 100644
index 000000000..d6394a7a3
--- /dev/null
+++ b/src/commands/cmd_zline.cpp
@@ -0,0 +1,77 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "xline.h"
+#include "commands/cmd_zline.h"
+
+
+
+extern "C" DllExport Command* init_command(InspIRCd* Instance)
+{
+ return new CommandZline(Instance);
+}
+
+CmdResult CommandZline::Handle (const char** parameters, int pcnt, User *user)
+{
+ if (pcnt >= 3)
+ {
+ if (strchr(parameters[0],'@') || strchr(parameters[0],'!'))
+ {
+ user->WriteServ("NOTICE %s :*** You cannot include a username or nickname in a zline, a zline must ban only an IP mask",user->nick);
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->IPMatchesEveryone(parameters[0],user))
+ return CMD_FAILURE;
+
+ long duration = ServerInstance->Duration(parameters[1]);
+ if (ServerInstance->XLines->add_zline(duration,user->nick,parameters[2],parameters[0]))
+ {
+ int to_apply = APPLY_ZLINES;
+
+ FOREACH_MOD(I_OnAddZLine,OnAddZLine(duration, user, parameters[2], parameters[0]));
+ if (!duration)
+ {
+ to_apply |= APPLY_PERM_ONLY;
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Z-line for %s.",user->nick,parameters[0]);
+ }
+ else
+ {
+ time_t c_requires_crap = duration + ServerInstance->Time();
+ ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Z-line for %s, expires on %s",user->nick,parameters[0],
+ ServerInstance->TimeString(c_requires_crap).c_str());
+ }
+ ServerInstance->XLines->apply_lines(to_apply);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** Z-Line for %s already exists",user->nick,parameters[0]);
+ }
+ }
+ else
+ {
+ if (ServerInstance->XLines->del_zline(parameters[0]))
+ {
+ FOREACH_MOD(I_OnDelZLine,OnDelZLine(user, parameters[0]));
+ ServerInstance->SNO->WriteToSnoMask('x',"%s Removed Z-line on %s.",user->nick,parameters[0]);
+ }
+ else
+ {
+ user->WriteServ("NOTICE %s :*** Z-Line %s not found in list, try /stats Z.",user->nick,parameters[0]);
+ return CMD_FAILURE;
+ }
+ }
+
+ return CMD_SUCCESS;
+}