aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--degesch.c60
1 files changed, 51 insertions, 9 deletions
diff --git a/degesch.c b/degesch.c
index dd7afaa..f92c86b 100644
--- a/degesch.c
+++ b/degesch.c
@@ -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;