Add support for CAP 3.2

This commit is contained in:
Patrick Griffis 2016-01-28 22:14:41 -05:00
parent 35d238ad3a
commit 981d55e84c
4 changed files with 35 additions and 6 deletions

View file

@ -572,6 +572,7 @@ typedef struct server
unsigned int sasl_mech; /* mechanism for sasl auth */ unsigned int sasl_mech; /* mechanism for sasl auth */
unsigned int sent_saslauth:1; /* have sent AUTHENICATE yet */ unsigned int sent_saslauth:1; /* have sent AUTHENICATE yet */
unsigned int sent_capend:1; /* have sent CAP END 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 #ifdef USE_OPENSSL
unsigned int use_ssl:1; /* is server SSL capable? */ unsigned int use_ssl:1; /* is server SSL capable? */
unsigned int accept_invalid_cert:1;/* ignore result of server's cert. verify */ unsigned int accept_invalid_cert:1;/* ignore result of server's cert. verify */

View file

@ -1735,12 +1735,23 @@ void
inbound_cap_ls (server *serv, char *nick, char *extensions_str, inbound_cap_ls (server *serv, char *nick, char *extensions_str,
const message_tags_data *tags_data) 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_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 */ gboolean want_sasl = FALSE; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */
char **extensions; char **extensions;
int i; 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, EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPLIST, serv->server_session, nick,
extensions_str, NULL, NULL, 0, tags_data->timestamp); 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++) for (i=0; extensions[i]; i++)
{ {
const char *extension = extensions[i]; char *extension = extensions[i];
char *value;
gsize x; 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 the SASL password is set AND auth mode is set to SASL, request SASL auth */
if (!g_strcmp0 (extension, "sasl") && if (!g_strcmp0 (extension, "sasl") &&
((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0) ((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); tags_data->timestamp);
tcp_sendf (serv, "%s\r\n", g_strchomp (buffer)); 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 */ /* if we use SASL, CAP END is dealt via raw numerics */
serv->sent_capend = TRUE; serv->sent_capend = TRUE;
@ -1795,15 +1814,23 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
void void
inbound_cap_nak (server *serv, const message_tags_data *tags_data) inbound_cap_nak (server *serv, const message_tags_data *tags_data)
{
if (!serv->waiting_on_cap && !serv->sent_capend)
{ {
serv->sent_capend = TRUE; serv->sent_capend = TRUE;
tcp_send_len (serv, "CAP END\r\n", 9); tcp_send_len (serv, "CAP END\r\n", 9);
} }
}
void void
inbound_cap_list (server *serv, char *nick, char *extensions, inbound_cap_list (server *serv, char *nick, char *extensions,
const message_tags_data *tags_data) 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, EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPACK, serv->server_session, nick, extensions,
NULL, NULL, 0, tags_data->timestamp); NULL, NULL, 0, tags_data->timestamp);
} }

View file

@ -48,7 +48,7 @@
static void static void
irc_login (server *serv, char *user, char *realname) 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 */ serv->sent_capend = FALSE; /* track if we have finished */
if (serv->password[0] && serv->loginmethod == LOGIN_PASS) if (serv->password[0] && serv->loginmethod == LOGIN_PASS)

View file

@ -1732,6 +1732,7 @@ server_set_defaults (server *serv)
serv->nickcount = 1; serv->nickcount = 1;
serv->end_of_motd = FALSE; serv->end_of_motd = FALSE;
serv->sent_capend = FALSE;
serv->is_away = FALSE; serv->is_away = FALSE;
serv->supports_watch = FALSE; serv->supports_watch = FALSE;
serv->supports_monitor = FALSE; serv->supports_monitor = FALSE;