diff options
-rw-r--r-- | degesch.c | 60 |
1 files changed, 51 insertions, 9 deletions
@@ -1035,6 +1035,11 @@ struct server // IRC: + // TODO: casemapping-specific strxfrm and/or tolower (CASEMAPPING=rfc1459) + // TODO: channel name prefixes (CHANTYPES=#& + IDCHAN) + char *irc_channel_prefixes; ///< Channel user prefixes + char *irc_channel_modes; ///< Channel user modes + struct str_map irc_users; ///< IRC user data struct str_map irc_channels; ///< IRC channel data struct str_map irc_buffer_map; ///< Maps IRC identifiers to buffers @@ -1063,6 +1068,10 @@ server_init (struct server *self, struct poller *poller) str_init (&self->read_buffer); self->state = IRC_DISCONNECTED; + // RFC 1459 as per the RPL_ISUPPORT draft + self->irc_channel_prefixes = xstrdup ("@+"); + self->irc_channel_modes = xstrdup ("ov"); + str_map_init (&self->irc_users); self->irc_users.key_xfrm = irc_strxfrm; str_map_init (&self->irc_channels); @@ -1110,6 +1119,9 @@ server_free (struct server *self) free (self->irc_user_mode); free (self->irc_user_host); + free (self->irc_channel_prefixes); + free (self->irc_channel_modes); + str_map_free (&self->irc_users); str_map_free (&self->irc_channels); str_map_free (&self->irc_buffer_map); @@ -4418,8 +4430,7 @@ irc_process_names (struct server *s, struct channel *channel) for (size_t i = 0; i < updates->len; i++) { const char *item = updates->vector[i]; - // FIXME: use server-specific chanmode characters - const char *nick = item + strspn (item, "@+"); + const char *nick = item + strspn (item, s->irc_channel_modes); struct channel_user *channel_user = str_map_find (&map, nick); if (!channel_user) { @@ -4460,6 +4471,43 @@ irc_handle_rpl_endofnames (struct server *s, const struct irc_message *msg) } static void +irc_handle_isupport_prefix (struct server *s, char *value) +{ + char *modes = value; + char *prefixes = strchr (value, ')'); + size_t n_prefixes = prefixes - modes; + if (*modes++ != '(' || !prefixes++ || strlen (value) != 2 * n_prefixes--) + return; + + free (s->irc_channel_modes); + free (s->irc_channel_prefixes); + + s->irc_channel_modes = xstrndup (modes, n_prefixes); + s->irc_channel_prefixes = xstrndup (prefixes, n_prefixes); +} + +static void +irc_handle_rpl_isupport (struct server *s, const struct irc_message *msg) +{ + if (msg->params.len < 2) + return; + + for (size_t i = 1; i < msg->params.len - 1; i++) + { + // TODO: if the parameter starts with "-", it resets to default + char *param = msg->params.vector[i]; + char *value = param + strcspn (param, "="); + if (*value) *value++ = '\0'; + + if (!strcmp (param, "PREFIX")) + irc_handle_isupport_prefix (s, value); + } + + // TODO: initialize key_strxfrm according to server properties; + // note that collisions may arise on reconnecting +} + +static void irc_process_numeric (struct server *s, const struct irc_message *msg, unsigned long numeric) { @@ -4491,14 +4539,8 @@ irc_process_numeric (struct server *s, if (msg->params.len == 2) irc_try_parse_welcome_for_userhost (s, msg->params.vector[1]); break; - case IRC_RPL_ISUPPORT: - // TODO: parse this, mainly PREFIX; see - // http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt - - // TODO: initialize key_strxfrm according to server properties; - // note that collisions may arise on reconnecting - break; + case IRC_RPL_ISUPPORT: irc_handle_rpl_isupport (s, msg); break; case IRC_RPL_USERHOST: irc_handle_rpl_userhost (s, msg); break; case IRC_RPL_NAMREPLY: irc_handle_rpl_namreply (s, msg); break; case IRC_RPL_ENDOFNAMES: irc_handle_rpl_endofnames (s, msg); break; |