degesch: some basic RPL_ISUPPORT parsing

This commit is contained in:
Přemysl Eric Janouch 2015-05-25 22:54:04 +02:00
parent 36185ddeee
commit 0b91604acd

View File

@ -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)
{
@ -4459,6 +4470,43 @@ irc_handle_rpl_endofnames (struct server *s, const struct irc_message *msg)
irc_process_names (s, channel);
}
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;