diff options
Diffstat (limited to 'xC.c')
-rw-r--r-- | xC.c | 49 |
1 files changed, 42 insertions, 7 deletions
@@ -1801,6 +1801,8 @@ struct server char *irc_user_host; ///< Our current user@host bool autoaway_active; ///< Autoaway is currently active + struct strv outstanding_joins; ///< JOINs we expect a response to + struct strv cap_ls_buf; ///< Buffer for IRCv3.2 CAP LS bool cap_echo_message; ///< Whether the server echoes messages bool cap_away_notify; ///< Whether we get AWAY notifications @@ -1934,6 +1936,7 @@ server_new (struct poller *poller) self->irc_user_mode = str_make (); + self->outstanding_joins = strv_make (); self->cap_ls_buf = strv_make (); server_init_specifics (self); return self; @@ -1981,6 +1984,7 @@ server_destroy (struct server *self) str_free (&self->irc_user_mode); free (self->irc_user_host); + strv_free (&self->outstanding_joins); strv_free (&self->cap_ls_buf); server_free_specifics (self); free (self); @@ -5670,6 +5674,7 @@ irc_destroy_state (struct server *s) str_reset (&s->irc_user_mode); cstr_set (&s->irc_user_host, NULL); + strv_reset (&s->outstanding_joins); strv_reset (&s->cap_ls_buf); s->cap_away_notify = false; s->cap_echo_message = false; @@ -7104,6 +7109,16 @@ irc_handle_sent_cap (struct server *s, const struct irc_message *msg) } static void +irc_handle_sent_join (struct server *s, const struct irc_message *msg) +{ + if (msg->params.len < 1) + return; + + if (strcmp (msg->params.vector[0], "0")) + cstr_split (msg->params.vector[0], ",", true, &s->outstanding_joins); +} + +static void irc_handle_sent_notice_text (struct server *s, const struct irc_message *msg, struct str *text) { @@ -7186,6 +7201,7 @@ g_irc_sent_handlers[] = { // This list needs to stay sorted { "CAP", irc_handle_sent_cap }, + { "JOIN", irc_handle_sent_join }, { "NOTICE", irc_handle_sent_notice }, { "PRIVMSG", irc_handle_sent_privmsg }, }; @@ -7435,12 +7451,27 @@ irc_handle_invite (struct server *s, const struct irc_message *msg) "#n has invited #n to #S", msg->prefix, target, channel_name); } +static bool +irc_satisfy_join (struct server *s, const char *target) +{ + // This queue could use some garbage collection, + // but it's unlikely to pose problems. + for (size_t i = 0; i < s->outstanding_joins.len; i++) + if (!irc_server_strcmp (s, target, s->outstanding_joins.vector[i])) + { + strv_remove (&s->outstanding_joins, i); + return true; + } + return false; +} + static void irc_handle_join (struct server *s, const struct irc_message *msg) { if (!msg->prefix || msg->params.len < 1) return; + // TODO: RFC 2812 doesn't guarantee that the argument isn't a target list. const char *channel_name = msg->params.vector[0]; if (!irc_is_channel (s, channel_name)) return; @@ -7466,7 +7497,7 @@ irc_handle_join (struct server *s, const struct irc_message *msg) buffer_add (s->ctx, buffer); char *input = CALL_ (s->ctx->input, get_line, NULL); - if (!*input) + if (irc_satisfy_join (s, channel_name) && !*input) buffer_activate (s->ctx, buffer); else buffer->highlighted = true; @@ -8841,12 +8872,16 @@ irc_process_numeric (struct server *s, // TODO: whitelist/blacklist a lot more replies in here. // TODO: we should either strip the first parameter from the resulting // buffer line, or at least put it in brackets - if (msg->params.len > 1) - { - struct buffer *x; - if ((x = str_map_find (&s->irc_buffer_map, msg->params.vector[1]))) - buffer = x; - } + if (msg->params.len < 2) + break; + + struct buffer *x; + if ((x = str_map_find (&s->irc_buffer_map, msg->params.vector[1]))) + buffer = x; + + // A JOIN request should be split at commas, + // then for each element produce either a JOIN response, or a numeric. + (void) irc_satisfy_join (s, msg->params.vector[1]); } if (buffer) |