Commit Diff
Diff:
497edbaf3eb51e6c67975713ee5c52d2d1b48105
e3f300d3231f56efe2831fb79f7b484d96d051f5
Commit:
e3f300d3231f56efe2831fb79f7b484d96d051f5
Tree:
fb5c435a67fe2d6628bbc61f89d2ece2a92769c6
Author:
Alexander Barton <alex@barton.de>
Committer:
Alexander Barton <alex@barton.de>
Date:
Fri Nov 2 16:50:31 2012 UTC
Message:
Implement SVSNICK command to change remote nicknames The SVSNICK command allows other servers (and services on "pseudo-servers") to forcefully change nicknames of remote users. Syntax: ": SVSNICK " The SVSNICK command itself doesn't change the nickname, but it becomes forwarded to the server to which the user is connected to. And then this server initiates the real nickname changing using regular NICK commands. This allows to still run networks with old servers not supporting the SVSNICK command, because SVSNICK commands for nicknames on such servers are silently ignored and don't cause a desync of the network.
blob - c3f32b7e8b2516fe383b6482341817ce668269a6
blob + 977fc54666e75ee8e5d753104cd46512f8471382
--- src/ngircd/irc-login.c
+++ src/ngircd/irc-login.c
@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,8 +39,8 @@
#include "irc-login.h"
static void Kill_Nick PARAMS((char *Nick, char *Reason));
-static void Change_Nick PARAMS((CLIENT * Origin, CLIENT * Target,
- char *NewNick, bool RegisterWhowas));
+static void Change_Nick PARAMS((CLIENT * Origin, CLIENT * Target, char *NewNick,
+ bool InformClient));
/**
@@ -278,7 +278,8 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
Client_SetType( Client, CLIENT_GOTNICK );
} else {
/* Nickname change */
- Change_Nick(Client, target, Req->argv[0], true);
+ Change_Nick(Client, target, Req->argv[0],
+ Client_Type(Client) == CLIENT_USER ? true : false);
IRC_SetPenalty(target, 2);
}
@@ -360,6 +361,54 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
/**
+ * Handler for the IRC "SVSNICK" command.
+ *
+ * @param Client The client from which this command has been received.
+ * @param Req Request structure with prefix and all parameters.
+ * @return CONNECTED or DISCONNECTED.
+ */
+GLOBAL bool
+IRC_SVSNICK(CLIENT *Client, REQUEST *Req)
+{
+ CLIENT *from, *target;
+
+ assert(Client != NULL);
+ assert(Req != NULL);
+
+ if (Req->argc != 2)
+ return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
+ Client_ID(Client), Req->command);
+
+ /* Search the originator */
+ from = Client_Search(Req->prefix);
+ if (!from)
+ from = Client;
+
+ /* Search the target */
+ target = Client_Search(Req->argv[0]);
+ if (!target || Client_Type(target) != CLIENT_USER) {
+ return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
+ Client_ID(Client), Req->argv[0]);
+ }
+
+ if (Client_Conn(target) <= NONE) {
+ /* We have to forward the message to the server handling
+ * this user; this is required to make sure all servers
+ * in the network do follow the nick name change! */
+ return IRC_WriteStrClientPrefix(Client_NextHop(target), from,
+ "SVSNICK %s %s",
+ Req->argv[0], Req->argv[1]);
+ }
+
+ /* Make sure that the new nickname is valid */
+ if (!Client_CheckNick(from, Req->argv[1]))
+ return CONNECTED;
+
+ Change_Nick(from, target, Req->argv[1], true);
+ return CONNECTED;
+}
+
+/**
* Handler for the IRC "USER" command.
*
* See RFC 2812, 3.1.3 "User message".
@@ -904,7 +953,7 @@ Kill_Nick(char *Nick, char *Reason)
* @param NewNick The new nickname.
*/
static void
-Change_Nick(CLIENT *Origin, CLIENT *Target, char *NewNick, bool RegisterWhowas)
+Change_Nick(CLIENT *Origin, CLIENT *Target, char *NewNick, bool InformClient)
{
if (Client_Conn(Target) > NONE) {
/* Local client */
@@ -921,14 +970,15 @@ Change_Nick(CLIENT *Origin, CLIENT *Target, char *NewN
}
/* Inform all servers and users (which have to know) of the new name */
- if (Client_Type(Origin) == CLIENT_USER)
- IRC_WriteStrClientPrefix(Origin, Origin, "NICK :%s", NewNick);
- IRC_WriteStrServersPrefix(Origin, Target, "NICK :%s", NewNick);
+ if (InformClient) {
+ IRC_WriteStrClientPrefix(Target, Origin, "NICK :%s", NewNick);
+ IRC_WriteStrServersPrefix(NULL, Target, "NICK :%s", NewNick);
+ } else
+ IRC_WriteStrServersPrefix(Origin, Target, "NICK :%s", NewNick);
IRC_WriteStrRelatedPrefix(Target, Target, false, "NICK :%s", NewNick);
- /* Register old nickname for WHOWAS queries, if required */
- if (RegisterWhowas)
- Client_RegisterWhowas(Target);
+ /* Register old nickname for WHOWAS queries */
+ Client_RegisterWhowas(Target);
/* Save new nickname */
Client_SetID(Target, NewNick);
blob - f3138f6efaa0a8ddb55fa37910aec3f56850f7b3
blob + 15be7b4c56c22f54015a212fc0b055a3151006f6
--- src/ngircd/irc-login.h
+++ src/ngircd/irc-login.h
@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@ GLOBAL bool IRC_PING PARAMS((CLIENT *Client, REQUEST *
GLOBAL bool IRC_PONG PARAMS((CLIENT *Client, REQUEST *Req));
GLOBAL bool IRC_QUIT PARAMS((CLIENT *Client, REQUEST *Req));
GLOBAL bool IRC_QUIT_HTTP PARAMS((CLIENT *Client, REQUEST *Req));
+GLOBAL bool IRC_SVSNICK PARAMS(( CLIENT *Client, REQUEST *Req ));
#endif
blob - f3b04d0c2ee8617ceb21d32ce919859e640b55f4
blob + 446180b523653cf85e5e747026819e03272b531f
--- src/ngircd/parse.c
+++ src/ngircd/parse.c
@@ -99,6 +99,7 @@ static COMMAND My_Commands[] =
{ "SQUERY", IRC_SQUERY, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "SQUIT", IRC_SQUIT, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+ { "SVSNICK", IRC_SVSNICK, CLIENT_SERVER, 0, 0, 0 },
{ "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
IRCNow