aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--xC.c49
2 files changed, 44 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 5b187c9..59fb4f8 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,8 @@ Unreleased
* xC: improved pager integration capabilities
+ * xC: unsolicited JOINs will no longer automatically activate the buffer
+
* xC: normalized editline's history behaviour, making it a viable frontend
* xC: various bugfixes
diff --git a/xC.c b/xC.c
index dcecabb..b7aa712 100644
--- a/xC.c
+++ b/xC.c
@@ -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)