mirror of
https://github.com/irssi/irssi.git
synced 2025-01-03 14:56:47 -05:00
Parse multiline responses to CAP LS
The parsing logic isn't too elegant because of the optional parameter used for signaling if a response has a continuation one.
This commit is contained in:
parent
57827ca743
commit
8c87766132
@ -110,13 +110,31 @@ static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *add
|
|||||||
{
|
{
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
GString *cmd;
|
GString *cmd;
|
||||||
char *params, *evt, *list, **caps;
|
char *params, *evt, *list, *star, **caps;
|
||||||
int i, caps_length, disable, avail_caps;
|
int i, caps_length, disable, avail_caps, multiline;
|
||||||
|
|
||||||
params = event_get_params(args, 3, NULL, &evt, &list);
|
params = event_get_params(args, 4, NULL, &evt, &star, &list);
|
||||||
if (params == NULL)
|
if (params == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Multiline responses have an additional parameter and we have to do
|
||||||
|
* this stupid dance to parse them */
|
||||||
|
if (evt[0] == 'L' && !strcmp(star, "*")) {
|
||||||
|
multiline = TRUE;
|
||||||
|
}
|
||||||
|
/* This branch covers the '*' parameter isn't present, adjust the
|
||||||
|
* parameter pointer to compensate for this */
|
||||||
|
else if (list[0] == '\0') {
|
||||||
|
multiline = FALSE;
|
||||||
|
list = star;
|
||||||
|
}
|
||||||
|
/* Malformed request, terminate the negotiation */
|
||||||
|
else {
|
||||||
|
cap_finish_negotiation(server);
|
||||||
|
g_warn_if_reached();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Strip the trailing whitespaces before splitting the string, some servers send responses with
|
/* Strip the trailing whitespaces before splitting the string, some servers send responses with
|
||||||
* superfluous whitespaces that g_strsplit the interprets as tokens */
|
* superfluous whitespaces that g_strsplit the interprets as tokens */
|
||||||
caps = g_strsplit(g_strchomp(list), " ", -1);
|
caps = g_strsplit(g_strchomp(list), " ", -1);
|
||||||
@ -149,37 +167,41 @@ static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *add
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Request the required caps, if any */
|
/* A multiline response is always terminated by a normal one,
|
||||||
if (server->cap_queue == NULL) {
|
* wait until we receive that one to require any CAP */
|
||||||
cap_finish_negotiation(server);
|
if (multiline == FALSE) {
|
||||||
}
|
/* No CAP has been requested */
|
||||||
else {
|
if (server->cap_queue == NULL) {
|
||||||
cmd = g_string_new("CAP REQ :");
|
|
||||||
|
|
||||||
avail_caps = 0;
|
|
||||||
|
|
||||||
/* Check whether the cap is supported by the server */
|
|
||||||
for (tmp = server->cap_queue; tmp != NULL; tmp = tmp->next) {
|
|
||||||
if (g_hash_table_lookup_extended(server->cap_supported, tmp->data, NULL, NULL)) {
|
|
||||||
if (avail_caps > 0)
|
|
||||||
g_string_append_c(cmd, ' ');
|
|
||||||
g_string_append(cmd, tmp->data);
|
|
||||||
|
|
||||||
avail_caps++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the queue here */
|
|
||||||
gslist_free_full(server->cap_queue, (GDestroyNotify) g_free);
|
|
||||||
server->cap_queue = NULL;
|
|
||||||
|
|
||||||
/* If the server doesn't support any cap we requested close the negotiation here */
|
|
||||||
if (avail_caps > 0)
|
|
||||||
irc_send_cmd_now(server, cmd->str);
|
|
||||||
else
|
|
||||||
cap_finish_negotiation(server);
|
cap_finish_negotiation(server);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cmd = g_string_new("CAP REQ :");
|
||||||
|
|
||||||
g_string_free(cmd, TRUE);
|
avail_caps = 0;
|
||||||
|
|
||||||
|
/* Check whether the cap is supported by the server */
|
||||||
|
for (tmp = server->cap_queue; tmp != NULL; tmp = tmp->next) {
|
||||||
|
if (g_hash_table_lookup_extended(server->cap_supported, tmp->data, NULL, NULL)) {
|
||||||
|
if (avail_caps > 0)
|
||||||
|
g_string_append_c(cmd, ' ');
|
||||||
|
g_string_append(cmd, tmp->data);
|
||||||
|
|
||||||
|
avail_caps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the queue here */
|
||||||
|
gslist_free_full(server->cap_queue, (GDestroyNotify) g_free);
|
||||||
|
server->cap_queue = NULL;
|
||||||
|
|
||||||
|
/* If the server doesn't support any cap we requested close the negotiation here */
|
||||||
|
if (avail_caps > 0)
|
||||||
|
irc_send_cmd_now(server, cmd->str);
|
||||||
|
else
|
||||||
|
cap_finish_negotiation(server);
|
||||||
|
|
||||||
|
g_string_free(cmd, TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!g_strcmp0(evt, "ACK")) {
|
else if (!g_strcmp0(evt, "ACK")) {
|
||||||
@ -214,6 +236,9 @@ static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *add
|
|||||||
for (i = 0; i < caps_length; i++)
|
for (i = 0; i < caps_length; i++)
|
||||||
cap_emit_signal(server, "nak", caps[i]);
|
cap_emit_signal(server, "nak", caps[i]);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
g_warning("Unhandled CAP subcommand %s", evt);
|
||||||
|
}
|
||||||
|
|
||||||
g_strfreev(caps);
|
g_strfreev(caps);
|
||||||
g_free(params);
|
g_free(params);
|
||||||
|
Loading…
Reference in New Issue
Block a user