repo: ngircd action: commit revision: path_from: revision_from: ec0b405d9d75045e521136ff28e42d7212f14834: path_to: revision_to:
commit ec0b405d9d75045e521136ff28e42d7212f14834 Author: Alexander BartonDate: Mon Aug 18 01:35:32 2008 +0200 Respect RFC 1459 compatibility mode when announcing channels (no NJOIN). diff --git a/src/ngircd/irc-channel.c b/src/ngircd/irc-channel.c
--- a/src/ngircd/irc-channel.c +++ b/src/ngircd/irc-channel.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) + * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) * * 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 @@ -14,8 +14,6 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-channel.c,v 1.45 2008/02/24 18:57:38 fw Exp $"; - #include "imp.h" #include#include @@ -122,20 +120,45 @@ join_set_channelmodes(CHANNEL *chan, CLIENT *target, const char *flags) } +static void +cb_join_forward(CLIENT *To, CLIENT *Prefix, void *Data) +{ + CONN_ID conn; + char str[COMMAND_LEN], *ptr = NULL; + + strlcpy(str, (char *)Data, sizeof(str)); + conn = Client_Conn(To); + + if (Conn_Options(conn) & CONN_RFC1459) { + /* RFC 1459 compatibility mode, appended modes are NOT + * supported, so strip them off! */ + ptr = strchr(str, 0x7); + if (ptr) + *ptr++ = '\0'; + } + + IRC_WriteStrClientPrefix(To, Prefix, "JOIN %s", str); + if (ptr && *ptr) + IRC_WriteStrClientPrefix(To, Prefix, "MODE %s +%s %s", str, ptr, + Client_ID(Prefix)); +} /* cb_join_forward */ + + static void join_forward(CLIENT *Client, CLIENT *target, CHANNEL *chan, const char *channame) { - char modes[8]; + char modes[CHANNEL_MODE_LEN], str[COMMAND_LEN]; strlcpy(&modes[1], Channel_UserModes(chan, target), sizeof(modes) - 1); - if (modes[1]) modes[0] = 0x7; else modes[0] = '\0'; + /* forward to other servers */ - IRC_WriteStrServersPrefix(Client, target, "JOIN :%s%s", channame, modes); + snprintf(str, sizeof(str), "%s%s", channame, modes); + IRC_WriteStrServersPrefixFlag_CB(Client, target, '\0', cb_join_forward, str); /* tell users in this channel about the new client */ IRC_WriteStrChannelPrefix(Client, chan, target, false, "JOIN :%s", channame); @@ -460,7 +483,7 @@ IRC_LIST( CLIENT *Client, REQUEST *Req ) Req->argv[1] ); } } - + while( pattern ) { /* Loop through all the channels */ @@ -484,14 +507,14 @@ IRC_LIST( CLIENT *Client, REQUEST *Req ) } chan = Channel_Next( chan ); } - + /* Get next name ... */ if( Req->argc > 0 ) pattern = strtok( NULL, "," ); else pattern = NULL; } - + return IRC_WriteStrClient( from, RPL_LISTEND_MSG, Client_ID( from )); } /* IRC_LIST */ @@ -560,7 +583,7 @@ IRC_CHANINFO( CLIENT *Client, REQUEST *Req ) } ptr++; } - + /* Inform members of this channel */ IRC_WriteStrChannelPrefix( Client, chan, from, false, "MODE %s +%s%s", Req->argv[0], Channel_Modes( chan ), modes_add ); } diff --git a/src/ngircd/numeric.c b/src/ngircd/numeric.c
--- a/src/ngircd/numeric.c
+++ b/src/ngircd/numeric.c
@@ -37,6 +37,77 @@
#include "numeric.h"
+/**
+ * Announce a channel and its users in the network.
+ */
+static bool
+Announce_Channel(CLIENT *Client, CHANNEL *Chan)
+{
+ CL2CHAN *cl2chan;
+ CLIENT *cl;
+ char str[LINE_LEN], *ptr;
+ bool njoin;
+
+ if (Conn_Options(Client_Conn(Client)) & CONN_RFC1459)
+ njoin = false;
+ else
+ njoin = true;
+
+ /* Get all the members of this channel */
+ cl2chan = Channel_FirstMember(Chan);
+ snprintf(str, sizeof(str), "NJOIN %s :", Channel_Name(Chan));
+ while (cl2chan) {
+ cl = Channel_GetClient(cl2chan);
+ assert(cl != NULL);
+
+ if (njoin) {
+ /* RFC 2813: send NJOIN with nick names and modes
+ * (if user is channel operator or has voice) */
+ if (str[strlen(str) - 1] != ':')
+ strlcat(str, ",", sizeof(str));
+ if (strchr(Channel_UserModes(Chan, cl), 'v'))
+ strlcat(str, "+", sizeof(str));
+ if (strchr(Channel_UserModes(Chan, cl), 'o'))
+ strlcat(str, "@", sizeof(str));
+ strlcat(str, Client_ID(cl), sizeof(str));
+
+ /* Send the data if the buffer is "full" */
+ if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 8)) {
+ if (!IRC_WriteStrClient(Client, "%s", str))
+ return DISCONNECTED;
+ snprintf(str, sizeof(str), "NJOIN %s :",
+ Channel_Name(Chan));
+ }
+ } else {
+ /* RFC 1459: no NJOIN, send JOIN and MODE */
+ if (!IRC_WriteStrClientPrefix(Client, cl, "JOIN %s",
+ Channel_Name(Chan)))
+ return DISCONNECTED;
+ ptr = Channel_UserModes(Chan, cl);
+ while (*ptr) {
+ if (!IRC_WriteStrClientPrefix(Client, cl,
+ "MODE %s +%c %s",
+ Channel_Name(Chan), ptr[0],
+ Client_ID(cl)))
+ return DISCONNECTED;
+ ptr++;
+ }
+ }
+
+ cl2chan = Channel_NextMember(Chan, cl2chan);
+ }
+
+ /* Data left in the buffer? */
+ if (str[strlen(str) - 1] != ':') {
+ /* Yes, send it ... */
+ if (!IRC_WriteStrClient(Client, "%s", str))
+ return DISCONNECTED;
+ }
+
+ return CONNECTED;
+} /* Announce_Channel */
+
+
/**
* Announce new server in the network
* @param Client New server
@@ -219,11 +290,9 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan)
GLOBAL bool
IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
{
- char str[LINE_LEN];
int max_hops, i;
- CLIENT *c, *cl;
+ CLIENT *c;
CHANNEL *chan;
- CL2CHAN *cl2chan;
Client_SetType(Client, CLIENT_SERVER);
@@ -280,39 +349,8 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
}
#endif
- /* Get all the members of this channel */
- cl2chan = Channel_FirstMember(chan);
- snprintf(str, sizeof(str), "NJOIN %s :", Channel_Name(chan));
- while (cl2chan) {
- cl = Channel_GetClient(cl2chan);
- assert(cl != NULL);
-
- /* Nick name, with modes (if applicable) */
- if (str[strlen(str) - 1] != ':')
- strlcat(str, ",", sizeof(str));
- if (strchr(Channel_UserModes(chan, cl), 'v'))
- strlcat(str, "+", sizeof(str));
- if (strchr(Channel_UserModes(chan, cl), 'o'))
- strlcat(str, "@", sizeof(str));
- strlcat(str, Client_ID(cl), sizeof(str));
-
- /* Send the data if the buffer is "full" */
- if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 8)) {
- if (!IRC_WriteStrClient(Client, "%s", str))
- return DISCONNECTED;
- snprintf(str, sizeof(str), "NJOIN %s :",
- Channel_Name(chan));
- }
-
- cl2chan = Channel_NextMember(chan, cl2chan);
- }
-
- /* Data left in the buffer? */
- if (str[strlen(str) - 1] != ':') {
- /* Yes, send it ... */
- if (!IRC_WriteStrClient(Client, "%s", str))
- return DISCONNECTED;
- }
+ if (!Announce_Channel(Client, chan))
+ return DISCONNECTED;
/* Get next channel ... */
chan = Channel_Next(chan);
-----END OF PAGE-----