summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorBerke Viktor <bviktor@hexchat.org>2012-11-03 18:29:08 +0100
committerBerke Viktor <bviktor@hexchat.org>2012-11-03 18:29:08 +0100
commit7d664e755eb8bf8226695a735a631124421edc7a (patch)
tree4faae22f223345e545f5385f947648ffedb1d957 /src
parent7c1d2366b1a57a6ab244074f80adef2c8c66ef35 (diff)
More robust CAP management and CAP multi-prefix support
Diffstat (limited to 'src')
-rw-r--r--src/common/proto-irc.c45
-rw-r--r--src/common/server.c1
-rw-r--r--src/common/text.c4
-rw-r--r--src/common/textevents.in4
4 files changed, 38 insertions, 16 deletions
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index 4a64bed6..2e12d0e5 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -1130,7 +1130,10 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
 	else if (len == 3)
 	{
 		guint32 t;
-		char *pass;
+		guint32 want_cap;		/* format the CAP REQ string based on previous capabilities being requested or not */
+		guint32 want_sasl;		/* CAP END shouldn't be sent when SASL is requested, it needs further responses */
+		char *pass;				/* buffer for SASL password */
+		char buffer[256];		/* buffer for requesting capabilities and emitting the signal */
 
 		t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]);
 		switch (t)
@@ -1138,14 +1141,19 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
 			case WORDL('C','A','P','\0'):
 				if (strncasecmp (word[4], "ACK", 3) == 0)
 				{
-					/* should acknowledge only one at a time, but just make sure we don't miss anything, use word_eol */
-					EMIT_SIGNAL (XP_TE_CAPACK, sess->server->server_session, word[1], ++word_eol[5], NULL, NULL, 0);
+					EMIT_SIGNAL (XP_TE_CAPACK, sess->server->server_session, word[1], word[5][0]==':' ? ++word_eol[5] : word_eol[5], NULL, NULL, 0);
 
-					if (strncasecmp (word[5][0]==':' ? word[5] + 1 : word[5], "identify-msg", 12) == 0)
+					if (strstr (word_eol[5], "identify-msg") != 0)
 					{
 						serv->have_idmsg = TRUE;
 					}
-					if (strncasecmp (word[5][0]==':' ? word[5] + 1 : word[5], "sasl", 12) == 0)
+
+					if (strstr (word_eol[5], "multi-prefix") != 0)
+					{
+						serv->have_namesx = TRUE;
+					}
+
+					if (strstr (word_eol[5], "sasl") != 0)
 					{
 						serv->have_sasl = TRUE;
 						EMIT_SIGNAL (XP_TE_SASLAUTH, serv->server_session, sess->server->sasluser, NULL, NULL, NULL, 0);
@@ -1158,21 +1166,34 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
 				}
 				else if (strncasecmp (word[4], "LS", 2) == 0)
 				{
-					EMIT_SIGNAL (XP_TE_CAPLIST, serv->server_session, word[1], ++word_eol[5], NULL, NULL, 0);
+					EMIT_SIGNAL (XP_TE_CAPLIST, serv->server_session, word[1], word[5][0]==':' ? ++word_eol[5] : word_eol[5], NULL, NULL, 0);
+					want_cap = 0;
+					want_sasl = 0;
 
 					if (strstr (word_eol[5], "identify-msg") != 0)
 					{
-						EMIT_SIGNAL (XP_TE_CAPREQ, sess->server->server_session, "identify-msg", NULL, NULL, NULL, 0);
-						tcp_send_len (serv, "CAP REQ :identify-msg\r\n", 23);
+						strcpy (buffer, "CAP REQ :identify-msg");
+						want_cap = 1;
+					}
+					if (strstr (word_eol[5], "multi-prefix") != 0)
+					{
+						want_cap ? strcat (buffer, " multi-prefix") : strcpy (buffer, "CAP REQ :multi-prefix");
+						want_cap = 1;
 					}
-
 					/* if the SASL password is set, request SASL auth */
 					if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->saslpassword) != 0)
 					{
-						EMIT_SIGNAL (XP_TE_CAPREQ, sess->server->server_session, "sasl", NULL, NULL, NULL, 0);
-						tcp_send_len (serv, "CAP REQ :sasl\r\n", 23);
+						want_cap ? strcat (buffer, " sasl") : strcpy (buffer, "CAP REQ :sasl");
+						want_sasl = 1;
 					}
-					else
+
+					if (want_cap)
+					{
+						/* buffer + 9 = emit buffer without "CAP REQ :" */
+						EMIT_SIGNAL (XP_TE_CAPREQ, sess->server->server_session, buffer + 9, NULL, NULL, NULL, 0);
+						tcp_sendf (serv, "%s\r\n", buffer);
+					}
+					if (!want_sasl)
 					{
 						/* if we use SASL, CAP END is dealt via raw numerics */
 						tcp_send_len (serv, "CAP END\r\n", 9);
diff --git a/src/common/server.c b/src/common/server.c
index 29ffbd3a..2bb133b1 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -1903,6 +1903,7 @@ server_set_defaults (server *serv)
 	serv->have_whox = FALSE;
 	serv->have_capab = FALSE;
 	serv->have_idmsg = FALSE;
+	serv->have_sasl = FALSE;
 	serv->have_except = FALSE;
 }
 
diff --git a/src/common/text.c b/src/common/text.c
index 83c5ca98..6c472690 100644
--- a/src/common/text.c
+++ b/src/common/text.c
@@ -1171,7 +1171,7 @@ static char * const pevt_privmsg_help[] = {
 
 static char * const pevt_capack_help[] = {
 	N_("Server Name"),
-	N_("Acknowledged Capability")
+	N_("Acknowledged Capabilities")
 };
 
 static char * const pevt_caplist_help[] = {
@@ -1180,7 +1180,7 @@ static char * const pevt_caplist_help[] = {
 };
 
 static char * const pevt_capreq_help[] = {
-	N_("Requested Capability")
+	N_("Requested Capabilities")
 };
 
 static char * const pevt_changenick_help[] = {
diff --git a/src/common/textevents.in b/src/common/textevents.in
index 08c9bc01..0f574de1 100644
--- a/src/common/textevents.in
+++ b/src/common/textevents.in
@@ -25,7 +25,7 @@ n0
 Capability Acknowledgement
 XP_TE_CAPACK
 pevt_capack_help
-%C29*%O$tCapability acknowledged: %C29$2%O
+%C29*%O$tCapabilities acknowledged: %C29$2%O
 2
 
 Capability List
@@ -37,7 +37,7 @@ pevt_caplist_help
 Capability Request
 XP_TE_CAPREQ
 pevt_capreq_help
-%C23*%O$tCapability requested: %C29$1%O
+%C23*%O$tCapabilities requested: %C29$1%O
 1
 
 Change Nick