summary refs log tree commit diff
diff options
context:
space:
mode:
authorDana Dahlstrom <dana@cs.ucsd.edu>2008-02-05 13:31:50 +0000
committerFlorian Westphal <fw@strlen.de>2008-02-26 23:49:33 +0100
commit6bd35bf090694a77b4a6c13c8fe5bb52e5905ec1 (patch)
tree3bc591dbaba2d169050a1e8bb79f9f2f0a71f91d
parent3022d7cff35118b6651c1165227aa79d759d9bfd (diff)
downloadngircd-6bd35bf090694a77b4a6c13c8fe5bb52e5905ec1.tar.gz
ngircd-6bd35bf090694a77b4a6c13c8fe5bb52e5905ec1.zip
Implement RFC 2812 handling of "0" argument to JOIN
The students in my software-engineering class are writing IRC clients in
Java, and I'm running ngIRCd as a sandbox for them to play in. We
noticed ngIRCd doesn't obey the "JOIN 0" command specified in RFC 2812:

   JOIN 0             ; Leave all currently joined
                      channels.

http://tools.ietf.org/html/rfc2812#section-3.2.1
I believe the following patch addresses this. Cheers!

[fw@strlen.de: put it into a seperate function]
-rw-r--r--ChangeLog5
-rw-r--r--src/ngircd/irc-channel.c34
-rw-r--r--src/testsuite/channel-test.e32
3 files changed, 67 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 1ad48a4e..c18df41d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,9 @@
 
 ngIRCd HEAD
 
+  - implement RFC 2812 handling of "0" argument to 'JOIN':
+    must be treated as if the user had sent PART commands
+    for all channels the user is a member of. (Dana Dahlstrom)
   - allow NOTICEs to be sent to a channel. (Fabian Schlager)
 
 ngIRCd 0.11.0 (2008-01-15)
@@ -738,4 +741,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: ChangeLog,v 1.335 2008/01/15 22:28:15 fw Exp $
+$Id: ChangeLog,v 1.336 2008/02/05 13:31:50 fw Exp $
diff --git a/src/ngircd/irc-channel.c b/src/ngircd/irc-channel.c
index fcc6e4aa..3481e19e 100644
--- a/src/ngircd/irc-channel.c
+++ b/src/ngircd/irc-channel.c
@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-channel.c,v 1.41 2008/01/07 11:42:00 fw Exp $";
+static char UNUSED id[] = "$Id: irc-channel.c,v 1.42 2008/02/05 13:31:50 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -40,6 +40,32 @@ static char UNUSED id[] = "$Id: irc-channel.c,v 1.41 2008/01/07 11:42:00 fw Exp
 #include "irc-channel.h"
 
 
+/*
+ * RFC 2812, (3.2.1 Join message Command):
+ *  Note that this message
+ *  accepts a special argument ("0"), which is a special request to leave all
+ *  channels the user is currently a member of. The server will process this
+ *  message as if the user had sent a PART command (See Section 3.2.2) for
+ *  each channel he is a member of.
+ */
+static bool
+part_from_all_channels(CLIENT* client, CLIENT *target)
+{
+	CL2CHAN *cl2chan = Channel_FirstChannelOf(target);
+	CHANNEL *chan;
+
+	while (cl2chan) {
+		chan = Channel_GetChannel(cl2chan);
+		assert( chan != NULL );
+		Channel_Part(target, client, Channel_Name(chan), Client_ID(target));
+
+		/* next */
+		cl2chan = Channel_FirstChannelOf(target);
+	}
+	return CONNECTED;
+}
+
+
 GLOBAL bool
 IRC_JOIN( CLIENT *Client, REQUEST *Req )
 {
@@ -47,7 +73,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 	bool is_new_chan, is_invited, is_banned;
 	CLIENT *target;
 	CHANNEL *chan;
-	
+
 	assert( Client != NULL );
 	assert( Req != NULL );
 
@@ -61,6 +87,10 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 	else target = Client;
 	if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
 
+	/* Is argument "0"? */
+	if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2))
+		return part_from_all_channels(Client, target);
+
 	/* Are channel keys given? */
 	if (Req->argc > 1) {
 		key = Req->argv[1];
diff --git a/src/testsuite/channel-test.e b/src/testsuite/channel-test.e
index 240abf64..16c67ad4 100644
--- a/src/testsuite/channel-test.e
+++ b/src/testsuite/channel-test.e
@@ -1,4 +1,4 @@
-# $Id: channel-test.e,v 1.3 2003/12/27 13:01:12 alex Exp $
+# $Id: channel-test.e,v 1.4 2008/02/05 13:31:51 fw Exp $
 
 spawn telnet localhost 6789
 expect {
@@ -69,6 +69,36 @@ expect {
 	"@* PART #channel :nick"
 }
 
+send "join #channel\r"
+expect {
+	timeout { exit 1 }
+	"@* JOIN :#channel"
+}
+expect {
+	timeout { exit 1 }
+	"366"
+}
+
+send "join #channel2\r"
+expect {
+	timeout { exit 1 }
+	"@* JOIN :#channel2"
+}
+expect {
+	timeout { exit 1 }
+	"366"
+}
+
+send "join 0\r"
+expect {
+	timeout { exit 1 }
+	"@* PART #channel2 :nick"
+}
+expect {
+	timeout { exit 1 }
+	"@* PART #channel :nick"
+}
+
 send "quit\r"
 expect {
 	timeout { exit 1 }