summary refs log tree commit diff stats
path: root/src/common
diff options
context:
space:
mode:
authorPatrick Griffis <tingping@tingping.se>2016-01-28 22:14:41 -0500
committerPatrick Griffis <tingping@tingping.se>2016-01-29 15:28:33 -0500
commit981d55e84c417095c0f686a6e22ba83ef9aa4b4e (patch)
tree46b024436dc9bdddef2bb5d4b2b3abecda85d2fa /src/common
parent35d238ad3a48b07c0c204b22305f00805c190111 (diff)
Add support for CAP 3.2
Diffstat (limited to 'src/common')
-rw-r--r--src/common/hexchat.h1
-rw-r--r--src/common/inbound.c37
-rw-r--r--src/common/proto-irc.c2
-rw-r--r--src/common/server.c1
4 files changed, 35 insertions, 6 deletions
diff --git a/src/common/hexchat.h b/src/common/hexchat.h
index fb389179..a29ea1d8 100644
--- a/src/common/hexchat.h
+++ b/src/common/hexchat.h
@@ -572,6 +572,7 @@ typedef struct server
 	unsigned int sasl_mech;			/* mechanism for sasl auth */
 	unsigned int sent_saslauth:1;	/* have sent AUTHENICATE yet */
 	unsigned int sent_capend:1;	/* have sent CAP END yet */
+	unsigned int waiting_on_cap:1;	/* waiting on another line of CAP LS */
 #ifdef USE_OPENSSL
 	unsigned int use_ssl:1;				  /* is server SSL capable? */
 	unsigned int accept_invalid_cert:1;/* ignore result of server's cert. verify */
diff --git a/src/common/inbound.c b/src/common/inbound.c
index 3df0c520..0d24532f 100644
--- a/src/common/inbound.c
+++ b/src/common/inbound.c
@@ -1735,12 +1735,23 @@ void
 inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 					 const message_tags_data *tags_data)
 {
-	char buffer[256];	/* buffer for requesting capabilities and emitting the signal */
+	char buffer[500];	/* buffer for requesting capabilities and emitting the signal */
 	gboolean want_cap = FALSE; /* format the CAP REQ string based on previous capabilities being requested or not */
 	gboolean want_sasl = FALSE; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */
 	char **extensions;
 	int i;
 
+	if (g_str_has_prefix (extensions_str, "* "))
+	{
+		serv->waiting_on_cap = TRUE;
+		extensions_str += 2;
+		extensions_str += extensions_str[0] == ':' ? 1 : 0;
+	}
+	else
+	{
+		serv->waiting_on_cap = FALSE;
+	}
+
 	EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPLIST, serv->server_session, nick,
 								  extensions_str, NULL, NULL, 0, tags_data->timestamp);
 
@@ -1750,9 +1761,17 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 
 	for (i=0; extensions[i]; i++)
 	{
-		const char *extension = extensions[i];
+		char *extension = extensions[i];
+		char *value;
 		gsize x;
 
+		/* CAP 3.2 can provide values */
+		if ((value = strchr (extension, '=')))
+		{
+			*value = '\0';
+			value++;
+		}
+
 		/* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
 		if (!g_strcmp0 (extension, "sasl") &&
 			((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0)
@@ -1785,7 +1804,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 									  tags_data->timestamp);
 		tcp_sendf (serv, "%s\r\n", g_strchomp (buffer));
 	}
-	if (!want_sasl)
+	if (!want_sasl && !serv->waiting_on_cap)
 	{
 		/* if we use SASL, CAP END is dealt via raw numerics */
 		serv->sent_capend = TRUE;
@@ -1796,14 +1815,22 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
 void
 inbound_cap_nak (server *serv, const message_tags_data *tags_data)
 {
-	serv->sent_capend = TRUE;
-	tcp_send_len (serv, "CAP END\r\n", 9);
+	if (!serv->waiting_on_cap && !serv->sent_capend)
+	{
+		serv->sent_capend = TRUE;
+		tcp_send_len (serv, "CAP END\r\n", 9);
+	}
 }
 
 void
 inbound_cap_list (server *serv, char *nick, char *extensions,
 						const message_tags_data *tags_data)
 {
+	if (g_str_has_prefix (extensions, "* "))
+	{
+		extensions += 2;
+		extensions += extensions[0] == ':' ? 1 : 0;
+	}
 	EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPACK, serv->server_session, nick, extensions,
 								  NULL, NULL, 0, tags_data->timestamp);
 }
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index 6fe601ed..4174e182 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -48,7 +48,7 @@
 static void
 irc_login (server *serv, char *user, char *realname)
 {
-	tcp_sendf (serv, "CAP LS\r\n");		/* start with CAP LS as Charybdis sasl.txt suggests */
+	tcp_sendf (serv, "CAP LS 302\r\n");		/* start with CAP LS as Charybdis sasl.txt suggests */
 	serv->sent_capend = FALSE;	/* track if we have finished */
 
 	if (serv->password[0] && serv->loginmethod == LOGIN_PASS)
diff --git a/src/common/server.c b/src/common/server.c
index 8ff81553..926a9f43 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -1732,6 +1732,7 @@ server_set_defaults (server *serv)
 
 	serv->nickcount = 1;
 	serv->end_of_motd = FALSE;
+	serv->sent_capend = FALSE;
 	serv->is_away = FALSE;
 	serv->supports_watch = FALSE;
 	serv->supports_monitor = FALSE;