From c67d3103e9f7397f0ab9631bf07a5e5547deb2c3 Mon Sep 17 00:00:00 2001 From: Attila Molnar Date: Wed, 5 Mar 2014 15:41:06 +0100 Subject: Move src/commands/cmd_*.cpp to src/coremods[/core_*]/ --- src/commands/cmd_admin.cpp | 68 --- src/commands/cmd_away.cpp | 75 --- src/commands/cmd_commands.cpp | 67 --- src/commands/cmd_connect.cpp | 51 -- src/commands/cmd_die.cpp | 64 --- src/commands/cmd_dns.cpp | 833 ------------------------------- src/commands/cmd_eline.cpp | 105 ---- src/commands/cmd_gline.cpp | 115 ----- src/commands/cmd_hostname_lookup.cpp | 233 --------- src/commands/cmd_info.cpp | 109 ---- src/commands/cmd_invite.cpp | 159 ------ src/commands/cmd_ison.cpp | 102 ---- src/commands/cmd_join.cpp | 76 --- src/commands/cmd_kick.cpp | 96 ---- src/commands/cmd_kill.cpp | 170 ------- src/commands/cmd_kline.cpp | 114 ----- src/commands/cmd_links.cpp | 48 -- src/commands/cmd_list.cpp | 111 ---- src/commands/cmd_loadmodule.cpp | 56 --- src/commands/cmd_lusers.cpp | 172 ------- src/commands/cmd_mode.cpp | 53 -- src/commands/cmd_modules.cpp | 106 ---- src/commands/cmd_motd.cpp | 76 --- src/commands/cmd_names.cpp | 80 --- src/commands/cmd_nick.cpp | 94 ---- src/commands/cmd_oper.cpp | 83 --- src/commands/cmd_part.cpp | 78 --- src/commands/cmd_pass.cpp | 53 -- src/commands/cmd_ping.cpp | 45 -- src/commands/cmd_pong.cpp | 47 -- src/commands/cmd_privmsg.cpp | 278 ----------- src/commands/cmd_qline.cpp | 95 ---- src/commands/cmd_quit.cpp | 68 --- src/commands/cmd_rehash.cpp | 104 ---- src/commands/cmd_reloadmodule.cpp | 78 --- src/commands/cmd_restart.cpp | 75 --- src/commands/cmd_server.cpp | 52 -- src/commands/cmd_squit.cpp | 51 -- src/commands/cmd_stats.cpp | 406 --------------- src/commands/cmd_time.cpp | 60 --- src/commands/cmd_topic.cpp | 106 ---- src/commands/cmd_unloadmodule.cpp | 70 --- src/commands/cmd_user.cpp | 86 ---- src/commands/cmd_userhost.cpp | 83 --- src/commands/cmd_version.cpp | 51 -- src/commands/cmd_wallops.cpp | 68 --- src/commands/cmd_who.cpp | 395 --------------- src/commands/cmd_whois.cpp | 242 --------- src/commands/cmd_whowas.cpp | 272 ---------- src/commands/cmd_zline.cpp | 110 ---- src/coremods/core_channel/cmd_invite.cpp | 159 ++++++ src/coremods/core_channel/cmd_join.cpp | 76 +++ src/coremods/core_channel/cmd_kick.cpp | 96 ++++ src/coremods/core_channel/cmd_names.cpp | 80 +++ src/coremods/core_channel/cmd_topic.cpp | 106 ++++ src/coremods/core_connect.cpp | 51 ++ src/coremods/core_dns.cpp | 833 +++++++++++++++++++++++++++++++ src/coremods/core_hostname_lookup.cpp | 233 +++++++++ src/coremods/core_info/cmd_admin.cpp | 68 +++ src/coremods/core_info/cmd_commands.cpp | 67 +++ src/coremods/core_info/cmd_info.cpp | 109 ++++ src/coremods/core_info/cmd_modules.cpp | 106 ++++ src/coremods/core_info/cmd_motd.cpp | 76 +++ src/coremods/core_info/cmd_time.cpp | 60 +++ src/coremods/core_info/cmd_version.cpp | 51 ++ src/coremods/core_ison.cpp | 102 ++++ src/coremods/core_links.cpp | 48 ++ src/coremods/core_list.cpp | 111 ++++ src/coremods/core_loadmodule.cpp | 56 +++ src/coremods/core_lusers.cpp | 172 +++++++ src/coremods/core_oper/cmd_die.cpp | 64 +++ src/coremods/core_oper/cmd_kill.cpp | 170 +++++++ src/coremods/core_oper/cmd_oper.cpp | 83 +++ src/coremods/core_oper/cmd_rehash.cpp | 104 ++++ src/coremods/core_oper/cmd_restart.cpp | 75 +++ src/coremods/core_privmsg.cpp | 278 +++++++++++ src/coremods/core_reloadmodule.cpp | 78 +++ src/coremods/core_server.cpp | 52 ++ src/coremods/core_squit.cpp | 51 ++ src/coremods/core_stats.cpp | 406 +++++++++++++++ src/coremods/core_unloadmodule.cpp | 70 +++ src/coremods/core_user/cmd_away.cpp | 75 +++ src/coremods/core_user/cmd_mode.cpp | 53 ++ src/coremods/core_user/cmd_nick.cpp | 94 ++++ src/coremods/core_user/cmd_part.cpp | 78 +++ src/coremods/core_user/cmd_pass.cpp | 53 ++ src/coremods/core_user/cmd_ping.cpp | 45 ++ src/coremods/core_user/cmd_pong.cpp | 47 ++ src/coremods/core_user/cmd_quit.cpp | 68 +++ src/coremods/core_user/cmd_user.cpp | 86 ++++ src/coremods/core_userhost.cpp | 83 +++ src/coremods/core_wallops.cpp | 68 +++ src/coremods/core_who.cpp | 395 +++++++++++++++ src/coremods/core_whois.cpp | 242 +++++++++ src/coremods/core_whowas.cpp | 272 ++++++++++ src/coremods/core_xline/cmd_eline.cpp | 105 ++++ src/coremods/core_xline/cmd_gline.cpp | 115 +++++ src/coremods/core_xline/cmd_kline.cpp | 114 +++++ src/coremods/core_xline/cmd_qline.cpp | 95 ++++ src/coremods/core_xline/cmd_zline.cpp | 110 ++++ 100 files changed, 6289 insertions(+), 6289 deletions(-) delete mode 100644 src/commands/cmd_admin.cpp delete mode 100644 src/commands/cmd_away.cpp delete mode 100644 src/commands/cmd_commands.cpp delete mode 100644 src/commands/cmd_connect.cpp delete mode 100644 src/commands/cmd_die.cpp delete mode 100644 src/commands/cmd_dns.cpp delete mode 100644 src/commands/cmd_eline.cpp delete mode 100644 src/commands/cmd_gline.cpp delete mode 100644 src/commands/cmd_hostname_lookup.cpp delete mode 100644 src/commands/cmd_info.cpp delete mode 100644 src/commands/cmd_invite.cpp delete mode 100644 src/commands/cmd_ison.cpp delete mode 100644 src/commands/cmd_join.cpp delete mode 100644 src/commands/cmd_kick.cpp delete mode 100644 src/commands/cmd_kill.cpp delete mode 100644 src/commands/cmd_kline.cpp delete mode 100644 src/commands/cmd_links.cpp delete mode 100644 src/commands/cmd_list.cpp delete mode 100644 src/commands/cmd_loadmodule.cpp delete mode 100644 src/commands/cmd_lusers.cpp delete mode 100644 src/commands/cmd_mode.cpp delete mode 100644 src/commands/cmd_modules.cpp delete mode 100644 src/commands/cmd_motd.cpp delete mode 100644 src/commands/cmd_names.cpp delete mode 100644 src/commands/cmd_nick.cpp delete mode 100644 src/commands/cmd_oper.cpp delete mode 100644 src/commands/cmd_part.cpp delete mode 100644 src/commands/cmd_pass.cpp delete mode 100644 src/commands/cmd_ping.cpp delete mode 100644 src/commands/cmd_pong.cpp delete mode 100644 src/commands/cmd_privmsg.cpp delete mode 100644 src/commands/cmd_qline.cpp delete mode 100644 src/commands/cmd_quit.cpp delete mode 100644 src/commands/cmd_rehash.cpp delete mode 100644 src/commands/cmd_reloadmodule.cpp delete mode 100644 src/commands/cmd_restart.cpp delete mode 100644 src/commands/cmd_server.cpp delete mode 100644 src/commands/cmd_squit.cpp delete mode 100644 src/commands/cmd_stats.cpp delete mode 100644 src/commands/cmd_time.cpp delete mode 100644 src/commands/cmd_topic.cpp delete mode 100644 src/commands/cmd_unloadmodule.cpp delete mode 100644 src/commands/cmd_user.cpp delete mode 100644 src/commands/cmd_userhost.cpp delete mode 100644 src/commands/cmd_version.cpp delete mode 100644 src/commands/cmd_wallops.cpp delete mode 100644 src/commands/cmd_who.cpp delete mode 100644 src/commands/cmd_whois.cpp delete mode 100644 src/commands/cmd_whowas.cpp delete mode 100644 src/commands/cmd_zline.cpp create mode 100644 src/coremods/core_channel/cmd_invite.cpp create mode 100644 src/coremods/core_channel/cmd_join.cpp create mode 100644 src/coremods/core_channel/cmd_kick.cpp create mode 100644 src/coremods/core_channel/cmd_names.cpp create mode 100644 src/coremods/core_channel/cmd_topic.cpp create mode 100644 src/coremods/core_connect.cpp create mode 100644 src/coremods/core_dns.cpp create mode 100644 src/coremods/core_hostname_lookup.cpp create mode 100644 src/coremods/core_info/cmd_admin.cpp create mode 100644 src/coremods/core_info/cmd_commands.cpp create mode 100644 src/coremods/core_info/cmd_info.cpp create mode 100644 src/coremods/core_info/cmd_modules.cpp create mode 100644 src/coremods/core_info/cmd_motd.cpp create mode 100644 src/coremods/core_info/cmd_time.cpp create mode 100644 src/coremods/core_info/cmd_version.cpp create mode 100644 src/coremods/core_ison.cpp create mode 100644 src/coremods/core_links.cpp create mode 100644 src/coremods/core_list.cpp create mode 100644 src/coremods/core_loadmodule.cpp create mode 100644 src/coremods/core_lusers.cpp create mode 100644 src/coremods/core_oper/cmd_die.cpp create mode 100644 src/coremods/core_oper/cmd_kill.cpp create mode 100644 src/coremods/core_oper/cmd_oper.cpp create mode 100644 src/coremods/core_oper/cmd_rehash.cpp create mode 100644 src/coremods/core_oper/cmd_restart.cpp create mode 100644 src/coremods/core_privmsg.cpp create mode 100644 src/coremods/core_reloadmodule.cpp create mode 100644 src/coremods/core_server.cpp create mode 100644 src/coremods/core_squit.cpp create mode 100644 src/coremods/core_stats.cpp create mode 100644 src/coremods/core_unloadmodule.cpp create mode 100644 src/coremods/core_user/cmd_away.cpp create mode 100644 src/coremods/core_user/cmd_mode.cpp create mode 100644 src/coremods/core_user/cmd_nick.cpp create mode 100644 src/coremods/core_user/cmd_part.cpp create mode 100644 src/coremods/core_user/cmd_pass.cpp create mode 100644 src/coremods/core_user/cmd_ping.cpp create mode 100644 src/coremods/core_user/cmd_pong.cpp create mode 100644 src/coremods/core_user/cmd_quit.cpp create mode 100644 src/coremods/core_user/cmd_user.cpp create mode 100644 src/coremods/core_userhost.cpp create mode 100644 src/coremods/core_wallops.cpp create mode 100644 src/coremods/core_who.cpp create mode 100644 src/coremods/core_whois.cpp create mode 100644 src/coremods/core_whowas.cpp create mode 100644 src/coremods/core_xline/cmd_eline.cpp create mode 100644 src/coremods/core_xline/cmd_gline.cpp create mode 100644 src/coremods/core_xline/cmd_kline.cpp create mode 100644 src/coremods/core_xline/cmd_qline.cpp create mode 100644 src/coremods/core_xline/cmd_zline.cpp (limited to 'src') diff --git a/src/commands/cmd_admin.cpp b/src/commands/cmd_admin.cpp deleted file mode 100644 index 1f694bf2e..000000000 --- a/src/commands/cmd_admin.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /ADMIN. - */ -class CommandAdmin : public Command -{ - public: - /** Constructor for admin. - */ - CommandAdmin(Module* parent) : Command(parent,"ADMIN",0,0) - { - Penalty = 2; - syntax = "[]"; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - if (parameters.size() > 0) - return ROUTE_UNICAST(parameters[0]); - return ROUTE_LOCALONLY; - } -}; - -/** Handle /ADMIN - */ -CmdResult CommandAdmin::Handle (const std::vector& parameters, User *user) -{ - if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName) - return CMD_SUCCESS; - user->SendText(":%s %03d %s :Administrative info for %s", ServerInstance->Config->ServerName.c_str(), - RPL_ADMINME, user->nick.c_str(),ServerInstance->Config->ServerName.c_str()); - if (!ServerInstance->Config->AdminName.empty()) - user->SendText(":%s %03d %s :Name - %s", ServerInstance->Config->ServerName.c_str(), - RPL_ADMINLOC1, user->nick.c_str(), ServerInstance->Config->AdminName.c_str()); - user->SendText(":%s %03d %s :Nickname - %s", ServerInstance->Config->ServerName.c_str(), - RPL_ADMINLOC2, user->nick.c_str(), ServerInstance->Config->AdminNick.c_str()); - user->SendText(":%s %03d %s :E-Mail - %s", ServerInstance->Config->ServerName.c_str(), - RPL_ADMINEMAIL, user->nick.c_str(), ServerInstance->Config->AdminEmail.c_str()); - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandAdmin) diff --git a/src/commands/cmd_away.cpp b/src/commands/cmd_away.cpp deleted file mode 100644 index 4f61cec3f..000000000 --- a/src/commands/cmd_away.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /AWAY. - */ -class CommandAway : public Command -{ - public: - /** Constructor for away. - */ - CommandAway ( Module* parent) : Command(parent,"AWAY",0,0) { syntax = "[]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); - } -}; - -/** Handle /AWAY - */ -CmdResult CommandAway::Handle (const std::vector& parameters, User *user) -{ - ModResult MOD_RESULT; - - if ((parameters.size()) && (!parameters[0].empty())) - { - FIRST_MOD_RESULT(OnSetAway, MOD_RESULT, (user, parameters[0])); - - if (MOD_RESULT == MOD_RES_DENY && IS_LOCAL(user)) - return CMD_FAILURE; - - user->awaytime = ServerInstance->Time(); - user->awaymsg.assign(parameters[0], 0, ServerInstance->Config->Limits.MaxAway); - - user->WriteNumeric(RPL_NOWAWAY, ":You have been marked as being away"); - } - else - { - FIRST_MOD_RESULT(OnSetAway, MOD_RESULT, (user, "")); - - if (MOD_RESULT == MOD_RES_DENY && IS_LOCAL(user)) - return CMD_FAILURE; - - user->awaymsg.clear(); - user->WriteNumeric(RPL_UNAWAY, ":You are no longer marked as being away"); - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandAway) diff --git a/src/commands/cmd_commands.cpp b/src/commands/cmd_commands.cpp deleted file mode 100644 index 3f0ab99c1..000000000 --- a/src/commands/cmd_commands.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /COMMANDS. - */ -class CommandCommands : public Command -{ - public: - /** Constructor for commands. - */ - CommandCommands(Module* parent) : Command(parent,"COMMANDS",0,0) - { - Penalty = 3; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/** Handle /COMMANDS - */ -CmdResult CommandCommands::Handle (const std::vector&, User *user) -{ - std::vector list; - list.reserve(ServerInstance->Parser->cmdlist.size()); - for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) - { - // Don't show S2S commands to users - if (i->second->flags_needed == FLAG_SERVERONLY) - continue; - - Module* src = i->second->creator; - list.push_back(InspIRCd::Format(":%s %03d %s :%s %s %d %d", ServerInstance->Config->ServerName.c_str(), - RPL_COMMANDS, user->nick.c_str(), i->second->name.c_str(), src->ModuleSourceFile.c_str(), - i->second->min_params, i->second->Penalty)); - } - sort(list.begin(), list.end()); - for(unsigned int i=0; i < list.size(); i++) - user->Write(list[i]); - user->WriteNumeric(RPL_COMMANDSEND, ":End of COMMANDS list"); - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandCommands) diff --git a/src/commands/cmd_connect.cpp b/src/commands/cmd_connect.cpp deleted file mode 100644 index 59e7487a7..000000000 --- a/src/commands/cmd_connect.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /CONNECT. - */ -class CommandConnect : public Command -{ - public: - /** Constructor for connect. - */ - CommandConnect ( Module* parent) : Command(parent,"CONNECT",1) { flags_needed = 'o'; syntax = " []"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/* - * This is handled by the server linking module, if necessary. Do not remove this stub. - */ - -/** Handle /CONNECT - */ -CmdResult CommandConnect::Handle (const std::vector&, User *user) -{ - user->WriteServ( "NOTICE %s :Look into loading a linking module (like m_spanningtree) if you want this to do anything useful.", user->nick.c_str()); - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandConnect) diff --git a/src/commands/cmd_die.cpp b/src/commands/cmd_die.cpp deleted file mode 100644 index 63e4c596a..000000000 --- a/src/commands/cmd_die.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /DIE. - */ -class CommandDie : public Command -{ - public: - /** Constructor for die. - */ - CommandDie ( Module* parent) : Command(parent,"DIE",1) { flags_needed = 'o'; syntax = ""; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -#include "exitcodes.h" - -/** Handle /DIE - */ -CmdResult CommandDie::Handle (const std::vector& parameters, User *user) -{ - if (ServerInstance->PassCompare(user, ServerInstance->Config->diepass, parameters[0], ServerInstance->Config->powerhash)) - { - { - std::string diebuf = "*** DIE command from " + user->GetFullHost() + ". Terminating."; - ServerInstance->Logs->Log("COMMAND", LOG_SPARSE, diebuf); - ServerInstance->SendError(diebuf); - } - - ServerInstance->Exit(EXIT_STATUS_DIE); - } - else - { - ServerInstance->Logs->Log("COMMAND", LOG_SPARSE, "Failed /DIE command from %s", user->GetFullRealHost().c_str()); - ServerInstance->SNO->WriteGlobalSno('a', "Failed DIE Command from %s.", user->GetFullRealHost().c_str()); - return CMD_FAILURE; - } - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandDie) diff --git a/src/commands/cmd_dns.cpp b/src/commands/cmd_dns.cpp deleted file mode 100644 index 7b93c7bb3..000000000 --- a/src/commands/cmd_dns.cpp +++ /dev/null @@ -1,833 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2013 Adam - * Copyright (C) 2003-2013 Anope Team - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "inspircd.h" -#include "modules/dns.h" -#include -#include - -#ifdef _WIN32 -#include -#pragma comment(lib, "Iphlpapi.lib") -#endif - -using namespace DNS; - -/** A full packet sent or recieved to/from the nameserver - */ -class Packet : public Query -{ - void PackName(unsigned char* output, unsigned short output_size, unsigned short& pos, const std::string& name) - { - if (pos + name.length() + 2 > output_size) - throw Exception("Unable to pack name"); - - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Packing name " + name); - - irc::sepstream sep(name, '.'); - std::string token; - - while (sep.GetToken(token)) - { - output[pos++] = token.length(); - memcpy(&output[pos], token.data(), token.length()); - pos += token.length(); - } - - output[pos++] = 0; - } - - std::string UnpackName(const unsigned char* input, unsigned short input_size, unsigned short& pos) - { - std::string name; - unsigned short pos_ptr = pos, lowest_ptr = input_size; - bool compressed = false; - - if (pos_ptr >= input_size) - throw Exception("Unable to unpack name - no input"); - - while (input[pos_ptr] > 0) - { - unsigned short offset = input[pos_ptr]; - - if (offset & POINTER) - { - if ((offset & POINTER) != POINTER) - throw Exception("Unable to unpack name - bogus compression header"); - if (pos_ptr + 1 >= input_size) - throw Exception("Unable to unpack name - bogus compression header"); - - /* Place pos at the second byte of the first (farthest) compression pointer */ - if (compressed == false) - { - ++pos; - compressed = true; - } - - pos_ptr = (offset & LABEL) << 8 | input[pos_ptr + 1]; - - /* Pointers can only go back */ - if (pos_ptr >= lowest_ptr) - throw Exception("Unable to unpack name - bogus compression pointer"); - lowest_ptr = pos_ptr; - } - else - { - if (pos_ptr + offset + 1 >= input_size) - throw Exception("Unable to unpack name - offset too large"); - if (!name.empty()) - name += "."; - for (unsigned i = 1; i <= offset; ++i) - name += input[pos_ptr + i]; - - pos_ptr += offset + 1; - if (compressed == false) - /* Move up pos */ - pos = pos_ptr; - } - } - - /* +1 pos either to one byte after the compression pointer or one byte after the ending \0 */ - ++pos; - - if (name.empty()) - throw Exception("Unable to unpack name - no name"); - - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Unpack name " + name); - - return name; - } - - Question UnpackQuestion(const unsigned char* input, unsigned short input_size, unsigned short& pos) - { - Question question; - - question.name = this->UnpackName(input, input_size, pos); - - if (pos + 4 > input_size) - throw Exception("Unable to unpack question"); - - question.type = static_cast(input[pos] << 8 | input[pos + 1]); - pos += 2; - - question.qclass = input[pos] << 8 | input[pos + 1]; - pos += 2; - - return question; - } - - ResourceRecord UnpackResourceRecord(const unsigned char* input, unsigned short input_size, unsigned short& pos) - { - ResourceRecord record = static_cast(this->UnpackQuestion(input, input_size, pos)); - - if (pos + 6 > input_size) - throw Exception("Unable to unpack resource record"); - - record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3]; - pos += 4; - - //record.rdlength = input[pos] << 8 | input[pos + 1]; - pos += 2; - - switch (record.type) - { - case QUERY_A: - { - if (pos + 4 > input_size) - throw Exception("Unable to unpack resource record"); - - irc::sockets::sockaddrs addrs; - memset(&addrs, 0, sizeof(addrs)); - - addrs.in4.sin_family = AF_INET; - addrs.in4.sin_addr.s_addr = input[pos] | (input[pos + 1] << 8) | (input[pos + 2] << 16) | (input[pos + 3] << 24); - pos += 4; - - record.rdata = addrs.addr(); - break; - } - case QUERY_AAAA: - { - if (pos + 16 > input_size) - throw Exception("Unable to unpack resource record"); - - irc::sockets::sockaddrs addrs; - memset(&addrs, 0, sizeof(addrs)); - - addrs.in6.sin6_family = AF_INET6; - for (int j = 0; j < 16; ++j) - addrs.in6.sin6_addr.s6_addr[j] = input[pos + j]; - pos += 16; - - record.rdata = addrs.addr(); - - break; - } - case QUERY_CNAME: - case QUERY_PTR: - { - record.rdata = this->UnpackName(input, input_size, pos); - break; - } - default: - break; - } - - if (!record.name.empty() && !record.rdata.empty()) - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: " + record.name + " -> " + record.rdata); - - return record; - } - - public: - static const int POINTER = 0xC0; - static const int LABEL = 0x3F; - static const int HEADER_LENGTH = 12; - - /* ID for this packet */ - unsigned short id; - /* Flags on the packet */ - unsigned short flags; - - Packet() : id(0), flags(0) - { - } - - void Fill(const unsigned char* input, const unsigned short len) - { - if (len < HEADER_LENGTH) - throw Exception("Unable to fill packet"); - - unsigned short packet_pos = 0; - - this->id = (input[packet_pos] << 8) | input[packet_pos + 1]; - packet_pos += 2; - - if (this->id >= MAX_REQUEST_ID) - throw Exception("Query ID too large?"); - - this->flags = (input[packet_pos] << 8) | input[packet_pos + 1]; - packet_pos += 2; - - unsigned short qdcount = (input[packet_pos] << 8) | input[packet_pos + 1]; - packet_pos += 2; - - unsigned short ancount = (input[packet_pos] << 8) | input[packet_pos + 1]; - packet_pos += 2; - - unsigned short nscount = (input[packet_pos] << 8) | input[packet_pos + 1]; - packet_pos += 2; - - unsigned short arcount = (input[packet_pos] << 8) | input[packet_pos + 1]; - packet_pos += 2; - - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: qdcount: " + ConvToStr(qdcount) + " ancount: " + ConvToStr(ancount) + " nscount: " + ConvToStr(nscount) + " arcount: " + ConvToStr(arcount)); - - for (unsigned i = 0; i < qdcount; ++i) - this->questions.push_back(this->UnpackQuestion(input, len, packet_pos)); - - for (unsigned i = 0; i < ancount; ++i) - this->answers.push_back(this->UnpackResourceRecord(input, len, packet_pos)); - } - - unsigned short Pack(unsigned char* output, unsigned short output_size) - { - if (output_size < HEADER_LENGTH) - throw Exception("Unable to pack packet"); - - unsigned short pos = 0; - - output[pos++] = this->id >> 8; - output[pos++] = this->id & 0xFF; - output[pos++] = this->flags >> 8; - output[pos++] = this->flags & 0xFF; - output[pos++] = this->questions.size() >> 8; - output[pos++] = this->questions.size() & 0xFF; - output[pos++] = this->answers.size() >> 8; - output[pos++] = this->answers.size() & 0xFF; - output[pos++] = 0; - output[pos++] = 0; - output[pos++] = 0; - output[pos++] = 0; - - for (unsigned i = 0; i < this->questions.size(); ++i) - { - Question& q = this->questions[i]; - - if (q.type == QUERY_PTR) - { - irc::sockets::sockaddrs ip; - irc::sockets::aptosa(q.name, 0, ip); - - if (q.name.find(':') != std::string::npos) - { - static const char* const hex = "0123456789abcdef"; - char reverse_ip[128]; - unsigned reverse_ip_count = 0; - for (int j = 15; j >= 0; --j) - { - reverse_ip[reverse_ip_count++] = hex[ip.in6.sin6_addr.s6_addr[j] & 0xF]; - reverse_ip[reverse_ip_count++] = '.'; - reverse_ip[reverse_ip_count++] = hex[ip.in6.sin6_addr.s6_addr[j] >> 4]; - reverse_ip[reverse_ip_count++] = '.'; - } - reverse_ip[reverse_ip_count++] = 0; - - q.name = reverse_ip; - q.name += "ip6.arpa"; - } - else - { - unsigned long forward = ip.in4.sin_addr.s_addr; - ip.in4.sin_addr.s_addr = forward << 24 | (forward & 0xFF00) << 8 | (forward & 0xFF0000) >> 8 | forward >> 24; - - q.name = ip.addr() + ".in-addr.arpa"; - } - } - - this->PackName(output, output_size, pos, q.name); - - if (pos + 4 >= output_size) - throw Exception("Unable to pack packet"); - - short s = htons(q.type); - memcpy(&output[pos], &s, 2); - pos += 2; - - s = htons(q.qclass); - memcpy(&output[pos], &s, 2); - pos += 2; - } - - for (unsigned int i = 0; i < answers.size(); i++) - { - ResourceRecord& rr = answers[i]; - - this->PackName(output, output_size, pos, rr.name); - - if (pos + 8 >= output_size) - throw Exception("Unable to pack packet"); - - short s = htons(rr.type); - memcpy(&output[pos], &s, 2); - pos += 2; - - s = htons(rr.qclass); - memcpy(&output[pos], &s, 2); - pos += 2; - - long l = htonl(rr.ttl); - memcpy(&output[pos], &l, 4); - pos += 4; - - switch (rr.type) - { - case QUERY_A: - { - if (pos + 6 > output_size) - throw Exception("Unable to pack packet"); - - irc::sockets::sockaddrs a; - irc::sockets::aptosa(rr.rdata, 0, a); - - s = htons(4); - memcpy(&output[pos], &s, 2); - pos += 2; - - memcpy(&output[pos], &a.in4.sin_addr, 4); - pos += 4; - break; - } - case QUERY_AAAA: - { - if (pos + 18 > output_size) - throw Exception("Unable to pack packet"); - - irc::sockets::sockaddrs a; - irc::sockets::aptosa(rr.rdata, 0, a); - - s = htons(16); - memcpy(&output[pos], &s, 2); - pos += 2; - - memcpy(&output[pos], &a.in6.sin6_addr, 16); - pos += 16; - break; - } - case QUERY_CNAME: - case QUERY_PTR: - { - if (pos + 2 >= output_size) - throw Exception("Unable to pack packet"); - - unsigned short packet_pos_save = pos; - pos += 2; - - this->PackName(output, output_size, pos, rr.rdata); - - s = htons(pos - packet_pos_save - 2); - memcpy(&output[packet_pos_save], &s, 2); - break; - } - default: - break; - } - } - - return pos; - } -}; - -class MyManager : public Manager, public Timer, public EventHandler -{ - typedef TR1NS::unordered_map cache_map; - cache_map cache; - - irc::sockets::sockaddrs myserver; - - static bool IsExpired(const Query& record, time_t now = ServerInstance->Time()) - { - const ResourceRecord& req = record.answers[0]; - return (req.created + static_cast(req.ttl) < now); - } - - /** Check the DNS cache to see if request can be handled by a cached result - * @return true if a cached result was found. - */ - bool CheckCache(DNS::Request* req, const DNS::Question& question) - { - ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: cache: Checking cache for " + question.name); - - cache_map::iterator it = this->cache.find(question); - if (it == this->cache.end()) - return false; - - Query& record = it->second; - if (IsExpired(record)) - { - this->cache.erase(it); - return false; - } - - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: Using cached result for " + question.name); - record.cached = true; - req->OnLookupComplete(&record); - return true; - } - - /** Add a record to the dns cache - * @param r The record - */ - void AddCache(Query& r) - { - const ResourceRecord& rr = r.answers[0]; - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: added cache for " + rr.name + " -> " + rr.rdata + " ttl: " + ConvToStr(rr.ttl)); - this->cache[r.questions[0]] = r; - } - - public: - DNS::Request* requests[MAX_REQUEST_ID]; - - MyManager(Module* c) : Manager(c), Timer(3600, ServerInstance->Time(), true) - { - for (int i = 0; i < MAX_REQUEST_ID; ++i) - requests[i] = NULL; - ServerInstance->Timers->AddTimer(this); - } - - ~MyManager() - { - for (int i = 0; i < MAX_REQUEST_ID; ++i) - { - DNS::Request* request = requests[i]; - if (!request) - continue; - - Query rr(*request); - rr.error = ERROR_UNKNOWN; - request->OnError(&rr); - - delete request; - } - } - - void Process(DNS::Request* req) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Processing request to lookup " + req->name + " of type " + ConvToStr(req->type) + " to " + this->myserver.addr()); - - /* Create an id */ - unsigned int tries = 0; - do - { - req->id = ServerInstance->GenRandomInt(DNS::MAX_REQUEST_ID); - - if (++tries == DNS::MAX_REQUEST_ID*5) - { - // If we couldn't find an empty slot this many times, do a sequential scan as a last - // resort. If an empty slot is found that way, go on, otherwise throw an exception - req->id = 0; - for (int i = 1; i < DNS::MAX_REQUEST_ID; i++) - { - if (!this->requests[i]) - { - req->id = i; - break; - } - } - - if (req->id == 0) - throw Exception("DNS: All ids are in use"); - - break; - } - } - while (!req->id || this->requests[req->id]); - - this->requests[req->id] = req; - - Packet p; - p.flags = QUERYFLAGS_RD; - p.id = req->id; - p.questions.push_back(*req); - - unsigned char buffer[524]; - unsigned short len = p.Pack(buffer, sizeof(buffer)); - - /* Note that calling Pack() above can actually change the contents of p.questions[0].name, if the query is a PTR, - * to contain the value that would be in the DNS cache, which is why this is here. - */ - if (req->use_cache && this->CheckCache(req, p.questions[0])) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Using cached result"); - delete req; - return; - } - - if (SocketEngine::SendTo(this, buffer, len, 0, &this->myserver.sa, this->myserver.sa_size()) != len) - throw Exception("DNS: Unable to send query"); - } - - void RemoveRequest(DNS::Request* req) - { - this->requests[req->id] = NULL; - } - - std::string GetErrorStr(Error e) - { - switch (e) - { - case ERROR_UNLOADED: - return "Module is unloading"; - case ERROR_TIMEDOUT: - return "Request timed out"; - case ERROR_NOT_AN_ANSWER: - case ERROR_NONSTANDARD_QUERY: - case ERROR_FORMAT_ERROR: - return "Malformed answer"; - case ERROR_SERVER_FAILURE: - case ERROR_NOT_IMPLEMENTED: - case ERROR_REFUSED: - case ERROR_INVALIDTYPE: - return "Nameserver failure"; - case ERROR_DOMAIN_NOT_FOUND: - case ERROR_NO_RECORDS: - return "Domain not found"; - case ERROR_NONE: - case ERROR_UNKNOWN: - default: - return "Unknown error"; - } - } - - void HandleEvent(EventType et, int) - { - if (et == EVENT_ERROR) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: UDP socket got an error event"); - return; - } - - unsigned char buffer[524]; - irc::sockets::sockaddrs from; - socklen_t x = sizeof(from); - - int length = SocketEngine::RecvFrom(this, buffer, sizeof(buffer), 0, &from.sa, &x); - - if (length < Packet::HEADER_LENGTH) - return; - - Packet recv_packet; - - try - { - recv_packet.Fill(buffer, length); - } - catch (Exception& ex) - { - ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, ex.GetReason()); - return; - } - - if (myserver != from) - { - std::string server1 = from.str(); - std::string server2 = myserver.str(); - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Got a result from the wrong server! Bad NAT or DNS forging attempt? '%s' != '%s'", - server1.c_str(), server2.c_str()); - return; - } - - DNS::Request* request = this->requests[recv_packet.id]; - if (request == NULL) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Received an answer for something we didn't request"); - return; - } - - if (recv_packet.flags & QUERYFLAGS_OPCODE) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Received a nonstandard query"); - ServerInstance->stats->statsDnsBad++; - recv_packet.error = ERROR_NONSTANDARD_QUERY; - request->OnError(&recv_packet); - } - else if (recv_packet.flags & QUERYFLAGS_RCODE) - { - Error error = ERROR_UNKNOWN; - - switch (recv_packet.flags & QUERYFLAGS_RCODE) - { - case 1: - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: format error"); - error = ERROR_FORMAT_ERROR; - break; - case 2: - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: server error"); - error = ERROR_SERVER_FAILURE; - break; - case 3: - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: domain not found"); - error = ERROR_DOMAIN_NOT_FOUND; - break; - case 4: - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: not implemented"); - error = ERROR_NOT_IMPLEMENTED; - break; - case 5: - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: refused"); - error = ERROR_REFUSED; - break; - default: - break; - } - - ServerInstance->stats->statsDnsBad++; - recv_packet.error = error; - request->OnError(&recv_packet); - } - else if (recv_packet.questions.empty() || recv_packet.answers.empty()) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: No resource records returned"); - ServerInstance->stats->statsDnsBad++; - recv_packet.error = ERROR_NO_RECORDS; - request->OnError(&recv_packet); - } - else - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Lookup complete for " + request->name); - ServerInstance->stats->statsDnsGood++; - request->OnLookupComplete(&recv_packet); - this->AddCache(recv_packet); - } - - ServerInstance->stats->statsDns++; - - /* Request's destructor removes it from the request map */ - delete request; - } - - bool Tick(time_t now) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: purging DNS cache"); - - for (cache_map::iterator it = this->cache.begin(); it != this->cache.end(); ) - { - const Query& query = it->second; - if (IsExpired(query, now)) - this->cache.erase(it++); - else - ++it; - } - return true; - } - - void Rehash(const std::string& dnsserver) - { - if (this->GetFd() > -1) - { - SocketEngine::Shutdown(this, 2); - SocketEngine::Close(this); - - /* Remove expired entries from the cache */ - this->Tick(ServerInstance->Time()); - } - - irc::sockets::aptosa(dnsserver, DNS::PORT, myserver); - - /* Initialize mastersocket */ - int s = socket(myserver.sa.sa_family, SOCK_DGRAM, 0); - this->SetFd(s); - - /* Have we got a socket? */ - if (this->GetFd() != -1) - { - SocketEngine::SetReuse(s); - SocketEngine::NonBlocking(s); - - irc::sockets::sockaddrs bindto; - memset(&bindto, 0, sizeof(bindto)); - bindto.sa.sa_family = myserver.sa.sa_family; - - if (SocketEngine::Bind(this->GetFd(), bindto) < 0) - { - /* Failed to bind */ - ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Error binding dns socket - hostnames will NOT resolve"); - SocketEngine::Close(this->GetFd()); - this->SetFd(-1); - } - else if (!SocketEngine::AddFd(this, FD_WANT_POLL_READ | FD_WANT_NO_WRITE)) - { - ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Internal error starting DNS - hostnames will NOT resolve."); - SocketEngine::Close(this->GetFd()); - this->SetFd(-1); - } - } - else - { - ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Error creating DNS socket - hostnames will NOT resolve"); - } - } -}; - -class ModuleDNS : public Module -{ - MyManager manager; - std::string DNSServer; - - void FindDNSServer() - { -#ifdef _WIN32 - // attempt to look up their nameserver from the system - ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: not defined, attempting to find a working server in the system settings..."); - - PFIXED_INFO pFixedInfo; - DWORD dwBufferSize = sizeof(FIXED_INFO); - pFixedInfo = (PFIXED_INFO) HeapAlloc(GetProcessHeap(), 0, sizeof(FIXED_INFO)); - - if (pFixedInfo) - { - if (GetNetworkParams(pFixedInfo, &dwBufferSize) == ERROR_BUFFER_OVERFLOW) - { - HeapFree(GetProcessHeap(), 0, pFixedInfo); - pFixedInfo = (PFIXED_INFO) HeapAlloc(GetProcessHeap(), 0, dwBufferSize); - } - - if (pFixedInfo) - { - if (GetNetworkParams(pFixedInfo, &dwBufferSize) == NO_ERROR) - DNSServer = pFixedInfo->DnsServerList.IpAddress.String; - - HeapFree(GetProcessHeap(), 0, pFixedInfo); - } - - if (!DNSServer.empty()) - { - ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, " set to '%s' as first active resolver in the system settings.", DNSServer.c_str()); - return; - } - } - - ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "No viable nameserver found! Defaulting to nameserver '127.0.0.1'!"); -#else - // attempt to look up their nameserver from /etc/resolv.conf - ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: not defined, attempting to find working server in /etc/resolv.conf..."); - - std::ifstream resolv("/etc/resolv.conf"); - - while (resolv >> DNSServer) - { - if (DNSServer == "nameserver") - { - resolv >> DNSServer; - if (DNSServer.find_first_not_of("0123456789.") == std::string::npos) - { - ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, " set to '%s' as first resolver in /etc/resolv.conf.",DNSServer.c_str()); - return; - } - } - } - - ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!"); -#endif - DNSServer = "127.0.0.1"; - } - - public: - ModuleDNS() : manager(this) - { - } - - void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE - { - std::string oldserver = DNSServer; - DNSServer = ServerInstance->Config->ConfValue("dns")->getString("server"); - if (DNSServer.empty()) - FindDNSServer(); - - if (oldserver != DNSServer) - this->manager.Rehash(DNSServer); - } - - void OnUnloadModule(Module* mod) - { - for (int i = 0; i < MAX_REQUEST_ID; ++i) - { - DNS::Request* req = this->manager.requests[i]; - if (!req) - continue; - - if (req->creator == mod) - { - Query rr(*req); - rr.error = ERROR_UNLOADED; - req->OnError(&rr); - - delete req; - } - } - } - - Version GetVersion() - { - return Version("DNS support", VF_CORE|VF_VENDOR); - } -}; - -MODULE_INIT(ModuleDNS) - diff --git a/src/commands/cmd_eline.cpp b/src/commands/cmd_eline.cpp deleted file mode 100644 index 509089d3e..000000000 --- a/src/commands/cmd_eline.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "xline.h" - -/** Handle /ELINE. - */ -class CommandEline : public Command -{ - public: - /** Constructor for eline. - */ - CommandEline ( Module* parent) : Command(parent,"ELINE",1,3) { flags_needed = 'o'; syntax = " [ :]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/** Handle /ELINE - */ -CmdResult CommandEline::Handle (const std::vector& parameters, User *user) -{ - std::string target = parameters[0]; - - if (parameters.size() >= 3) - { - IdentHostPair ih; - User* find = ServerInstance->FindNick(target); - if ((find) && (find->registered == REG_ALL)) - { - ih.first = "*"; - ih.second = find->GetIPString(); - target = std::string("*@") + find->GetIPString(); - } - else - ih = ServerInstance->XLines->IdentSplit(target); - - if (ih.first.empty()) - { - user->WriteNotice("*** Target not found"); - return CMD_FAILURE; - } - - if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) - return CMD_FAILURE; - - unsigned long duration = InspIRCd::Duration(parameters[1]); - ELine* el = new ELine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); - if (ServerInstance->XLines->AddLine(el, user)) - { - if (!duration) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent E-line for %s: %s", user->nick.c_str(), target.c_str(), parameters[2].c_str()); - } - else - { - time_t c_requires_crap = duration + ServerInstance->Time(); - std::string timestr = InspIRCd::TimeString(c_requires_crap); - ServerInstance->SNO->WriteToSnoMask('x',"%s added timed E-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(), - timestr.c_str(), parameters[2].c_str()); - } - } - else - { - delete el; - user->WriteNotice("*** E-Line for " + target + " already exists"); - } - } - else - { - if (ServerInstance->XLines->DelLine(target.c_str(), "E", user)) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s removed E-line on %s",user->nick.c_str(),target.c_str()); - } - else - { - user->WriteNotice("*** E-Line " + target + " not found in list, try /stats e"); - } - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandEline) diff --git a/src/commands/cmd_gline.cpp b/src/commands/cmd_gline.cpp deleted file mode 100644 index 18a661b24..000000000 --- a/src/commands/cmd_gline.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "xline.h" - -/** Handle /GLINE. - */ -class CommandGline : public Command -{ - public: - /** Constructor for gline. - */ - CommandGline (Module* parent) : Command(parent,"GLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = " [ :]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - - -/** Handle /GLINE - */ -CmdResult CommandGline::Handle (const std::vector& parameters, User *user) -{ - std::string target = parameters[0]; - - if (parameters.size() >= 3) - { - IdentHostPair ih; - User* find = ServerInstance->FindNick(target); - if ((find) && (find->registered == REG_ALL)) - { - ih.first = "*"; - ih.second = find->GetIPString(); - target = std::string("*@") + find->GetIPString(); - } - else - ih = ServerInstance->XLines->IdentSplit(target); - - if (ih.first.empty()) - { - user->WriteNotice("*** Target not found"); - return CMD_FAILURE; - } - - if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) - return CMD_FAILURE; - - else if (target.find('!') != std::string::npos) - { - user->WriteNotice("*** G-Line cannot operate on nick!user@host masks"); - return CMD_FAILURE; - } - - unsigned long duration = InspIRCd::Duration(parameters[1]); - GLine* gl = new GLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); - if (ServerInstance->XLines->AddLine(gl, user)) - { - if (!duration) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent G-line for %s: %s",user->nick.c_str(),target.c_str(), parameters[2].c_str()); - } - else - { - time_t c_requires_crap = duration + ServerInstance->Time(); - std::string timestr = InspIRCd::TimeString(c_requires_crap); - ServerInstance->SNO->WriteToSnoMask('x',"%s added timed G-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(), - timestr.c_str(), parameters[2].c_str()); - } - - ServerInstance->XLines->ApplyLines(); - } - else - { - delete gl; - user->WriteNotice("** G-Line for " + target + " already exists"); - } - - } - else - { - if (ServerInstance->XLines->DelLine(target.c_str(),"G",user)) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s removed G-line on %s",user->nick.c_str(),target.c_str()); - } - else - { - user->WriteNotice("*** G-Line " + target + " not found in list, try /stats g."); - } - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandGline) diff --git a/src/commands/cmd_hostname_lookup.cpp b/src/commands/cmd_hostname_lookup.cpp deleted file mode 100644 index c26d3b3d3..000000000 --- a/src/commands/cmd_hostname_lookup.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2013 Adam - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "modules/dns.h" - -namespace -{ - LocalIntExt* dl; - LocalStringExt* ph; -} - -/** Derived from Resolver, and performs user forward/reverse lookups. - */ -class UserResolver : public DNS::Request -{ - /** UUID we are looking up */ - const std::string uuid; - - /** True if the lookup is forward, false if is a reverse lookup - */ - const bool fwd; - - public: - /** Create a resolver. - * @param mgr DNS Manager - * @param me this module - * @param user The user to begin lookup on - * @param to_resolve The IP or host to resolve - * @param qt The query type - */ - UserResolver(DNS::Manager* mgr, Module* me, LocalUser* user, const std::string& to_resolve, DNS::QueryType qt) - : DNS::Request(mgr, me, to_resolve, qt) - , uuid(user->uuid) - , fwd(qt == DNS::QUERY_A || qt == DNS::QUERY_AAAA) - { - } - - /** Called on successful lookup - * if a previous result has already come back. - * @param r The finished query - */ - void OnLookupComplete(const DNS::Query* r) - { - LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid); - if (!bound_user) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolution finished for user '%s' who is gone", uuid.c_str()); - return; - } - - const DNS::ResourceRecord& ans_record = r->answers[0]; - - ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "DNS result for %s: '%s' -> '%s'", uuid.c_str(), ans_record.name.c_str(), ans_record.rdata.c_str()); - - if (!fwd) - { - // first half of resolution is done. We now need to verify that the host matches. - ph->set(bound_user, ans_record.rdata); - - UserResolver* res_forward; - if (bound_user->client_sa.sa.sa_family == AF_INET6) - { - /* IPV6 forward lookup */ - res_forward = new UserResolver(this->manager, this->creator, bound_user, ans_record.rdata, DNS::QUERY_AAAA); - } - else - { - /* IPV4 lookup */ - res_forward = new UserResolver(this->manager, this->creator, bound_user, ans_record.rdata, DNS::QUERY_A); - } - try - { - this->manager->Process(res_forward); - } - catch (DNS::Exception& e) - { - delete res_forward; - ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Error in resolver: " + e.GetReason()); - - bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead."); - dl->set(bound_user, 0); - } - } - else - { - /* Both lookups completed */ - - irc::sockets::sockaddrs* user_ip = &bound_user->client_sa; - bool rev_match = false; - if (user_ip->sa.sa_family == AF_INET6) - { - struct in6_addr res_bin; - if (inet_pton(AF_INET6, ans_record.rdata.c_str(), &res_bin)) - { - rev_match = !memcmp(&user_ip->in6.sin6_addr, &res_bin, sizeof(res_bin)); - } - } - else - { - struct in_addr res_bin; - if (inet_pton(AF_INET, ans_record.rdata.c_str(), &res_bin)) - { - rev_match = !memcmp(&user_ip->in4.sin_addr, &res_bin, sizeof(res_bin)); - } - } - - dl->set(bound_user, 0); - - if (rev_match) - { - std::string* hostname = ph->get(bound_user); - - if (hostname == NULL) - { - ServerInstance->Logs->Log("RESOLVER", LOG_DEFAULT, "ERROR: User has no hostname attached when doing a forward lookup"); - bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead."); - return; - } - else if (hostname->length() < 65) - { - /* Hostnames starting with : are not a good thing (tm) */ - if ((*hostname)[0] == ':') - hostname->insert(0, "0"); - - bound_user->WriteNotice("*** Found your hostname (" + *hostname + (r->cached ? ") -- cached" : ")")); - bound_user->host.assign(*hostname, 0, 64); - bound_user->dhost = bound_user->host; - - /* Invalidate cache */ - bound_user->InvalidateCache(); - } - else - { - bound_user->WriteNotice("*** Your hostname is longer than the maximum of 64 characters, using your IP address (" + bound_user->GetIPString() + ") instead."); - } - - ph->unset(bound_user); - } - else - { - bound_user->WriteNotice("*** Your hostname does not match up with your IP address. Sorry, using your IP address (" + bound_user->GetIPString() + ") instead."); - } - } - } - - /** Called on failed lookup - * @param query The errored query - */ - void OnError(const DNS::Query* query) - { - LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid); - if (bound_user) - { - bound_user->WriteNotice("*** Could not resolve your hostname: " + this->manager->GetErrorStr(query->error) + "; using your IP address (" + bound_user->GetIPString() + ") instead."); - dl->set(bound_user, 0); - ServerInstance->stats->statsDnsBad++; - } - } -}; - -class ModuleHostnameLookup : public Module -{ - LocalIntExt dnsLookup; - LocalStringExt ptrHosts; - dynamic_reference DNS; - - public: - ModuleHostnameLookup() - : dnsLookup("dnsLookup", this) - , ptrHosts("ptrHosts", this) - , DNS(this, "DNS") - { - dl = &dnsLookup; - ph = &ptrHosts; - } - - void OnUserInit(LocalUser *user) - { - if (!DNS || !user->MyClass->resolvehostnames) - { - user->WriteNotice("*** Skipping host resolution (disabled by server administrator)"); - return; - } - - user->WriteNotice("*** Looking up your hostname..."); - - UserResolver* res_reverse = new UserResolver(*this->DNS, this, user, user->GetIPString(), DNS::QUERY_PTR); - try - { - /* If both the reverse and forward queries are cached, the user will be able to pass DNS completely - * before Process() completes, which is why dnsLookup.set() is here, before Process() - */ - this->dnsLookup.set(user, 1); - this->DNS->Process(res_reverse); - } - catch (DNS::Exception& e) - { - this->dnsLookup.set(user, 0); - delete res_reverse; - ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Error in resolver: " + e.GetReason()); - ServerInstance->stats->statsDnsBad++; - } - } - - ModResult OnCheckReady(LocalUser* user) - { - return this->dnsLookup.get(user) ? MOD_RES_DENY : MOD_RES_PASSTHRU; - } - - Version GetVersion() - { - return Version("Provides support for DNS lookups on connecting clients", VF_CORE|VF_VENDOR); - } -}; - -MODULE_INIT(ModuleHostnameLookup) diff --git a/src/commands/cmd_info.cpp b/src/commands/cmd_info.cpp deleted file mode 100644 index 7f1e923c9..000000000 --- a/src/commands/cmd_info.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2011 Jackmcbarn - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * Copyright (C) 2008 Thomas Stagner - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /INFO. - */ -class CommandInfo : public Command -{ - public: - /** Constructor for info. - */ - CommandInfo(Module* parent) : Command(parent,"INFO") - { - Penalty = 4; - syntax = "[]"; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - if (parameters.size() > 0) - return ROUTE_UNICAST(parameters[0]); - return ROUTE_LOCALONLY; - } -}; - -static const char* const lines[] = { - " -/\\- \2InspIRCd\2 -\\/-", - " November 2002 - Present", - " ", - "\2Core Developers\2:", - " Craig Edwards, Brain, ", - " Craig McLure, Craig, ", - " Robin Burchell, w00t, ", - " Oliver Lupton, Om, ", - " John Brooks, Special, ", - " Dennis Friis, peavey, ", - " Thomas Stagner, aquanight, ", - " Uli Schlachter, psychon, ", - " Matt Smith, dz, ", - " Daniel De Graaf, danieldg, ", - " jackmcbarn, ", - " Attila Molnar, Attila, ", - " ", - "\2Regular Contributors\2:", - " Adam SaberUK", - " ", - "\2Other Contributors\2:", - " ChrisTX Shawn Shutter", - " ", - "\2Former Contributors\2:", - " dmb Zaba skenmy GreenReaper", - " Dan Jason satmd owine", - " Adremelech John2 jilles HiroP", - " eggy Bricker AnMaster djGrrr", - " nenolod Quension praetorian pippijn", - " CC jamie typobox43 Burlex (win32)", - " Stskeeps ThaPrince BuildSmart Thunderhacker", - " Skip LeaChim Majic MacGyver", - " Namegduf Ankit Phoenix Taros", - " ", - "\2Thanks To\2:", - " searchirc.com irc-junkie.org Brik fraggeln", - " ", - " Best experienced with: \2An IRC client\2", - NULL -}; - -/** Handle /INFO - */ -CmdResult CommandInfo::Handle (const std::vector& parameters, User *user) -{ - if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName) - return CMD_SUCCESS; - - int i=0; - while (lines[i]) - user->SendText(":%s %03d %s :%s", ServerInstance->Config->ServerName.c_str(), RPL_INFO, user->nick.c_str(), lines[i++]); - FOREACH_MOD(OnInfo, (user)); - user->SendText(":%s %03d %s :End of /INFO list", ServerInstance->Config->ServerName.c_str(), RPL_ENDOFINFO, user->nick.c_str()); - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandInfo) diff --git a/src/commands/cmd_invite.cpp b/src/commands/cmd_invite.cpp deleted file mode 100644 index 25afc0713..000000000 --- a/src/commands/cmd_invite.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * Copyright (C) 2008 Craig Edwards - * Copyright (C) 2008 Thomas Stagner - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /INVITE. - */ -class CommandInvite : public Command -{ - public: - /** Constructor for invite. - */ - CommandInvite ( Module* parent) : Command(parent,"INVITE", 0, 0) { Penalty = 4; syntax = "[ ]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); - } -}; - -/** Handle /INVITE - */ -CmdResult CommandInvite::Handle (const std::vector& parameters, User *user) -{ - ModResult MOD_RESULT; - - if (parameters.size() == 2 || parameters.size() == 3) - { - User* u; - if (IS_LOCAL(user)) - u = ServerInstance->FindNickOnly(parameters[0]); - else - u = ServerInstance->FindNick(parameters[0]); - - Channel* c = ServerInstance->FindChan(parameters[1]); - time_t timeout = 0; - if (parameters.size() == 3) - { - if (IS_LOCAL(user)) - timeout = ServerInstance->Time() + InspIRCd::Duration(parameters[2]); - else - timeout = ConvToInt(parameters[2]); - } - - if ((!c) || (!u) || (u->registered != REG_ALL)) - { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c ? parameters[0].c_str() : parameters[1].c_str()); - return CMD_FAILURE; - } - - if ((IS_LOCAL(user)) && (!c->HasUser(user))) - { - user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", c->name.c_str()); - return CMD_FAILURE; - } - - if (c->HasUser(u)) - { - user->WriteNumeric(ERR_USERONCHANNEL, "%s %s :is already on channel", u->nick.c_str(), c->name.c_str()); - return CMD_FAILURE; - } - - FIRST_MOD_RESULT(OnUserPreInvite, MOD_RESULT, (user,u,c,timeout)); - - if (MOD_RESULT == MOD_RES_DENY) - { - return CMD_FAILURE; - } - else if (MOD_RESULT == MOD_RES_PASSTHRU) - { - if (IS_LOCAL(user)) - { - unsigned int rank = c->GetPrefixValue(user); - if (rank < HALFOP_VALUE) - { - // Check whether halfop mode is available and phrase error message accordingly - ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL); - user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You must be a channel %soperator", - c->name.c_str(), (mh && mh->name == "halfop" ? "half-" : "")); - return CMD_FAILURE; - } - } - } - - if (IS_LOCAL(u)) - { - Invitation::Create(c, IS_LOCAL(u), timeout); - u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str()); - } - - if (IS_LOCAL(user)) - user->WriteNumeric(RPL_INVITING, "%s %s", u->nick.c_str(),c->name.c_str()); - - if (ServerInstance->Config->AnnounceInvites != ServerConfig::INVITE_ANNOUNCE_NONE) - { - char prefix; - switch (ServerInstance->Config->AnnounceInvites) - { - case ServerConfig::INVITE_ANNOUNCE_OPS: - { - prefix = '@'; - break; - } - case ServerConfig::INVITE_ANNOUNCE_DYNAMIC: - { - PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h'); - prefix = (mh && mh->name == "halfop" ? mh->GetPrefix() : '@'); - break; - } - default: - { - prefix = 0; - break; - } - } - c->WriteAllExceptSender(user, true, prefix, "NOTICE %s :*** %s invited %s into the channel", c->name.c_str(), user->nick.c_str(), u->nick.c_str()); - } - FOREACH_MOD(OnUserInvite, (user,u,c,timeout)); - } - else if (IS_LOCAL(user)) - { - // pinched from ircu - invite with not enough parameters shows channels - // youve been invited to but haven't joined yet. - InviteList& il = IS_LOCAL(user)->GetInviteList(); - for (InviteList::const_iterator i = il.begin(); i != il.end(); ++i) - { - user->WriteNumeric(RPL_INVITELIST, ":%s", (*i)->chan->name.c_str()); - } - user->WriteNumeric(RPL_ENDOFINVITELIST, ":End of INVITE list"); - } - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandInvite) diff --git a/src/commands/cmd_ison.cpp b/src/commands/cmd_ison.cpp deleted file mode 100644 index c7ead2a87..000000000 --- a/src/commands/cmd_ison.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /ISON. - */ -class CommandIson : public Command -{ - public: - /** Constructor for ison. - */ - CommandIson ( Module* parent) : Command(parent,"ISON", 1) { - syntax = " {nick}"; - } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/** Handle /ISON - */ -CmdResult CommandIson::Handle (const std::vector& parameters, User *user) -{ - std::map ison_already; - User *u; - std::string reply = "303 " + user->nick + " :"; - - for (unsigned int i = 0; i < parameters.size(); i++) - { - u = ServerInstance->FindNickOnly(parameters[i]); - if (ison_already.find(u) != ison_already.end()) - continue; - - if (u) - { - reply.append(u->nick).append(" "); - if (reply.length() > 450) - { - user->WriteServ(reply); - reply = "303 " + user->nick + " :"; - } - ison_already[u] = u; - } - else - { - if ((i == parameters.size() - 1) && (parameters[i].find(' ') != std::string::npos)) - { - /* Its a space seperated list of nicks (RFC1459 says to support this) - */ - irc::spacesepstream list(parameters[i]); - std::string item; - - while (list.GetToken(item)) - { - u = ServerInstance->FindNickOnly(item); - if (ison_already.find(u) != ison_already.end()) - continue; - - if (u) - { - reply.append(u->nick).append(" "); - if (reply.length() > 450) - { - user->WriteServ(reply); - reply = "303 " + user->nick + " :"; - } - ison_already[u] = u; - } - } - } - } - } - - if (!reply.empty()) - user->WriteServ(reply); - - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandIson) diff --git a/src/commands/cmd_join.cpp b/src/commands/cmd_join.cpp deleted file mode 100644 index 1e6e515ba..000000000 --- a/src/commands/cmd_join.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /JOIN. - */ -class CommandJoin : public SplitCommand -{ - public: - /** Constructor for join. - */ - CommandJoin(Module* parent) - : SplitCommand(parent, "JOIN", 1, 2) - { - syntax = "{,} {{,}}"; - Penalty = 2; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult HandleLocal(const std::vector& parameters, LocalUser* user); -}; - -/** Handle /JOIN - */ -CmdResult CommandJoin::HandleLocal(const std::vector& parameters, LocalUser *user) -{ - if (parameters.size() > 1) - { - if (CommandParser::LoopCall(user, this, parameters, 0, 1, false)) - return CMD_SUCCESS; - - if (ServerInstance->IsChannel(parameters[0])) - { - Channel::JoinUser(user, parameters[0], false, parameters[1]); - return CMD_SUCCESS; - } - } - else - { - if (CommandParser::LoopCall(user, this, parameters, 0, -1, false)) - return CMD_SUCCESS; - - if (ServerInstance->IsChannel(parameters[0])) - { - Channel::JoinUser(user, parameters[0]); - return CMD_SUCCESS; - } - } - - user->WriteNumeric(ERR_NOSUCHCHANNEL, "%s :Invalid channel name", parameters[0].c_str()); - return CMD_FAILURE; -} - -COMMAND_INIT(CommandJoin) diff --git a/src/commands/cmd_kick.cpp b/src/commands/cmd_kick.cpp deleted file mode 100644 index 01f2039fa..000000000 --- a/src/commands/cmd_kick.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /KICK. - */ -class CommandKick : public Command -{ - public: - /** Constructor for kick. - */ - CommandKick ( Module* parent) : Command(parent,"KICK",2,3) { syntax = " {,} []"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); - } -}; - -/** Handle /KICK - */ -CmdResult CommandKick::Handle (const std::vector& parameters, User *user) -{ - std::string reason; - Channel* c = ServerInstance->FindChan(parameters[0]); - User* u; - - if (CommandParser::LoopCall(user, this, parameters, 1)) - return CMD_SUCCESS; - - if (IS_LOCAL(user)) - u = ServerInstance->FindNickOnly(parameters[1]); - else - u = ServerInstance->FindNick(parameters[1]); - - if (!u || !c) - { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", u ? parameters[0].c_str() : parameters[1].c_str()); - return CMD_FAILURE; - } - - Membership* srcmemb = NULL; - if (IS_LOCAL(user)) - { - srcmemb = c->GetUser(user); - if (!srcmemb) - { - user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", parameters[0].c_str()); - return CMD_FAILURE; - } - - if (u->server->IsULine()) - { - user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You may not kick a u-lined client", c->name.c_str()); - return CMD_FAILURE; - } - } - - if (parameters.size() > 2) - { - reason.assign(parameters[2], 0, ServerInstance->Config->Limits.MaxKick); - } - else - { - reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick); - } - - c->KickUser(user, u, reason, srcmemb); - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandKick) diff --git a/src/commands/cmd_kill.cpp b/src/commands/cmd_kill.cpp deleted file mode 100644 index 454bab03f..000000000 --- a/src/commands/cmd_kill.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2008 Craig Edwards - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /KILL. - */ -class CommandKill : public Command -{ - std::string lastuuid; - std::string killreason; - - public: - /** Constructor for kill. - */ - CommandKill ( Module* parent) : Command(parent,"KILL",2,2) { - flags_needed = 'o'; - syntax = " "; - TRANSLATE2(TR_CUSTOM, TR_CUSTOM); - } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - // FindNick() doesn't work here because we quit the target user in Handle() which - // removes it from the nicklist, so we check lastuuid: if it's empty then this KILL - // was for a local user, otherwise it contains the uuid of the user who was killed. - if (lastuuid.empty()) - return ROUTE_LOCALONLY; - return ROUTE_BROADCAST; - } - - void EncodeParameter(std::string& param, int index) - { - // Manually translate the nick -> uuid (see above), and also the reason (params[1]) - // because we decorate it if the oper is local and want remote servers to see the - // decorated reason not the original. - param = ((index == 0) ? lastuuid : killreason); - } -}; - -/** Handle /KILL - */ -CmdResult CommandKill::Handle (const std::vector& parameters, User *user) -{ - /* Allow comma seperated lists of users for /KILL (thanks w00t) */ - if (CommandParser::LoopCall(user, this, parameters, 0)) - { - // If we got a colon delimited list of nicks then the handler ran for each nick, - // and KILL commands were broadcast for remote targets. - return CMD_FAILURE; - } - - User *u = ServerInstance->FindNick(parameters[0]); - if ((u) && (!IS_SERVER(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 - */ - ModResult MOD_RESULT; - FIRST_MOD_RESULT(OnKill, MOD_RESULT, (user, u, parameters[1])); - - if (MOD_RESULT == MOD_RES_DENY) - return CMD_FAILURE; - - killreason = "Killed ("; - if (!ServerInstance->Config->HideKillsServer.empty()) - { - // hidekills is on, use it - killreason += ServerInstance->Config->HideKillsServer; - } - else - { - // hidekills is off, do nothing - killreason += user->nick; - } - - killreason += " (" + parameters[1] + "))"; - } - else - { - /* Leave it alone, remote server has already formatted it */ - killreason.assign(parameters[1], 0, ServerInstance->Config->Limits.MaxQuit); - } - - /* - * Now we need to decide whether or not to send a local or remote snotice. Currently this checking is a little flawed. - * No time to fix it right now, so left a note. -- w00t - */ - if (!IS_LOCAL(u)) - { - // remote kill - if (!user->server->IsULine()) - ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); - this->lastuuid = u->uuid; - } - 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 - */ - if (!user->server->IsULine()) - { - if (IS_LOCAL(user)) - ServerInstance->SNO->WriteGlobalSno('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); - else - ServerInstance->SNO->WriteToSnoMask('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); - } - - ServerInstance->Logs->Log("KILL", LOG_DEFAULT, "LOCAL KILL: %s :%s!%s!%s (%s)", u->nick.c_str(), ServerInstance->Config->ServerName.c_str(), user->dhost.c_str(), user->nick.c_str(), parameters[1].c_str()); - - u->Write(":%s KILL %s :%s!%s!%s (%s)", ServerInstance->Config->HideKillsServer.empty() ? user->GetFullHost().c_str() : ServerInstance->Config->HideKillsServer.c_str(), - u->nick.c_str(), - ServerInstance->Config->ServerName.c_str(), - user->dhost.c_str(), - ServerInstance->Config->HideKillsServer.empty() ? user->nick.c_str() : ServerInstance->Config->HideKillsServer.c_str(), - parameters[1].c_str()); - - this->lastuuid.clear(); - } - - // send the quit out - ServerInstance->Users->QuitUser(u, killreason); - } - else - { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); - return CMD_FAILURE; - } - - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandKill) diff --git a/src/commands/cmd_kline.cpp b/src/commands/cmd_kline.cpp deleted file mode 100644 index c6a8c7cad..000000000 --- a/src/commands/cmd_kline.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "xline.h" - -/** Handle /KLINE. - */ -class CommandKline : public Command -{ - public: - /** Constructor for kline. - */ - CommandKline ( Module* parent) : Command(parent,"KLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = " [ :]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - - -/** Handle /KLINE - */ -CmdResult CommandKline::Handle (const std::vector& parameters, User *user) -{ - std::string target = parameters[0]; - - if (parameters.size() >= 3) - { - IdentHostPair ih; - User* find = ServerInstance->FindNick(target); - if ((find) && (find->registered == REG_ALL)) - { - ih.first = "*"; - ih.second = find->GetIPString(); - target = std::string("*@") + find->GetIPString(); - } - else - ih = ServerInstance->XLines->IdentSplit(target); - - if (ih.first.empty()) - { - user->WriteNotice("*** Target not found"); - return CMD_FAILURE; - } - - if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) - return CMD_FAILURE; - - if (target.find('!') != std::string::npos) - { - user->WriteNotice("*** K-Line cannot operate on nick!user@host masks"); - return CMD_FAILURE; - } - - unsigned long duration = InspIRCd::Duration(parameters[1]); - KLine* kl = new KLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); - if (ServerInstance->XLines->AddLine(kl,user)) - { - if (!duration) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent K-line for %s: %s",user->nick.c_str(),target.c_str(), parameters[2].c_str()); - } - else - { - time_t c_requires_crap = duration + ServerInstance->Time(); - std::string timestr = InspIRCd::TimeString(c_requires_crap); - ServerInstance->SNO->WriteToSnoMask('x',"%s added timed K-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(), - timestr.c_str(), parameters[2].c_str()); - } - - ServerInstance->XLines->ApplyLines(); - } - else - { - delete kl; - user->WriteNotice("*** K-Line for " + target + " already exists"); - } - } - else - { - if (ServerInstance->XLines->DelLine(target.c_str(),"K",user)) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s removed K-line on %s",user->nick.c_str(),target.c_str()); - } - else - { - user->WriteNotice("*** K-Line " + target + " not found in list, try /stats k."); - } - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandKline) diff --git a/src/commands/cmd_links.cpp b/src/commands/cmd_links.cpp deleted file mode 100644 index 8b44d7a19..000000000 --- a/src/commands/cmd_links.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /LINKS. - */ -class CommandLinks : public Command -{ - public: - /** Constructor for links. - */ - CommandLinks ( Module* parent) : Command(parent,"LINKS",0,0) { } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/** Handle /LINKS - */ -CmdResult CommandLinks::Handle (const std::vector&, User *user) -{ - user->WriteNumeric(RPL_LINKS, "%s %s :0 %s", ServerInstance->Config->ServerName.c_str(),ServerInstance->Config->ServerName.c_str(),ServerInstance->Config->ServerDesc.c_str()); - user->WriteNumeric(RPL_ENDOFLINKS, "* :End of /LINKS list."); - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandLinks) diff --git a/src/commands/cmd_list.cpp b/src/commands/cmd_list.cpp deleted file mode 100644 index ceffae43a..000000000 --- a/src/commands/cmd_list.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /LIST. - */ -class CommandList : public Command -{ - ChanModeReference secretmode; - ChanModeReference privatemode; - - public: - /** Constructor for list. - */ - CommandList(Module* parent) - : Command(parent,"LIST", 0, 0) - , secretmode(creator, "secret") - , privatemode(creator, "private") - { - Penalty = 5; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - - -/** Handle /LIST - */ -CmdResult CommandList::Handle (const std::vector& parameters, User *user) -{ - int minusers = 0, maxusers = 0; - - user->WriteNumeric(RPL_LISTSTART, "Channel :Users Name"); - - /* Work around mIRC suckyness. YOU SUCK, KHALED! */ - if (parameters.size() == 1) - { - if (parameters[0][0] == '<') - { - maxusers = atoi((parameters[0].c_str())+1); - } - else if (parameters[0][0] == '>') - { - minusers = atoi((parameters[0].c_str())+1); - } - } - - for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++) - { - // attempt to match a glob pattern - long users = i->second->GetUserCounter(); - - bool too_few = (minusers && (users <= minusers)); - bool too_many = (maxusers && (users >= maxusers)); - - if (too_many || too_few) - continue; - - if (parameters.size() && !parameters[0].empty() && (parameters[0][0] != '<' && parameters[0][0] != '>')) - { - if (!InspIRCd::Match(i->second->name, parameters[0]) && !InspIRCd::Match(i->second->topic, parameters[0])) - continue; - } - - // if the channel is not private/secret, OR the user is on the channel anyway - bool n = (i->second->HasUser(user) || user->HasPrivPermission("channels/auspex")); - - if (!n && i->second->IsModeSet(privatemode)) - { - /* Channel is +p and user is outside/not privileged */ - user->WriteNumeric(RPL_LIST, "* %ld :", users); - } - else - { - if (n || !i->second->IsModeSet(secretmode)) - { - /* User is in the channel/privileged, channel is not +s */ - user->WriteNumeric(RPL_LIST, "%s %ld :[+%s] %s",i->second->name.c_str(),users,i->second->ChanModes(n),i->second->topic.c_str()); - } - } - } - user->WriteNumeric(RPL_LISTEND, ":End of channel list."); - - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandList) diff --git a/src/commands/cmd_loadmodule.cpp b/src/commands/cmd_loadmodule.cpp deleted file mode 100644 index 458a8cd6f..000000000 --- a/src/commands/cmd_loadmodule.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /LOADMODULE. - */ -class CommandLoadmodule : public Command -{ - public: - /** Constructor for loadmodule. - */ - CommandLoadmodule ( Module* parent) : Command(parent,"LOADMODULE",1,1) { flags_needed='o'; syntax = ""; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/** Handle /LOADMODULE - */ -CmdResult CommandLoadmodule::Handle (const std::vector& parameters, User *user) -{ - if (ServerInstance->Modules->Load(parameters[0])) - { - ServerInstance->SNO->WriteGlobalSno('a', "NEW MODULE: %s loaded %s",user->nick.c_str(), parameters[0].c_str()); - user->WriteNumeric(RPL_LOADEDMODULE, "%s :Module successfully loaded.", parameters[0].c_str()); - return CMD_SUCCESS; - } - else - { - user->WriteNumeric(ERR_CANTLOADMODULE, "%s :%s", parameters[0].c_str(), ServerInstance->Modules->LastError().c_str()); - return CMD_FAILURE; - } -} - -COMMAND_INIT(CommandLoadmodule) diff --git a/src/commands/cmd_lusers.cpp b/src/commands/cmd_lusers.cpp deleted file mode 100644 index e56b1c0bb..000000000 --- a/src/commands/cmd_lusers.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -struct LusersCounters -{ - unsigned int max_local; - unsigned int max_global; - unsigned int invisible; - - LusersCounters(unsigned int inv) - : max_local(ServerInstance->Users->LocalUserCount()) - , max_global(ServerInstance->Users->RegisteredUserCount()) - , invisible(inv) - { - } - - inline void UpdateMaxUsers() - { - unsigned int current = ServerInstance->Users->LocalUserCount(); - if (current > max_local) - max_local = current; - - current = ServerInstance->Users->RegisteredUserCount(); - if (current > max_global) - max_global = current; - } -}; - -/** Handle /LUSERS. - */ -class CommandLusers : public Command -{ - LusersCounters& counters; - public: - /** Constructor for lusers. - */ - CommandLusers(Module* parent, LusersCounters& Counters) - : Command(parent,"LUSERS",0,0), counters(Counters) - { } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/** Handle /LUSERS - */ -CmdResult CommandLusers::Handle (const std::vector&, User *user) -{ - unsigned int n_users = ServerInstance->Users->RegisteredUserCount(); - ProtocolInterface::ServerList serverlist; - ServerInstance->PI->GetServerList(serverlist); - unsigned int n_serv = serverlist.size(); - unsigned int n_local_servs = 0; - for (ProtocolInterface::ServerList::const_iterator i = serverlist.begin(); i != serverlist.end(); ++i) - { - if (i->parentname == ServerInstance->Config->ServerName) - n_local_servs++; - } - // fix for default GetServerList not returning us - if (!n_serv) - n_serv = 1; - - counters.UpdateMaxUsers(); - - user->WriteNumeric(RPL_LUSERCLIENT, ":There are %d users and %d invisible on %d servers", - n_users - counters.invisible, counters.invisible, n_serv); - - if (ServerInstance->Users->OperCount()) - user->WriteNumeric(RPL_LUSEROP, "%d :operator(s) online", ServerInstance->Users->OperCount()); - - if (ServerInstance->Users->UnregisteredUserCount()) - user->WriteNumeric(RPL_LUSERUNKNOWN, "%d :unknown connections", ServerInstance->Users->UnregisteredUserCount()); - - user->WriteNumeric(RPL_LUSERCHANNELS, "%ld :channels formed", ServerInstance->ChannelCount()); - user->WriteNumeric(RPL_LUSERME, ":I have %d clients and %d servers", ServerInstance->Users->LocalUserCount(),n_local_servs); - user->WriteNumeric(RPL_LOCALUSERS, ":Current Local Users: %d Max: %d", ServerInstance->Users->LocalUserCount(), counters.max_local); - user->WriteNumeric(RPL_GLOBALUSERS, ":Current Global Users: %d Max: %d", n_users, counters.max_global); - - return CMD_SUCCESS; -} - -class InvisibleWatcher : public ModeWatcher -{ - unsigned int& invisible; -public: - InvisibleWatcher(Module* mod, unsigned int& Invisible) - : ModeWatcher(mod, "invisible", MODETYPE_USER), invisible(Invisible) - { - } - - void AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding) - { - if (dest->registered != REG_ALL) - return; - - if (adding) - invisible++; - else - invisible--; - } -}; - -class ModuleLusers : public Module -{ - UserModeReference invisiblemode; - LusersCounters counters; - CommandLusers cmd; - InvisibleWatcher mw; - - unsigned int CountInvisible() - { - unsigned int c = 0; - for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); ++i) - { - User* u = i->second; - if (u->IsModeSet(invisiblemode)) - c++; - } - return c; - } - - public: - ModuleLusers() - : invisiblemode(this, "invisible") - , counters(CountInvisible()) - , cmd(this, counters) - , mw(this, counters.invisible) - { - } - - void OnPostConnect(User* user) - { - counters.UpdateMaxUsers(); - if (user->IsModeSet(invisiblemode)) - counters.invisible++; - } - - void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) - { - if (user->IsModeSet(invisiblemode)) - counters.invisible--; - } - - Version GetVersion() - { - return Version("LUSERS", VF_VENDOR | VF_CORE); - } -}; - -MODULE_INIT(ModuleLusers) diff --git a/src/commands/cmd_mode.cpp b/src/commands/cmd_mode.cpp deleted file mode 100644 index d2e9b4f63..000000000 --- a/src/commands/cmd_mode.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /MODE. - */ -class CommandMode : public Command -{ - public: - /** Constructor for mode. - */ - CommandMode ( Module* parent) : Command(parent,"MODE",1) { syntax = " {}"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); - } -}; - - -/** Handle /MODE - */ -CmdResult CommandMode::Handle (const std::vector& parameters, User *user) -{ - ServerInstance->Modes->Process(parameters, user, (IS_LOCAL(user) ? ModeParser::MODE_NONE : ModeParser::MODE_LOCALONLY)); - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandMode) diff --git a/src/commands/cmd_modules.cpp b/src/commands/cmd_modules.cpp deleted file mode 100644 index 01774390d..000000000 --- a/src/commands/cmd_modules.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2008 Craig Edwards - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /MODULES. - */ -class CommandModules : public Command -{ - public: - /** Constructor for modules. - */ - CommandModules(Module* parent) : Command(parent,"MODULES",0,0) - { - Penalty = 4; - syntax = "[]"; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - if (parameters.size() >= 1) - return ROUTE_UNICAST(parameters[0]); - return ROUTE_LOCALONLY; - } -}; - -/** Handle /MODULES - */ -CmdResult CommandModules::Handle (const std::vector& parameters, User *user) -{ - // Don't ask remote servers about their modules unless the local user asking is an oper - // 2.0 asks anyway, so let's handle that the same way - bool for_us = (parameters.empty() || parameters[0] == ServerInstance->Config->ServerName); - if ((!for_us) || (!IS_LOCAL(user))) - { - if (!user->IsOper()) - { - user->WriteNotice("*** You cannot check what modules other servers have loaded."); - return CMD_FAILURE; - } - - // From an oper and not for us, forward - if (!for_us) - return CMD_SUCCESS; - } - - const ModuleManager::ModuleMap& mods = ServerInstance->Modules->GetModules(); - - for (ModuleManager::ModuleMap::const_iterator i = mods.begin(); i != mods.end(); ++i) - { - Module* m = i->second; - Version V = m->GetVersion(); - - if (IS_LOCAL(user) && user->HasPrivPermission("servers/auspex")) - { - std::string flags("SvcC"); - int pos = 0; - for (int mult = 1; mult <= VF_OPTCOMMON; mult *= 2, ++pos) - if (!(V.Flags & mult)) - flags[pos] = '-'; - -#ifdef PURE_STATIC - user->SendText(":%s 702 %s :%p %s %s :%s", ServerInstance->Config->ServerName.c_str(), - user->nick.c_str(), (void*)m, m->ModuleSourceFile.c_str(), flags.c_str(), V.description.c_str()); -#else - std::string srcrev = m->ModuleDLLManager->GetVersion(); - user->SendText(":%s 702 %s :%p %s %s :%s - %s", ServerInstance->Config->ServerName.c_str(), - user->nick.c_str(), (void*)m, m->ModuleSourceFile.c_str(), flags.c_str(), V.description.c_str(), srcrev.c_str()); -#endif - } - else - { - user->SendText(":%s 702 %s :%s %s", ServerInstance->Config->ServerName.c_str(), - user->nick.c_str(), m->ModuleSourceFile.c_str(), V.description.c_str()); - } - } - user->SendText(":%s 703 %s :End of MODULES list", ServerInstance->Config->ServerName.c_str(), user->nick.c_str()); - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandModules) diff --git a/src/commands/cmd_motd.cpp b/src/commands/cmd_motd.cpp deleted file mode 100644 index 71df7017a..000000000 --- a/src/commands/cmd_motd.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /MOTD. - */ -class CommandMotd : public Command -{ - public: - /** Constructor for motd. - */ - CommandMotd ( Module* parent) : Command(parent,"MOTD",0,1) { syntax = "[]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - if (parameters.size() > 0) - return ROUTE_UNICAST(parameters[0]); - return ROUTE_LOCALONLY; - } -}; - -/** Handle /MOTD - */ -CmdResult CommandMotd::Handle (const std::vector& parameters, User *user) -{ - if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName) - return CMD_SUCCESS; - - ConfigTag* tag = NULL; - LocalUser* localuser = IS_LOCAL(user); - if (localuser) - tag = localuser->GetClass()->config; - std::string motd_name = tag->getString("motd", "motd"); - ConfigFileCache::iterator motd = ServerInstance->Config->Files.find(motd_name); - if (motd == ServerInstance->Config->Files.end()) - { - user->SendText(":%s %03d %s :Message of the day file is missing.", - ServerInstance->Config->ServerName.c_str(), ERR_NOMOTD, user->nick.c_str()); - return CMD_SUCCESS; - } - - user->SendText(":%s %03d %s :%s message of the day", ServerInstance->Config->ServerName.c_str(), - RPL_MOTDSTART, user->nick.c_str(), ServerInstance->Config->ServerName.c_str()); - - for (file_cache::iterator i = motd->second.begin(); i != motd->second.end(); i++) - user->SendText(":%s %03d %s :- %s", ServerInstance->Config->ServerName.c_str(), RPL_MOTD, user->nick.c_str(), i->c_str()); - - user->SendText(":%s %03d %s :End of message of the day.", ServerInstance->Config->ServerName.c_str(), RPL_ENDOFMOTD, user->nick.c_str()); - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandMotd) diff --git a/src/commands/cmd_names.cpp b/src/commands/cmd_names.cpp deleted file mode 100644 index 8c8bc58dd..000000000 --- a/src/commands/cmd_names.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /NAMES. - */ -class CommandNames : public Command -{ - ChanModeReference secretmode; - - public: - /** Constructor for names. - */ - CommandNames(Module* parent) - : Command(parent, "NAMES", 0, 0) - , secretmode(parent, "secret") - { - syntax = "{{,}}"; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/** Handle /NAMES - */ -CmdResult CommandNames::Handle (const std::vector& parameters, User *user) -{ - Channel* c; - - if (!parameters.size()) - { - user->WriteNumeric(RPL_ENDOFNAMES, "* :End of /NAMES list."); - return CMD_SUCCESS; - } - - if (CommandParser::LoopCall(user, this, parameters, 0)) - return CMD_SUCCESS; - - c = ServerInstance->FindChan(parameters[0]); - if (c) - { - if ((c->IsModeSet(secretmode)) && (!c->HasUser(user))) - { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c->name.c_str()); - return CMD_FAILURE; - } - c->UserList(user); - } - else - { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandNames) diff --git a/src/commands/cmd_nick.cpp b/src/commands/cmd_nick.cpp deleted file mode 100644 index 486fce7eb..000000000 --- a/src/commands/cmd_nick.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2008 Craig Edwards - * Copyright (C) 2008 Thomas Stagner - * Copyright (C) 2007-2008 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /NICK. - */ -class CommandNick : public Command -{ - public: - /** Constructor for nick. - */ - CommandNick ( Module* parent) : Command(parent,"NICK", 1, 1) { works_before_reg = true; syntax = ""; Penalty = 0; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -/** Handle nick changes from users. - * NOTE: If you are used to ircds based on ircd2.8, and are looking - * for the client introduction code in here, youre in the wrong place. - * You need to look in the spanningtree module for this! - */ -CmdResult CommandNick::Handle (const std::vector& parameters, User *user) -{ - std::string oldnick = user->nick; - std::string newnick = parameters[0]; - - // anything except the initial NICK gets a flood penalty - if (user->registered == REG_ALL && IS_LOCAL(user)) - IS_LOCAL(user)->CommandFloodPenalty += 4000; - - if (newnick.empty()) - { - user->WriteNumeric(ERR_ERRONEUSNICKNAME, "* :Erroneous Nickname"); - return CMD_FAILURE; - } - - if (newnick == "0") - { - newnick = user->uuid; - } - else if (!ServerInstance->IsNick(newnick)) - { - user->WriteNumeric(ERR_ERRONEUSNICKNAME, "%s :Erroneous Nickname", newnick.c_str()); - return CMD_FAILURE; - } - - if (!user->ChangeNick(newnick, false)) - return CMD_FAILURE; - - if (user->registered < REG_NICKUSER) - { - user->registered = (user->registered | REG_NICK); - if (user->registered == REG_NICKUSER) - { - /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ - ModResult MOD_RESULT; - FIRST_MOD_RESULT(OnUserRegister, MOD_RESULT, (IS_LOCAL(user))); - if (MOD_RESULT == MOD_RES_DENY) - return CMD_FAILURE; - - // return early to not penalize new users - return CMD_SUCCESS; - } - } - - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandNick) diff --git a/src/commands/cmd_oper.cpp b/src/commands/cmd_oper.cpp deleted file mode 100644 index bd7a35060..000000000 --- a/src/commands/cmd_oper.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2008 Thomas Stagner - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /OPER. - */ -class CommandOper : public SplitCommand -{ - public: - /** Constructor for oper. - */ - CommandOper ( Module* parent) : SplitCommand(parent,"OPER",2,2) { syntax = " "; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult HandleLocal(const std::vector& parameters, LocalUser *user); -}; - -CmdResult CommandOper::HandleLocal(const std::vector& parameters, LocalUser *user) -{ - bool match_login = false; - bool match_pass = false; - bool match_hosts = false; - - const std::string userHost = user->ident + "@" + user->host; - const std::string userIP = user->ident + "@" + user->GetIPString(); - - OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]); - if (i != ServerInstance->Config->oper_blocks.end()) - { - OperInfo* ifo = i->second; - ConfigTag* tag = ifo->oper_block; - match_login = true; - match_pass = ServerInstance->PassCompare(user, tag->getString("password"), parameters[1], tag->getString("hash")); - match_hosts = InspIRCd::MatchMask(tag->getString("host"), userHost, userIP); - - if (match_pass && match_hosts) - { - /* found this oper's opertype */ - user->Oper(ifo); - return CMD_SUCCESS; - } - } - - std::string fields; - if (!match_login) - fields.append("login "); - if (!match_pass) - fields.append("password "); - if (!match_hosts) - fields.append("hosts"); - - // tell them they suck, and lag them up to help prevent brute-force attacks - user->WriteNumeric(ERR_NOOPERHOST, ":Invalid oper credentials"); - user->CommandFloodPenalty += 10000; - - ServerInstance->SNO->WriteGlobalSno('o', "WARNING! Failed oper attempt by %s using login '%s': The following fields do not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str()); - ServerInstance->Logs->Log("OPER", LOG_DEFAULT, "OPER: Failed oper attempt by %s using login '%s': The following fields did not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str()); - return CMD_FAILURE; -} - -COMMAND_INIT(CommandOper) diff --git a/src/commands/cmd_part.cpp b/src/commands/cmd_part.cpp deleted file mode 100644 index f427063ea..000000000 --- a/src/commands/cmd_part.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /PART. - */ -class CommandPart : public Command -{ - public: - /** Constructor for part. - */ - CommandPart (Module* parent) : Command(parent,"PART", 1, 2) { Penalty = 5; syntax = "{,} []"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); - } -}; - -CmdResult CommandPart::Handle (const std::vector& parameters, User *user) -{ - std::string reason; - - if (IS_LOCAL(user)) - { - if (!ServerInstance->Config->FixedPart.empty()) - reason = ServerInstance->Config->FixedPart; - else if (parameters.size() > 1) - reason = ServerInstance->Config->PrefixPart + parameters[1] + ServerInstance->Config->SuffixPart; - } - else - { - if (parameters.size() > 1) - reason = parameters[1]; - } - - if (CommandParser::LoopCall(user, this, parameters, 0)) - return CMD_SUCCESS; - - Channel* c = ServerInstance->FindChan(parameters[0]); - - if (c) - { - c->PartUser(user, reason); - } - else - { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); - return CMD_FAILURE; - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandPart) diff --git a/src/commands/cmd_pass.cpp b/src/commands/cmd_pass.cpp deleted file mode 100644 index 66b2b5726..000000000 --- a/src/commands/cmd_pass.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /PASS. - */ -class CommandPass : public SplitCommand -{ - public: - /** Constructor for pass. - */ - CommandPass (Module* parent) : SplitCommand(parent,"PASS",1,1) { works_before_reg = true; Penalty = 0; syntax = ""; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult HandleLocal(const std::vector& parameters, LocalUser *user); -}; - - -CmdResult CommandPass::HandleLocal(const std::vector& parameters, LocalUser *user) -{ - // Check to make sure they haven't registered -- Fix by FCS - if (user->registered == REG_ALL) - { - user->WriteNumeric(ERR_ALREADYREGISTERED, ":You may not reregister"); - return CMD_FAILURE; - } - user->password = parameters[0]; - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandPass) diff --git a/src/commands/cmd_ping.cpp b/src/commands/cmd_ping.cpp deleted file mode 100644 index 06135f83c..000000000 --- a/src/commands/cmd_ping.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /PING. - */ -class CommandPing : public Command -{ - public: - /** Constructor for ping. - */ - CommandPing ( Module* parent) : Command(parent,"PING", 1, 2) { Penalty = 0; syntax = " [:]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandPing::Handle (const std::vector& parameters, User *user) -{ - user->WriteServ("PONG %s :%s", ServerInstance->Config->ServerName.c_str(), parameters[0].c_str()); - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandPing) diff --git a/src/commands/cmd_pong.cpp b/src/commands/cmd_pong.cpp deleted file mode 100644 index 06db92604..000000000 --- a/src/commands/cmd_pong.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /PONG. - */ -class CommandPong : public Command -{ - public: - /** Constructor for pong. - */ - CommandPong ( Module* parent) : Command(parent,"PONG", 0, 1) { Penalty = 0; syntax = ""; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandPong::Handle (const std::vector&, User *user) -{ - // set the user as alive so they survive to next ping - if (IS_LOCAL(user)) - IS_LOCAL(user)->lastping = 1; - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandPong) diff --git a/src/commands/cmd_privmsg.cpp b/src/commands/cmd_privmsg.cpp deleted file mode 100644 index 0cca56771..000000000 --- a/src/commands/cmd_privmsg.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007-2008 Craig Edwards - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -namespace -{ - const char* MessageTypeString[] = { "PRIVMSG", "NOTICE" }; -} - -class MessageCommandBase : public Command -{ - ChanModeReference moderatedmode; - ChanModeReference noextmsgmode; - - public: - MessageCommandBase(Module* parent, MessageType mt) - : Command(parent, MessageTypeString[mt], 2, 2) - , moderatedmode(parent, "moderated") - , noextmsgmode(parent, "noextmsg") - { - syntax = "{,} "; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult HandleMessage(const std::vector& parameters, User* user, MessageType mt); - - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - if (IS_LOCAL(user)) - // This is handled by the OnUserMessage hook to split the LoopCall pieces - return ROUTE_LOCALONLY; - else - return ROUTE_MESSAGE(parameters[0]); - } -}; - -CmdResult MessageCommandBase::HandleMessage(const std::vector& parameters, User* user, MessageType mt) -{ - User *dest; - Channel *chan; - CUList except_list; - - LocalUser* localuser = IS_LOCAL(user); - if (localuser) - localuser->idle_lastmsg = ServerInstance->Time(); - - if (CommandParser::LoopCall(user, this, parameters, 0)) - return CMD_SUCCESS; - - if (parameters[0][0] == '$') - { - if (!user->HasPrivPermission("users/mass-message")) - return CMD_SUCCESS; - - ModResult MOD_RESULT; - std::string temp = parameters[1]; - FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, except_list, mt)); - if (MOD_RESULT == MOD_RES_DENY) - return CMD_FAILURE; - - const char* text = temp.c_str(); - const char* servermask = (parameters[0].c_str()) + 1; - - FOREACH_MOD(OnText, (user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list)); - if (InspIRCd::Match(ServerInstance->Config->ServerName, servermask, NULL)) - { - user->SendAll(MessageTypeString[mt], "%s", text); - } - FOREACH_MOD(OnUserMessage, (user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list, mt)); - return CMD_SUCCESS; - } - char status = 0; - const char* target = parameters[0].c_str(); - - if (ServerInstance->Modes->FindPrefix(*target)) - { - status = *target; - target++; - } - if (*target == '#') - { - chan = ServerInstance->FindChan(target); - - except_list.insert(user); - - if (chan) - { - if (localuser && chan->GetPrefixValue(user) < VOICE_VALUE) - { - if (chan->IsModeSet(noextmsgmode) && !chan->HasUser(user)) - { - user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (no external messages)", chan->name.c_str()); - return CMD_FAILURE; - } - - if (chan->IsModeSet(moderatedmode)) - { - user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (+m)", chan->name.c_str()); - return CMD_FAILURE; - } - - if (ServerInstance->Config->RestrictBannedUsers) - { - if (chan->IsBanned(user)) - { - user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (you're banned)", chan->name.c_str()); - return CMD_FAILURE; - } - } - } - ModResult MOD_RESULT; - - std::string temp = parameters[1]; - FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, chan, TYPE_CHANNEL, temp, status, except_list, mt)); - if (MOD_RESULT == MOD_RES_DENY) - return CMD_FAILURE; - - const char* text = temp.c_str(); - - /* Check again, a module may have zapped the input string */ - if (temp.empty()) - { - user->WriteNumeric(ERR_NOTEXTTOSEND, ":No text to send"); - return CMD_FAILURE; - } - - FOREACH_MOD(OnText, (user,chan,TYPE_CHANNEL,text,status,except_list)); - - if (status) - { - if (ServerInstance->Config->UndernetMsgPrefix) - { - chan->WriteAllExcept(user, false, status, except_list, "%s %c%s :%c %s", MessageTypeString[mt], status, chan->name.c_str(), status, text); - } - else - { - chan->WriteAllExcept(user, false, status, except_list, "%s %c%s :%s", MessageTypeString[mt], status, chan->name.c_str(), text); - } - } - else - { - chan->WriteAllExcept(user, false, status, except_list, "%s %s :%s", MessageTypeString[mt], chan->name.c_str(), text); - } - - FOREACH_MOD(OnUserMessage, (user,chan, TYPE_CHANNEL, text, status, except_list, mt)); - } - else - { - /* no such nick/channel */ - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", target); - return CMD_FAILURE; - } - return CMD_SUCCESS; - } - - const char* destnick = parameters[0].c_str(); - - if (localuser) - { - const char* targetserver = strchr(destnick, '@'); - - if (targetserver) - { - std::string nickonly; - - nickonly.assign(destnick, 0, targetserver - destnick); - dest = ServerInstance->FindNickOnly(nickonly); - if (dest && strcasecmp(dest->server->GetName().c_str(), targetserver + 1)) - { - /* Incorrect server for user */ - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); - return CMD_FAILURE; - } - } - else - dest = ServerInstance->FindNickOnly(destnick); - } - else - dest = ServerInstance->FindNick(destnick); - - if ((dest) && (dest->registered == REG_ALL)) - { - if (parameters[1].empty()) - { - user->WriteNumeric(ERR_NOTEXTTOSEND, ":No text to send"); - return CMD_FAILURE; - } - - if ((dest->IsAway()) && (mt == MSG_PRIVMSG)) - { - /* auto respond with aweh msg */ - user->WriteNumeric(RPL_AWAY, "%s :%s", dest->nick.c_str(), dest->awaymsg.c_str()); - } - - ModResult MOD_RESULT; - - std::string temp = parameters[1]; - FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, dest, TYPE_USER, temp, 0, except_list, mt)); - if (MOD_RESULT == MOD_RES_DENY) - return CMD_FAILURE; - - const char* text = temp.c_str(); - - FOREACH_MOD(OnText, (user, dest, TYPE_USER, text, 0, except_list)); - - if (IS_LOCAL(dest)) - { - // direct write, same server - user->WriteTo(dest, "%s %s :%s", MessageTypeString[mt], dest->nick.c_str(), text); - } - - FOREACH_MOD(OnUserMessage, (user, dest, TYPE_USER, text, 0, except_list, mt)); - } - else - { - /* no such nick/channel */ - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); - return CMD_FAILURE; - } - return CMD_SUCCESS; -} - -template -class CommandMessage : public MessageCommandBase -{ - public: - CommandMessage(Module* parent) - : MessageCommandBase(parent, MT) - { - } - - CmdResult Handle(const std::vector& parameters, User* user) - { - return HandleMessage(parameters, user, MT); - } -}; - -class ModuleCoreMessage : public Module -{ - CommandMessage CommandPrivmsg; - CommandMessage CommandNotice; - - public: - ModuleCoreMessage() - : CommandPrivmsg(this), CommandNotice(this) - { - } - - Version GetVersion() - { - return Version("PRIVMSG, NOTICE", VF_CORE|VF_VENDOR); - } -}; - -MODULE_INIT(ModuleCoreMessage) diff --git a/src/commands/cmd_qline.cpp b/src/commands/cmd_qline.cpp deleted file mode 100644 index 003aacbef..000000000 --- a/src/commands/cmd_qline.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2008 Craig Edwards - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "xline.h" - -/** Handle /QLINE. */ -class CommandQline : public Command -{ - public: - /** Constructor for qline. - */ - CommandQline ( Module* parent) : Command(parent,"QLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = " [ :]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param pcnt The number of parameters passed to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - - -CmdResult CommandQline::Handle (const std::vector& parameters, User *user) -{ - if (parameters.size() >= 3) - { - if (ServerInstance->NickMatchesEveryone(parameters[0],user)) - return CMD_FAILURE; - - if (parameters[0].find('@') != std::string::npos || parameters[0].find('!') != std::string::npos || parameters[0].find('.') != std::string::npos) - { - user->WriteNotice("*** A Q-Line only bans a nick pattern, not a nick!user@host pattern."); - return CMD_FAILURE; - } - - unsigned long duration = InspIRCd::Duration(parameters[1]); - QLine* ql = new QLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str()); - if (ServerInstance->XLines->AddLine(ql,user)) - { - if (!duration) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Q-line for %s: %s",user->nick.c_str(), parameters[0].c_str(), parameters[2].c_str()); - } - else - { - time_t c_requires_crap = duration + ServerInstance->Time(); - std::string timestr = InspIRCd::TimeString(c_requires_crap); - ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Q-line for %s, expires on %s: %s",user->nick.c_str(),parameters[0].c_str(), - timestr.c_str(), parameters[2].c_str()); - } - ServerInstance->XLines->ApplyLines(); - } - else - { - delete ql; - user->WriteNotice("*** Q-Line for " + parameters[0] + " already exists"); - } - } - else - { - if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "Q", user)) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s removed Q-line on %s",user->nick.c_str(),parameters[0].c_str()); - } - else - { - user->WriteNotice("*** Q-Line " + parameters[0] + " not found in list, try /stats q."); - return CMD_FAILURE; - } - } - - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandQline) diff --git a/src/commands/cmd_quit.cpp b/src/commands/cmd_quit.cpp deleted file mode 100644 index 15dc07d6c..000000000 --- a/src/commands/cmd_quit.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /QUIT. - */ -class CommandQuit : public Command -{ - public: - /** Constructor for quit. - */ - CommandQuit ( Module* parent) : Command(parent,"QUIT",0,1) { works_before_reg = true; syntax = "[]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); - } -}; - - -CmdResult CommandQuit::Handle (const std::vector& parameters, User *user) -{ - - std::string quitmsg; - - if (IS_LOCAL(user)) - { - if (!ServerInstance->Config->FixedQuit.empty()) - quitmsg = ServerInstance->Config->FixedQuit; - else - quitmsg = parameters.size() ? - ServerInstance->Config->PrefixQuit + parameters[0] + ServerInstance->Config->SuffixQuit - : "Client exited"; - } - else - quitmsg = parameters.size() ? parameters[0] : "Client exited"; - - std::string* operquit = ServerInstance->OperQuit.get(user); - ServerInstance->Users->QuitUser(user, quitmsg, operquit); - - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandQuit) diff --git a/src/commands/cmd_rehash.cpp b/src/commands/cmd_rehash.cpp deleted file mode 100644 index f71219f75..000000000 --- a/src/commands/cmd_rehash.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * Copyright (C) 2008 Craig Edwards - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /REHASH. - */ -class CommandRehash : public Command -{ - public: - /** Constructor for rehash. - */ - CommandRehash ( Module* parent) : Command(parent,"REHASH",0) { flags_needed = 'o'; Penalty = 2; syntax = "[]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandRehash::Handle (const std::vector& parameters, User *user) -{ - std::string param = parameters.size() ? parameters[0] : ""; - - FOREACH_MOD(OnPreRehash, (user, param)); - - if (param.empty()) - { - // standard rehash of local server - } - else if (param.find_first_of("*.") != std::string::npos) - { - // rehash of servers by server name (with wildcard) - if (!InspIRCd::Match(ServerInstance->Config->ServerName, parameters[0])) - { - // Doesn't match us. PreRehash is already done, nothing left to do - return CMD_SUCCESS; - } - } - else - { - // parameterized rehash - - // the leading "-" is optional; remove it if present. - if (param[0] == '-') - param = param.substr(1); - - FOREACH_MOD(OnModuleRehash, (user, param)); - return CMD_SUCCESS; - } - - // Rehash for me. Try to start the rehash thread - if (!ServerInstance->ConfigThread) - { - std::string m = user->nick + " is rehashing config file " + FileSystem::GetFileName(ServerInstance->ConfigFileName) + " on " + ServerInstance->Config->ServerName; - ServerInstance->SNO->WriteGlobalSno('a', m); - - if (IS_LOCAL(user)) - user->WriteNumeric(RPL_REHASHING, "%s :Rehashing", FileSystem::GetFileName(ServerInstance->ConfigFileName).c_str()); - else - ServerInstance->PI->SendUserNotice(user, "*** Rehashing server " + FileSystem::GetFileName(ServerInstance->ConfigFileName)); - - /* Don't do anything with the logs here -- logs are restarted - * after the config thread has completed. - */ - ServerInstance->Rehash(user->uuid); - } - else - { - /* - * A rehash is already in progress! ahh shit. - * XXX, todo: we should find some way to kill runaway rehashes that are blocking, this is a major problem for unrealircd users - */ - if (IS_LOCAL(user)) - user->WriteNotice("*** Could not rehash: A rehash is already in progress."); - else - ServerInstance->PI->SendUserNotice(user, "*** Could not rehash: A rehash is already in progress."); - } - - // Always return success so spanningtree forwards an incoming REHASH even if we failed - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandRehash) diff --git a/src/commands/cmd_reloadmodule.cpp b/src/commands/cmd_reloadmodule.cpp deleted file mode 100644 index 765c465fd..000000000 --- a/src/commands/cmd_reloadmodule.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -class CommandReloadmodule : public Command -{ - public: - /** Constructor for reloadmodule. - */ - CommandReloadmodule ( Module* parent) : Command( parent, "RELOADMODULE",1) { flags_needed = 'o'; syntax = ""; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -class ReloadModuleWorker : public HandlerBase1 -{ - public: - const std::string name; - const std::string uid; - ReloadModuleWorker(const std::string& uuid, const std::string& modn) - : name(modn), uid(uuid) {} - void Call(bool result) - { - ServerInstance->SNO->WriteGlobalSno('a', "RELOAD MODULE: %s %ssuccessfully reloaded", - name.c_str(), result ? "" : "un"); - User* user = ServerInstance->FindNick(uid); - if (user) - user->WriteNumeric(RPL_LOADEDMODULE, "%s :Module %ssuccessfully reloaded.", - name.c_str(), result ? "" : "un"); - ServerInstance->GlobalCulls.AddItem(this); - } -}; - -CmdResult CommandReloadmodule::Handle (const std::vector& parameters, User *user) -{ - if (parameters[0] == "cmd_reloadmodule.so") - { - user->WriteNumeric(RPL_LOADEDMODULE, "%s :You cannot reload cmd_reloadmodule.so (unload and load it)", - parameters[0].c_str()); - return CMD_FAILURE; - } - - Module* m = ServerInstance->Modules->Find(parameters[0]); - if (m) - { - ServerInstance->Modules->Reload(m, new ReloadModuleWorker(user->uuid, parameters[0])); - return CMD_SUCCESS; - } - else - { - user->WriteNumeric(RPL_LOADEDMODULE, "%s :Could not find module by that name", parameters[0].c_str()); - return CMD_FAILURE; - } -} - -COMMAND_INIT(CommandReloadmodule) diff --git a/src/commands/cmd_restart.cpp b/src/commands/cmd_restart.cpp deleted file mode 100644 index 33627b540..000000000 --- a/src/commands/cmd_restart.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /RESTART - */ -class CommandRestart : public Command -{ - public: - /** Constructor for restart. - */ - CommandRestart(Module* parent) : Command(parent,"RESTART",1,1) { flags_needed = 'o'; syntax = ""; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandRestart::Handle (const std::vector& parameters, User *user) -{ - ServerInstance->Logs->Log("COMMAND", LOG_DEFAULT, "Restart: %s",user->nick.c_str()); - if (ServerInstance->PassCompare(user, ServerInstance->Config->restartpass, parameters[0], ServerInstance->Config->powerhash)) - { - ServerInstance->SNO->WriteGlobalSno('a', "RESTART command from %s, restarting server.", user->GetFullRealHost().c_str()); - - ServerInstance->SendError("Server restarting."); - -#ifndef _WIN32 - /* XXX: This hack sets FD_CLOEXEC on all possible file descriptors, so they're closed if the execv() below succeeds. - * Certainly, this is not a nice way to do things and it's slow when the fd limit is high. - * - * A better solution would be to set the close-on-exec flag for each fd we create (or create them with O_CLOEXEC), - * however there is no guarantee that third party libs will do the same. - */ - for (int i = getdtablesize(); --i > 2;) - { - int flags = fcntl(i, F_GETFD); - if (flags != -1) - fcntl(i, F_SETFD, flags | FD_CLOEXEC); - } -#endif - - execv(ServerInstance->Config->cmdline.argv[0], ServerInstance->Config->cmdline.argv); - ServerInstance->SNO->WriteGlobalSno('a', "Failed RESTART - could not execute '%s' (%s)", - ServerInstance->Config->cmdline.argv[0], strerror(errno)); - } - else - { - ServerInstance->SNO->WriteGlobalSno('a', "Failed RESTART Command from %s.", user->GetFullRealHost().c_str()); - } - return CMD_FAILURE; -} - - -COMMAND_INIT(CommandRestart) diff --git a/src/commands/cmd_server.cpp b/src/commands/cmd_server.cpp deleted file mode 100644 index 8c32dafa8..000000000 --- a/src/commands/cmd_server.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /SERVER. - */ -class CommandServer : public Command -{ - public: - /** Constructor for server. - */ - CommandServer ( Module* parent) : Command(parent,"SERVER") { works_before_reg = true;} - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandServer::Handle (const std::vector&, User *user) -{ - if (user->registered == REG_ALL) - { - user->WriteNumeric(ERR_ALREADYREGISTERED, ":You are already registered. (Perhaps your IRC client does not have a /SERVER command)."); - } - else - { - user->WriteNumeric(ERR_NOTREGISTERED, ":You may not register as a server (servers have separate ports from clients, change your config)"); - } - return CMD_FAILURE; -} - -COMMAND_INIT(CommandServer) diff --git a/src/commands/cmd_squit.cpp b/src/commands/cmd_squit.cpp deleted file mode 100644 index e64f5fc0f..000000000 --- a/src/commands/cmd_squit.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /SQUIT. - */ -class CommandSquit : public Command -{ - public: - /** Constructor for squit. - */ - CommandSquit ( Module* parent) : Command(parent,"SQUIT",1,2) { flags_needed = 'o'; syntax = " []"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - - -/* - * This is handled by the server linking module, if necessary. Do not remove this stub. - */ - - -CmdResult CommandSquit::Handle (const std::vector&, User *user) -{ - user->WriteServ( "NOTICE %s :Look into loading a linking module (like m_spanningtree) if you want this to do anything useful.", user->nick.c_str()); - return CMD_FAILURE; -} - -COMMAND_INIT(CommandSquit) diff --git a/src/commands/cmd_stats.cpp b/src/commands/cmd_stats.cpp deleted file mode 100644 index 8e74b8376..000000000 --- a/src/commands/cmd_stats.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2007-2008 Craig Edwards - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "xline.h" - -#ifdef _WIN32 -#include -#pragma comment(lib, "psapi.lib") // For GetProcessMemoryInfo() -#endif - -/** Handle /STATS. - */ -class CommandStats : public Command -{ - void DoStats(char statschar, User* user, string_list &results); - public: - /** Constructor for stats. - */ - CommandStats ( Module* parent) : Command(parent,"STATS",1,2) { syntax = " []"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - if (parameters.size() > 1) - return ROUTE_UNICAST(parameters[1]); - return ROUTE_LOCALONLY; - } -}; - -void CommandStats::DoStats(char statschar, User* user, string_list &results) -{ - bool isPublic = ServerInstance->Config->UserStats.find(statschar) != std::string::npos; - bool isRemoteOper = IS_REMOTE(user) && (user->IsOper()); - bool isLocalOperWithPrivs = IS_LOCAL(user) && user->HasPrivPermission("servers/auspex"); - - if (!isPublic && !isRemoteOper && !isLocalOperWithPrivs) - { - ServerInstance->SNO->WriteToSnoMask('t', - "%s '%c' denied for %s (%s@%s)", - (IS_LOCAL(user) ? "Stats" : "Remote stats"), - statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); - results.push_back("481 " + user->nick + " :Permission denied - STATS " + statschar + " requires the servers/auspex priv."); - return; - } - - ModResult MOD_RESULT; - FIRST_MOD_RESULT(OnStats, MOD_RESULT, (statschar, user, results)); - if (MOD_RESULT == MOD_RES_DENY) - { - results.push_back("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.c_str(), user->ident.c_str(), user->host.c_str()); - return; - } - - switch (statschar) - { - /* stats p (show listening ports) */ - case 'p': - { - for (std::vector::const_iterator i = ServerInstance->ports.begin(); i != ServerInstance->ports.end(); ++i) - { - ListenSocket* ls = *i; - std::string ip = ls->bind_addr; - if (ip.empty()) - ip.assign("*"); - std::string type = ls->bind_tag->getString("type", "clients"); - std::string hook = ls->bind_tag->getString("ssl", "plaintext"); - - results.push_back("249 "+user->nick+" :"+ ip + ":"+ConvToStr(ls->bind_port)+ - " (" + type + ", " + hook + ")"); - } - } - break; - - /* These stats symbols must be handled by a linking module */ - case 'n': - case 'c': - break; - - case 'i': - { - for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) - { - ConnectClass* c = *i; - std::stringstream res; - res << "215 " << user->nick << " I " << c->name << ' '; - if (c->type == CC_ALLOW) - res << '+'; - if (c->type == CC_DENY) - res << '-'; - - if (c->type == CC_NAMED) - res << '*'; - else - res << c->host; - - res << ' ' << c->config->getString("port", "*") << ' '; - - res << c->GetRecvqMax() << ' ' << c->GetSendqSoftMax() << ' ' << c->GetSendqHardMax() - << ' ' << c->GetCommandRate() << ' ' << c->GetPenaltyThreshold(); - if (c->fakelag) - res << '*'; - results.push_back(res.str()); - } - } - break; - - case 'Y': - { - int idx = 0; - for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) - { - ConnectClass* c = *i; - results.push_back("215 "+user->nick+" i NOMATCH * "+c->GetHost()+" "+ConvToStr(c->limit ? c->limit : SocketEngine::GetMaxFds())+" "+ConvToStr(idx)+" "+ServerInstance->Config->ServerName+" *"); - results.push_back("218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqHardMax())+" :"+ - ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout())); - idx++; - } - } - break; - - case 'P': - { - unsigned int idx = 0; - for (std::list::const_iterator i = ServerInstance->Users->all_opers.begin(); i != ServerInstance->Users->all_opers.end(); ++i) - { - User* oper = *i; - if (!oper->server->IsULine()) - { - LocalUser* lu = IS_LOCAL(oper); - results.push_back("249 " + user->nick + " :" + oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " + - (lu ? ConvToStr(ServerInstance->Time() - lu->idle_lastmsg) + " secs" : "unavailable")); - idx++; - } - } - results.push_back("249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)"); - } - break; - - case 'k': - ServerInstance->XLines->InvokeStats("K",216,user,results); - break; - case 'g': - ServerInstance->XLines->InvokeStats("G",223,user,results); - break; - case 'q': - ServerInstance->XLines->InvokeStats("Q",217,user,results); - break; - case 'Z': - ServerInstance->XLines->InvokeStats("Z",223,user,results); - break; - case 'e': - ServerInstance->XLines->InvokeStats("E",223,user,results); - break; - case 'E': - { - const SocketEngine::Statistics& stats = SocketEngine::GetStats(); - results.push_back("249 "+user->nick+" :Total events: "+ConvToStr(stats.TotalEvents)); - results.push_back("249 "+user->nick+" :Read events: "+ConvToStr(stats.ReadEvents)); - results.push_back("249 "+user->nick+" :Write events: "+ConvToStr(stats.WriteEvents)); - results.push_back("249 "+user->nick+" :Error events: "+ConvToStr(stats.ErrorEvents)); - break; - } - - /* stats m (list number of times each command has been used, plus bytecount) */ - case 'm': - for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) - { - if (i->second->use_count) - { - /* RPL_STATSCOMMANDS */ - results.push_back("212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count)); - } - } - break; - - /* stats z (debug and memory info) */ - case 'z': - { - results.push_back("249 "+user->nick+" :Users: "+ConvToStr(ServerInstance->Users->clientlist->size())); - results.push_back("249 "+user->nick+" :Channels: "+ConvToStr(ServerInstance->chanlist->size())); - results.push_back("249 "+user->nick+" :Commands: "+ConvToStr(ServerInstance->Parser->cmdlist.size())); - - float kbitpersec_in, kbitpersec_out, kbitpersec_total; - char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30]; - - SocketEngine::GetStats().GetBandwidth(kbitpersec_in, kbitpersec_out, kbitpersec_total); - - snprintf(kbitpersec_total_s, 30, "%03.5f", kbitpersec_total); - snprintf(kbitpersec_out_s, 30, "%03.5f", kbitpersec_out); - snprintf(kbitpersec_in_s, 30, "%03.5f", kbitpersec_in); - - results.push_back("249 "+user->nick+" :Bandwidth total: "+ConvToStr(kbitpersec_total_s)+" kilobits/sec"); - results.push_back("249 "+user->nick+" :Bandwidth out: "+ConvToStr(kbitpersec_out_s)+" kilobits/sec"); - results.push_back("249 "+user->nick+" :Bandwidth in: "+ConvToStr(kbitpersec_in_s)+" kilobits/sec"); - -#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("249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K"); - results.push_back("249 "+user->nick+" :Signals: "+ConvToStr(R.ru_nsignals)); - results.push_back("249 "+user->nick+" :Page faults: "+ConvToStr(R.ru_majflt)); - results.push_back("249 "+user->nick+" :Swaps: "+ConvToStr(R.ru_nswap)); - results.push_back("249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw)); - - char percent[30]; - - float n_elapsed = (ServerInstance->Time() - ServerInstance->stats->LastSampled.tv_sec) * 1000000 - + (ServerInstance->Time_ns() - ServerInstance->stats->LastSampled.tv_nsec) / 1000; - 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("249 "+user->nick+" :CPU Use (now): "+percent); - - n_elapsed = ServerInstance->Time() - ServerInstance->startup_time; - n_eaten = (float)R.ru_utime.tv_sec + R.ru_utime.tv_usec / 100000.0; - per = (n_eaten / n_elapsed) * 100; - snprintf(percent, 30, "%03.5f%%", per); - results.push_back("249 "+user->nick+" :CPU Use (total): "+percent); - } -#else - PROCESS_MEMORY_COUNTERS MemCounters; - if (GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters))) - { - results.push_back("249 "+user->nick+" :Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K"); - results.push_back("249 "+user->nick+" :Pagefile usage: "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K"); - results.push_back("249 "+user->nick+" :Page faults: "+ConvToStr(MemCounters.PageFaultCount)); - } - - FILETIME CreationTime; - FILETIME ExitTime; - FILETIME KernelTime; - FILETIME UserTime; - LARGE_INTEGER ThisSample; - if(GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime) && - QueryPerformanceCounter(&ThisSample)) - { - KernelTime.dwHighDateTime += UserTime.dwHighDateTime; - KernelTime.dwLowDateTime += UserTime.dwLowDateTime; - double n_eaten = (double)( ( (uint64_t)(KernelTime.dwHighDateTime - ServerInstance->stats->LastCPU.dwHighDateTime) << 32 ) + (uint64_t)(KernelTime.dwLowDateTime - ServerInstance->stats->LastCPU.dwLowDateTime) )/100000; - double n_elapsed = (double)(ThisSample.QuadPart - ServerInstance->stats->LastSampled.QuadPart) / ServerInstance->stats->QPFrequency.QuadPart; - double per = (n_eaten/n_elapsed); - - char percent[30]; - - snprintf(percent, 30, "%03.5f%%", per); - results.push_back("249 "+user->nick+" :CPU Use (now): "+percent); - - n_elapsed = ServerInstance->Time() - ServerInstance->startup_time; - n_eaten = (double)(( (uint64_t)(KernelTime.dwHighDateTime) << 32 ) + (uint64_t)(KernelTime.dwLowDateTime))/100000; - per = (n_eaten / n_elapsed); - snprintf(percent, 30, "%03.5f%%", per); - results.push_back("249 "+user->nick+" :CPU Use (total): "+percent); - } -#endif - } - break; - - case 'T': - { - results.push_back("249 "+user->nick+" :accepts "+ConvToStr(ServerInstance->stats->statsAccept)+" refused "+ConvToStr(ServerInstance->stats->statsRefused)); - results.push_back("249 "+user->nick+" :unknown commands "+ConvToStr(ServerInstance->stats->statsUnknown)); - results.push_back("249 "+user->nick+" :nick collisions "+ConvToStr(ServerInstance->stats->statsCollisions)); - results.push_back("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("249 "+user->nick+" :connection count "+ConvToStr(ServerInstance->stats->statsConnects)); - results.push_back(InspIRCd::Format("249 %s :bytes sent %5.2fK recv %5.2fK", user->nick.c_str(), - ServerInstance->stats->statsSent / 1024.0, ServerInstance->stats->statsRecv / 1024.0)); - } - break; - - /* stats o */ - case 'o': - { - ConfigTagList tags = ServerInstance->Config->ConfTags("oper"); - for(ConfigIter i = tags.first; i != tags.second; ++i) - { - ConfigTag* tag = i->second; - results.push_back("243 "+user->nick+" O "+tag->getString("host")+" * "+ - tag->getString("name") + " " + tag->getString("type")+" 0"); - } - } - break; - case 'O': - { - for (OperIndex::const_iterator i = ServerInstance->Config->OperTypes.begin(); i != ServerInstance->Config->OperTypes.end(); ++i) - { - OperInfo* tag = i->second; - tag->init(); - std::string umodes; - std::string cmodes; - for(char c='A'; c < 'z'; c++) - { - ModeHandler* mh = ServerInstance->Modes->FindMode(c, MODETYPE_USER); - if (mh && mh->NeedsOper() && tag->AllowedUserModes[c - 'A']) - umodes.push_back(c); - mh = ServerInstance->Modes->FindMode(c, MODETYPE_CHANNEL); - if (mh && mh->NeedsOper() && tag->AllowedChanModes[c - 'A']) - cmodes.push_back(c); - } - results.push_back("243 "+user->nick+" O "+tag->name.c_str() + " " + umodes + " " + cmodes); - } - } - break; - - /* stats l (show user I/O stats) */ - case 'l': - results.push_back("211 "+user->nick+" :nick[ident@host] sendq cmds_out bytes_out cmds_in bytes_in time_open"); - for (LocalUserList::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) - { - LocalUser* i = *n; - results.push_back("211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->eh.getSendQSize())+" "+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("211 "+user->nick+" :nick[ident@ip] sendq cmds_out bytes_out cmds_in bytes_in time_open"); - for (LocalUserList::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) - { - LocalUser* i = *n; - results.push_back("211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->eh.getSendQSize())+" "+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) - { - results.push_back(InspIRCd::Format("242 %s :Server up %d years, %d days, %.2d:%.2d:%.2d", - user->nick.c_str(), stime->tm_year - 70, stime->tm_yday, stime->tm_hour, - stime->tm_min, stime->tm_sec)); - } - else - { - results.push_back(InspIRCd::Format("242 %s :Server up %d days, %.2d:%.2d:%.2d", - user->nick.c_str(), stime->tm_yday, stime->tm_hour, stime->tm_min, - stime->tm_sec)); - } - } - break; - - default: - break; - } - - results.push_back("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.c_str(), user->ident.c_str(), user->host.c_str()); - return; -} - -CmdResult CommandStats::Handle (const std::vector& parameters, User *user) -{ - if (parameters.size() > 1 && parameters[1] != ServerInstance->Config->ServerName) - return CMD_SUCCESS; - string_list values; - char search = parameters[0][0]; - DoStats(search, user, values); - - const std::string p = ":" + ServerInstance->Config->ServerName + " "; - for (size_t i = 0; i < values.size(); i++) - user->SendText(p + values[i]); - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandStats) diff --git a/src/commands/cmd_time.cpp b/src/commands/cmd_time.cpp deleted file mode 100644 index 9c4688029..000000000 --- a/src/commands/cmd_time.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /TIME. - */ -class CommandTime : public Command -{ - public: - /** Constructor for time. - */ - CommandTime ( Module* parent) : Command(parent,"TIME",0,0) { syntax = "[]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - if (parameters.size() > 0) - return ROUTE_UNICAST(parameters[0]); - return ROUTE_LOCALONLY; - } -}; - -CmdResult CommandTime::Handle (const std::vector& parameters, User *user) -{ - if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName) - return CMD_SUCCESS; - - time_t local = ServerInstance->Time(); - struct tm* timeinfo = localtime(&local); - const std::string& humanTime = asctime(timeinfo); - - user->SendText(":%s %03d %s %s :%s", ServerInstance->Config->ServerName.c_str(), RPL_TIME, user->nick.c_str(), - ServerInstance->Config->ServerName.c_str(), humanTime.c_str()); - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandTime) diff --git a/src/commands/cmd_topic.cpp b/src/commands/cmd_topic.cpp deleted file mode 100644 index 2b0f81fb6..000000000 --- a/src/commands/cmd_topic.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * Copyright (C) 2008 Craig Edwards - * Copyright (C) 2008 Thomas Stagner - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /TOPIC. - */ -class CommandTopic : public SplitCommand -{ - ChanModeReference secretmode; - ChanModeReference topiclockmode; - - public: - /** Constructor for topic. - */ - CommandTopic(Module* parent) - : SplitCommand(parent, "TOPIC", 1, 2) - , secretmode(parent, "secret") - , topiclockmode(parent, "topiclock") - { - syntax = " []"; - Penalty = 2; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult HandleLocal(const std::vector& parameters, LocalUser* user); -}; - -CmdResult CommandTopic::HandleLocal(const std::vector& parameters, LocalUser* user) -{ - Channel* c = ServerInstance->FindChan(parameters[0]); - if (!c) - { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); - return CMD_FAILURE; - } - - if (parameters.size() == 1) - { - if ((c->IsModeSet(secretmode)) && (!c->HasUser(user))) - { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c->name.c_str()); - return CMD_FAILURE; - } - - if (c->topic.length()) - { - user->WriteNumeric(RPL_TOPIC, "%s :%s", c->name.c_str(), c->topic.c_str()); - user->WriteNumeric(RPL_TOPICTIME, "%s %s %lu", c->name.c_str(), c->setby.c_str(), (unsigned long)c->topicset); - } - else - { - user->WriteNumeric(RPL_NOTOPICSET, "%s :No topic is set.", c->name.c_str()); - } - return CMD_SUCCESS; - } - - std::string t = parameters[1]; // needed, in case a module wants to change it - ModResult res; - FIRST_MOD_RESULT(OnPreTopicChange, res, (user,c,t)); - - if (res == MOD_RES_DENY) - return CMD_FAILURE; - if (res != MOD_RES_ALLOW) - { - if (!c->HasUser(user)) - { - user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", c->name.c_str()); - return CMD_FAILURE; - } - if (c->IsModeSet(topiclockmode) && !ServerInstance->OnCheckExemption(user, c, "topiclock").check(c->GetPrefixValue(user) >= HALFOP_VALUE)) - { - user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You do not have access to change the topic on this channel", c->name.c_str()); - return CMD_FAILURE; - } - } - - c->SetTopic(user, t); - return CMD_SUCCESS; -} - - -COMMAND_INIT(CommandTopic) diff --git a/src/commands/cmd_unloadmodule.cpp b/src/commands/cmd_unloadmodule.cpp deleted file mode 100644 index 5d11e0256..000000000 --- a/src/commands/cmd_unloadmodule.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /UNLOADMODULE. - */ -class CommandUnloadmodule : public Command -{ - public: - /** Constructor for unloadmodule. - */ - CommandUnloadmodule ( Module* parent) : Command(parent,"UNLOADMODULE",1) { flags_needed = 'o'; syntax = ""; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandUnloadmodule::Handle (const std::vector& parameters, User *user) -{ - if (!ServerInstance->Config->ConfValue("security")->getBool("allowcoreunload") && - InspIRCd::Match(parameters[0], "cmd_*.so", ascii_case_insensitive_map)) - { - user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :You cannot unload core commands!", parameters[0].c_str()); - return CMD_FAILURE; - } - - if (parameters[0] == "cmd_unloadmodule.so" || parameters[0] == "cmd_loadmodule.so") - { - user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :You cannot unload module loading commands!", parameters[0].c_str()); - return CMD_FAILURE; - } - - Module* m = ServerInstance->Modules->Find(parameters[0]); - if (m && ServerInstance->Modules->Unload(m)) - { - ServerInstance->SNO->WriteGlobalSno('a', "MODULE UNLOADED: %s unloaded %s", user->nick.c_str(), parameters[0].c_str()); - user->WriteNumeric(RPL_UNLOADEDMODULE, "%s :Module successfully unloaded.", parameters[0].c_str()); - } - else - { - user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :%s", parameters[0].c_str(), - m ? ServerInstance->Modules->LastError().c_str() : "No such module"); - return CMD_FAILURE; - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandUnloadmodule) diff --git a/src/commands/cmd_user.cpp b/src/commands/cmd_user.cpp deleted file mode 100644 index cec11c104..000000000 --- a/src/commands/cmd_user.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /USER. - */ -class CommandUser : public SplitCommand -{ - public: - /** Constructor for user. - */ - CommandUser ( Module* parent) : SplitCommand(parent,"USER",4,4) { works_before_reg = true; Penalty = 0; syntax = " "; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult HandleLocal(const std::vector& parameters, LocalUser *user); -}; - -CmdResult CommandUser::HandleLocal(const std::vector& parameters, LocalUser *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->WriteNumeric(ERR_NEEDMOREPARAMS, "USER :Your username is not valid"); - return CMD_FAILURE; - } - else - { - /* - * The ident field is IDENTMAX+2 in size to account for +1 for the optional - * ~ character, and +1 for null termination, therefore we can safely use up to - * IDENTMAX here. - */ - user->ChangeIdent(parameters[0]); - user->fullname.assign(parameters[3].empty() ? "No info" : parameters[3], 0, ServerInstance->Config->Limits.MaxGecos); - user->registered = (user->registered | REG_USER); - } - } - else - { - user->WriteNumeric(ERR_ALREADYREGISTERED, ":You may not reregister"); - return CMD_FAILURE; - } - - /* parameters 2 and 3 are local and remote hosts, and are ignored */ - if (user->registered == REG_NICKUSER) - { - ModResult MOD_RESULT; - - /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ - FIRST_MOD_RESULT(OnUserRegister, MOD_RESULT, (user)); - if (MOD_RESULT == MOD_RES_DENY) - return CMD_FAILURE; - - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandUser) diff --git a/src/commands/cmd_userhost.cpp b/src/commands/cmd_userhost.cpp deleted file mode 100644 index 541402c10..000000000 --- a/src/commands/cmd_userhost.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /USERHOST. - */ -class CommandUserhost : public Command -{ - public: - /** Constructor for userhost. - */ - CommandUserhost ( Module* parent) : Command(parent,"USERHOST", 1, 5) { - syntax = " {}"; - } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandUserhost::Handle (const std::vector& parameters, User *user) -{ - std::string retbuf = "302 " + user->nick + " :"; - - for (unsigned int i = 0; i < parameters.size(); i++) - { - User *u = ServerInstance->FindNickOnly(parameters[i]); - - if ((u) && (u->registered == REG_ALL)) - { - retbuf = retbuf + u->nick; - - if (u->IsOper()) - retbuf = retbuf + "*"; - - retbuf = retbuf + "="; - - if (u->IsAway()) - retbuf += "-"; - else - retbuf += "+"; - - retbuf = retbuf + u->ident + "@"; - - if (user->HasPrivPermission("users/auspex")) - { - retbuf = retbuf + u->host; - } - else - { - retbuf = retbuf + u->dhost; - } - - retbuf = retbuf + " "; - } - } - - user->WriteServ(retbuf); - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandUserhost) diff --git a/src/commands/cmd_version.cpp b/src/commands/cmd_version.cpp deleted file mode 100644 index 032d9ea0c..000000000 --- a/src/commands/cmd_version.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /VERSION. - */ -class CommandVersion : public Command -{ - public: - /** Constructor for version. - */ - CommandVersion ( Module* parent) : Command(parent,"VERSION",0,0) { syntax = "[]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandVersion::Handle (const std::vector&, User *user) -{ - std::string version = ServerInstance->GetVersionString((user->IsOper())); - user->WriteNumeric(RPL_VERSION, ":%s", version.c_str()); - LocalUser *lu = IS_LOCAL(user); - if (lu != NULL) - { - ServerInstance->ISupport.SendTo(lu); - } - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandVersion) diff --git a/src/commands/cmd_wallops.cpp b/src/commands/cmd_wallops.cpp deleted file mode 100644 index 731eaf3d2..000000000 --- a/src/commands/cmd_wallops.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /WALLOPS. - */ -class CommandWallops : public Command -{ - UserModeReference wallopsmode; - - public: - /** Constructor for wallops. - */ - CommandWallops(Module* parent) - : Command(parent, "WALLOPS", 1, 1) - , wallopsmode(parent, "wallops") - { - flags_needed = 'o'; - syntax = ""; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - return ROUTE_BROADCAST; - } -}; - -CmdResult CommandWallops::Handle (const std::vector& parameters, User *user) -{ - std::string wallop("WALLOPS :"); - wallop.append(parameters[0]); - - for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); i++) - { - User* t = *i; - if (t->IsModeSet(wallopsmode)) - user->WriteTo(t,wallop); - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandWallops) diff --git a/src/commands/cmd_who.cpp b/src/commands/cmd_who.cpp deleted file mode 100644 index dc39e296c..000000000 --- a/src/commands/cmd_who.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009-2010 Daniel De Graaf - * Copyright (C) 2007-2008 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /WHO. - */ -class CommandWho : public Command -{ - bool CanView(Channel* chan, User* user); - bool opt_viewopersonly; - bool opt_showrealhost; - bool opt_realname; - bool opt_mode; - bool opt_ident; - bool opt_metadata; - bool opt_port; - bool opt_away; - bool opt_local; - bool opt_far; - bool opt_time; - ChanModeReference secretmode; - ChanModeReference privatemode; - UserModeReference invisiblemode; - - Membership* get_first_visible_channel(User* u) - { - for (UCListIter i = u->chans.begin(); i != u->chans.end(); ++i) - { - Membership* memb = *i; - if (!memb->chan->IsModeSet(secretmode)) - return memb; - } - return NULL; - } - - public: - /** Constructor for who. - */ - CommandWho(Module* parent) - : Command(parent, "WHO", 1) - , secretmode(parent, "secret") - , privatemode(parent, "private") - , invisiblemode(parent, "invisible") - { - syntax = "|||||0 [ohurmMiaplf]"; - } - - void SendWhoLine(User* user, const std::vector& parms, const std::string& initial, Membership* memb, User* u, std::vector& whoresults); - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - bool whomatch(User* cuser, User* user, const char* matchtext); -}; - -bool CommandWho::whomatch(User* cuser, User* user, const char* matchtext) -{ - bool match = false; - bool positive = false; - - if (user->registered != REG_ALL) - return false; - - if (opt_local && !IS_LOCAL(user)) - return false; - else if (opt_far && IS_LOCAL(user)) - return false; - - if (opt_mode) - { - for (const char* n = matchtext; *n; n++) - { - if (*n == '+') - { - positive = true; - continue; - } - else if (*n == '-') - { - positive = false; - continue; - } - if (user->IsModeSet(*n) != positive) - return false; - } - return true; - } - else - { - /* - * This was previously one awesome pile of ugly nested if, when really, it didn't need - * to be, since only one condition was ever checked, a chained if works just fine. - * -- w00t - */ - if (opt_metadata) - { - match = false; - const Extensible::ExtensibleStore& list = user->GetExtList(); - for(Extensible::ExtensibleStore::const_iterator i = list.begin(); i != list.end(); ++i) - if (InspIRCd::Match(i->first->name, matchtext)) - match = true; - } - else if (opt_realname) - match = InspIRCd::Match(user->fullname, matchtext); - else if (opt_showrealhost) - match = InspIRCd::Match(user->host, matchtext, ascii_case_insensitive_map); - else if (opt_ident) - match = InspIRCd::Match(user->ident, matchtext, ascii_case_insensitive_map); - else if (opt_port) - { - irc::portparser portrange(matchtext, false); - long portno = -1; - while ((portno = portrange.GetToken())) - if (IS_LOCAL(user) && portno == IS_LOCAL(user)->GetServerPort()) - { - match = true; - break; - } - } - else if (opt_away) - match = InspIRCd::Match(user->awaymsg, matchtext); - else if (opt_time) - { - long seconds = InspIRCd::Duration(matchtext); - - // Okay, so time matching, we want all users connected `seconds' ago - if (user->age >= ServerInstance->Time() - seconds) - match = true; - } - - /* - * Once the conditionals have been checked, only check dhost/nick/server - * if they didn't match this user -- and only match if we don't find a match. - * - * This should make things minutely faster, and again, less ugly. - * -- w00t - */ - if (!match) - match = InspIRCd::Match(user->dhost, matchtext, ascii_case_insensitive_map); - - if (!match) - match = InspIRCd::Match(user->nick, matchtext); - - /* Don't allow server name matches if HideWhoisServer is enabled, unless the command user has the priv */ - if (!match && (ServerInstance->Config->HideWhoisServer.empty() || cuser->HasPrivPermission("users/auspex"))) - match = InspIRCd::Match(user->server->GetName(), matchtext); - - return match; - } -} - -bool CommandWho::CanView(Channel* chan, User* user) -{ - if (!user || !chan) - return false; - - /* Bug #383 - moved higher up the list, because if we are in the channel - * we can see all its users - */ - if (chan->HasUser(user)) - return true; - /* Opers see all */ - if (user->HasPrivPermission("users/auspex")) - return true; - /* Cant see inside a +s or a +p channel unless we are a member (see above) */ - else if (!chan->IsModeSet(secretmode) && !chan->IsModeSet(privatemode)) - return true; - - return false; -} - -void CommandWho::SendWhoLine(User* user, const std::vector& parms, const std::string& initial, Membership* memb, User* u, std::vector& whoresults) -{ - if (!memb) - memb = get_first_visible_channel(u); - - std::string wholine = initial + (memb ? memb->chan->name : "*") + " " + u->ident + " " + - (opt_showrealhost ? u->host : u->dhost) + " "; - if (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex")) - wholine.append(ServerInstance->Config->HideWhoisServer); - else - wholine.append(u->server->GetName()); - - wholine.append(" " + u->nick + " "); - - /* away? */ - if (u->IsAway()) - { - wholine.append("G"); - } - else - { - wholine.append("H"); - } - - /* oper? */ - if (u->IsOper()) - { - wholine.push_back('*'); - } - - if (memb) - wholine.push_back(memb->GetPrefixChar()); - - wholine.append(" :0 " + u->fullname); - - FOREACH_MOD(OnSendWhoLine, (user, parms, u, memb, wholine)); - - if (!wholine.empty()) - whoresults.push_back(wholine); -} - -CmdResult CommandWho::Handle (const std::vector& parameters, User *user) -{ - /* - * XXX - RFC says: - * The 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_realname = false; - opt_mode = false; - opt_ident = false; - opt_metadata = false; - opt_port = false; - opt_away = false; - opt_local = false; - opt_far = false; - opt_time = false; - - std::vector whoresults; - std::string initial = "352 " + user->nick + " "; - - /* Change '0' into '*' so the wildcard matcher can grok it */ - std::string matchtext = ((parameters[0] == "0") ? "*" : parameters[0]); - - // WHO flags count as a wildcard - bool usingwildcards = ((parameters.size() > 1) || (matchtext.find_first_of("*?.") != std::string::npos)); - - if (parameters.size() > 1) - { - for (std::string::const_iterator iter = parameters[1].begin(); iter != parameters[1].end(); ++iter) - { - switch (*iter) - { - case 'o': - opt_viewopersonly = true; - break; - case 'h': - if (user->HasPrivPermission("users/auspex")) - opt_showrealhost = true; - break; - case 'r': - opt_realname = true; - break; - case 'm': - if (user->HasPrivPermission("users/auspex")) - opt_mode = true; - break; - case 'M': - if (user->HasPrivPermission("users/auspex")) - opt_metadata = true; - break; - case 'i': - opt_ident = true; - break; - case 'p': - if (user->HasPrivPermission("users/auspex")) - opt_port = true; - break; - case 'a': - opt_away = true; - break; - case 'l': - if (user->HasPrivPermission("users/auspex") || ServerInstance->Config->HideWhoisServer.empty()) - opt_local = true; - break; - case 'f': - if (user->HasPrivPermission("users/auspex") || ServerInstance->Config->HideWhoisServer.empty()) - opt_far = true; - break; - case 't': - opt_time = true; - break; - } - } - } - - - /* who on a channel? */ - Channel* ch = ServerInstance->FindChan(matchtext); - - if (ch) - { - if (CanView(ch,user)) - { - bool inside = ch->HasUser(user); - - /* who on a channel. */ - const UserMembList *cu = ch->GetUsers(); - - for (UserMembCIter i = cu->begin(); i != cu->end(); i++) - { - /* None of this applies if we WHO ourselves */ - if (user != i->first) - { - /* opers only, please */ - if (opt_viewopersonly && !i->first->IsOper()) - continue; - - /* If we're not inside the channel, hide +i users */ - if (i->first->IsModeSet(invisiblemode) && !inside && !user->HasPrivPermission("users/auspex")) - continue; - } - - SendWhoLine(user, parameters, initial, i->second, i->first, whoresults); - } - } - } - else - { - /* Match against wildcard of nick, server or host */ - if (opt_viewopersonly) - { - /* Showing only opers */ - for (std::list::iterator i = ServerInstance->Users->all_opers.begin(); i != ServerInstance->Users->all_opers.end(); i++) - { - User* oper = *i; - - if (whomatch(user, oper, matchtext.c_str())) - { - if (!user->SharesChannelWith(oper)) - { - if (usingwildcards && (!oper->IsModeSet(invisiblemode)) && (!user->HasPrivPermission("users/auspex"))) - continue; - } - - SendWhoLine(user, parameters, initial, NULL, oper, whoresults); - } - } - } - else - { - for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++) - { - if (whomatch(user, i->second, matchtext.c_str())) - { - if (!user->SharesChannelWith(i->second)) - { - if (usingwildcards && (i->second->IsModeSet(invisiblemode)) && (!user->HasPrivPermission("users/auspex"))) - continue; - } - - SendWhoLine(user, parameters, initial, NULL, i->second, whoresults); - } - } - } - } - /* Send the results out */ - for (std::vector::const_iterator n = whoresults.begin(); n != whoresults.end(); n++) - user->WriteServ(*n); - user->WriteNumeric(RPL_ENDOFWHO, "%s :End of /WHO list.", *parameters[0].c_str() ? parameters[0].c_str() : "*"); - - // Penalize the user a bit for large queries - // (add one unit of penalty per 200 results) - if (IS_LOCAL(user)) - IS_LOCAL(user)->CommandFloodPenalty += whoresults.size() * 5; - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandWho) diff --git a/src/commands/cmd_whois.cpp b/src/commands/cmd_whois.cpp deleted file mode 100644 index bd0b624d1..000000000 --- a/src/commands/cmd_whois.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2008 Thomas Stagner - * Copyright (C) 2007 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" - -/** Handle /WHOIS. - */ -class CommandWhois : public SplitCommand -{ - ChanModeReference secretmode; - ChanModeReference privatemode; - UserModeReference snomaskmode; - - void SplitChanList(User* source, User* dest, const std::string& cl); - void DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle); - std::string ChannelList(User* source, User* dest, bool spy); - - public: - /** Constructor for whois. - */ - CommandWhois(Module* parent) - : SplitCommand(parent, "WHOIS", 1) - , secretmode(parent, "secret") - , privatemode(parent, "private") - , snomaskmode(parent, "snomask") - { - Penalty = 2; - syntax = "{,}"; - } - - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult HandleLocal(const std::vector& parameters, LocalUser* user); - CmdResult HandleRemote(const std::vector& parameters, RemoteUser* target); -}; - -std::string CommandWhois::ChannelList(User* source, User* dest, bool spy) -{ - std::string list; - - for (UCListIter i = dest->chans.begin(); i != dest->chans.end(); i++) - { - Membership* memb = *i; - Channel* c = memb->chan; - /* If the target is the sender, neither +p nor +s is set, or - * the channel contains the user, it is not a spy channel - */ - if (spy != (source == dest || !(c->IsModeSet(privatemode) || c->IsModeSet(secretmode)) || c->HasUser(source))) - { - list.push_back(memb->GetPrefixChar()); - list.append(c->name).push_back(' '); - } - } - - return list; -} - -void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl) -{ - std::string line; - std::ostringstream prefix; - std::string::size_type start, pos; - - prefix << dest->nick << " :"; - line = prefix.str(); - int namelen = ServerInstance->Config->ServerName.length() + 6; - - for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1) - { - if (line.length() + namelen + pos - start > 510) - { - ServerInstance->SendWhoisLine(source, dest, 319, line); - line = prefix.str(); - } - - line.append(cl.substr(start, pos - start + 1)); - } - - if (line.length() != prefix.str().length()) - { - ServerInstance->SendWhoisLine(source, dest, 319, line); - } -} - -void CommandWhois::DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle) -{ - ServerInstance->SendWhoisLine(user, dest, 311, "%s %s %s * :%s", dest->nick.c_str(), dest->ident.c_str(), dest->dhost.c_str(), dest->fullname.c_str()); - if (user == dest || user->HasPrivPermission("users/auspex")) - { - ServerInstance->SendWhoisLine(user, dest, 378, "%s :is connecting from %s@%s %s", dest->nick.c_str(), dest->ident.c_str(), dest->host.c_str(), dest->GetIPString().c_str()); - } - - std::string cl = ChannelList(user, dest, false); - const ServerConfig::OperSpyWhoisState state = user->HasPrivPermission("users/auspex") ? ServerInstance->Config->OperSpyWhois : ServerConfig::SPYWHOIS_NONE; - - if (state == ServerConfig::SPYWHOIS_SINGLEMSG) - cl.append(ChannelList(user, dest, true)); - - SplitChanList(user, dest, cl); - - if (state == ServerConfig::SPYWHOIS_SPLITMSG) - { - std::string scl = ChannelList(user, dest, true); - if (scl.length()) - { - ServerInstance->SendWhoisLine(user, dest, 336, "%s :is on private/secret channels:", dest->nick.c_str()); - SplitChanList(user, dest, scl); - } - } - if (user != dest && !ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex")) - { - ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), ServerInstance->Config->HideWhoisServer.c_str(), ServerInstance->Config->Network.c_str()); - } - else - { - ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), dest->server->GetName().c_str(), dest->server->GetDesc().c_str()); - } - - if (dest->IsAway()) - { - ServerInstance->SendWhoisLine(user, dest, 301, "%s :%s", dest->nick.c_str(), dest->awaymsg.c_str()); - } - - if (dest->IsOper()) - { - if (ServerInstance->Config->GenericOper) - ServerInstance->SendWhoisLine(user, dest, 313, "%s :is an IRC operator", dest->nick.c_str()); - else - ServerInstance->SendWhoisLine(user, dest, 313, "%s :is %s %s on %s", dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->name.c_str(), ServerInstance->Config->Network.c_str()); - } - - if (user == dest || user->HasPrivPermission("users/auspex")) - { - if (dest->IsModeSet(snomaskmode)) - { - ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s %s", dest->nick.c_str(), dest->FormatModes(), snomaskmode->GetUserParameter(dest).c_str()); - } - else - { - ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s", dest->nick.c_str(), dest->FormatModes()); - } - } - - FOREACH_MOD(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 %lu %lu :seconds idle, signon time", dest->nick.c_str(), idle, signon); - } - - ServerInstance->SendWhoisLine(user, dest, 318, "%s :End of /WHOIS list.", dest->nick.c_str()); -} - -CmdResult CommandWhois::HandleRemote(const std::vector& parameters, RemoteUser* target) -{ - if (parameters.size() < 2) - return CMD_FAILURE; - - User* user = ServerInstance->FindUUID(parameters[0]); - if (!user) - return CMD_FAILURE; - - unsigned long idle = ConvToInt(parameters.back()); - DoWhois(user, target, target->signon, idle); - - return CMD_SUCCESS; -} - -CmdResult CommandWhois::HandleLocal(const std::vector& parameters, LocalUser* user) -{ - User *dest; - int userindex = 0; - unsigned long idle = 0, signon = 0; - - if (CommandParser::LoopCall(user, this, parameters, 0)) - return CMD_SUCCESS; - - /* - * If 2 paramters are specified (/whois nick nick), ignore the first one like spanningtree - * does, and use the second one, otherwise, use the only paramter. -- djGrrr - */ - if (parameters.size() > 1) - userindex = 1; - - dest = ServerInstance->FindNickOnly(parameters[userindex]); - - if ((dest) && (dest->registered == REG_ALL)) - { - /* - * Okay. Umpteenth attempt at doing this, so let's re-comment... - * For local users (/w localuser), we show idletime if hidewhois is disabled - * For local users (/w localuser localuser), we always show idletime, hence parameters.size() > 1 check. - * For remote users (/w remoteuser), we do NOT show idletime - * For remote users (/w remoteuser remoteuser), spanningtree will handle calling do_whois, so we can ignore this case. - * Thanks to djGrrr for not being impatient while I have a crap day coding. :p -- w00t - */ - LocalUser* localuser = IS_LOCAL(dest); - if (localuser && (ServerInstance->Config->HideWhoisServer.empty() || parameters.size() > 1)) - { - idle = abs((long)((localuser->idle_lastmsg)-ServerInstance->Time())); - signon = dest->signon; - } - - DoWhois(user,dest,signon,idle); - } - else - { - /* no such nick/channel */ - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*"); - user->WriteNumeric(RPL_ENDOFWHOIS, "%s :End of /WHOIS list.", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*"); - return CMD_FAILURE; - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandWhois) diff --git a/src/commands/cmd_whowas.cpp b/src/commands/cmd_whowas.cpp deleted file mode 100644 index 0a3a994a8..000000000 --- a/src/commands/cmd_whowas.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2008 Thomas Stagner - * Copyright (C) 2008 Craig Edwards - * Copyright (C) 2007-2008 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "commands/cmd_whowas.h" - -CommandWhowas::CommandWhowas( Module* parent) - : Command(parent, "WHOWAS", 1) - , GroupSize(0), MaxGroups(0), MaxKeep(0) -{ - syntax = "{,}"; - Penalty = 2; -} - -CmdResult CommandWhowas::Handle (const std::vector& parameters, User* user) -{ - /* if whowas disabled in config */ - if (this->GroupSize == 0 || this->MaxGroups == 0) - { - user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :This command has been disabled.", name.c_str()); - return CMD_FAILURE; - } - - whowas_users::iterator i = whowas.find(assign(parameters[0])); - - if (i == whowas.end()) - { - user->WriteNumeric(ERR_WASNOSUCHNICK, "%s :There was no such nickname", parameters[0].c_str()); - } - else - { - whowas_set* grp = i->second; - if (!grp->empty()) - { - for (whowas_set::iterator ux = grp->begin(); ux != grp->end(); ux++) - { - WhoWasGroup* u = *ux; - - user->WriteNumeric(RPL_WHOWASUSER, "%s %s %s * :%s", parameters[0].c_str(), - u->ident.c_str(),u->dhost.c_str(),u->gecos.c_str()); - - if (user->HasPrivPermission("users/auspex")) - user->WriteNumeric(RPL_WHOWASIP, "%s :was connecting from *@%s", - parameters[0].c_str(), u->host.c_str()); - - std::string signon = InspIRCd::TimeString(u->signon); - bool hide_server = (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex")); - user->WriteNumeric(RPL_WHOISSERVER, "%s %s :%s", parameters[0].c_str(), (hide_server ? ServerInstance->Config->HideWhoisServer.c_str() : u->server.c_str()), signon.c_str()); - } - } - else - { - user->WriteNumeric(ERR_WASNOSUCHNICK, "%s :There was no such nickname", parameters[0].c_str()); - } - } - - user->WriteNumeric(RPL_ENDOFWHOWAS, "%s :End of WHOWAS", parameters[0].c_str()); - return CMD_SUCCESS; -} - -std::string CommandWhowas::GetStats() -{ - int whowas_size = 0; - int whowas_bytes = 0; - for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i) - { - whowas_set* n = i->second; - whowas_size += n->size(); - whowas_bytes += (sizeof(whowas_set) + ( sizeof(WhoWasGroup) * n->size() ) ); - } - return "Whowas entries: " +ConvToStr(whowas_size)+" ("+ConvToStr(whowas_bytes)+" bytes)"; -} - -void CommandWhowas::AddToWhoWas(User* user) -{ - /* if whowas disabled */ - if (this->GroupSize == 0 || this->MaxGroups == 0) - { - return; - } - - // Insert nick if it doesn't exist - // 'first' will point to the newly inserted element or to the existing element with an equivalent key - std::pair ret = whowas.insert(std::make_pair(irc::string(user->nick.c_str()), static_cast(NULL))); - - if (ret.second) // If inserted - { - // This nick is new, create a list for it and add the first record to it - whowas_set* n = new whowas_set; - n->push_back(new WhoWasGroup(user)); - ret.first->second = n; - - // Add this nick to the fifo too - whowas_fifo.push_back(std::make_pair(ServerInstance->Time(), ret.first->first)); - - if (whowas.size() > this->MaxGroups) - { - // Too many nicks, remove the nick which was inserted the longest time ago from both the map and the fifo - whowas_users::iterator it = whowas.find(whowas_fifo.front().second); - if (it != whowas.end()) - { - whowas_set* set = it->second; - for (whowas_set::iterator i = set->begin(); i != set->end(); ++i) - delete *i; - - delete set; - whowas.erase(it); - } - whowas_fifo.pop_front(); - } - } - else - { - // We've met this nick before, add a new record to the list - whowas_set* set = ret.first->second; - set->push_back(new WhoWasGroup(user)); - - // If there are too many records for this nick, remove the oldest (front) - if (set->size() > this->GroupSize) - { - delete set->front(); - set->pop_front(); - } - } -} - -/* on rehash, refactor maps according to new conf values */ -void CommandWhowas::Prune() -{ - time_t min = ServerInstance->Time() - this->MaxKeep; - - /* first cut the list to new size (maxgroups) and also prune entries that are timed out. */ - while (!whowas_fifo.empty()) - { - if ((whowas_fifo.size() > this->MaxGroups) || (whowas_fifo.front().first < min)) - { - whowas_users::iterator iter = whowas.find(whowas_fifo.front().second); - - /* hopefully redundant integrity check, but added while debugging r6216 */ - if (iter == whowas.end()) - { - /* this should never happen, if it does maps are corrupt */ - ServerInstance->Logs->Log("WHOWAS", LOG_DEFAULT, "BUG: Whowas maps got corrupted! (1)"); - return; - } - - whowas_set* set = iter->second; - for (whowas_set::iterator i = set->begin(); i != set->end(); ++i) - delete *i; - - delete set; - whowas.erase(iter); - whowas_fifo.pop_front(); - } - else - break; - } - - /* Then cut the whowas sets to new size (groupsize) */ - for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i) - { - whowas_set* n = i->second; - while (n->size() > this->GroupSize) - { - delete n->front(); - n->pop_front(); - } - } -} - -/* call maintain once an hour to remove expired nicks */ -void CommandWhowas::Maintain() -{ - time_t min = ServerInstance->Time() - this->MaxKeep; - for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i) - { - whowas_set* set = i->second; - while (!set->empty() && set->front()->signon < min) - { - delete set->front(); - set->pop_front(); - } - } -} - -CommandWhowas::~CommandWhowas() -{ - for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i) - { - whowas_set* set = i->second; - for (whowas_set::iterator j = set->begin(); j != set->end(); ++j) - delete *j; - - delete set; - } -} - -WhoWasGroup::WhoWasGroup(User* user) : host(user->host), dhost(user->dhost), ident(user->ident), - server(user->server->GetName()), gecos(user->fullname), signon(user->signon) -{ -} - -class ModuleWhoWas : public Module -{ - CommandWhowas cmd; - - public: - ModuleWhoWas() : cmd(this) - { - } - - void OnGarbageCollect() - { - // Remove all entries older than MaxKeep - cmd.Maintain(); - } - - void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) - { - cmd.AddToWhoWas(user); - } - - ModResult OnStats(char symbol, User* user, string_list &results) - { - if (symbol == 'z') - results.push_back("249 "+user->nick+" :"+cmd.GetStats()); - - return MOD_RES_PASSTHRU; - } - - void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE - { - ConfigTag* tag = ServerInstance->Config->ConfValue("whowas"); - unsigned int NewGroupSize = tag->getInt("groupsize", 10, 0, 10000); - unsigned int NewMaxGroups = tag->getInt("maxgroups", 10240, 0, 1000000); - unsigned int NewMaxKeep = tag->getDuration("maxkeep", 3600, 3600); - - if ((NewGroupSize == cmd.GroupSize) && (NewMaxGroups == cmd.MaxGroups) && (NewMaxKeep == cmd.MaxKeep)) - return; - - cmd.GroupSize = NewGroupSize; - cmd.MaxGroups = NewMaxGroups; - cmd.MaxKeep = NewMaxKeep; - cmd.Prune(); - } - - Version GetVersion() - { - return Version("WHOWAS", VF_VENDOR); - } -}; - -MODULE_INIT(ModuleWhoWas) diff --git a/src/commands/cmd_zline.cpp b/src/commands/cmd_zline.cpp deleted file mode 100644 index eda5b2a46..000000000 --- a/src/commands/cmd_zline.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf - * Copyright (C) 2009 Matt Smith - * Copyright (C) 2007-2008 Robin Burchell - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "inspircd.h" -#include "xline.h" -/** Handle /ZLINE. - */ -class CommandZline : public Command -{ - public: - /** Constructor for zline. - */ - CommandZline ( Module* parent) : Command(parent,"ZLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = " [ :]"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); -}; - -CmdResult CommandZline::Handle (const std::vector& parameters, User *user) -{ - std::string target = parameters[0]; - - if (parameters.size() >= 3) - { - if (target.find('!') != std::string::npos) - { - user->WriteNotice("*** You cannot include a nickname in a zline, a zline must ban only an IP mask"); - return CMD_FAILURE; - } - - User *u = ServerInstance->FindNick(target); - - if ((u) && (u->registered == REG_ALL)) - { - target = u->GetIPString(); - } - - const char* ipaddr = target.c_str(); - - if (strchr(ipaddr,'@')) - { - while (*ipaddr != '@') - ipaddr++; - ipaddr++; - } - - if (ServerInstance->IPMatchesEveryone(ipaddr,user)) - return CMD_FAILURE; - - unsigned long duration = InspIRCd::Duration(parameters[1]); - ZLine* zl = new ZLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr); - if (ServerInstance->XLines->AddLine(zl,user)) - { - if (!duration) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Z-line for %s: %s", user->nick.c_str(), ipaddr, parameters[2].c_str()); - } - else - { - time_t c_requires_crap = duration + ServerInstance->Time(); - std::string timestr = InspIRCd::TimeString(c_requires_crap); - ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Z-line for %s, expires on %s: %s",user->nick.c_str(),ipaddr, - timestr.c_str(), parameters[2].c_str()); - } - ServerInstance->XLines->ApplyLines(); - } - else - { - delete zl; - user->WriteNotice("*** Z-Line for " + std::string(ipaddr) + " already exists"); - } - } - else - { - if (ServerInstance->XLines->DelLine(target.c_str(),"Z",user)) - { - ServerInstance->SNO->WriteToSnoMask('x',"%s removed Z-line on %s",user->nick.c_str(),target.c_str()); - } - else - { - user->WriteNotice("*** Z-Line " + target + " not found in list, try /stats Z."); - return CMD_FAILURE; - } - } - - return CMD_SUCCESS; -} - -COMMAND_INIT(CommandZline) diff --git a/src/coremods/core_channel/cmd_invite.cpp b/src/coremods/core_channel/cmd_invite.cpp new file mode 100644 index 000000000..25afc0713 --- /dev/null +++ b/src/coremods/core_channel/cmd_invite.cpp @@ -0,0 +1,159 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * Copyright (C) 2008 Craig Edwards + * Copyright (C) 2008 Thomas Stagner + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /INVITE. + */ +class CommandInvite : public Command +{ + public: + /** Constructor for invite. + */ + CommandInvite ( Module* parent) : Command(parent,"INVITE", 0, 0) { Penalty = 4; syntax = "[ ]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); + } +}; + +/** Handle /INVITE + */ +CmdResult CommandInvite::Handle (const std::vector& parameters, User *user) +{ + ModResult MOD_RESULT; + + if (parameters.size() == 2 || parameters.size() == 3) + { + User* u; + if (IS_LOCAL(user)) + u = ServerInstance->FindNickOnly(parameters[0]); + else + u = ServerInstance->FindNick(parameters[0]); + + Channel* c = ServerInstance->FindChan(parameters[1]); + time_t timeout = 0; + if (parameters.size() == 3) + { + if (IS_LOCAL(user)) + timeout = ServerInstance->Time() + InspIRCd::Duration(parameters[2]); + else + timeout = ConvToInt(parameters[2]); + } + + if ((!c) || (!u) || (u->registered != REG_ALL)) + { + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c ? parameters[0].c_str() : parameters[1].c_str()); + return CMD_FAILURE; + } + + if ((IS_LOCAL(user)) && (!c->HasUser(user))) + { + user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", c->name.c_str()); + return CMD_FAILURE; + } + + if (c->HasUser(u)) + { + user->WriteNumeric(ERR_USERONCHANNEL, "%s %s :is already on channel", u->nick.c_str(), c->name.c_str()); + return CMD_FAILURE; + } + + FIRST_MOD_RESULT(OnUserPreInvite, MOD_RESULT, (user,u,c,timeout)); + + if (MOD_RESULT == MOD_RES_DENY) + { + return CMD_FAILURE; + } + else if (MOD_RESULT == MOD_RES_PASSTHRU) + { + if (IS_LOCAL(user)) + { + unsigned int rank = c->GetPrefixValue(user); + if (rank < HALFOP_VALUE) + { + // Check whether halfop mode is available and phrase error message accordingly + ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL); + user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You must be a channel %soperator", + c->name.c_str(), (mh && mh->name == "halfop" ? "half-" : "")); + return CMD_FAILURE; + } + } + } + + if (IS_LOCAL(u)) + { + Invitation::Create(c, IS_LOCAL(u), timeout); + u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str()); + } + + if (IS_LOCAL(user)) + user->WriteNumeric(RPL_INVITING, "%s %s", u->nick.c_str(),c->name.c_str()); + + if (ServerInstance->Config->AnnounceInvites != ServerConfig::INVITE_ANNOUNCE_NONE) + { + char prefix; + switch (ServerInstance->Config->AnnounceInvites) + { + case ServerConfig::INVITE_ANNOUNCE_OPS: + { + prefix = '@'; + break; + } + case ServerConfig::INVITE_ANNOUNCE_DYNAMIC: + { + PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h'); + prefix = (mh && mh->name == "halfop" ? mh->GetPrefix() : '@'); + break; + } + default: + { + prefix = 0; + break; + } + } + c->WriteAllExceptSender(user, true, prefix, "NOTICE %s :*** %s invited %s into the channel", c->name.c_str(), user->nick.c_str(), u->nick.c_str()); + } + FOREACH_MOD(OnUserInvite, (user,u,c,timeout)); + } + else if (IS_LOCAL(user)) + { + // pinched from ircu - invite with not enough parameters shows channels + // youve been invited to but haven't joined yet. + InviteList& il = IS_LOCAL(user)->GetInviteList(); + for (InviteList::const_iterator i = il.begin(); i != il.end(); ++i) + { + user->WriteNumeric(RPL_INVITELIST, ":%s", (*i)->chan->name.c_str()); + } + user->WriteNumeric(RPL_ENDOFINVITELIST, ":End of INVITE list"); + } + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandInvite) diff --git a/src/coremods/core_channel/cmd_join.cpp b/src/coremods/core_channel/cmd_join.cpp new file mode 100644 index 000000000..1e6e515ba --- /dev/null +++ b/src/coremods/core_channel/cmd_join.cpp @@ -0,0 +1,76 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /JOIN. + */ +class CommandJoin : public SplitCommand +{ + public: + /** Constructor for join. + */ + CommandJoin(Module* parent) + : SplitCommand(parent, "JOIN", 1, 2) + { + syntax = "{,} {{,}}"; + Penalty = 2; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult HandleLocal(const std::vector& parameters, LocalUser* user); +}; + +/** Handle /JOIN + */ +CmdResult CommandJoin::HandleLocal(const std::vector& parameters, LocalUser *user) +{ + if (parameters.size() > 1) + { + if (CommandParser::LoopCall(user, this, parameters, 0, 1, false)) + return CMD_SUCCESS; + + if (ServerInstance->IsChannel(parameters[0])) + { + Channel::JoinUser(user, parameters[0], false, parameters[1]); + return CMD_SUCCESS; + } + } + else + { + if (CommandParser::LoopCall(user, this, parameters, 0, -1, false)) + return CMD_SUCCESS; + + if (ServerInstance->IsChannel(parameters[0])) + { + Channel::JoinUser(user, parameters[0]); + return CMD_SUCCESS; + } + } + + user->WriteNumeric(ERR_NOSUCHCHANNEL, "%s :Invalid channel name", parameters[0].c_str()); + return CMD_FAILURE; +} + +COMMAND_INIT(CommandJoin) diff --git a/src/coremods/core_channel/cmd_kick.cpp b/src/coremods/core_channel/cmd_kick.cpp new file mode 100644 index 000000000..01f2039fa --- /dev/null +++ b/src/coremods/core_channel/cmd_kick.cpp @@ -0,0 +1,96 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /KICK. + */ +class CommandKick : public Command +{ + public: + /** Constructor for kick. + */ + CommandKick ( Module* parent) : Command(parent,"KICK",2,3) { syntax = " {,} []"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); + } +}; + +/** Handle /KICK + */ +CmdResult CommandKick::Handle (const std::vector& parameters, User *user) +{ + std::string reason; + Channel* c = ServerInstance->FindChan(parameters[0]); + User* u; + + if (CommandParser::LoopCall(user, this, parameters, 1)) + return CMD_SUCCESS; + + if (IS_LOCAL(user)) + u = ServerInstance->FindNickOnly(parameters[1]); + else + u = ServerInstance->FindNick(parameters[1]); + + if (!u || !c) + { + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", u ? parameters[0].c_str() : parameters[1].c_str()); + return CMD_FAILURE; + } + + Membership* srcmemb = NULL; + if (IS_LOCAL(user)) + { + srcmemb = c->GetUser(user); + if (!srcmemb) + { + user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", parameters[0].c_str()); + return CMD_FAILURE; + } + + if (u->server->IsULine()) + { + user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You may not kick a u-lined client", c->name.c_str()); + return CMD_FAILURE; + } + } + + if (parameters.size() > 2) + { + reason.assign(parameters[2], 0, ServerInstance->Config->Limits.MaxKick); + } + else + { + reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick); + } + + c->KickUser(user, u, reason, srcmemb); + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandKick) diff --git a/src/coremods/core_channel/cmd_names.cpp b/src/coremods/core_channel/cmd_names.cpp new file mode 100644 index 000000000..8c8bc58dd --- /dev/null +++ b/src/coremods/core_channel/cmd_names.cpp @@ -0,0 +1,80 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /NAMES. + */ +class CommandNames : public Command +{ + ChanModeReference secretmode; + + public: + /** Constructor for names. + */ + CommandNames(Module* parent) + : Command(parent, "NAMES", 0, 0) + , secretmode(parent, "secret") + { + syntax = "{{,}}"; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/** Handle /NAMES + */ +CmdResult CommandNames::Handle (const std::vector& parameters, User *user) +{ + Channel* c; + + if (!parameters.size()) + { + user->WriteNumeric(RPL_ENDOFNAMES, "* :End of /NAMES list."); + return CMD_SUCCESS; + } + + if (CommandParser::LoopCall(user, this, parameters, 0)) + return CMD_SUCCESS; + + c = ServerInstance->FindChan(parameters[0]); + if (c) + { + if ((c->IsModeSet(secretmode)) && (!c->HasUser(user))) + { + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c->name.c_str()); + return CMD_FAILURE; + } + c->UserList(user); + } + else + { + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandNames) diff --git a/src/coremods/core_channel/cmd_topic.cpp b/src/coremods/core_channel/cmd_topic.cpp new file mode 100644 index 000000000..2b0f81fb6 --- /dev/null +++ b/src/coremods/core_channel/cmd_topic.cpp @@ -0,0 +1,106 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * Copyright (C) 2008 Craig Edwards + * Copyright (C) 2008 Thomas Stagner + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /TOPIC. + */ +class CommandTopic : public SplitCommand +{ + ChanModeReference secretmode; + ChanModeReference topiclockmode; + + public: + /** Constructor for topic. + */ + CommandTopic(Module* parent) + : SplitCommand(parent, "TOPIC", 1, 2) + , secretmode(parent, "secret") + , topiclockmode(parent, "topiclock") + { + syntax = " []"; + Penalty = 2; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult HandleLocal(const std::vector& parameters, LocalUser* user); +}; + +CmdResult CommandTopic::HandleLocal(const std::vector& parameters, LocalUser* user) +{ + Channel* c = ServerInstance->FindChan(parameters[0]); + if (!c) + { + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); + return CMD_FAILURE; + } + + if (parameters.size() == 1) + { + if ((c->IsModeSet(secretmode)) && (!c->HasUser(user))) + { + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", c->name.c_str()); + return CMD_FAILURE; + } + + if (c->topic.length()) + { + user->WriteNumeric(RPL_TOPIC, "%s :%s", c->name.c_str(), c->topic.c_str()); + user->WriteNumeric(RPL_TOPICTIME, "%s %s %lu", c->name.c_str(), c->setby.c_str(), (unsigned long)c->topicset); + } + else + { + user->WriteNumeric(RPL_NOTOPICSET, "%s :No topic is set.", c->name.c_str()); + } + return CMD_SUCCESS; + } + + std::string t = parameters[1]; // needed, in case a module wants to change it + ModResult res; + FIRST_MOD_RESULT(OnPreTopicChange, res, (user,c,t)); + + if (res == MOD_RES_DENY) + return CMD_FAILURE; + if (res != MOD_RES_ALLOW) + { + if (!c->HasUser(user)) + { + user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", c->name.c_str()); + return CMD_FAILURE; + } + if (c->IsModeSet(topiclockmode) && !ServerInstance->OnCheckExemption(user, c, "topiclock").check(c->GetPrefixValue(user) >= HALFOP_VALUE)) + { + user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You do not have access to change the topic on this channel", c->name.c_str()); + return CMD_FAILURE; + } + } + + c->SetTopic(user, t); + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandTopic) diff --git a/src/coremods/core_connect.cpp b/src/coremods/core_connect.cpp new file mode 100644 index 000000000..59e7487a7 --- /dev/null +++ b/src/coremods/core_connect.cpp @@ -0,0 +1,51 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /CONNECT. + */ +class CommandConnect : public Command +{ + public: + /** Constructor for connect. + */ + CommandConnect ( Module* parent) : Command(parent,"CONNECT",1) { flags_needed = 'o'; syntax = " []"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/* + * This is handled by the server linking module, if necessary. Do not remove this stub. + */ + +/** Handle /CONNECT + */ +CmdResult CommandConnect::Handle (const std::vector&, User *user) +{ + user->WriteServ( "NOTICE %s :Look into loading a linking module (like m_spanningtree) if you want this to do anything useful.", user->nick.c_str()); + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandConnect) diff --git a/src/coremods/core_dns.cpp b/src/coremods/core_dns.cpp new file mode 100644 index 000000000..7b93c7bb3 --- /dev/null +++ b/src/coremods/core_dns.cpp @@ -0,0 +1,833 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Adam + * Copyright (C) 2003-2013 Anope Team + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "inspircd.h" +#include "modules/dns.h" +#include +#include + +#ifdef _WIN32 +#include +#pragma comment(lib, "Iphlpapi.lib") +#endif + +using namespace DNS; + +/** A full packet sent or recieved to/from the nameserver + */ +class Packet : public Query +{ + void PackName(unsigned char* output, unsigned short output_size, unsigned short& pos, const std::string& name) + { + if (pos + name.length() + 2 > output_size) + throw Exception("Unable to pack name"); + + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Packing name " + name); + + irc::sepstream sep(name, '.'); + std::string token; + + while (sep.GetToken(token)) + { + output[pos++] = token.length(); + memcpy(&output[pos], token.data(), token.length()); + pos += token.length(); + } + + output[pos++] = 0; + } + + std::string UnpackName(const unsigned char* input, unsigned short input_size, unsigned short& pos) + { + std::string name; + unsigned short pos_ptr = pos, lowest_ptr = input_size; + bool compressed = false; + + if (pos_ptr >= input_size) + throw Exception("Unable to unpack name - no input"); + + while (input[pos_ptr] > 0) + { + unsigned short offset = input[pos_ptr]; + + if (offset & POINTER) + { + if ((offset & POINTER) != POINTER) + throw Exception("Unable to unpack name - bogus compression header"); + if (pos_ptr + 1 >= input_size) + throw Exception("Unable to unpack name - bogus compression header"); + + /* Place pos at the second byte of the first (farthest) compression pointer */ + if (compressed == false) + { + ++pos; + compressed = true; + } + + pos_ptr = (offset & LABEL) << 8 | input[pos_ptr + 1]; + + /* Pointers can only go back */ + if (pos_ptr >= lowest_ptr) + throw Exception("Unable to unpack name - bogus compression pointer"); + lowest_ptr = pos_ptr; + } + else + { + if (pos_ptr + offset + 1 >= input_size) + throw Exception("Unable to unpack name - offset too large"); + if (!name.empty()) + name += "."; + for (unsigned i = 1; i <= offset; ++i) + name += input[pos_ptr + i]; + + pos_ptr += offset + 1; + if (compressed == false) + /* Move up pos */ + pos = pos_ptr; + } + } + + /* +1 pos either to one byte after the compression pointer or one byte after the ending \0 */ + ++pos; + + if (name.empty()) + throw Exception("Unable to unpack name - no name"); + + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Unpack name " + name); + + return name; + } + + Question UnpackQuestion(const unsigned char* input, unsigned short input_size, unsigned short& pos) + { + Question question; + + question.name = this->UnpackName(input, input_size, pos); + + if (pos + 4 > input_size) + throw Exception("Unable to unpack question"); + + question.type = static_cast(input[pos] << 8 | input[pos + 1]); + pos += 2; + + question.qclass = input[pos] << 8 | input[pos + 1]; + pos += 2; + + return question; + } + + ResourceRecord UnpackResourceRecord(const unsigned char* input, unsigned short input_size, unsigned short& pos) + { + ResourceRecord record = static_cast(this->UnpackQuestion(input, input_size, pos)); + + if (pos + 6 > input_size) + throw Exception("Unable to unpack resource record"); + + record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3]; + pos += 4; + + //record.rdlength = input[pos] << 8 | input[pos + 1]; + pos += 2; + + switch (record.type) + { + case QUERY_A: + { + if (pos + 4 > input_size) + throw Exception("Unable to unpack resource record"); + + irc::sockets::sockaddrs addrs; + memset(&addrs, 0, sizeof(addrs)); + + addrs.in4.sin_family = AF_INET; + addrs.in4.sin_addr.s_addr = input[pos] | (input[pos + 1] << 8) | (input[pos + 2] << 16) | (input[pos + 3] << 24); + pos += 4; + + record.rdata = addrs.addr(); + break; + } + case QUERY_AAAA: + { + if (pos + 16 > input_size) + throw Exception("Unable to unpack resource record"); + + irc::sockets::sockaddrs addrs; + memset(&addrs, 0, sizeof(addrs)); + + addrs.in6.sin6_family = AF_INET6; + for (int j = 0; j < 16; ++j) + addrs.in6.sin6_addr.s6_addr[j] = input[pos + j]; + pos += 16; + + record.rdata = addrs.addr(); + + break; + } + case QUERY_CNAME: + case QUERY_PTR: + { + record.rdata = this->UnpackName(input, input_size, pos); + break; + } + default: + break; + } + + if (!record.name.empty() && !record.rdata.empty()) + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: " + record.name + " -> " + record.rdata); + + return record; + } + + public: + static const int POINTER = 0xC0; + static const int LABEL = 0x3F; + static const int HEADER_LENGTH = 12; + + /* ID for this packet */ + unsigned short id; + /* Flags on the packet */ + unsigned short flags; + + Packet() : id(0), flags(0) + { + } + + void Fill(const unsigned char* input, const unsigned short len) + { + if (len < HEADER_LENGTH) + throw Exception("Unable to fill packet"); + + unsigned short packet_pos = 0; + + this->id = (input[packet_pos] << 8) | input[packet_pos + 1]; + packet_pos += 2; + + if (this->id >= MAX_REQUEST_ID) + throw Exception("Query ID too large?"); + + this->flags = (input[packet_pos] << 8) | input[packet_pos + 1]; + packet_pos += 2; + + unsigned short qdcount = (input[packet_pos] << 8) | input[packet_pos + 1]; + packet_pos += 2; + + unsigned short ancount = (input[packet_pos] << 8) | input[packet_pos + 1]; + packet_pos += 2; + + unsigned short nscount = (input[packet_pos] << 8) | input[packet_pos + 1]; + packet_pos += 2; + + unsigned short arcount = (input[packet_pos] << 8) | input[packet_pos + 1]; + packet_pos += 2; + + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: qdcount: " + ConvToStr(qdcount) + " ancount: " + ConvToStr(ancount) + " nscount: " + ConvToStr(nscount) + " arcount: " + ConvToStr(arcount)); + + for (unsigned i = 0; i < qdcount; ++i) + this->questions.push_back(this->UnpackQuestion(input, len, packet_pos)); + + for (unsigned i = 0; i < ancount; ++i) + this->answers.push_back(this->UnpackResourceRecord(input, len, packet_pos)); + } + + unsigned short Pack(unsigned char* output, unsigned short output_size) + { + if (output_size < HEADER_LENGTH) + throw Exception("Unable to pack packet"); + + unsigned short pos = 0; + + output[pos++] = this->id >> 8; + output[pos++] = this->id & 0xFF; + output[pos++] = this->flags >> 8; + output[pos++] = this->flags & 0xFF; + output[pos++] = this->questions.size() >> 8; + output[pos++] = this->questions.size() & 0xFF; + output[pos++] = this->answers.size() >> 8; + output[pos++] = this->answers.size() & 0xFF; + output[pos++] = 0; + output[pos++] = 0; + output[pos++] = 0; + output[pos++] = 0; + + for (unsigned i = 0; i < this->questions.size(); ++i) + { + Question& q = this->questions[i]; + + if (q.type == QUERY_PTR) + { + irc::sockets::sockaddrs ip; + irc::sockets::aptosa(q.name, 0, ip); + + if (q.name.find(':') != std::string::npos) + { + static const char* const hex = "0123456789abcdef"; + char reverse_ip[128]; + unsigned reverse_ip_count = 0; + for (int j = 15; j >= 0; --j) + { + reverse_ip[reverse_ip_count++] = hex[ip.in6.sin6_addr.s6_addr[j] & 0xF]; + reverse_ip[reverse_ip_count++] = '.'; + reverse_ip[reverse_ip_count++] = hex[ip.in6.sin6_addr.s6_addr[j] >> 4]; + reverse_ip[reverse_ip_count++] = '.'; + } + reverse_ip[reverse_ip_count++] = 0; + + q.name = reverse_ip; + q.name += "ip6.arpa"; + } + else + { + unsigned long forward = ip.in4.sin_addr.s_addr; + ip.in4.sin_addr.s_addr = forward << 24 | (forward & 0xFF00) << 8 | (forward & 0xFF0000) >> 8 | forward >> 24; + + q.name = ip.addr() + ".in-addr.arpa"; + } + } + + this->PackName(output, output_size, pos, q.name); + + if (pos + 4 >= output_size) + throw Exception("Unable to pack packet"); + + short s = htons(q.type); + memcpy(&output[pos], &s, 2); + pos += 2; + + s = htons(q.qclass); + memcpy(&output[pos], &s, 2); + pos += 2; + } + + for (unsigned int i = 0; i < answers.size(); i++) + { + ResourceRecord& rr = answers[i]; + + this->PackName(output, output_size, pos, rr.name); + + if (pos + 8 >= output_size) + throw Exception("Unable to pack packet"); + + short s = htons(rr.type); + memcpy(&output[pos], &s, 2); + pos += 2; + + s = htons(rr.qclass); + memcpy(&output[pos], &s, 2); + pos += 2; + + long l = htonl(rr.ttl); + memcpy(&output[pos], &l, 4); + pos += 4; + + switch (rr.type) + { + case QUERY_A: + { + if (pos + 6 > output_size) + throw Exception("Unable to pack packet"); + + irc::sockets::sockaddrs a; + irc::sockets::aptosa(rr.rdata, 0, a); + + s = htons(4); + memcpy(&output[pos], &s, 2); + pos += 2; + + memcpy(&output[pos], &a.in4.sin_addr, 4); + pos += 4; + break; + } + case QUERY_AAAA: + { + if (pos + 18 > output_size) + throw Exception("Unable to pack packet"); + + irc::sockets::sockaddrs a; + irc::sockets::aptosa(rr.rdata, 0, a); + + s = htons(16); + memcpy(&output[pos], &s, 2); + pos += 2; + + memcpy(&output[pos], &a.in6.sin6_addr, 16); + pos += 16; + break; + } + case QUERY_CNAME: + case QUERY_PTR: + { + if (pos + 2 >= output_size) + throw Exception("Unable to pack packet"); + + unsigned short packet_pos_save = pos; + pos += 2; + + this->PackName(output, output_size, pos, rr.rdata); + + s = htons(pos - packet_pos_save - 2); + memcpy(&output[packet_pos_save], &s, 2); + break; + } + default: + break; + } + } + + return pos; + } +}; + +class MyManager : public Manager, public Timer, public EventHandler +{ + typedef TR1NS::unordered_map cache_map; + cache_map cache; + + irc::sockets::sockaddrs myserver; + + static bool IsExpired(const Query& record, time_t now = ServerInstance->Time()) + { + const ResourceRecord& req = record.answers[0]; + return (req.created + static_cast(req.ttl) < now); + } + + /** Check the DNS cache to see if request can be handled by a cached result + * @return true if a cached result was found. + */ + bool CheckCache(DNS::Request* req, const DNS::Question& question) + { + ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: cache: Checking cache for " + question.name); + + cache_map::iterator it = this->cache.find(question); + if (it == this->cache.end()) + return false; + + Query& record = it->second; + if (IsExpired(record)) + { + this->cache.erase(it); + return false; + } + + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: Using cached result for " + question.name); + record.cached = true; + req->OnLookupComplete(&record); + return true; + } + + /** Add a record to the dns cache + * @param r The record + */ + void AddCache(Query& r) + { + const ResourceRecord& rr = r.answers[0]; + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: added cache for " + rr.name + " -> " + rr.rdata + " ttl: " + ConvToStr(rr.ttl)); + this->cache[r.questions[0]] = r; + } + + public: + DNS::Request* requests[MAX_REQUEST_ID]; + + MyManager(Module* c) : Manager(c), Timer(3600, ServerInstance->Time(), true) + { + for (int i = 0; i < MAX_REQUEST_ID; ++i) + requests[i] = NULL; + ServerInstance->Timers->AddTimer(this); + } + + ~MyManager() + { + for (int i = 0; i < MAX_REQUEST_ID; ++i) + { + DNS::Request* request = requests[i]; + if (!request) + continue; + + Query rr(*request); + rr.error = ERROR_UNKNOWN; + request->OnError(&rr); + + delete request; + } + } + + void Process(DNS::Request* req) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Processing request to lookup " + req->name + " of type " + ConvToStr(req->type) + " to " + this->myserver.addr()); + + /* Create an id */ + unsigned int tries = 0; + do + { + req->id = ServerInstance->GenRandomInt(DNS::MAX_REQUEST_ID); + + if (++tries == DNS::MAX_REQUEST_ID*5) + { + // If we couldn't find an empty slot this many times, do a sequential scan as a last + // resort. If an empty slot is found that way, go on, otherwise throw an exception + req->id = 0; + for (int i = 1; i < DNS::MAX_REQUEST_ID; i++) + { + if (!this->requests[i]) + { + req->id = i; + break; + } + } + + if (req->id == 0) + throw Exception("DNS: All ids are in use"); + + break; + } + } + while (!req->id || this->requests[req->id]); + + this->requests[req->id] = req; + + Packet p; + p.flags = QUERYFLAGS_RD; + p.id = req->id; + p.questions.push_back(*req); + + unsigned char buffer[524]; + unsigned short len = p.Pack(buffer, sizeof(buffer)); + + /* Note that calling Pack() above can actually change the contents of p.questions[0].name, if the query is a PTR, + * to contain the value that would be in the DNS cache, which is why this is here. + */ + if (req->use_cache && this->CheckCache(req, p.questions[0])) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Using cached result"); + delete req; + return; + } + + if (SocketEngine::SendTo(this, buffer, len, 0, &this->myserver.sa, this->myserver.sa_size()) != len) + throw Exception("DNS: Unable to send query"); + } + + void RemoveRequest(DNS::Request* req) + { + this->requests[req->id] = NULL; + } + + std::string GetErrorStr(Error e) + { + switch (e) + { + case ERROR_UNLOADED: + return "Module is unloading"; + case ERROR_TIMEDOUT: + return "Request timed out"; + case ERROR_NOT_AN_ANSWER: + case ERROR_NONSTANDARD_QUERY: + case ERROR_FORMAT_ERROR: + return "Malformed answer"; + case ERROR_SERVER_FAILURE: + case ERROR_NOT_IMPLEMENTED: + case ERROR_REFUSED: + case ERROR_INVALIDTYPE: + return "Nameserver failure"; + case ERROR_DOMAIN_NOT_FOUND: + case ERROR_NO_RECORDS: + return "Domain not found"; + case ERROR_NONE: + case ERROR_UNKNOWN: + default: + return "Unknown error"; + } + } + + void HandleEvent(EventType et, int) + { + if (et == EVENT_ERROR) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: UDP socket got an error event"); + return; + } + + unsigned char buffer[524]; + irc::sockets::sockaddrs from; + socklen_t x = sizeof(from); + + int length = SocketEngine::RecvFrom(this, buffer, sizeof(buffer), 0, &from.sa, &x); + + if (length < Packet::HEADER_LENGTH) + return; + + Packet recv_packet; + + try + { + recv_packet.Fill(buffer, length); + } + catch (Exception& ex) + { + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, ex.GetReason()); + return; + } + + if (myserver != from) + { + std::string server1 = from.str(); + std::string server2 = myserver.str(); + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Got a result from the wrong server! Bad NAT or DNS forging attempt? '%s' != '%s'", + server1.c_str(), server2.c_str()); + return; + } + + DNS::Request* request = this->requests[recv_packet.id]; + if (request == NULL) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Received an answer for something we didn't request"); + return; + } + + if (recv_packet.flags & QUERYFLAGS_OPCODE) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Received a nonstandard query"); + ServerInstance->stats->statsDnsBad++; + recv_packet.error = ERROR_NONSTANDARD_QUERY; + request->OnError(&recv_packet); + } + else if (recv_packet.flags & QUERYFLAGS_RCODE) + { + Error error = ERROR_UNKNOWN; + + switch (recv_packet.flags & QUERYFLAGS_RCODE) + { + case 1: + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: format error"); + error = ERROR_FORMAT_ERROR; + break; + case 2: + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: server error"); + error = ERROR_SERVER_FAILURE; + break; + case 3: + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: domain not found"); + error = ERROR_DOMAIN_NOT_FOUND; + break; + case 4: + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: not implemented"); + error = ERROR_NOT_IMPLEMENTED; + break; + case 5: + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: refused"); + error = ERROR_REFUSED; + break; + default: + break; + } + + ServerInstance->stats->statsDnsBad++; + recv_packet.error = error; + request->OnError(&recv_packet); + } + else if (recv_packet.questions.empty() || recv_packet.answers.empty()) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: No resource records returned"); + ServerInstance->stats->statsDnsBad++; + recv_packet.error = ERROR_NO_RECORDS; + request->OnError(&recv_packet); + } + else + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Lookup complete for " + request->name); + ServerInstance->stats->statsDnsGood++; + request->OnLookupComplete(&recv_packet); + this->AddCache(recv_packet); + } + + ServerInstance->stats->statsDns++; + + /* Request's destructor removes it from the request map */ + delete request; + } + + bool Tick(time_t now) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: purging DNS cache"); + + for (cache_map::iterator it = this->cache.begin(); it != this->cache.end(); ) + { + const Query& query = it->second; + if (IsExpired(query, now)) + this->cache.erase(it++); + else + ++it; + } + return true; + } + + void Rehash(const std::string& dnsserver) + { + if (this->GetFd() > -1) + { + SocketEngine::Shutdown(this, 2); + SocketEngine::Close(this); + + /* Remove expired entries from the cache */ + this->Tick(ServerInstance->Time()); + } + + irc::sockets::aptosa(dnsserver, DNS::PORT, myserver); + + /* Initialize mastersocket */ + int s = socket(myserver.sa.sa_family, SOCK_DGRAM, 0); + this->SetFd(s); + + /* Have we got a socket? */ + if (this->GetFd() != -1) + { + SocketEngine::SetReuse(s); + SocketEngine::NonBlocking(s); + + irc::sockets::sockaddrs bindto; + memset(&bindto, 0, sizeof(bindto)); + bindto.sa.sa_family = myserver.sa.sa_family; + + if (SocketEngine::Bind(this->GetFd(), bindto) < 0) + { + /* Failed to bind */ + ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Error binding dns socket - hostnames will NOT resolve"); + SocketEngine::Close(this->GetFd()); + this->SetFd(-1); + } + else if (!SocketEngine::AddFd(this, FD_WANT_POLL_READ | FD_WANT_NO_WRITE)) + { + ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Internal error starting DNS - hostnames will NOT resolve."); + SocketEngine::Close(this->GetFd()); + this->SetFd(-1); + } + } + else + { + ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Error creating DNS socket - hostnames will NOT resolve"); + } + } +}; + +class ModuleDNS : public Module +{ + MyManager manager; + std::string DNSServer; + + void FindDNSServer() + { +#ifdef _WIN32 + // attempt to look up their nameserver from the system + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: not defined, attempting to find a working server in the system settings..."); + + PFIXED_INFO pFixedInfo; + DWORD dwBufferSize = sizeof(FIXED_INFO); + pFixedInfo = (PFIXED_INFO) HeapAlloc(GetProcessHeap(), 0, sizeof(FIXED_INFO)); + + if (pFixedInfo) + { + if (GetNetworkParams(pFixedInfo, &dwBufferSize) == ERROR_BUFFER_OVERFLOW) + { + HeapFree(GetProcessHeap(), 0, pFixedInfo); + pFixedInfo = (PFIXED_INFO) HeapAlloc(GetProcessHeap(), 0, dwBufferSize); + } + + if (pFixedInfo) + { + if (GetNetworkParams(pFixedInfo, &dwBufferSize) == NO_ERROR) + DNSServer = pFixedInfo->DnsServerList.IpAddress.String; + + HeapFree(GetProcessHeap(), 0, pFixedInfo); + } + + if (!DNSServer.empty()) + { + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, " set to '%s' as first active resolver in the system settings.", DNSServer.c_str()); + return; + } + } + + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "No viable nameserver found! Defaulting to nameserver '127.0.0.1'!"); +#else + // attempt to look up their nameserver from /etc/resolv.conf + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: not defined, attempting to find working server in /etc/resolv.conf..."); + + std::ifstream resolv("/etc/resolv.conf"); + + while (resolv >> DNSServer) + { + if (DNSServer == "nameserver") + { + resolv >> DNSServer; + if (DNSServer.find_first_not_of("0123456789.") == std::string::npos) + { + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, " set to '%s' as first resolver in /etc/resolv.conf.",DNSServer.c_str()); + return; + } + } + } + + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!"); +#endif + DNSServer = "127.0.0.1"; + } + + public: + ModuleDNS() : manager(this) + { + } + + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + std::string oldserver = DNSServer; + DNSServer = ServerInstance->Config->ConfValue("dns")->getString("server"); + if (DNSServer.empty()) + FindDNSServer(); + + if (oldserver != DNSServer) + this->manager.Rehash(DNSServer); + } + + void OnUnloadModule(Module* mod) + { + for (int i = 0; i < MAX_REQUEST_ID; ++i) + { + DNS::Request* req = this->manager.requests[i]; + if (!req) + continue; + + if (req->creator == mod) + { + Query rr(*req); + rr.error = ERROR_UNLOADED; + req->OnError(&rr); + + delete req; + } + } + } + + Version GetVersion() + { + return Version("DNS support", VF_CORE|VF_VENDOR); + } +}; + +MODULE_INIT(ModuleDNS) + diff --git a/src/coremods/core_hostname_lookup.cpp b/src/coremods/core_hostname_lookup.cpp new file mode 100644 index 000000000..c26d3b3d3 --- /dev/null +++ b/src/coremods/core_hostname_lookup.cpp @@ -0,0 +1,233 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Adam + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "modules/dns.h" + +namespace +{ + LocalIntExt* dl; + LocalStringExt* ph; +} + +/** Derived from Resolver, and performs user forward/reverse lookups. + */ +class UserResolver : public DNS::Request +{ + /** UUID we are looking up */ + const std::string uuid; + + /** True if the lookup is forward, false if is a reverse lookup + */ + const bool fwd; + + public: + /** Create a resolver. + * @param mgr DNS Manager + * @param me this module + * @param user The user to begin lookup on + * @param to_resolve The IP or host to resolve + * @param qt The query type + */ + UserResolver(DNS::Manager* mgr, Module* me, LocalUser* user, const std::string& to_resolve, DNS::QueryType qt) + : DNS::Request(mgr, me, to_resolve, qt) + , uuid(user->uuid) + , fwd(qt == DNS::QUERY_A || qt == DNS::QUERY_AAAA) + { + } + + /** Called on successful lookup + * if a previous result has already come back. + * @param r The finished query + */ + void OnLookupComplete(const DNS::Query* r) + { + LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid); + if (!bound_user) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolution finished for user '%s' who is gone", uuid.c_str()); + return; + } + + const DNS::ResourceRecord& ans_record = r->answers[0]; + + ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "DNS result for %s: '%s' -> '%s'", uuid.c_str(), ans_record.name.c_str(), ans_record.rdata.c_str()); + + if (!fwd) + { + // first half of resolution is done. We now need to verify that the host matches. + ph->set(bound_user, ans_record.rdata); + + UserResolver* res_forward; + if (bound_user->client_sa.sa.sa_family == AF_INET6) + { + /* IPV6 forward lookup */ + res_forward = new UserResolver(this->manager, this->creator, bound_user, ans_record.rdata, DNS::QUERY_AAAA); + } + else + { + /* IPV4 lookup */ + res_forward = new UserResolver(this->manager, this->creator, bound_user, ans_record.rdata, DNS::QUERY_A); + } + try + { + this->manager->Process(res_forward); + } + catch (DNS::Exception& e) + { + delete res_forward; + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Error in resolver: " + e.GetReason()); + + bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead."); + dl->set(bound_user, 0); + } + } + else + { + /* Both lookups completed */ + + irc::sockets::sockaddrs* user_ip = &bound_user->client_sa; + bool rev_match = false; + if (user_ip->sa.sa_family == AF_INET6) + { + struct in6_addr res_bin; + if (inet_pton(AF_INET6, ans_record.rdata.c_str(), &res_bin)) + { + rev_match = !memcmp(&user_ip->in6.sin6_addr, &res_bin, sizeof(res_bin)); + } + } + else + { + struct in_addr res_bin; + if (inet_pton(AF_INET, ans_record.rdata.c_str(), &res_bin)) + { + rev_match = !memcmp(&user_ip->in4.sin_addr, &res_bin, sizeof(res_bin)); + } + } + + dl->set(bound_user, 0); + + if (rev_match) + { + std::string* hostname = ph->get(bound_user); + + if (hostname == NULL) + { + ServerInstance->Logs->Log("RESOLVER", LOG_DEFAULT, "ERROR: User has no hostname attached when doing a forward lookup"); + bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead."); + return; + } + else if (hostname->length() < 65) + { + /* Hostnames starting with : are not a good thing (tm) */ + if ((*hostname)[0] == ':') + hostname->insert(0, "0"); + + bound_user->WriteNotice("*** Found your hostname (" + *hostname + (r->cached ? ") -- cached" : ")")); + bound_user->host.assign(*hostname, 0, 64); + bound_user->dhost = bound_user->host; + + /* Invalidate cache */ + bound_user->InvalidateCache(); + } + else + { + bound_user->WriteNotice("*** Your hostname is longer than the maximum of 64 characters, using your IP address (" + bound_user->GetIPString() + ") instead."); + } + + ph->unset(bound_user); + } + else + { + bound_user->WriteNotice("*** Your hostname does not match up with your IP address. Sorry, using your IP address (" + bound_user->GetIPString() + ") instead."); + } + } + } + + /** Called on failed lookup + * @param query The errored query + */ + void OnError(const DNS::Query* query) + { + LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid); + if (bound_user) + { + bound_user->WriteNotice("*** Could not resolve your hostname: " + this->manager->GetErrorStr(query->error) + "; using your IP address (" + bound_user->GetIPString() + ") instead."); + dl->set(bound_user, 0); + ServerInstance->stats->statsDnsBad++; + } + } +}; + +class ModuleHostnameLookup : public Module +{ + LocalIntExt dnsLookup; + LocalStringExt ptrHosts; + dynamic_reference DNS; + + public: + ModuleHostnameLookup() + : dnsLookup("dnsLookup", this) + , ptrHosts("ptrHosts", this) + , DNS(this, "DNS") + { + dl = &dnsLookup; + ph = &ptrHosts; + } + + void OnUserInit(LocalUser *user) + { + if (!DNS || !user->MyClass->resolvehostnames) + { + user->WriteNotice("*** Skipping host resolution (disabled by server administrator)"); + return; + } + + user->WriteNotice("*** Looking up your hostname..."); + + UserResolver* res_reverse = new UserResolver(*this->DNS, this, user, user->GetIPString(), DNS::QUERY_PTR); + try + { + /* If both the reverse and forward queries are cached, the user will be able to pass DNS completely + * before Process() completes, which is why dnsLookup.set() is here, before Process() + */ + this->dnsLookup.set(user, 1); + this->DNS->Process(res_reverse); + } + catch (DNS::Exception& e) + { + this->dnsLookup.set(user, 0); + delete res_reverse; + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Error in resolver: " + e.GetReason()); + ServerInstance->stats->statsDnsBad++; + } + } + + ModResult OnCheckReady(LocalUser* user) + { + return this->dnsLookup.get(user) ? MOD_RES_DENY : MOD_RES_PASSTHRU; + } + + Version GetVersion() + { + return Version("Provides support for DNS lookups on connecting clients", VF_CORE|VF_VENDOR); + } +}; + +MODULE_INIT(ModuleHostnameLookup) diff --git a/src/coremods/core_info/cmd_admin.cpp b/src/coremods/core_info/cmd_admin.cpp new file mode 100644 index 000000000..1f694bf2e --- /dev/null +++ b/src/coremods/core_info/cmd_admin.cpp @@ -0,0 +1,68 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /ADMIN. + */ +class CommandAdmin : public Command +{ + public: + /** Constructor for admin. + */ + CommandAdmin(Module* parent) : Command(parent,"ADMIN",0,0) + { + Penalty = 2; + syntax = "[]"; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + if (parameters.size() > 0) + return ROUTE_UNICAST(parameters[0]); + return ROUTE_LOCALONLY; + } +}; + +/** Handle /ADMIN + */ +CmdResult CommandAdmin::Handle (const std::vector& parameters, User *user) +{ + if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName) + return CMD_SUCCESS; + user->SendText(":%s %03d %s :Administrative info for %s", ServerInstance->Config->ServerName.c_str(), + RPL_ADMINME, user->nick.c_str(),ServerInstance->Config->ServerName.c_str()); + if (!ServerInstance->Config->AdminName.empty()) + user->SendText(":%s %03d %s :Name - %s", ServerInstance->Config->ServerName.c_str(), + RPL_ADMINLOC1, user->nick.c_str(), ServerInstance->Config->AdminName.c_str()); + user->SendText(":%s %03d %s :Nickname - %s", ServerInstance->Config->ServerName.c_str(), + RPL_ADMINLOC2, user->nick.c_str(), ServerInstance->Config->AdminNick.c_str()); + user->SendText(":%s %03d %s :E-Mail - %s", ServerInstance->Config->ServerName.c_str(), + RPL_ADMINEMAIL, user->nick.c_str(), ServerInstance->Config->AdminEmail.c_str()); + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandAdmin) diff --git a/src/coremods/core_info/cmd_commands.cpp b/src/coremods/core_info/cmd_commands.cpp new file mode 100644 index 000000000..3f0ab99c1 --- /dev/null +++ b/src/coremods/core_info/cmd_commands.cpp @@ -0,0 +1,67 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /COMMANDS. + */ +class CommandCommands : public Command +{ + public: + /** Constructor for commands. + */ + CommandCommands(Module* parent) : Command(parent,"COMMANDS",0,0) + { + Penalty = 3; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/** Handle /COMMANDS + */ +CmdResult CommandCommands::Handle (const std::vector&, User *user) +{ + std::vector list; + list.reserve(ServerInstance->Parser->cmdlist.size()); + for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) + { + // Don't show S2S commands to users + if (i->second->flags_needed == FLAG_SERVERONLY) + continue; + + Module* src = i->second->creator; + list.push_back(InspIRCd::Format(":%s %03d %s :%s %s %d %d", ServerInstance->Config->ServerName.c_str(), + RPL_COMMANDS, user->nick.c_str(), i->second->name.c_str(), src->ModuleSourceFile.c_str(), + i->second->min_params, i->second->Penalty)); + } + sort(list.begin(), list.end()); + for(unsigned int i=0; i < list.size(); i++) + user->Write(list[i]); + user->WriteNumeric(RPL_COMMANDSEND, ":End of COMMANDS list"); + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandCommands) diff --git a/src/coremods/core_info/cmd_info.cpp b/src/coremods/core_info/cmd_info.cpp new file mode 100644 index 000000000..7f1e923c9 --- /dev/null +++ b/src/coremods/core_info/cmd_info.cpp @@ -0,0 +1,109 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2011 Jackmcbarn + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * Copyright (C) 2008 Thomas Stagner + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /INFO. + */ +class CommandInfo : public Command +{ + public: + /** Constructor for info. + */ + CommandInfo(Module* parent) : Command(parent,"INFO") + { + Penalty = 4; + syntax = "[]"; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + if (parameters.size() > 0) + return ROUTE_UNICAST(parameters[0]); + return ROUTE_LOCALONLY; + } +}; + +static const char* const lines[] = { + " -/\\- \2InspIRCd\2 -\\/-", + " November 2002 - Present", + " ", + "\2Core Developers\2:", + " Craig Edwards, Brain, ", + " Craig McLure, Craig, ", + " Robin Burchell, w00t, ", + " Oliver Lupton, Om, ", + " John Brooks, Special, ", + " Dennis Friis, peavey, ", + " Thomas Stagner, aquanight, ", + " Uli Schlachter, psychon, ", + " Matt Smith, dz, ", + " Daniel De Graaf, danieldg, ", + " jackmcbarn, ", + " Attila Molnar, Attila, ", + " ", + "\2Regular Contributors\2:", + " Adam SaberUK", + " ", + "\2Other Contributors\2:", + " ChrisTX Shawn Shutter", + " ", + "\2Former Contributors\2:", + " dmb Zaba skenmy GreenReaper", + " Dan Jason satmd owine", + " Adremelech John2 jilles HiroP", + " eggy Bricker AnMaster djGrrr", + " nenolod Quension praetorian pippijn", + " CC jamie typobox43 Burlex (win32)", + " Stskeeps ThaPrince BuildSmart Thunderhacker", + " Skip LeaChim Majic MacGyver", + " Namegduf Ankit Phoenix Taros", + " ", + "\2Thanks To\2:", + " searchirc.com irc-junkie.org Brik fraggeln", + " ", + " Best experienced with: \2An IRC client\2", + NULL +}; + +/** Handle /INFO + */ +CmdResult CommandInfo::Handle (const std::vector& parameters, User *user) +{ + if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName) + return CMD_SUCCESS; + + int i=0; + while (lines[i]) + user->SendText(":%s %03d %s :%s", ServerInstance->Config->ServerName.c_str(), RPL_INFO, user->nick.c_str(), lines[i++]); + FOREACH_MOD(OnInfo, (user)); + user->SendText(":%s %03d %s :End of /INFO list", ServerInstance->Config->ServerName.c_str(), RPL_ENDOFINFO, user->nick.c_str()); + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandInfo) diff --git a/src/coremods/core_info/cmd_modules.cpp b/src/coremods/core_info/cmd_modules.cpp new file mode 100644 index 000000000..01774390d --- /dev/null +++ b/src/coremods/core_info/cmd_modules.cpp @@ -0,0 +1,106 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2008 Craig Edwards + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /MODULES. + */ +class CommandModules : public Command +{ + public: + /** Constructor for modules. + */ + CommandModules(Module* parent) : Command(parent,"MODULES",0,0) + { + Penalty = 4; + syntax = "[]"; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + if (parameters.size() >= 1) + return ROUTE_UNICAST(parameters[0]); + return ROUTE_LOCALONLY; + } +}; + +/** Handle /MODULES + */ +CmdResult CommandModules::Handle (const std::vector& parameters, User *user) +{ + // Don't ask remote servers about their modules unless the local user asking is an oper + // 2.0 asks anyway, so let's handle that the same way + bool for_us = (parameters.empty() || parameters[0] == ServerInstance->Config->ServerName); + if ((!for_us) || (!IS_LOCAL(user))) + { + if (!user->IsOper()) + { + user->WriteNotice("*** You cannot check what modules other servers have loaded."); + return CMD_FAILURE; + } + + // From an oper and not for us, forward + if (!for_us) + return CMD_SUCCESS; + } + + const ModuleManager::ModuleMap& mods = ServerInstance->Modules->GetModules(); + + for (ModuleManager::ModuleMap::const_iterator i = mods.begin(); i != mods.end(); ++i) + { + Module* m = i->second; + Version V = m->GetVersion(); + + if (IS_LOCAL(user) && user->HasPrivPermission("servers/auspex")) + { + std::string flags("SvcC"); + int pos = 0; + for (int mult = 1; mult <= VF_OPTCOMMON; mult *= 2, ++pos) + if (!(V.Flags & mult)) + flags[pos] = '-'; + +#ifdef PURE_STATIC + user->SendText(":%s 702 %s :%p %s %s :%s", ServerInstance->Config->ServerName.c_str(), + user->nick.c_str(), (void*)m, m->ModuleSourceFile.c_str(), flags.c_str(), V.description.c_str()); +#else + std::string srcrev = m->ModuleDLLManager->GetVersion(); + user->SendText(":%s 702 %s :%p %s %s :%s - %s", ServerInstance->Config->ServerName.c_str(), + user->nick.c_str(), (void*)m, m->ModuleSourceFile.c_str(), flags.c_str(), V.description.c_str(), srcrev.c_str()); +#endif + } + else + { + user->SendText(":%s 702 %s :%s %s", ServerInstance->Config->ServerName.c_str(), + user->nick.c_str(), m->ModuleSourceFile.c_str(), V.description.c_str()); + } + } + user->SendText(":%s 703 %s :End of MODULES list", ServerInstance->Config->ServerName.c_str(), user->nick.c_str()); + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandModules) diff --git a/src/coremods/core_info/cmd_motd.cpp b/src/coremods/core_info/cmd_motd.cpp new file mode 100644 index 000000000..71df7017a --- /dev/null +++ b/src/coremods/core_info/cmd_motd.cpp @@ -0,0 +1,76 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /MOTD. + */ +class CommandMotd : public Command +{ + public: + /** Constructor for motd. + */ + CommandMotd ( Module* parent) : Command(parent,"MOTD",0,1) { syntax = "[]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + if (parameters.size() > 0) + return ROUTE_UNICAST(parameters[0]); + return ROUTE_LOCALONLY; + } +}; + +/** Handle /MOTD + */ +CmdResult CommandMotd::Handle (const std::vector& parameters, User *user) +{ + if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName) + return CMD_SUCCESS; + + ConfigTag* tag = NULL; + LocalUser* localuser = IS_LOCAL(user); + if (localuser) + tag = localuser->GetClass()->config; + std::string motd_name = tag->getString("motd", "motd"); + ConfigFileCache::iterator motd = ServerInstance->Config->Files.find(motd_name); + if (motd == ServerInstance->Config->Files.end()) + { + user->SendText(":%s %03d %s :Message of the day file is missing.", + ServerInstance->Config->ServerName.c_str(), ERR_NOMOTD, user->nick.c_str()); + return CMD_SUCCESS; + } + + user->SendText(":%s %03d %s :%s message of the day", ServerInstance->Config->ServerName.c_str(), + RPL_MOTDSTART, user->nick.c_str(), ServerInstance->Config->ServerName.c_str()); + + for (file_cache::iterator i = motd->second.begin(); i != motd->second.end(); i++) + user->SendText(":%s %03d %s :- %s", ServerInstance->Config->ServerName.c_str(), RPL_MOTD, user->nick.c_str(), i->c_str()); + + user->SendText(":%s %03d %s :End of message of the day.", ServerInstance->Config->ServerName.c_str(), RPL_ENDOFMOTD, user->nick.c_str()); + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandMotd) diff --git a/src/coremods/core_info/cmd_time.cpp b/src/coremods/core_info/cmd_time.cpp new file mode 100644 index 000000000..9c4688029 --- /dev/null +++ b/src/coremods/core_info/cmd_time.cpp @@ -0,0 +1,60 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /TIME. + */ +class CommandTime : public Command +{ + public: + /** Constructor for time. + */ + CommandTime ( Module* parent) : Command(parent,"TIME",0,0) { syntax = "[]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + if (parameters.size() > 0) + return ROUTE_UNICAST(parameters[0]); + return ROUTE_LOCALONLY; + } +}; + +CmdResult CommandTime::Handle (const std::vector& parameters, User *user) +{ + if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName) + return CMD_SUCCESS; + + time_t local = ServerInstance->Time(); + struct tm* timeinfo = localtime(&local); + const std::string& humanTime = asctime(timeinfo); + + user->SendText(":%s %03d %s %s :%s", ServerInstance->Config->ServerName.c_str(), RPL_TIME, user->nick.c_str(), + ServerInstance->Config->ServerName.c_str(), humanTime.c_str()); + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandTime) diff --git a/src/coremods/core_info/cmd_version.cpp b/src/coremods/core_info/cmd_version.cpp new file mode 100644 index 000000000..032d9ea0c --- /dev/null +++ b/src/coremods/core_info/cmd_version.cpp @@ -0,0 +1,51 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /VERSION. + */ +class CommandVersion : public Command +{ + public: + /** Constructor for version. + */ + CommandVersion ( Module* parent) : Command(parent,"VERSION",0,0) { syntax = "[]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandVersion::Handle (const std::vector&, User *user) +{ + std::string version = ServerInstance->GetVersionString((user->IsOper())); + user->WriteNumeric(RPL_VERSION, ":%s", version.c_str()); + LocalUser *lu = IS_LOCAL(user); + if (lu != NULL) + { + ServerInstance->ISupport.SendTo(lu); + } + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandVersion) diff --git a/src/coremods/core_ison.cpp b/src/coremods/core_ison.cpp new file mode 100644 index 000000000..c7ead2a87 --- /dev/null +++ b/src/coremods/core_ison.cpp @@ -0,0 +1,102 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /ISON. + */ +class CommandIson : public Command +{ + public: + /** Constructor for ison. + */ + CommandIson ( Module* parent) : Command(parent,"ISON", 1) { + syntax = " {nick}"; + } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/** Handle /ISON + */ +CmdResult CommandIson::Handle (const std::vector& parameters, User *user) +{ + std::map ison_already; + User *u; + std::string reply = "303 " + user->nick + " :"; + + for (unsigned int i = 0; i < parameters.size(); i++) + { + u = ServerInstance->FindNickOnly(parameters[i]); + if (ison_already.find(u) != ison_already.end()) + continue; + + if (u) + { + reply.append(u->nick).append(" "); + if (reply.length() > 450) + { + user->WriteServ(reply); + reply = "303 " + user->nick + " :"; + } + ison_already[u] = u; + } + else + { + if ((i == parameters.size() - 1) && (parameters[i].find(' ') != std::string::npos)) + { + /* Its a space seperated list of nicks (RFC1459 says to support this) + */ + irc::spacesepstream list(parameters[i]); + std::string item; + + while (list.GetToken(item)) + { + u = ServerInstance->FindNickOnly(item); + if (ison_already.find(u) != ison_already.end()) + continue; + + if (u) + { + reply.append(u->nick).append(" "); + if (reply.length() > 450) + { + user->WriteServ(reply); + reply = "303 " + user->nick + " :"; + } + ison_already[u] = u; + } + } + } + } + } + + if (!reply.empty()) + user->WriteServ(reply); + + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandIson) diff --git a/src/coremods/core_links.cpp b/src/coremods/core_links.cpp new file mode 100644 index 000000000..8b44d7a19 --- /dev/null +++ b/src/coremods/core_links.cpp @@ -0,0 +1,48 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /LINKS. + */ +class CommandLinks : public Command +{ + public: + /** Constructor for links. + */ + CommandLinks ( Module* parent) : Command(parent,"LINKS",0,0) { } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/** Handle /LINKS + */ +CmdResult CommandLinks::Handle (const std::vector&, User *user) +{ + user->WriteNumeric(RPL_LINKS, "%s %s :0 %s", ServerInstance->Config->ServerName.c_str(),ServerInstance->Config->ServerName.c_str(),ServerInstance->Config->ServerDesc.c_str()); + user->WriteNumeric(RPL_ENDOFLINKS, "* :End of /LINKS list."); + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandLinks) diff --git a/src/coremods/core_list.cpp b/src/coremods/core_list.cpp new file mode 100644 index 000000000..ceffae43a --- /dev/null +++ b/src/coremods/core_list.cpp @@ -0,0 +1,111 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /LIST. + */ +class CommandList : public Command +{ + ChanModeReference secretmode; + ChanModeReference privatemode; + + public: + /** Constructor for list. + */ + CommandList(Module* parent) + : Command(parent,"LIST", 0, 0) + , secretmode(creator, "secret") + , privatemode(creator, "private") + { + Penalty = 5; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + + +/** Handle /LIST + */ +CmdResult CommandList::Handle (const std::vector& parameters, User *user) +{ + int minusers = 0, maxusers = 0; + + user->WriteNumeric(RPL_LISTSTART, "Channel :Users Name"); + + /* Work around mIRC suckyness. YOU SUCK, KHALED! */ + if (parameters.size() == 1) + { + if (parameters[0][0] == '<') + { + maxusers = atoi((parameters[0].c_str())+1); + } + else if (parameters[0][0] == '>') + { + minusers = atoi((parameters[0].c_str())+1); + } + } + + for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++) + { + // attempt to match a glob pattern + long users = i->second->GetUserCounter(); + + bool too_few = (minusers && (users <= minusers)); + bool too_many = (maxusers && (users >= maxusers)); + + if (too_many || too_few) + continue; + + if (parameters.size() && !parameters[0].empty() && (parameters[0][0] != '<' && parameters[0][0] != '>')) + { + if (!InspIRCd::Match(i->second->name, parameters[0]) && !InspIRCd::Match(i->second->topic, parameters[0])) + continue; + } + + // if the channel is not private/secret, OR the user is on the channel anyway + bool n = (i->second->HasUser(user) || user->HasPrivPermission("channels/auspex")); + + if (!n && i->second->IsModeSet(privatemode)) + { + /* Channel is +p and user is outside/not privileged */ + user->WriteNumeric(RPL_LIST, "* %ld :", users); + } + else + { + if (n || !i->second->IsModeSet(secretmode)) + { + /* User is in the channel/privileged, channel is not +s */ + user->WriteNumeric(RPL_LIST, "%s %ld :[+%s] %s",i->second->name.c_str(),users,i->second->ChanModes(n),i->second->topic.c_str()); + } + } + } + user->WriteNumeric(RPL_LISTEND, ":End of channel list."); + + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandList) diff --git a/src/coremods/core_loadmodule.cpp b/src/coremods/core_loadmodule.cpp new file mode 100644 index 000000000..458a8cd6f --- /dev/null +++ b/src/coremods/core_loadmodule.cpp @@ -0,0 +1,56 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /LOADMODULE. + */ +class CommandLoadmodule : public Command +{ + public: + /** Constructor for loadmodule. + */ + CommandLoadmodule ( Module* parent) : Command(parent,"LOADMODULE",1,1) { flags_needed='o'; syntax = ""; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/** Handle /LOADMODULE + */ +CmdResult CommandLoadmodule::Handle (const std::vector& parameters, User *user) +{ + if (ServerInstance->Modules->Load(parameters[0])) + { + ServerInstance->SNO->WriteGlobalSno('a', "NEW MODULE: %s loaded %s",user->nick.c_str(), parameters[0].c_str()); + user->WriteNumeric(RPL_LOADEDMODULE, "%s :Module successfully loaded.", parameters[0].c_str()); + return CMD_SUCCESS; + } + else + { + user->WriteNumeric(ERR_CANTLOADMODULE, "%s :%s", parameters[0].c_str(), ServerInstance->Modules->LastError().c_str()); + return CMD_FAILURE; + } +} + +COMMAND_INIT(CommandLoadmodule) diff --git a/src/coremods/core_lusers.cpp b/src/coremods/core_lusers.cpp new file mode 100644 index 000000000..e56b1c0bb --- /dev/null +++ b/src/coremods/core_lusers.cpp @@ -0,0 +1,172 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +struct LusersCounters +{ + unsigned int max_local; + unsigned int max_global; + unsigned int invisible; + + LusersCounters(unsigned int inv) + : max_local(ServerInstance->Users->LocalUserCount()) + , max_global(ServerInstance->Users->RegisteredUserCount()) + , invisible(inv) + { + } + + inline void UpdateMaxUsers() + { + unsigned int current = ServerInstance->Users->LocalUserCount(); + if (current > max_local) + max_local = current; + + current = ServerInstance->Users->RegisteredUserCount(); + if (current > max_global) + max_global = current; + } +}; + +/** Handle /LUSERS. + */ +class CommandLusers : public Command +{ + LusersCounters& counters; + public: + /** Constructor for lusers. + */ + CommandLusers(Module* parent, LusersCounters& Counters) + : Command(parent,"LUSERS",0,0), counters(Counters) + { } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/** Handle /LUSERS + */ +CmdResult CommandLusers::Handle (const std::vector&, User *user) +{ + unsigned int n_users = ServerInstance->Users->RegisteredUserCount(); + ProtocolInterface::ServerList serverlist; + ServerInstance->PI->GetServerList(serverlist); + unsigned int n_serv = serverlist.size(); + unsigned int n_local_servs = 0; + for (ProtocolInterface::ServerList::const_iterator i = serverlist.begin(); i != serverlist.end(); ++i) + { + if (i->parentname == ServerInstance->Config->ServerName) + n_local_servs++; + } + // fix for default GetServerList not returning us + if (!n_serv) + n_serv = 1; + + counters.UpdateMaxUsers(); + + user->WriteNumeric(RPL_LUSERCLIENT, ":There are %d users and %d invisible on %d servers", + n_users - counters.invisible, counters.invisible, n_serv); + + if (ServerInstance->Users->OperCount()) + user->WriteNumeric(RPL_LUSEROP, "%d :operator(s) online", ServerInstance->Users->OperCount()); + + if (ServerInstance->Users->UnregisteredUserCount()) + user->WriteNumeric(RPL_LUSERUNKNOWN, "%d :unknown connections", ServerInstance->Users->UnregisteredUserCount()); + + user->WriteNumeric(RPL_LUSERCHANNELS, "%ld :channels formed", ServerInstance->ChannelCount()); + user->WriteNumeric(RPL_LUSERME, ":I have %d clients and %d servers", ServerInstance->Users->LocalUserCount(),n_local_servs); + user->WriteNumeric(RPL_LOCALUSERS, ":Current Local Users: %d Max: %d", ServerInstance->Users->LocalUserCount(), counters.max_local); + user->WriteNumeric(RPL_GLOBALUSERS, ":Current Global Users: %d Max: %d", n_users, counters.max_global); + + return CMD_SUCCESS; +} + +class InvisibleWatcher : public ModeWatcher +{ + unsigned int& invisible; +public: + InvisibleWatcher(Module* mod, unsigned int& Invisible) + : ModeWatcher(mod, "invisible", MODETYPE_USER), invisible(Invisible) + { + } + + void AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding) + { + if (dest->registered != REG_ALL) + return; + + if (adding) + invisible++; + else + invisible--; + } +}; + +class ModuleLusers : public Module +{ + UserModeReference invisiblemode; + LusersCounters counters; + CommandLusers cmd; + InvisibleWatcher mw; + + unsigned int CountInvisible() + { + unsigned int c = 0; + for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); ++i) + { + User* u = i->second; + if (u->IsModeSet(invisiblemode)) + c++; + } + return c; + } + + public: + ModuleLusers() + : invisiblemode(this, "invisible") + , counters(CountInvisible()) + , cmd(this, counters) + , mw(this, counters.invisible) + { + } + + void OnPostConnect(User* user) + { + counters.UpdateMaxUsers(); + if (user->IsModeSet(invisiblemode)) + counters.invisible++; + } + + void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) + { + if (user->IsModeSet(invisiblemode)) + counters.invisible--; + } + + Version GetVersion() + { + return Version("LUSERS", VF_VENDOR | VF_CORE); + } +}; + +MODULE_INIT(ModuleLusers) diff --git a/src/coremods/core_oper/cmd_die.cpp b/src/coremods/core_oper/cmd_die.cpp new file mode 100644 index 000000000..63e4c596a --- /dev/null +++ b/src/coremods/core_oper/cmd_die.cpp @@ -0,0 +1,64 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /DIE. + */ +class CommandDie : public Command +{ + public: + /** Constructor for die. + */ + CommandDie ( Module* parent) : Command(parent,"DIE",1) { flags_needed = 'o'; syntax = ""; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +#include "exitcodes.h" + +/** Handle /DIE + */ +CmdResult CommandDie::Handle (const std::vector& parameters, User *user) +{ + if (ServerInstance->PassCompare(user, ServerInstance->Config->diepass, parameters[0], ServerInstance->Config->powerhash)) + { + { + std::string diebuf = "*** DIE command from " + user->GetFullHost() + ". Terminating."; + ServerInstance->Logs->Log("COMMAND", LOG_SPARSE, diebuf); + ServerInstance->SendError(diebuf); + } + + ServerInstance->Exit(EXIT_STATUS_DIE); + } + else + { + ServerInstance->Logs->Log("COMMAND", LOG_SPARSE, "Failed /DIE command from %s", user->GetFullRealHost().c_str()); + ServerInstance->SNO->WriteGlobalSno('a', "Failed DIE Command from %s.", user->GetFullRealHost().c_str()); + return CMD_FAILURE; + } + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandDie) diff --git a/src/coremods/core_oper/cmd_kill.cpp b/src/coremods/core_oper/cmd_kill.cpp new file mode 100644 index 000000000..454bab03f --- /dev/null +++ b/src/coremods/core_oper/cmd_kill.cpp @@ -0,0 +1,170 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2008 Craig Edwards + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /KILL. + */ +class CommandKill : public Command +{ + std::string lastuuid; + std::string killreason; + + public: + /** Constructor for kill. + */ + CommandKill ( Module* parent) : Command(parent,"KILL",2,2) { + flags_needed = 'o'; + syntax = " "; + TRANSLATE2(TR_CUSTOM, TR_CUSTOM); + } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + // FindNick() doesn't work here because we quit the target user in Handle() which + // removes it from the nicklist, so we check lastuuid: if it's empty then this KILL + // was for a local user, otherwise it contains the uuid of the user who was killed. + if (lastuuid.empty()) + return ROUTE_LOCALONLY; + return ROUTE_BROADCAST; + } + + void EncodeParameter(std::string& param, int index) + { + // Manually translate the nick -> uuid (see above), and also the reason (params[1]) + // because we decorate it if the oper is local and want remote servers to see the + // decorated reason not the original. + param = ((index == 0) ? lastuuid : killreason); + } +}; + +/** Handle /KILL + */ +CmdResult CommandKill::Handle (const std::vector& parameters, User *user) +{ + /* Allow comma seperated lists of users for /KILL (thanks w00t) */ + if (CommandParser::LoopCall(user, this, parameters, 0)) + { + // If we got a colon delimited list of nicks then the handler ran for each nick, + // and KILL commands were broadcast for remote targets. + return CMD_FAILURE; + } + + User *u = ServerInstance->FindNick(parameters[0]); + if ((u) && (!IS_SERVER(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 + */ + ModResult MOD_RESULT; + FIRST_MOD_RESULT(OnKill, MOD_RESULT, (user, u, parameters[1])); + + if (MOD_RESULT == MOD_RES_DENY) + return CMD_FAILURE; + + killreason = "Killed ("; + if (!ServerInstance->Config->HideKillsServer.empty()) + { + // hidekills is on, use it + killreason += ServerInstance->Config->HideKillsServer; + } + else + { + // hidekills is off, do nothing + killreason += user->nick; + } + + killreason += " (" + parameters[1] + "))"; + } + else + { + /* Leave it alone, remote server has already formatted it */ + killreason.assign(parameters[1], 0, ServerInstance->Config->Limits.MaxQuit); + } + + /* + * Now we need to decide whether or not to send a local or remote snotice. Currently this checking is a little flawed. + * No time to fix it right now, so left a note. -- w00t + */ + if (!IS_LOCAL(u)) + { + // remote kill + if (!user->server->IsULine()) + ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); + this->lastuuid = u->uuid; + } + 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 + */ + if (!user->server->IsULine()) + { + if (IS_LOCAL(user)) + ServerInstance->SNO->WriteGlobalSno('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); + else + ServerInstance->SNO->WriteToSnoMask('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); + } + + ServerInstance->Logs->Log("KILL", LOG_DEFAULT, "LOCAL KILL: %s :%s!%s!%s (%s)", u->nick.c_str(), ServerInstance->Config->ServerName.c_str(), user->dhost.c_str(), user->nick.c_str(), parameters[1].c_str()); + + u->Write(":%s KILL %s :%s!%s!%s (%s)", ServerInstance->Config->HideKillsServer.empty() ? user->GetFullHost().c_str() : ServerInstance->Config->HideKillsServer.c_str(), + u->nick.c_str(), + ServerInstance->Config->ServerName.c_str(), + user->dhost.c_str(), + ServerInstance->Config->HideKillsServer.empty() ? user->nick.c_str() : ServerInstance->Config->HideKillsServer.c_str(), + parameters[1].c_str()); + + this->lastuuid.clear(); + } + + // send the quit out + ServerInstance->Users->QuitUser(u, killreason); + } + else + { + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); + return CMD_FAILURE; + } + + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandKill) diff --git a/src/coremods/core_oper/cmd_oper.cpp b/src/coremods/core_oper/cmd_oper.cpp new file mode 100644 index 000000000..bd7a35060 --- /dev/null +++ b/src/coremods/core_oper/cmd_oper.cpp @@ -0,0 +1,83 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2008 Thomas Stagner + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /OPER. + */ +class CommandOper : public SplitCommand +{ + public: + /** Constructor for oper. + */ + CommandOper ( Module* parent) : SplitCommand(parent,"OPER",2,2) { syntax = " "; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult HandleLocal(const std::vector& parameters, LocalUser *user); +}; + +CmdResult CommandOper::HandleLocal(const std::vector& parameters, LocalUser *user) +{ + bool match_login = false; + bool match_pass = false; + bool match_hosts = false; + + const std::string userHost = user->ident + "@" + user->host; + const std::string userIP = user->ident + "@" + user->GetIPString(); + + OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]); + if (i != ServerInstance->Config->oper_blocks.end()) + { + OperInfo* ifo = i->second; + ConfigTag* tag = ifo->oper_block; + match_login = true; + match_pass = ServerInstance->PassCompare(user, tag->getString("password"), parameters[1], tag->getString("hash")); + match_hosts = InspIRCd::MatchMask(tag->getString("host"), userHost, userIP); + + if (match_pass && match_hosts) + { + /* found this oper's opertype */ + user->Oper(ifo); + return CMD_SUCCESS; + } + } + + std::string fields; + if (!match_login) + fields.append("login "); + if (!match_pass) + fields.append("password "); + if (!match_hosts) + fields.append("hosts"); + + // tell them they suck, and lag them up to help prevent brute-force attacks + user->WriteNumeric(ERR_NOOPERHOST, ":Invalid oper credentials"); + user->CommandFloodPenalty += 10000; + + ServerInstance->SNO->WriteGlobalSno('o', "WARNING! Failed oper attempt by %s using login '%s': The following fields do not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str()); + ServerInstance->Logs->Log("OPER", LOG_DEFAULT, "OPER: Failed oper attempt by %s using login '%s': The following fields did not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str()); + return CMD_FAILURE; +} + +COMMAND_INIT(CommandOper) diff --git a/src/coremods/core_oper/cmd_rehash.cpp b/src/coremods/core_oper/cmd_rehash.cpp new file mode 100644 index 000000000..f71219f75 --- /dev/null +++ b/src/coremods/core_oper/cmd_rehash.cpp @@ -0,0 +1,104 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * Copyright (C) 2008 Craig Edwards + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /REHASH. + */ +class CommandRehash : public Command +{ + public: + /** Constructor for rehash. + */ + CommandRehash ( Module* parent) : Command(parent,"REHASH",0) { flags_needed = 'o'; Penalty = 2; syntax = "[]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandRehash::Handle (const std::vector& parameters, User *user) +{ + std::string param = parameters.size() ? parameters[0] : ""; + + FOREACH_MOD(OnPreRehash, (user, param)); + + if (param.empty()) + { + // standard rehash of local server + } + else if (param.find_first_of("*.") != std::string::npos) + { + // rehash of servers by server name (with wildcard) + if (!InspIRCd::Match(ServerInstance->Config->ServerName, parameters[0])) + { + // Doesn't match us. PreRehash is already done, nothing left to do + return CMD_SUCCESS; + } + } + else + { + // parameterized rehash + + // the leading "-" is optional; remove it if present. + if (param[0] == '-') + param = param.substr(1); + + FOREACH_MOD(OnModuleRehash, (user, param)); + return CMD_SUCCESS; + } + + // Rehash for me. Try to start the rehash thread + if (!ServerInstance->ConfigThread) + { + std::string m = user->nick + " is rehashing config file " + FileSystem::GetFileName(ServerInstance->ConfigFileName) + " on " + ServerInstance->Config->ServerName; + ServerInstance->SNO->WriteGlobalSno('a', m); + + if (IS_LOCAL(user)) + user->WriteNumeric(RPL_REHASHING, "%s :Rehashing", FileSystem::GetFileName(ServerInstance->ConfigFileName).c_str()); + else + ServerInstance->PI->SendUserNotice(user, "*** Rehashing server " + FileSystem::GetFileName(ServerInstance->ConfigFileName)); + + /* Don't do anything with the logs here -- logs are restarted + * after the config thread has completed. + */ + ServerInstance->Rehash(user->uuid); + } + else + { + /* + * A rehash is already in progress! ahh shit. + * XXX, todo: we should find some way to kill runaway rehashes that are blocking, this is a major problem for unrealircd users + */ + if (IS_LOCAL(user)) + user->WriteNotice("*** Could not rehash: A rehash is already in progress."); + else + ServerInstance->PI->SendUserNotice(user, "*** Could not rehash: A rehash is already in progress."); + } + + // Always return success so spanningtree forwards an incoming REHASH even if we failed + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandRehash) diff --git a/src/coremods/core_oper/cmd_restart.cpp b/src/coremods/core_oper/cmd_restart.cpp new file mode 100644 index 000000000..33627b540 --- /dev/null +++ b/src/coremods/core_oper/cmd_restart.cpp @@ -0,0 +1,75 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /RESTART + */ +class CommandRestart : public Command +{ + public: + /** Constructor for restart. + */ + CommandRestart(Module* parent) : Command(parent,"RESTART",1,1) { flags_needed = 'o'; syntax = ""; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandRestart::Handle (const std::vector& parameters, User *user) +{ + ServerInstance->Logs->Log("COMMAND", LOG_DEFAULT, "Restart: %s",user->nick.c_str()); + if (ServerInstance->PassCompare(user, ServerInstance->Config->restartpass, parameters[0], ServerInstance->Config->powerhash)) + { + ServerInstance->SNO->WriteGlobalSno('a', "RESTART command from %s, restarting server.", user->GetFullRealHost().c_str()); + + ServerInstance->SendError("Server restarting."); + +#ifndef _WIN32 + /* XXX: This hack sets FD_CLOEXEC on all possible file descriptors, so they're closed if the execv() below succeeds. + * Certainly, this is not a nice way to do things and it's slow when the fd limit is high. + * + * A better solution would be to set the close-on-exec flag for each fd we create (or create them with O_CLOEXEC), + * however there is no guarantee that third party libs will do the same. + */ + for (int i = getdtablesize(); --i > 2;) + { + int flags = fcntl(i, F_GETFD); + if (flags != -1) + fcntl(i, F_SETFD, flags | FD_CLOEXEC); + } +#endif + + execv(ServerInstance->Config->cmdline.argv[0], ServerInstance->Config->cmdline.argv); + ServerInstance->SNO->WriteGlobalSno('a', "Failed RESTART - could not execute '%s' (%s)", + ServerInstance->Config->cmdline.argv[0], strerror(errno)); + } + else + { + ServerInstance->SNO->WriteGlobalSno('a', "Failed RESTART Command from %s.", user->GetFullRealHost().c_str()); + } + return CMD_FAILURE; +} + + +COMMAND_INIT(CommandRestart) diff --git a/src/coremods/core_privmsg.cpp b/src/coremods/core_privmsg.cpp new file mode 100644 index 000000000..0cca56771 --- /dev/null +++ b/src/coremods/core_privmsg.cpp @@ -0,0 +1,278 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007-2008 Craig Edwards + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +namespace +{ + const char* MessageTypeString[] = { "PRIVMSG", "NOTICE" }; +} + +class MessageCommandBase : public Command +{ + ChanModeReference moderatedmode; + ChanModeReference noextmsgmode; + + public: + MessageCommandBase(Module* parent, MessageType mt) + : Command(parent, MessageTypeString[mt], 2, 2) + , moderatedmode(parent, "moderated") + , noextmsgmode(parent, "noextmsg") + { + syntax = "{,} "; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult HandleMessage(const std::vector& parameters, User* user, MessageType mt); + + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + if (IS_LOCAL(user)) + // This is handled by the OnUserMessage hook to split the LoopCall pieces + return ROUTE_LOCALONLY; + else + return ROUTE_MESSAGE(parameters[0]); + } +}; + +CmdResult MessageCommandBase::HandleMessage(const std::vector& parameters, User* user, MessageType mt) +{ + User *dest; + Channel *chan; + CUList except_list; + + LocalUser* localuser = IS_LOCAL(user); + if (localuser) + localuser->idle_lastmsg = ServerInstance->Time(); + + if (CommandParser::LoopCall(user, this, parameters, 0)) + return CMD_SUCCESS; + + if (parameters[0][0] == '$') + { + if (!user->HasPrivPermission("users/mass-message")) + return CMD_SUCCESS; + + ModResult MOD_RESULT; + std::string temp = parameters[1]; + FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, except_list, mt)); + if (MOD_RESULT == MOD_RES_DENY) + return CMD_FAILURE; + + const char* text = temp.c_str(); + const char* servermask = (parameters[0].c_str()) + 1; + + FOREACH_MOD(OnText, (user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list)); + if (InspIRCd::Match(ServerInstance->Config->ServerName, servermask, NULL)) + { + user->SendAll(MessageTypeString[mt], "%s", text); + } + FOREACH_MOD(OnUserMessage, (user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list, mt)); + return CMD_SUCCESS; + } + char status = 0; + const char* target = parameters[0].c_str(); + + if (ServerInstance->Modes->FindPrefix(*target)) + { + status = *target; + target++; + } + if (*target == '#') + { + chan = ServerInstance->FindChan(target); + + except_list.insert(user); + + if (chan) + { + if (localuser && chan->GetPrefixValue(user) < VOICE_VALUE) + { + if (chan->IsModeSet(noextmsgmode) && !chan->HasUser(user)) + { + user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (no external messages)", chan->name.c_str()); + return CMD_FAILURE; + } + + if (chan->IsModeSet(moderatedmode)) + { + user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (+m)", chan->name.c_str()); + return CMD_FAILURE; + } + + if (ServerInstance->Config->RestrictBannedUsers) + { + if (chan->IsBanned(user)) + { + user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (you're banned)", chan->name.c_str()); + return CMD_FAILURE; + } + } + } + ModResult MOD_RESULT; + + std::string temp = parameters[1]; + FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, chan, TYPE_CHANNEL, temp, status, except_list, mt)); + if (MOD_RESULT == MOD_RES_DENY) + return CMD_FAILURE; + + const char* text = temp.c_str(); + + /* Check again, a module may have zapped the input string */ + if (temp.empty()) + { + user->WriteNumeric(ERR_NOTEXTTOSEND, ":No text to send"); + return CMD_FAILURE; + } + + FOREACH_MOD(OnText, (user,chan,TYPE_CHANNEL,text,status,except_list)); + + if (status) + { + if (ServerInstance->Config->UndernetMsgPrefix) + { + chan->WriteAllExcept(user, false, status, except_list, "%s %c%s :%c %s", MessageTypeString[mt], status, chan->name.c_str(), status, text); + } + else + { + chan->WriteAllExcept(user, false, status, except_list, "%s %c%s :%s", MessageTypeString[mt], status, chan->name.c_str(), text); + } + } + else + { + chan->WriteAllExcept(user, false, status, except_list, "%s %s :%s", MessageTypeString[mt], chan->name.c_str(), text); + } + + FOREACH_MOD(OnUserMessage, (user,chan, TYPE_CHANNEL, text, status, except_list, mt)); + } + else + { + /* no such nick/channel */ + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", target); + return CMD_FAILURE; + } + return CMD_SUCCESS; + } + + const char* destnick = parameters[0].c_str(); + + if (localuser) + { + const char* targetserver = strchr(destnick, '@'); + + if (targetserver) + { + std::string nickonly; + + nickonly.assign(destnick, 0, targetserver - destnick); + dest = ServerInstance->FindNickOnly(nickonly); + if (dest && strcasecmp(dest->server->GetName().c_str(), targetserver + 1)) + { + /* Incorrect server for user */ + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); + return CMD_FAILURE; + } + } + else + dest = ServerInstance->FindNickOnly(destnick); + } + else + dest = ServerInstance->FindNick(destnick); + + if ((dest) && (dest->registered == REG_ALL)) + { + if (parameters[1].empty()) + { + user->WriteNumeric(ERR_NOTEXTTOSEND, ":No text to send"); + return CMD_FAILURE; + } + + if ((dest->IsAway()) && (mt == MSG_PRIVMSG)) + { + /* auto respond with aweh msg */ + user->WriteNumeric(RPL_AWAY, "%s :%s", dest->nick.c_str(), dest->awaymsg.c_str()); + } + + ModResult MOD_RESULT; + + std::string temp = parameters[1]; + FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, dest, TYPE_USER, temp, 0, except_list, mt)); + if (MOD_RESULT == MOD_RES_DENY) + return CMD_FAILURE; + + const char* text = temp.c_str(); + + FOREACH_MOD(OnText, (user, dest, TYPE_USER, text, 0, except_list)); + + if (IS_LOCAL(dest)) + { + // direct write, same server + user->WriteTo(dest, "%s %s :%s", MessageTypeString[mt], dest->nick.c_str(), text); + } + + FOREACH_MOD(OnUserMessage, (user, dest, TYPE_USER, text, 0, except_list, mt)); + } + else + { + /* no such nick/channel */ + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); + return CMD_FAILURE; + } + return CMD_SUCCESS; +} + +template +class CommandMessage : public MessageCommandBase +{ + public: + CommandMessage(Module* parent) + : MessageCommandBase(parent, MT) + { + } + + CmdResult Handle(const std::vector& parameters, User* user) + { + return HandleMessage(parameters, user, MT); + } +}; + +class ModuleCoreMessage : public Module +{ + CommandMessage CommandPrivmsg; + CommandMessage CommandNotice; + + public: + ModuleCoreMessage() + : CommandPrivmsg(this), CommandNotice(this) + { + } + + Version GetVersion() + { + return Version("PRIVMSG, NOTICE", VF_CORE|VF_VENDOR); + } +}; + +MODULE_INIT(ModuleCoreMessage) diff --git a/src/coremods/core_reloadmodule.cpp b/src/coremods/core_reloadmodule.cpp new file mode 100644 index 000000000..765c465fd --- /dev/null +++ b/src/coremods/core_reloadmodule.cpp @@ -0,0 +1,78 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +class CommandReloadmodule : public Command +{ + public: + /** Constructor for reloadmodule. + */ + CommandReloadmodule ( Module* parent) : Command( parent, "RELOADMODULE",1) { flags_needed = 'o'; syntax = ""; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +class ReloadModuleWorker : public HandlerBase1 +{ + public: + const std::string name; + const std::string uid; + ReloadModuleWorker(const std::string& uuid, const std::string& modn) + : name(modn), uid(uuid) {} + void Call(bool result) + { + ServerInstance->SNO->WriteGlobalSno('a', "RELOAD MODULE: %s %ssuccessfully reloaded", + name.c_str(), result ? "" : "un"); + User* user = ServerInstance->FindNick(uid); + if (user) + user->WriteNumeric(RPL_LOADEDMODULE, "%s :Module %ssuccessfully reloaded.", + name.c_str(), result ? "" : "un"); + ServerInstance->GlobalCulls.AddItem(this); + } +}; + +CmdResult CommandReloadmodule::Handle (const std::vector& parameters, User *user) +{ + if (parameters[0] == "cmd_reloadmodule.so") + { + user->WriteNumeric(RPL_LOADEDMODULE, "%s :You cannot reload cmd_reloadmodule.so (unload and load it)", + parameters[0].c_str()); + return CMD_FAILURE; + } + + Module* m = ServerInstance->Modules->Find(parameters[0]); + if (m) + { + ServerInstance->Modules->Reload(m, new ReloadModuleWorker(user->uuid, parameters[0])); + return CMD_SUCCESS; + } + else + { + user->WriteNumeric(RPL_LOADEDMODULE, "%s :Could not find module by that name", parameters[0].c_str()); + return CMD_FAILURE; + } +} + +COMMAND_INIT(CommandReloadmodule) diff --git a/src/coremods/core_server.cpp b/src/coremods/core_server.cpp new file mode 100644 index 000000000..8c32dafa8 --- /dev/null +++ b/src/coremods/core_server.cpp @@ -0,0 +1,52 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /SERVER. + */ +class CommandServer : public Command +{ + public: + /** Constructor for server. + */ + CommandServer ( Module* parent) : Command(parent,"SERVER") { works_before_reg = true;} + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandServer::Handle (const std::vector&, User *user) +{ + if (user->registered == REG_ALL) + { + user->WriteNumeric(ERR_ALREADYREGISTERED, ":You are already registered. (Perhaps your IRC client does not have a /SERVER command)."); + } + else + { + user->WriteNumeric(ERR_NOTREGISTERED, ":You may not register as a server (servers have separate ports from clients, change your config)"); + } + return CMD_FAILURE; +} + +COMMAND_INIT(CommandServer) diff --git a/src/coremods/core_squit.cpp b/src/coremods/core_squit.cpp new file mode 100644 index 000000000..e64f5fc0f --- /dev/null +++ b/src/coremods/core_squit.cpp @@ -0,0 +1,51 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /SQUIT. + */ +class CommandSquit : public Command +{ + public: + /** Constructor for squit. + */ + CommandSquit ( Module* parent) : Command(parent,"SQUIT",1,2) { flags_needed = 'o'; syntax = " []"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + + +/* + * This is handled by the server linking module, if necessary. Do not remove this stub. + */ + + +CmdResult CommandSquit::Handle (const std::vector&, User *user) +{ + user->WriteServ( "NOTICE %s :Look into loading a linking module (like m_spanningtree) if you want this to do anything useful.", user->nick.c_str()); + return CMD_FAILURE; +} + +COMMAND_INIT(CommandSquit) diff --git a/src/coremods/core_stats.cpp b/src/coremods/core_stats.cpp new file mode 100644 index 000000000..8e74b8376 --- /dev/null +++ b/src/coremods/core_stats.cpp @@ -0,0 +1,406 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2007-2008 Craig Edwards + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "xline.h" + +#ifdef _WIN32 +#include +#pragma comment(lib, "psapi.lib") // For GetProcessMemoryInfo() +#endif + +/** Handle /STATS. + */ +class CommandStats : public Command +{ + void DoStats(char statschar, User* user, string_list &results); + public: + /** Constructor for stats. + */ + CommandStats ( Module* parent) : Command(parent,"STATS",1,2) { syntax = " []"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + if (parameters.size() > 1) + return ROUTE_UNICAST(parameters[1]); + return ROUTE_LOCALONLY; + } +}; + +void CommandStats::DoStats(char statschar, User* user, string_list &results) +{ + bool isPublic = ServerInstance->Config->UserStats.find(statschar) != std::string::npos; + bool isRemoteOper = IS_REMOTE(user) && (user->IsOper()); + bool isLocalOperWithPrivs = IS_LOCAL(user) && user->HasPrivPermission("servers/auspex"); + + if (!isPublic && !isRemoteOper && !isLocalOperWithPrivs) + { + ServerInstance->SNO->WriteToSnoMask('t', + "%s '%c' denied for %s (%s@%s)", + (IS_LOCAL(user) ? "Stats" : "Remote stats"), + statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); + results.push_back("481 " + user->nick + " :Permission denied - STATS " + statschar + " requires the servers/auspex priv."); + return; + } + + ModResult MOD_RESULT; + FIRST_MOD_RESULT(OnStats, MOD_RESULT, (statschar, user, results)); + if (MOD_RESULT == MOD_RES_DENY) + { + results.push_back("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.c_str(), user->ident.c_str(), user->host.c_str()); + return; + } + + switch (statschar) + { + /* stats p (show listening ports) */ + case 'p': + { + for (std::vector::const_iterator i = ServerInstance->ports.begin(); i != ServerInstance->ports.end(); ++i) + { + ListenSocket* ls = *i; + std::string ip = ls->bind_addr; + if (ip.empty()) + ip.assign("*"); + std::string type = ls->bind_tag->getString("type", "clients"); + std::string hook = ls->bind_tag->getString("ssl", "plaintext"); + + results.push_back("249 "+user->nick+" :"+ ip + ":"+ConvToStr(ls->bind_port)+ + " (" + type + ", " + hook + ")"); + } + } + break; + + /* These stats symbols must be handled by a linking module */ + case 'n': + case 'c': + break; + + case 'i': + { + for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) + { + ConnectClass* c = *i; + std::stringstream res; + res << "215 " << user->nick << " I " << c->name << ' '; + if (c->type == CC_ALLOW) + res << '+'; + if (c->type == CC_DENY) + res << '-'; + + if (c->type == CC_NAMED) + res << '*'; + else + res << c->host; + + res << ' ' << c->config->getString("port", "*") << ' '; + + res << c->GetRecvqMax() << ' ' << c->GetSendqSoftMax() << ' ' << c->GetSendqHardMax() + << ' ' << c->GetCommandRate() << ' ' << c->GetPenaltyThreshold(); + if (c->fakelag) + res << '*'; + results.push_back(res.str()); + } + } + break; + + case 'Y': + { + int idx = 0; + for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) + { + ConnectClass* c = *i; + results.push_back("215 "+user->nick+" i NOMATCH * "+c->GetHost()+" "+ConvToStr(c->limit ? c->limit : SocketEngine::GetMaxFds())+" "+ConvToStr(idx)+" "+ServerInstance->Config->ServerName+" *"); + results.push_back("218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqHardMax())+" :"+ + ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout())); + idx++; + } + } + break; + + case 'P': + { + unsigned int idx = 0; + for (std::list::const_iterator i = ServerInstance->Users->all_opers.begin(); i != ServerInstance->Users->all_opers.end(); ++i) + { + User* oper = *i; + if (!oper->server->IsULine()) + { + LocalUser* lu = IS_LOCAL(oper); + results.push_back("249 " + user->nick + " :" + oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " + + (lu ? ConvToStr(ServerInstance->Time() - lu->idle_lastmsg) + " secs" : "unavailable")); + idx++; + } + } + results.push_back("249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)"); + } + break; + + case 'k': + ServerInstance->XLines->InvokeStats("K",216,user,results); + break; + case 'g': + ServerInstance->XLines->InvokeStats("G",223,user,results); + break; + case 'q': + ServerInstance->XLines->InvokeStats("Q",217,user,results); + break; + case 'Z': + ServerInstance->XLines->InvokeStats("Z",223,user,results); + break; + case 'e': + ServerInstance->XLines->InvokeStats("E",223,user,results); + break; + case 'E': + { + const SocketEngine::Statistics& stats = SocketEngine::GetStats(); + results.push_back("249 "+user->nick+" :Total events: "+ConvToStr(stats.TotalEvents)); + results.push_back("249 "+user->nick+" :Read events: "+ConvToStr(stats.ReadEvents)); + results.push_back("249 "+user->nick+" :Write events: "+ConvToStr(stats.WriteEvents)); + results.push_back("249 "+user->nick+" :Error events: "+ConvToStr(stats.ErrorEvents)); + break; + } + + /* stats m (list number of times each command has been used, plus bytecount) */ + case 'm': + for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) + { + if (i->second->use_count) + { + /* RPL_STATSCOMMANDS */ + results.push_back("212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count)); + } + } + break; + + /* stats z (debug and memory info) */ + case 'z': + { + results.push_back("249 "+user->nick+" :Users: "+ConvToStr(ServerInstance->Users->clientlist->size())); + results.push_back("249 "+user->nick+" :Channels: "+ConvToStr(ServerInstance->chanlist->size())); + results.push_back("249 "+user->nick+" :Commands: "+ConvToStr(ServerInstance->Parser->cmdlist.size())); + + float kbitpersec_in, kbitpersec_out, kbitpersec_total; + char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30]; + + SocketEngine::GetStats().GetBandwidth(kbitpersec_in, kbitpersec_out, kbitpersec_total); + + snprintf(kbitpersec_total_s, 30, "%03.5f", kbitpersec_total); + snprintf(kbitpersec_out_s, 30, "%03.5f", kbitpersec_out); + snprintf(kbitpersec_in_s, 30, "%03.5f", kbitpersec_in); + + results.push_back("249 "+user->nick+" :Bandwidth total: "+ConvToStr(kbitpersec_total_s)+" kilobits/sec"); + results.push_back("249 "+user->nick+" :Bandwidth out: "+ConvToStr(kbitpersec_out_s)+" kilobits/sec"); + results.push_back("249 "+user->nick+" :Bandwidth in: "+ConvToStr(kbitpersec_in_s)+" kilobits/sec"); + +#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("249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K"); + results.push_back("249 "+user->nick+" :Signals: "+ConvToStr(R.ru_nsignals)); + results.push_back("249 "+user->nick+" :Page faults: "+ConvToStr(R.ru_majflt)); + results.push_back("249 "+user->nick+" :Swaps: "+ConvToStr(R.ru_nswap)); + results.push_back("249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw)); + + char percent[30]; + + float n_elapsed = (ServerInstance->Time() - ServerInstance->stats->LastSampled.tv_sec) * 1000000 + + (ServerInstance->Time_ns() - ServerInstance->stats->LastSampled.tv_nsec) / 1000; + 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("249 "+user->nick+" :CPU Use (now): "+percent); + + n_elapsed = ServerInstance->Time() - ServerInstance->startup_time; + n_eaten = (float)R.ru_utime.tv_sec + R.ru_utime.tv_usec / 100000.0; + per = (n_eaten / n_elapsed) * 100; + snprintf(percent, 30, "%03.5f%%", per); + results.push_back("249 "+user->nick+" :CPU Use (total): "+percent); + } +#else + PROCESS_MEMORY_COUNTERS MemCounters; + if (GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters))) + { + results.push_back("249 "+user->nick+" :Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K"); + results.push_back("249 "+user->nick+" :Pagefile usage: "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K"); + results.push_back("249 "+user->nick+" :Page faults: "+ConvToStr(MemCounters.PageFaultCount)); + } + + FILETIME CreationTime; + FILETIME ExitTime; + FILETIME KernelTime; + FILETIME UserTime; + LARGE_INTEGER ThisSample; + if(GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime) && + QueryPerformanceCounter(&ThisSample)) + { + KernelTime.dwHighDateTime += UserTime.dwHighDateTime; + KernelTime.dwLowDateTime += UserTime.dwLowDateTime; + double n_eaten = (double)( ( (uint64_t)(KernelTime.dwHighDateTime - ServerInstance->stats->LastCPU.dwHighDateTime) << 32 ) + (uint64_t)(KernelTime.dwLowDateTime - ServerInstance->stats->LastCPU.dwLowDateTime) )/100000; + double n_elapsed = (double)(ThisSample.QuadPart - ServerInstance->stats->LastSampled.QuadPart) / ServerInstance->stats->QPFrequency.QuadPart; + double per = (n_eaten/n_elapsed); + + char percent[30]; + + snprintf(percent, 30, "%03.5f%%", per); + results.push_back("249 "+user->nick+" :CPU Use (now): "+percent); + + n_elapsed = ServerInstance->Time() - ServerInstance->startup_time; + n_eaten = (double)(( (uint64_t)(KernelTime.dwHighDateTime) << 32 ) + (uint64_t)(KernelTime.dwLowDateTime))/100000; + per = (n_eaten / n_elapsed); + snprintf(percent, 30, "%03.5f%%", per); + results.push_back("249 "+user->nick+" :CPU Use (total): "+percent); + } +#endif + } + break; + + case 'T': + { + results.push_back("249 "+user->nick+" :accepts "+ConvToStr(ServerInstance->stats->statsAccept)+" refused "+ConvToStr(ServerInstance->stats->statsRefused)); + results.push_back("249 "+user->nick+" :unknown commands "+ConvToStr(ServerInstance->stats->statsUnknown)); + results.push_back("249 "+user->nick+" :nick collisions "+ConvToStr(ServerInstance->stats->statsCollisions)); + results.push_back("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("249 "+user->nick+" :connection count "+ConvToStr(ServerInstance->stats->statsConnects)); + results.push_back(InspIRCd::Format("249 %s :bytes sent %5.2fK recv %5.2fK", user->nick.c_str(), + ServerInstance->stats->statsSent / 1024.0, ServerInstance->stats->statsRecv / 1024.0)); + } + break; + + /* stats o */ + case 'o': + { + ConfigTagList tags = ServerInstance->Config->ConfTags("oper"); + for(ConfigIter i = tags.first; i != tags.second; ++i) + { + ConfigTag* tag = i->second; + results.push_back("243 "+user->nick+" O "+tag->getString("host")+" * "+ + tag->getString("name") + " " + tag->getString("type")+" 0"); + } + } + break; + case 'O': + { + for (OperIndex::const_iterator i = ServerInstance->Config->OperTypes.begin(); i != ServerInstance->Config->OperTypes.end(); ++i) + { + OperInfo* tag = i->second; + tag->init(); + std::string umodes; + std::string cmodes; + for(char c='A'; c < 'z'; c++) + { + ModeHandler* mh = ServerInstance->Modes->FindMode(c, MODETYPE_USER); + if (mh && mh->NeedsOper() && tag->AllowedUserModes[c - 'A']) + umodes.push_back(c); + mh = ServerInstance->Modes->FindMode(c, MODETYPE_CHANNEL); + if (mh && mh->NeedsOper() && tag->AllowedChanModes[c - 'A']) + cmodes.push_back(c); + } + results.push_back("243 "+user->nick+" O "+tag->name.c_str() + " " + umodes + " " + cmodes); + } + } + break; + + /* stats l (show user I/O stats) */ + case 'l': + results.push_back("211 "+user->nick+" :nick[ident@host] sendq cmds_out bytes_out cmds_in bytes_in time_open"); + for (LocalUserList::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) + { + LocalUser* i = *n; + results.push_back("211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->eh.getSendQSize())+" "+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("211 "+user->nick+" :nick[ident@ip] sendq cmds_out bytes_out cmds_in bytes_in time_open"); + for (LocalUserList::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) + { + LocalUser* i = *n; + results.push_back("211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->eh.getSendQSize())+" "+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) + { + results.push_back(InspIRCd::Format("242 %s :Server up %d years, %d days, %.2d:%.2d:%.2d", + user->nick.c_str(), stime->tm_year - 70, stime->tm_yday, stime->tm_hour, + stime->tm_min, stime->tm_sec)); + } + else + { + results.push_back(InspIRCd::Format("242 %s :Server up %d days, %.2d:%.2d:%.2d", + user->nick.c_str(), stime->tm_yday, stime->tm_hour, stime->tm_min, + stime->tm_sec)); + } + } + break; + + default: + break; + } + + results.push_back("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.c_str(), user->ident.c_str(), user->host.c_str()); + return; +} + +CmdResult CommandStats::Handle (const std::vector& parameters, User *user) +{ + if (parameters.size() > 1 && parameters[1] != ServerInstance->Config->ServerName) + return CMD_SUCCESS; + string_list values; + char search = parameters[0][0]; + DoStats(search, user, values); + + const std::string p = ":" + ServerInstance->Config->ServerName + " "; + for (size_t i = 0; i < values.size(); i++) + user->SendText(p + values[i]); + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandStats) diff --git a/src/coremods/core_unloadmodule.cpp b/src/coremods/core_unloadmodule.cpp new file mode 100644 index 000000000..5d11e0256 --- /dev/null +++ b/src/coremods/core_unloadmodule.cpp @@ -0,0 +1,70 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /UNLOADMODULE. + */ +class CommandUnloadmodule : public Command +{ + public: + /** Constructor for unloadmodule. + */ + CommandUnloadmodule ( Module* parent) : Command(parent,"UNLOADMODULE",1) { flags_needed = 'o'; syntax = ""; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandUnloadmodule::Handle (const std::vector& parameters, User *user) +{ + if (!ServerInstance->Config->ConfValue("security")->getBool("allowcoreunload") && + InspIRCd::Match(parameters[0], "cmd_*.so", ascii_case_insensitive_map)) + { + user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :You cannot unload core commands!", parameters[0].c_str()); + return CMD_FAILURE; + } + + if (parameters[0] == "cmd_unloadmodule.so" || parameters[0] == "cmd_loadmodule.so") + { + user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :You cannot unload module loading commands!", parameters[0].c_str()); + return CMD_FAILURE; + } + + Module* m = ServerInstance->Modules->Find(parameters[0]); + if (m && ServerInstance->Modules->Unload(m)) + { + ServerInstance->SNO->WriteGlobalSno('a', "MODULE UNLOADED: %s unloaded %s", user->nick.c_str(), parameters[0].c_str()); + user->WriteNumeric(RPL_UNLOADEDMODULE, "%s :Module successfully unloaded.", parameters[0].c_str()); + } + else + { + user->WriteNumeric(ERR_CANTUNLOADMODULE, "%s :%s", parameters[0].c_str(), + m ? ServerInstance->Modules->LastError().c_str() : "No such module"); + return CMD_FAILURE; + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandUnloadmodule) diff --git a/src/coremods/core_user/cmd_away.cpp b/src/coremods/core_user/cmd_away.cpp new file mode 100644 index 000000000..4f61cec3f --- /dev/null +++ b/src/coremods/core_user/cmd_away.cpp @@ -0,0 +1,75 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /AWAY. + */ +class CommandAway : public Command +{ + public: + /** Constructor for away. + */ + CommandAway ( Module* parent) : Command(parent,"AWAY",0,0) { syntax = "[]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); + } +}; + +/** Handle /AWAY + */ +CmdResult CommandAway::Handle (const std::vector& parameters, User *user) +{ + ModResult MOD_RESULT; + + if ((parameters.size()) && (!parameters[0].empty())) + { + FIRST_MOD_RESULT(OnSetAway, MOD_RESULT, (user, parameters[0])); + + if (MOD_RESULT == MOD_RES_DENY && IS_LOCAL(user)) + return CMD_FAILURE; + + user->awaytime = ServerInstance->Time(); + user->awaymsg.assign(parameters[0], 0, ServerInstance->Config->Limits.MaxAway); + + user->WriteNumeric(RPL_NOWAWAY, ":You have been marked as being away"); + } + else + { + FIRST_MOD_RESULT(OnSetAway, MOD_RESULT, (user, "")); + + if (MOD_RESULT == MOD_RES_DENY && IS_LOCAL(user)) + return CMD_FAILURE; + + user->awaymsg.clear(); + user->WriteNumeric(RPL_UNAWAY, ":You are no longer marked as being away"); + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandAway) diff --git a/src/coremods/core_user/cmd_mode.cpp b/src/coremods/core_user/cmd_mode.cpp new file mode 100644 index 000000000..d2e9b4f63 --- /dev/null +++ b/src/coremods/core_user/cmd_mode.cpp @@ -0,0 +1,53 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /MODE. + */ +class CommandMode : public Command +{ + public: + /** Constructor for mode. + */ + CommandMode ( Module* parent) : Command(parent,"MODE",1) { syntax = " {}"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); + } +}; + + +/** Handle /MODE + */ +CmdResult CommandMode::Handle (const std::vector& parameters, User *user) +{ + ServerInstance->Modes->Process(parameters, user, (IS_LOCAL(user) ? ModeParser::MODE_NONE : ModeParser::MODE_LOCALONLY)); + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandMode) diff --git a/src/coremods/core_user/cmd_nick.cpp b/src/coremods/core_user/cmd_nick.cpp new file mode 100644 index 000000000..486fce7eb --- /dev/null +++ b/src/coremods/core_user/cmd_nick.cpp @@ -0,0 +1,94 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2008 Craig Edwards + * Copyright (C) 2008 Thomas Stagner + * Copyright (C) 2007-2008 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /NICK. + */ +class CommandNick : public Command +{ + public: + /** Constructor for nick. + */ + CommandNick ( Module* parent) : Command(parent,"NICK", 1, 1) { works_before_reg = true; syntax = ""; Penalty = 0; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/** Handle nick changes from users. + * NOTE: If you are used to ircds based on ircd2.8, and are looking + * for the client introduction code in here, youre in the wrong place. + * You need to look in the spanningtree module for this! + */ +CmdResult CommandNick::Handle (const std::vector& parameters, User *user) +{ + std::string oldnick = user->nick; + std::string newnick = parameters[0]; + + // anything except the initial NICK gets a flood penalty + if (user->registered == REG_ALL && IS_LOCAL(user)) + IS_LOCAL(user)->CommandFloodPenalty += 4000; + + if (newnick.empty()) + { + user->WriteNumeric(ERR_ERRONEUSNICKNAME, "* :Erroneous Nickname"); + return CMD_FAILURE; + } + + if (newnick == "0") + { + newnick = user->uuid; + } + else if (!ServerInstance->IsNick(newnick)) + { + user->WriteNumeric(ERR_ERRONEUSNICKNAME, "%s :Erroneous Nickname", newnick.c_str()); + return CMD_FAILURE; + } + + if (!user->ChangeNick(newnick, false)) + return CMD_FAILURE; + + if (user->registered < REG_NICKUSER) + { + user->registered = (user->registered | REG_NICK); + if (user->registered == REG_NICKUSER) + { + /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ + ModResult MOD_RESULT; + FIRST_MOD_RESULT(OnUserRegister, MOD_RESULT, (IS_LOCAL(user))); + if (MOD_RESULT == MOD_RES_DENY) + return CMD_FAILURE; + + // return early to not penalize new users + return CMD_SUCCESS; + } + } + + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandNick) diff --git a/src/coremods/core_user/cmd_part.cpp b/src/coremods/core_user/cmd_part.cpp new file mode 100644 index 000000000..f427063ea --- /dev/null +++ b/src/coremods/core_user/cmd_part.cpp @@ -0,0 +1,78 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /PART. + */ +class CommandPart : public Command +{ + public: + /** Constructor for part. + */ + CommandPart (Module* parent) : Command(parent,"PART", 1, 2) { Penalty = 5; syntax = "{,} []"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); + } +}; + +CmdResult CommandPart::Handle (const std::vector& parameters, User *user) +{ + std::string reason; + + if (IS_LOCAL(user)) + { + if (!ServerInstance->Config->FixedPart.empty()) + reason = ServerInstance->Config->FixedPart; + else if (parameters.size() > 1) + reason = ServerInstance->Config->PrefixPart + parameters[1] + ServerInstance->Config->SuffixPart; + } + else + { + if (parameters.size() > 1) + reason = parameters[1]; + } + + if (CommandParser::LoopCall(user, this, parameters, 0)) + return CMD_SUCCESS; + + Channel* c = ServerInstance->FindChan(parameters[0]); + + if (c) + { + c->PartUser(user, reason); + } + else + { + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameters[0].c_str()); + return CMD_FAILURE; + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandPart) diff --git a/src/coremods/core_user/cmd_pass.cpp b/src/coremods/core_user/cmd_pass.cpp new file mode 100644 index 000000000..66b2b5726 --- /dev/null +++ b/src/coremods/core_user/cmd_pass.cpp @@ -0,0 +1,53 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /PASS. + */ +class CommandPass : public SplitCommand +{ + public: + /** Constructor for pass. + */ + CommandPass (Module* parent) : SplitCommand(parent,"PASS",1,1) { works_before_reg = true; Penalty = 0; syntax = ""; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult HandleLocal(const std::vector& parameters, LocalUser *user); +}; + + +CmdResult CommandPass::HandleLocal(const std::vector& parameters, LocalUser *user) +{ + // Check to make sure they haven't registered -- Fix by FCS + if (user->registered == REG_ALL) + { + user->WriteNumeric(ERR_ALREADYREGISTERED, ":You may not reregister"); + return CMD_FAILURE; + } + user->password = parameters[0]; + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandPass) diff --git a/src/coremods/core_user/cmd_ping.cpp b/src/coremods/core_user/cmd_ping.cpp new file mode 100644 index 000000000..06135f83c --- /dev/null +++ b/src/coremods/core_user/cmd_ping.cpp @@ -0,0 +1,45 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /PING. + */ +class CommandPing : public Command +{ + public: + /** Constructor for ping. + */ + CommandPing ( Module* parent) : Command(parent,"PING", 1, 2) { Penalty = 0; syntax = " [:]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandPing::Handle (const std::vector& parameters, User *user) +{ + user->WriteServ("PONG %s :%s", ServerInstance->Config->ServerName.c_str(), parameters[0].c_str()); + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandPing) diff --git a/src/coremods/core_user/cmd_pong.cpp b/src/coremods/core_user/cmd_pong.cpp new file mode 100644 index 000000000..06db92604 --- /dev/null +++ b/src/coremods/core_user/cmd_pong.cpp @@ -0,0 +1,47 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /PONG. + */ +class CommandPong : public Command +{ + public: + /** Constructor for pong. + */ + CommandPong ( Module* parent) : Command(parent,"PONG", 0, 1) { Penalty = 0; syntax = ""; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandPong::Handle (const std::vector&, User *user) +{ + // set the user as alive so they survive to next ping + if (IS_LOCAL(user)) + IS_LOCAL(user)->lastping = 1; + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandPong) diff --git a/src/coremods/core_user/cmd_quit.cpp b/src/coremods/core_user/cmd_quit.cpp new file mode 100644 index 000000000..15dc07d6c --- /dev/null +++ b/src/coremods/core_user/cmd_quit.cpp @@ -0,0 +1,68 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /QUIT. + */ +class CommandQuit : public Command +{ + public: + /** Constructor for quit. + */ + CommandQuit ( Module* parent) : Command(parent,"QUIT",0,1) { works_before_reg = true; syntax = "[]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); + } +}; + + +CmdResult CommandQuit::Handle (const std::vector& parameters, User *user) +{ + + std::string quitmsg; + + if (IS_LOCAL(user)) + { + if (!ServerInstance->Config->FixedQuit.empty()) + quitmsg = ServerInstance->Config->FixedQuit; + else + quitmsg = parameters.size() ? + ServerInstance->Config->PrefixQuit + parameters[0] + ServerInstance->Config->SuffixQuit + : "Client exited"; + } + else + quitmsg = parameters.size() ? parameters[0] : "Client exited"; + + std::string* operquit = ServerInstance->OperQuit.get(user); + ServerInstance->Users->QuitUser(user, quitmsg, operquit); + + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandQuit) diff --git a/src/coremods/core_user/cmd_user.cpp b/src/coremods/core_user/cmd_user.cpp new file mode 100644 index 000000000..cec11c104 --- /dev/null +++ b/src/coremods/core_user/cmd_user.cpp @@ -0,0 +1,86 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /USER. + */ +class CommandUser : public SplitCommand +{ + public: + /** Constructor for user. + */ + CommandUser ( Module* parent) : SplitCommand(parent,"USER",4,4) { works_before_reg = true; Penalty = 0; syntax = " "; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult HandleLocal(const std::vector& parameters, LocalUser *user); +}; + +CmdResult CommandUser::HandleLocal(const std::vector& parameters, LocalUser *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->WriteNumeric(ERR_NEEDMOREPARAMS, "USER :Your username is not valid"); + return CMD_FAILURE; + } + else + { + /* + * The ident field is IDENTMAX+2 in size to account for +1 for the optional + * ~ character, and +1 for null termination, therefore we can safely use up to + * IDENTMAX here. + */ + user->ChangeIdent(parameters[0]); + user->fullname.assign(parameters[3].empty() ? "No info" : parameters[3], 0, ServerInstance->Config->Limits.MaxGecos); + user->registered = (user->registered | REG_USER); + } + } + else + { + user->WriteNumeric(ERR_ALREADYREGISTERED, ":You may not reregister"); + return CMD_FAILURE; + } + + /* parameters 2 and 3 are local and remote hosts, and are ignored */ + if (user->registered == REG_NICKUSER) + { + ModResult MOD_RESULT; + + /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ + FIRST_MOD_RESULT(OnUserRegister, MOD_RESULT, (user)); + if (MOD_RESULT == MOD_RES_DENY) + return CMD_FAILURE; + + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandUser) diff --git a/src/coremods/core_userhost.cpp b/src/coremods/core_userhost.cpp new file mode 100644 index 000000000..541402c10 --- /dev/null +++ b/src/coremods/core_userhost.cpp @@ -0,0 +1,83 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /USERHOST. + */ +class CommandUserhost : public Command +{ + public: + /** Constructor for userhost. + */ + CommandUserhost ( Module* parent) : Command(parent,"USERHOST", 1, 5) { + syntax = " {}"; + } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandUserhost::Handle (const std::vector& parameters, User *user) +{ + std::string retbuf = "302 " + user->nick + " :"; + + for (unsigned int i = 0; i < parameters.size(); i++) + { + User *u = ServerInstance->FindNickOnly(parameters[i]); + + if ((u) && (u->registered == REG_ALL)) + { + retbuf = retbuf + u->nick; + + if (u->IsOper()) + retbuf = retbuf + "*"; + + retbuf = retbuf + "="; + + if (u->IsAway()) + retbuf += "-"; + else + retbuf += "+"; + + retbuf = retbuf + u->ident + "@"; + + if (user->HasPrivPermission("users/auspex")) + { + retbuf = retbuf + u->host; + } + else + { + retbuf = retbuf + u->dhost; + } + + retbuf = retbuf + " "; + } + } + + user->WriteServ(retbuf); + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandUserhost) diff --git a/src/coremods/core_wallops.cpp b/src/coremods/core_wallops.cpp new file mode 100644 index 000000000..731eaf3d2 --- /dev/null +++ b/src/coremods/core_wallops.cpp @@ -0,0 +1,68 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /WALLOPS. + */ +class CommandWallops : public Command +{ + UserModeReference wallopsmode; + + public: + /** Constructor for wallops. + */ + CommandWallops(Module* parent) + : Command(parent, "WALLOPS", 1, 1) + , wallopsmode(parent, "wallops") + { + flags_needed = 'o'; + syntax = ""; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + + RouteDescriptor GetRouting(User* user, const std::vector& parameters) + { + return ROUTE_BROADCAST; + } +}; + +CmdResult CommandWallops::Handle (const std::vector& parameters, User *user) +{ + std::string wallop("WALLOPS :"); + wallop.append(parameters[0]); + + for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); i++) + { + User* t = *i; + if (t->IsModeSet(wallopsmode)) + user->WriteTo(t,wallop); + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandWallops) diff --git a/src/coremods/core_who.cpp b/src/coremods/core_who.cpp new file mode 100644 index 000000000..dc39e296c --- /dev/null +++ b/src/coremods/core_who.cpp @@ -0,0 +1,395 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /WHO. + */ +class CommandWho : public Command +{ + bool CanView(Channel* chan, User* user); + bool opt_viewopersonly; + bool opt_showrealhost; + bool opt_realname; + bool opt_mode; + bool opt_ident; + bool opt_metadata; + bool opt_port; + bool opt_away; + bool opt_local; + bool opt_far; + bool opt_time; + ChanModeReference secretmode; + ChanModeReference privatemode; + UserModeReference invisiblemode; + + Membership* get_first_visible_channel(User* u) + { + for (UCListIter i = u->chans.begin(); i != u->chans.end(); ++i) + { + Membership* memb = *i; + if (!memb->chan->IsModeSet(secretmode)) + return memb; + } + return NULL; + } + + public: + /** Constructor for who. + */ + CommandWho(Module* parent) + : Command(parent, "WHO", 1) + , secretmode(parent, "secret") + , privatemode(parent, "private") + , invisiblemode(parent, "invisible") + { + syntax = "|||||0 [ohurmMiaplf]"; + } + + void SendWhoLine(User* user, const std::vector& parms, const std::string& initial, Membership* memb, User* u, std::vector& whoresults); + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); + bool whomatch(User* cuser, User* user, const char* matchtext); +}; + +bool CommandWho::whomatch(User* cuser, User* user, const char* matchtext) +{ + bool match = false; + bool positive = false; + + if (user->registered != REG_ALL) + return false; + + if (opt_local && !IS_LOCAL(user)) + return false; + else if (opt_far && IS_LOCAL(user)) + return false; + + if (opt_mode) + { + for (const char* n = matchtext; *n; n++) + { + if (*n == '+') + { + positive = true; + continue; + } + else if (*n == '-') + { + positive = false; + continue; + } + if (user->IsModeSet(*n) != positive) + return false; + } + return true; + } + else + { + /* + * This was previously one awesome pile of ugly nested if, when really, it didn't need + * to be, since only one condition was ever checked, a chained if works just fine. + * -- w00t + */ + if (opt_metadata) + { + match = false; + const Extensible::ExtensibleStore& list = user->GetExtList(); + for(Extensible::ExtensibleStore::const_iterator i = list.begin(); i != list.end(); ++i) + if (InspIRCd::Match(i->first->name, matchtext)) + match = true; + } + else if (opt_realname) + match = InspIRCd::Match(user->fullname, matchtext); + else if (opt_showrealhost) + match = InspIRCd::Match(user->host, matchtext, ascii_case_insensitive_map); + else if (opt_ident) + match = InspIRCd::Match(user->ident, matchtext, ascii_case_insensitive_map); + else if (opt_port) + { + irc::portparser portrange(matchtext, false); + long portno = -1; + while ((portno = portrange.GetToken())) + if (IS_LOCAL(user) && portno == IS_LOCAL(user)->GetServerPort()) + { + match = true; + break; + } + } + else if (opt_away) + match = InspIRCd::Match(user->awaymsg, matchtext); + else if (opt_time) + { + long seconds = InspIRCd::Duration(matchtext); + + // Okay, so time matching, we want all users connected `seconds' ago + if (user->age >= ServerInstance->Time() - seconds) + match = true; + } + + /* + * Once the conditionals have been checked, only check dhost/nick/server + * if they didn't match this user -- and only match if we don't find a match. + * + * This should make things minutely faster, and again, less ugly. + * -- w00t + */ + if (!match) + match = InspIRCd::Match(user->dhost, matchtext, ascii_case_insensitive_map); + + if (!match) + match = InspIRCd::Match(user->nick, matchtext); + + /* Don't allow server name matches if HideWhoisServer is enabled, unless the command user has the priv */ + if (!match && (ServerInstance->Config->HideWhoisServer.empty() || cuser->HasPrivPermission("users/auspex"))) + match = InspIRCd::Match(user->server->GetName(), matchtext); + + return match; + } +} + +bool CommandWho::CanView(Channel* chan, User* user) +{ + if (!user || !chan) + return false; + + /* Bug #383 - moved higher up the list, because if we are in the channel + * we can see all its users + */ + if (chan->HasUser(user)) + return true; + /* Opers see all */ + if (user->HasPrivPermission("users/auspex")) + return true; + /* Cant see inside a +s or a +p channel unless we are a member (see above) */ + else if (!chan->IsModeSet(secretmode) && !chan->IsModeSet(privatemode)) + return true; + + return false; +} + +void CommandWho::SendWhoLine(User* user, const std::vector& parms, const std::string& initial, Membership* memb, User* u, std::vector& whoresults) +{ + if (!memb) + memb = get_first_visible_channel(u); + + std::string wholine = initial + (memb ? memb->chan->name : "*") + " " + u->ident + " " + + (opt_showrealhost ? u->host : u->dhost) + " "; + if (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex")) + wholine.append(ServerInstance->Config->HideWhoisServer); + else + wholine.append(u->server->GetName()); + + wholine.append(" " + u->nick + " "); + + /* away? */ + if (u->IsAway()) + { + wholine.append("G"); + } + else + { + wholine.append("H"); + } + + /* oper? */ + if (u->IsOper()) + { + wholine.push_back('*'); + } + + if (memb) + wholine.push_back(memb->GetPrefixChar()); + + wholine.append(" :0 " + u->fullname); + + FOREACH_MOD(OnSendWhoLine, (user, parms, u, memb, wholine)); + + if (!wholine.empty()) + whoresults.push_back(wholine); +} + +CmdResult CommandWho::Handle (const std::vector& parameters, User *user) +{ + /* + * XXX - RFC says: + * The 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_realname = false; + opt_mode = false; + opt_ident = false; + opt_metadata = false; + opt_port = false; + opt_away = false; + opt_local = false; + opt_far = false; + opt_time = false; + + std::vector whoresults; + std::string initial = "352 " + user->nick + " "; + + /* Change '0' into '*' so the wildcard matcher can grok it */ + std::string matchtext = ((parameters[0] == "0") ? "*" : parameters[0]); + + // WHO flags count as a wildcard + bool usingwildcards = ((parameters.size() > 1) || (matchtext.find_first_of("*?.") != std::string::npos)); + + if (parameters.size() > 1) + { + for (std::string::const_iterator iter = parameters[1].begin(); iter != parameters[1].end(); ++iter) + { + switch (*iter) + { + case 'o': + opt_viewopersonly = true; + break; + case 'h': + if (user->HasPrivPermission("users/auspex")) + opt_showrealhost = true; + break; + case 'r': + opt_realname = true; + break; + case 'm': + if (user->HasPrivPermission("users/auspex")) + opt_mode = true; + break; + case 'M': + if (user->HasPrivPermission("users/auspex")) + opt_metadata = true; + break; + case 'i': + opt_ident = true; + break; + case 'p': + if (user->HasPrivPermission("users/auspex")) + opt_port = true; + break; + case 'a': + opt_away = true; + break; + case 'l': + if (user->HasPrivPermission("users/auspex") || ServerInstance->Config->HideWhoisServer.empty()) + opt_local = true; + break; + case 'f': + if (user->HasPrivPermission("users/auspex") || ServerInstance->Config->HideWhoisServer.empty()) + opt_far = true; + break; + case 't': + opt_time = true; + break; + } + } + } + + + /* who on a channel? */ + Channel* ch = ServerInstance->FindChan(matchtext); + + if (ch) + { + if (CanView(ch,user)) + { + bool inside = ch->HasUser(user); + + /* who on a channel. */ + const UserMembList *cu = ch->GetUsers(); + + for (UserMembCIter i = cu->begin(); i != cu->end(); i++) + { + /* None of this applies if we WHO ourselves */ + if (user != i->first) + { + /* opers only, please */ + if (opt_viewopersonly && !i->first->IsOper()) + continue; + + /* If we're not inside the channel, hide +i users */ + if (i->first->IsModeSet(invisiblemode) && !inside && !user->HasPrivPermission("users/auspex")) + continue; + } + + SendWhoLine(user, parameters, initial, i->second, i->first, whoresults); + } + } + } + else + { + /* Match against wildcard of nick, server or host */ + if (opt_viewopersonly) + { + /* Showing only opers */ + for (std::list::iterator i = ServerInstance->Users->all_opers.begin(); i != ServerInstance->Users->all_opers.end(); i++) + { + User* oper = *i; + + if (whomatch(user, oper, matchtext.c_str())) + { + if (!user->SharesChannelWith(oper)) + { + if (usingwildcards && (!oper->IsModeSet(invisiblemode)) && (!user->HasPrivPermission("users/auspex"))) + continue; + } + + SendWhoLine(user, parameters, initial, NULL, oper, whoresults); + } + } + } + else + { + for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++) + { + if (whomatch(user, i->second, matchtext.c_str())) + { + if (!user->SharesChannelWith(i->second)) + { + if (usingwildcards && (i->second->IsModeSet(invisiblemode)) && (!user->HasPrivPermission("users/auspex"))) + continue; + } + + SendWhoLine(user, parameters, initial, NULL, i->second, whoresults); + } + } + } + } + /* Send the results out */ + for (std::vector::const_iterator n = whoresults.begin(); n != whoresults.end(); n++) + user->WriteServ(*n); + user->WriteNumeric(RPL_ENDOFWHO, "%s :End of /WHO list.", *parameters[0].c_str() ? parameters[0].c_str() : "*"); + + // Penalize the user a bit for large queries + // (add one unit of penalty per 200 results) + if (IS_LOCAL(user)) + IS_LOCAL(user)->CommandFloodPenalty += whoresults.size() * 5; + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandWho) diff --git a/src/coremods/core_whois.cpp b/src/coremods/core_whois.cpp new file mode 100644 index 000000000..bd0b624d1 --- /dev/null +++ b/src/coremods/core_whois.cpp @@ -0,0 +1,242 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2008 Thomas Stagner + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" + +/** Handle /WHOIS. + */ +class CommandWhois : public SplitCommand +{ + ChanModeReference secretmode; + ChanModeReference privatemode; + UserModeReference snomaskmode; + + void SplitChanList(User* source, User* dest, const std::string& cl); + void DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle); + std::string ChannelList(User* source, User* dest, bool spy); + + public: + /** Constructor for whois. + */ + CommandWhois(Module* parent) + : SplitCommand(parent, "WHOIS", 1) + , secretmode(parent, "secret") + , privatemode(parent, "private") + , snomaskmode(parent, "snomask") + { + Penalty = 2; + syntax = "{,}"; + } + + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult HandleLocal(const std::vector& parameters, LocalUser* user); + CmdResult HandleRemote(const std::vector& parameters, RemoteUser* target); +}; + +std::string CommandWhois::ChannelList(User* source, User* dest, bool spy) +{ + std::string list; + + for (UCListIter i = dest->chans.begin(); i != dest->chans.end(); i++) + { + Membership* memb = *i; + Channel* c = memb->chan; + /* If the target is the sender, neither +p nor +s is set, or + * the channel contains the user, it is not a spy channel + */ + if (spy != (source == dest || !(c->IsModeSet(privatemode) || c->IsModeSet(secretmode)) || c->HasUser(source))) + { + list.push_back(memb->GetPrefixChar()); + list.append(c->name).push_back(' '); + } + } + + return list; +} + +void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl) +{ + std::string line; + std::ostringstream prefix; + std::string::size_type start, pos; + + prefix << dest->nick << " :"; + line = prefix.str(); + int namelen = ServerInstance->Config->ServerName.length() + 6; + + for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1) + { + if (line.length() + namelen + pos - start > 510) + { + ServerInstance->SendWhoisLine(source, dest, 319, line); + line = prefix.str(); + } + + line.append(cl.substr(start, pos - start + 1)); + } + + if (line.length() != prefix.str().length()) + { + ServerInstance->SendWhoisLine(source, dest, 319, line); + } +} + +void CommandWhois::DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle) +{ + ServerInstance->SendWhoisLine(user, dest, 311, "%s %s %s * :%s", dest->nick.c_str(), dest->ident.c_str(), dest->dhost.c_str(), dest->fullname.c_str()); + if (user == dest || user->HasPrivPermission("users/auspex")) + { + ServerInstance->SendWhoisLine(user, dest, 378, "%s :is connecting from %s@%s %s", dest->nick.c_str(), dest->ident.c_str(), dest->host.c_str(), dest->GetIPString().c_str()); + } + + std::string cl = ChannelList(user, dest, false); + const ServerConfig::OperSpyWhoisState state = user->HasPrivPermission("users/auspex") ? ServerInstance->Config->OperSpyWhois : ServerConfig::SPYWHOIS_NONE; + + if (state == ServerConfig::SPYWHOIS_SINGLEMSG) + cl.append(ChannelList(user, dest, true)); + + SplitChanList(user, dest, cl); + + if (state == ServerConfig::SPYWHOIS_SPLITMSG) + { + std::string scl = ChannelList(user, dest, true); + if (scl.length()) + { + ServerInstance->SendWhoisLine(user, dest, 336, "%s :is on private/secret channels:", dest->nick.c_str()); + SplitChanList(user, dest, scl); + } + } + if (user != dest && !ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex")) + { + ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), ServerInstance->Config->HideWhoisServer.c_str(), ServerInstance->Config->Network.c_str()); + } + else + { + ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), dest->server->GetName().c_str(), dest->server->GetDesc().c_str()); + } + + if (dest->IsAway()) + { + ServerInstance->SendWhoisLine(user, dest, 301, "%s :%s", dest->nick.c_str(), dest->awaymsg.c_str()); + } + + if (dest->IsOper()) + { + if (ServerInstance->Config->GenericOper) + ServerInstance->SendWhoisLine(user, dest, 313, "%s :is an IRC operator", dest->nick.c_str()); + else + ServerInstance->SendWhoisLine(user, dest, 313, "%s :is %s %s on %s", dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->name.c_str(), ServerInstance->Config->Network.c_str()); + } + + if (user == dest || user->HasPrivPermission("users/auspex")) + { + if (dest->IsModeSet(snomaskmode)) + { + ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s %s", dest->nick.c_str(), dest->FormatModes(), snomaskmode->GetUserParameter(dest).c_str()); + } + else + { + ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s", dest->nick.c_str(), dest->FormatModes()); + } + } + + FOREACH_MOD(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 %lu %lu :seconds idle, signon time", dest->nick.c_str(), idle, signon); + } + + ServerInstance->SendWhoisLine(user, dest, 318, "%s :End of /WHOIS list.", dest->nick.c_str()); +} + +CmdResult CommandWhois::HandleRemote(const std::vector& parameters, RemoteUser* target) +{ + if (parameters.size() < 2) + return CMD_FAILURE; + + User* user = ServerInstance->FindUUID(parameters[0]); + if (!user) + return CMD_FAILURE; + + unsigned long idle = ConvToInt(parameters.back()); + DoWhois(user, target, target->signon, idle); + + return CMD_SUCCESS; +} + +CmdResult CommandWhois::HandleLocal(const std::vector& parameters, LocalUser* user) +{ + User *dest; + int userindex = 0; + unsigned long idle = 0, signon = 0; + + if (CommandParser::LoopCall(user, this, parameters, 0)) + return CMD_SUCCESS; + + /* + * If 2 paramters are specified (/whois nick nick), ignore the first one like spanningtree + * does, and use the second one, otherwise, use the only paramter. -- djGrrr + */ + if (parameters.size() > 1) + userindex = 1; + + dest = ServerInstance->FindNickOnly(parameters[userindex]); + + if ((dest) && (dest->registered == REG_ALL)) + { + /* + * Okay. Umpteenth attempt at doing this, so let's re-comment... + * For local users (/w localuser), we show idletime if hidewhois is disabled + * For local users (/w localuser localuser), we always show idletime, hence parameters.size() > 1 check. + * For remote users (/w remoteuser), we do NOT show idletime + * For remote users (/w remoteuser remoteuser), spanningtree will handle calling do_whois, so we can ignore this case. + * Thanks to djGrrr for not being impatient while I have a crap day coding. :p -- w00t + */ + LocalUser* localuser = IS_LOCAL(dest); + if (localuser && (ServerInstance->Config->HideWhoisServer.empty() || parameters.size() > 1)) + { + idle = abs((long)((localuser->idle_lastmsg)-ServerInstance->Time())); + signon = dest->signon; + } + + DoWhois(user,dest,signon,idle); + } + else + { + /* no such nick/channel */ + user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*"); + user->WriteNumeric(RPL_ENDOFWHOIS, "%s :End of /WHOIS list.", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*"); + return CMD_FAILURE; + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandWhois) diff --git a/src/coremods/core_whowas.cpp b/src/coremods/core_whowas.cpp new file mode 100644 index 000000000..0a3a994a8 --- /dev/null +++ b/src/coremods/core_whowas.cpp @@ -0,0 +1,272 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2008 Thomas Stagner + * Copyright (C) 2008 Craig Edwards + * Copyright (C) 2007-2008 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "commands/cmd_whowas.h" + +CommandWhowas::CommandWhowas( Module* parent) + : Command(parent, "WHOWAS", 1) + , GroupSize(0), MaxGroups(0), MaxKeep(0) +{ + syntax = "{,}"; + Penalty = 2; +} + +CmdResult CommandWhowas::Handle (const std::vector& parameters, User* user) +{ + /* if whowas disabled in config */ + if (this->GroupSize == 0 || this->MaxGroups == 0) + { + user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :This command has been disabled.", name.c_str()); + return CMD_FAILURE; + } + + whowas_users::iterator i = whowas.find(assign(parameters[0])); + + if (i == whowas.end()) + { + user->WriteNumeric(ERR_WASNOSUCHNICK, "%s :There was no such nickname", parameters[0].c_str()); + } + else + { + whowas_set* grp = i->second; + if (!grp->empty()) + { + for (whowas_set::iterator ux = grp->begin(); ux != grp->end(); ux++) + { + WhoWasGroup* u = *ux; + + user->WriteNumeric(RPL_WHOWASUSER, "%s %s %s * :%s", parameters[0].c_str(), + u->ident.c_str(),u->dhost.c_str(),u->gecos.c_str()); + + if (user->HasPrivPermission("users/auspex")) + user->WriteNumeric(RPL_WHOWASIP, "%s :was connecting from *@%s", + parameters[0].c_str(), u->host.c_str()); + + std::string signon = InspIRCd::TimeString(u->signon); + bool hide_server = (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex")); + user->WriteNumeric(RPL_WHOISSERVER, "%s %s :%s", parameters[0].c_str(), (hide_server ? ServerInstance->Config->HideWhoisServer.c_str() : u->server.c_str()), signon.c_str()); + } + } + else + { + user->WriteNumeric(ERR_WASNOSUCHNICK, "%s :There was no such nickname", parameters[0].c_str()); + } + } + + user->WriteNumeric(RPL_ENDOFWHOWAS, "%s :End of WHOWAS", parameters[0].c_str()); + return CMD_SUCCESS; +} + +std::string CommandWhowas::GetStats() +{ + int whowas_size = 0; + int whowas_bytes = 0; + for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i) + { + whowas_set* n = i->second; + whowas_size += n->size(); + whowas_bytes += (sizeof(whowas_set) + ( sizeof(WhoWasGroup) * n->size() ) ); + } + return "Whowas entries: " +ConvToStr(whowas_size)+" ("+ConvToStr(whowas_bytes)+" bytes)"; +} + +void CommandWhowas::AddToWhoWas(User* user) +{ + /* if whowas disabled */ + if (this->GroupSize == 0 || this->MaxGroups == 0) + { + return; + } + + // Insert nick if it doesn't exist + // 'first' will point to the newly inserted element or to the existing element with an equivalent key + std::pair ret = whowas.insert(std::make_pair(irc::string(user->nick.c_str()), static_cast(NULL))); + + if (ret.second) // If inserted + { + // This nick is new, create a list for it and add the first record to it + whowas_set* n = new whowas_set; + n->push_back(new WhoWasGroup(user)); + ret.first->second = n; + + // Add this nick to the fifo too + whowas_fifo.push_back(std::make_pair(ServerInstance->Time(), ret.first->first)); + + if (whowas.size() > this->MaxGroups) + { + // Too many nicks, remove the nick which was inserted the longest time ago from both the map and the fifo + whowas_users::iterator it = whowas.find(whowas_fifo.front().second); + if (it != whowas.end()) + { + whowas_set* set = it->second; + for (whowas_set::iterator i = set->begin(); i != set->end(); ++i) + delete *i; + + delete set; + whowas.erase(it); + } + whowas_fifo.pop_front(); + } + } + else + { + // We've met this nick before, add a new record to the list + whowas_set* set = ret.first->second; + set->push_back(new WhoWasGroup(user)); + + // If there are too many records for this nick, remove the oldest (front) + if (set->size() > this->GroupSize) + { + delete set->front(); + set->pop_front(); + } + } +} + +/* on rehash, refactor maps according to new conf values */ +void CommandWhowas::Prune() +{ + time_t min = ServerInstance->Time() - this->MaxKeep; + + /* first cut the list to new size (maxgroups) and also prune entries that are timed out. */ + while (!whowas_fifo.empty()) + { + if ((whowas_fifo.size() > this->MaxGroups) || (whowas_fifo.front().first < min)) + { + whowas_users::iterator iter = whowas.find(whowas_fifo.front().second); + + /* hopefully redundant integrity check, but added while debugging r6216 */ + if (iter == whowas.end()) + { + /* this should never happen, if it does maps are corrupt */ + ServerInstance->Logs->Log("WHOWAS", LOG_DEFAULT, "BUG: Whowas maps got corrupted! (1)"); + return; + } + + whowas_set* set = iter->second; + for (whowas_set::iterator i = set->begin(); i != set->end(); ++i) + delete *i; + + delete set; + whowas.erase(iter); + whowas_fifo.pop_front(); + } + else + break; + } + + /* Then cut the whowas sets to new size (groupsize) */ + for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i) + { + whowas_set* n = i->second; + while (n->size() > this->GroupSize) + { + delete n->front(); + n->pop_front(); + } + } +} + +/* call maintain once an hour to remove expired nicks */ +void CommandWhowas::Maintain() +{ + time_t min = ServerInstance->Time() - this->MaxKeep; + for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i) + { + whowas_set* set = i->second; + while (!set->empty() && set->front()->signon < min) + { + delete set->front(); + set->pop_front(); + } + } +} + +CommandWhowas::~CommandWhowas() +{ + for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i) + { + whowas_set* set = i->second; + for (whowas_set::iterator j = set->begin(); j != set->end(); ++j) + delete *j; + + delete set; + } +} + +WhoWasGroup::WhoWasGroup(User* user) : host(user->host), dhost(user->dhost), ident(user->ident), + server(user->server->GetName()), gecos(user->fullname), signon(user->signon) +{ +} + +class ModuleWhoWas : public Module +{ + CommandWhowas cmd; + + public: + ModuleWhoWas() : cmd(this) + { + } + + void OnGarbageCollect() + { + // Remove all entries older than MaxKeep + cmd.Maintain(); + } + + void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) + { + cmd.AddToWhoWas(user); + } + + ModResult OnStats(char symbol, User* user, string_list &results) + { + if (symbol == 'z') + results.push_back("249 "+user->nick+" :"+cmd.GetStats()); + + return MOD_RES_PASSTHRU; + } + + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + ConfigTag* tag = ServerInstance->Config->ConfValue("whowas"); + unsigned int NewGroupSize = tag->getInt("groupsize", 10, 0, 10000); + unsigned int NewMaxGroups = tag->getInt("maxgroups", 10240, 0, 1000000); + unsigned int NewMaxKeep = tag->getDuration("maxkeep", 3600, 3600); + + if ((NewGroupSize == cmd.GroupSize) && (NewMaxGroups == cmd.MaxGroups) && (NewMaxKeep == cmd.MaxKeep)) + return; + + cmd.GroupSize = NewGroupSize; + cmd.MaxGroups = NewMaxGroups; + cmd.MaxKeep = NewMaxKeep; + cmd.Prune(); + } + + Version GetVersion() + { + return Version("WHOWAS", VF_VENDOR); + } +}; + +MODULE_INIT(ModuleWhoWas) diff --git a/src/coremods/core_xline/cmd_eline.cpp b/src/coremods/core_xline/cmd_eline.cpp new file mode 100644 index 000000000..509089d3e --- /dev/null +++ b/src/coremods/core_xline/cmd_eline.cpp @@ -0,0 +1,105 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "xline.h" + +/** Handle /ELINE. + */ +class CommandEline : public Command +{ + public: + /** Constructor for eline. + */ + CommandEline ( Module* parent) : Command(parent,"ELINE",1,3) { flags_needed = 'o'; syntax = " [ :]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +/** Handle /ELINE + */ +CmdResult CommandEline::Handle (const std::vector& parameters, User *user) +{ + std::string target = parameters[0]; + + if (parameters.size() >= 3) + { + IdentHostPair ih; + User* find = ServerInstance->FindNick(target); + if ((find) && (find->registered == REG_ALL)) + { + ih.first = "*"; + ih.second = find->GetIPString(); + target = std::string("*@") + find->GetIPString(); + } + else + ih = ServerInstance->XLines->IdentSplit(target); + + if (ih.first.empty()) + { + user->WriteNotice("*** Target not found"); + return CMD_FAILURE; + } + + if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) + return CMD_FAILURE; + + unsigned long duration = InspIRCd::Duration(parameters[1]); + ELine* el = new ELine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); + if (ServerInstance->XLines->AddLine(el, user)) + { + if (!duration) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent E-line for %s: %s", user->nick.c_str(), target.c_str(), parameters[2].c_str()); + } + else + { + time_t c_requires_crap = duration + ServerInstance->Time(); + std::string timestr = InspIRCd::TimeString(c_requires_crap); + ServerInstance->SNO->WriteToSnoMask('x',"%s added timed E-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(), + timestr.c_str(), parameters[2].c_str()); + } + } + else + { + delete el; + user->WriteNotice("*** E-Line for " + target + " already exists"); + } + } + else + { + if (ServerInstance->XLines->DelLine(target.c_str(), "E", user)) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s removed E-line on %s",user->nick.c_str(),target.c_str()); + } + else + { + user->WriteNotice("*** E-Line " + target + " not found in list, try /stats e"); + } + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandEline) diff --git a/src/coremods/core_xline/cmd_gline.cpp b/src/coremods/core_xline/cmd_gline.cpp new file mode 100644 index 000000000..18a661b24 --- /dev/null +++ b/src/coremods/core_xline/cmd_gline.cpp @@ -0,0 +1,115 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "xline.h" + +/** Handle /GLINE. + */ +class CommandGline : public Command +{ + public: + /** Constructor for gline. + */ + CommandGline (Module* parent) : Command(parent,"GLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = " [ :]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + + +/** Handle /GLINE + */ +CmdResult CommandGline::Handle (const std::vector& parameters, User *user) +{ + std::string target = parameters[0]; + + if (parameters.size() >= 3) + { + IdentHostPair ih; + User* find = ServerInstance->FindNick(target); + if ((find) && (find->registered == REG_ALL)) + { + ih.first = "*"; + ih.second = find->GetIPString(); + target = std::string("*@") + find->GetIPString(); + } + else + ih = ServerInstance->XLines->IdentSplit(target); + + if (ih.first.empty()) + { + user->WriteNotice("*** Target not found"); + return CMD_FAILURE; + } + + if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) + return CMD_FAILURE; + + else if (target.find('!') != std::string::npos) + { + user->WriteNotice("*** G-Line cannot operate on nick!user@host masks"); + return CMD_FAILURE; + } + + unsigned long duration = InspIRCd::Duration(parameters[1]); + GLine* gl = new GLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); + if (ServerInstance->XLines->AddLine(gl, user)) + { + if (!duration) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent G-line for %s: %s",user->nick.c_str(),target.c_str(), parameters[2].c_str()); + } + else + { + time_t c_requires_crap = duration + ServerInstance->Time(); + std::string timestr = InspIRCd::TimeString(c_requires_crap); + ServerInstance->SNO->WriteToSnoMask('x',"%s added timed G-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(), + timestr.c_str(), parameters[2].c_str()); + } + + ServerInstance->XLines->ApplyLines(); + } + else + { + delete gl; + user->WriteNotice("** G-Line for " + target + " already exists"); + } + + } + else + { + if (ServerInstance->XLines->DelLine(target.c_str(),"G",user)) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s removed G-line on %s",user->nick.c_str(),target.c_str()); + } + else + { + user->WriteNotice("*** G-Line " + target + " not found in list, try /stats g."); + } + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandGline) diff --git a/src/coremods/core_xline/cmd_kline.cpp b/src/coremods/core_xline/cmd_kline.cpp new file mode 100644 index 000000000..c6a8c7cad --- /dev/null +++ b/src/coremods/core_xline/cmd_kline.cpp @@ -0,0 +1,114 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2007-2008 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "xline.h" + +/** Handle /KLINE. + */ +class CommandKline : public Command +{ + public: + /** Constructor for kline. + */ + CommandKline ( Module* parent) : Command(parent,"KLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = " [ :]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + + +/** Handle /KLINE + */ +CmdResult CommandKline::Handle (const std::vector& parameters, User *user) +{ + std::string target = parameters[0]; + + if (parameters.size() >= 3) + { + IdentHostPair ih; + User* find = ServerInstance->FindNick(target); + if ((find) && (find->registered == REG_ALL)) + { + ih.first = "*"; + ih.second = find->GetIPString(); + target = std::string("*@") + find->GetIPString(); + } + else + ih = ServerInstance->XLines->IdentSplit(target); + + if (ih.first.empty()) + { + user->WriteNotice("*** Target not found"); + return CMD_FAILURE; + } + + if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user)) + return CMD_FAILURE; + + if (target.find('!') != std::string::npos) + { + user->WriteNotice("*** K-Line cannot operate on nick!user@host masks"); + return CMD_FAILURE; + } + + unsigned long duration = InspIRCd::Duration(parameters[1]); + KLine* kl = new KLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); + if (ServerInstance->XLines->AddLine(kl,user)) + { + if (!duration) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent K-line for %s: %s",user->nick.c_str(),target.c_str(), parameters[2].c_str()); + } + else + { + time_t c_requires_crap = duration + ServerInstance->Time(); + std::string timestr = InspIRCd::TimeString(c_requires_crap); + ServerInstance->SNO->WriteToSnoMask('x',"%s added timed K-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(), + timestr.c_str(), parameters[2].c_str()); + } + + ServerInstance->XLines->ApplyLines(); + } + else + { + delete kl; + user->WriteNotice("*** K-Line for " + target + " already exists"); + } + } + else + { + if (ServerInstance->XLines->DelLine(target.c_str(),"K",user)) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s removed K-line on %s",user->nick.c_str(),target.c_str()); + } + else + { + user->WriteNotice("*** K-Line " + target + " not found in list, try /stats k."); + } + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandKline) diff --git a/src/coremods/core_xline/cmd_qline.cpp b/src/coremods/core_xline/cmd_qline.cpp new file mode 100644 index 000000000..003aacbef --- /dev/null +++ b/src/coremods/core_xline/cmd_qline.cpp @@ -0,0 +1,95 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2008 Craig Edwards + * Copyright (C) 2007 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "xline.h" + +/** Handle /QLINE. */ +class CommandQline : public Command +{ + public: + /** Constructor for qline. + */ + CommandQline ( Module* parent) : Command(parent,"QLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = " [ :]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param pcnt The number of parameters passed to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + + +CmdResult CommandQline::Handle (const std::vector& parameters, User *user) +{ + if (parameters.size() >= 3) + { + if (ServerInstance->NickMatchesEveryone(parameters[0],user)) + return CMD_FAILURE; + + if (parameters[0].find('@') != std::string::npos || parameters[0].find('!') != std::string::npos || parameters[0].find('.') != std::string::npos) + { + user->WriteNotice("*** A Q-Line only bans a nick pattern, not a nick!user@host pattern."); + return CMD_FAILURE; + } + + unsigned long duration = InspIRCd::Duration(parameters[1]); + QLine* ql = new QLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str()); + if (ServerInstance->XLines->AddLine(ql,user)) + { + if (!duration) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Q-line for %s: %s",user->nick.c_str(), parameters[0].c_str(), parameters[2].c_str()); + } + else + { + time_t c_requires_crap = duration + ServerInstance->Time(); + std::string timestr = InspIRCd::TimeString(c_requires_crap); + ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Q-line for %s, expires on %s: %s",user->nick.c_str(),parameters[0].c_str(), + timestr.c_str(), parameters[2].c_str()); + } + ServerInstance->XLines->ApplyLines(); + } + else + { + delete ql; + user->WriteNotice("*** Q-Line for " + parameters[0] + " already exists"); + } + } + else + { + if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "Q", user)) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s removed Q-line on %s",user->nick.c_str(),parameters[0].c_str()); + } + else + { + user->WriteNotice("*** Q-Line " + parameters[0] + " not found in list, try /stats q."); + return CMD_FAILURE; + } + } + + return CMD_SUCCESS; +} + + +COMMAND_INIT(CommandQline) diff --git a/src/coremods/core_xline/cmd_zline.cpp b/src/coremods/core_xline/cmd_zline.cpp new file mode 100644 index 000000000..eda5b2a46 --- /dev/null +++ b/src/coremods/core_xline/cmd_zline.cpp @@ -0,0 +1,110 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2009 Matt Smith + * Copyright (C) 2007-2008 Robin Burchell + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "inspircd.h" +#include "xline.h" +/** Handle /ZLINE. + */ +class CommandZline : public Command +{ + public: + /** Constructor for zline. + */ + CommandZline ( Module* parent) : Command(parent,"ZLINE",1,3) { flags_needed = 'o'; Penalty = 0; syntax = " [ :]"; } + /** Handle command. + * @param parameters The parameters to the command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; + +CmdResult CommandZline::Handle (const std::vector& parameters, User *user) +{ + std::string target = parameters[0]; + + if (parameters.size() >= 3) + { + if (target.find('!') != std::string::npos) + { + user->WriteNotice("*** You cannot include a nickname in a zline, a zline must ban only an IP mask"); + return CMD_FAILURE; + } + + User *u = ServerInstance->FindNick(target); + + if ((u) && (u->registered == REG_ALL)) + { + target = u->GetIPString(); + } + + const char* ipaddr = target.c_str(); + + if (strchr(ipaddr,'@')) + { + while (*ipaddr != '@') + ipaddr++; + ipaddr++; + } + + if (ServerInstance->IPMatchesEveryone(ipaddr,user)) + return CMD_FAILURE; + + unsigned long duration = InspIRCd::Duration(parameters[1]); + ZLine* zl = new ZLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr); + if (ServerInstance->XLines->AddLine(zl,user)) + { + if (!duration) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Z-line for %s: %s", user->nick.c_str(), ipaddr, parameters[2].c_str()); + } + else + { + time_t c_requires_crap = duration + ServerInstance->Time(); + std::string timestr = InspIRCd::TimeString(c_requires_crap); + ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Z-line for %s, expires on %s: %s",user->nick.c_str(),ipaddr, + timestr.c_str(), parameters[2].c_str()); + } + ServerInstance->XLines->ApplyLines(); + } + else + { + delete zl; + user->WriteNotice("*** Z-Line for " + std::string(ipaddr) + " already exists"); + } + } + else + { + if (ServerInstance->XLines->DelLine(target.c_str(),"Z",user)) + { + ServerInstance->SNO->WriteToSnoMask('x',"%s removed Z-line on %s",user->nick.c_str(),target.c_str()); + } + else + { + user->WriteNotice("*** Z-Line " + target + " not found in list, try /stats Z."); + return CMD_FAILURE; + } + } + + return CMD_SUCCESS; +} + +COMMAND_INIT(CommandZline) -- cgit v1.2.3