inspircd

A modular C++ IRC daemon (ircd). https://www.inspircd.org/
Log | Files | Refs | README

commit c8cc16040d6d36a5e50f260047024b86052ed575
parent 1f4651e24dc9c233c3fda74dfe6186fab3d03740
Author: Peter Powell <petpow@saberuk.com>
Date:   Sat,  9 Feb 2019 10:35:03 +0000

Implement support for SQUERY from RFC 2812.

This is treated internally as a PRIVMSG with a few exceptions:

1. The command MUST have exactly one target.
2. The target MUST be a user.
3. The target MUST be on a u-lined server (e.g. NickServ).

Diffstat:
Mdocs/conf/helpop-full.conf.example | 6+++++-
Msrc/coremods/core_message.cpp | 66+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/docs/conf/helpop-full.conf.example b/docs/conf/helpop-full.conf.example @@ -38,10 +38,14 @@ WHOIS WHOWAS ISON USERHOST WATCH LIST NAMES WHO MOTD ADMIN MAP LINKS LUSERS TIME STATS VERSION INFO MODULES COMMANDS -SSLINFO +SSLINFO SQUERY USER PASS PING PONG QUIT"> +<helpop key="squery" value="/SQUERY <target> <text> + +Sends a message to the network service specified in <target>."> + <helpop key="sslinfo" value="/SSLINFO <nick> Displays information on the SSL connection and certificate of the diff --git a/src/coremods/core_message.cpp b/src/coremods/core_message.cpp @@ -21,6 +21,12 @@ #include "inspircd.h" +enum +{ + // From RFC 2812. + ERR_NOSUCHSERVICE = 408 +}; + class MessageDetailsImpl : public MessageDetails { public: @@ -345,22 +351,80 @@ class CommandMessage : public Command } }; +class CommandSQuery : public SplitCommand +{ + public: + CommandSQuery(Module* Creator) + : SplitCommand(Creator, "SQUERY", 2, 2) + { + syntax = "<service> <message>"; + } + + CmdResult HandleLocal(LocalUser* user, const Params& parameters) CXX11_OVERRIDE + { + // The specified message was empty. + if (parameters[1].empty()) + { + user->WriteNumeric(ERR_NOTEXTTOSEND, "No text to send"); + return CMD_FAILURE; + } + + // The target can be either a nick or a nick@server mask. + User* target; + const char* targetserver = strchr(parameters[0].c_str(), '@'); + if (targetserver) + { + // The target is a user on a specific server (e.g. jto@tolsun.oulu.fi). + target = ServerInstance->FindNickOnly(parameters[0].substr(0, targetserver - parameters[0].c_str())); + if (target && strcasecmp(target->server->GetName().c_str(), targetserver + 1)) + target = NULL; + } + else + { + // The targer can be on any server. + target = ServerInstance->FindNickOnly(parameters[0]); + } + + if (!target || target->registered != REG_ALL || !target->server->IsULine()) + { + // The target user does not exist, is not fully registered, or is not a service. + user->WriteNumeric(ERR_NOSUCHSERVICE, parameters[0], "No such service"); + return CMD_FAILURE; + } + + // Fire the pre-message events. + MessageTarget msgtarget(target); + MessageDetailsImpl msgdetails(MSG_PRIVMSG, parameters[1], parameters.GetTags()); + if (!FirePreEvents(user, msgtarget, msgdetails)) + return CMD_FAILURE; + + // The SQUERY command targets a service on a u-lined server. This can never + // be on the server local to the source so we don't need to do any routing + // logic and can forward it as a PRIVMSG. + + // Fire the post-message event. + return FirePostEvent(user, msgtarget, msgdetails); + } +}; + class ModuleCoreMessage : public Module { private: CommandMessage cmdprivmsg; CommandMessage cmdnotice; + CommandSQuery cmdsquery; public: ModuleCoreMessage() : cmdprivmsg(this, MSG_PRIVMSG) , cmdnotice(this, MSG_NOTICE) + , cmdsquery(this) { } Version GetVersion() CXX11_OVERRIDE { - return Version("PRIVMSG, NOTICE", VF_CORE|VF_VENDOR); + return Version("Provides the NOTICE, PRIVMSG, and SQUERY commands", VF_CORE|VF_VENDOR); } };