diff options
| -rw-r--r-- | degesch.c | 132 | 
1 files changed, 111 insertions, 21 deletions
| @@ -1035,11 +1035,6 @@ 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 @@ -1048,6 +1043,22 @@ struct server  	char *irc_user_mode;                ///< Our current user mode  	char *irc_user_host;                ///< Our current user@host +	// Server-specific information (from RPL_ISUPPORT): + +	// TODO: implement a generic strcmp() on top of "irc_tolower" +	/// Convert an IRC identifier character to lower-case +	int (*irc_tolower) (int); + +	/// Key conversion function for hashmap lookups +	size_t (*irc_strxfrm) (char *, const char *, size_t); + +	char *irc_chantypes;                ///< Channel types (name prefixes) +	char *irc_idchan_prefixes;          ///< Prefixes for "safe channels" +	char *irc_statusmsg;                ///< Prefixes for channel targets + +	char *irc_chanuser_prefixes;        ///< Channel user prefixes +	char *irc_chanuser_modes;           ///< Channel user modes +  	// Events:  	struct poller_timer ping_tmr;       ///< We should send a ping @@ -1068,9 +1079,16 @@ 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"); +	// Defaults as per the RPL_ISUPPORT draft +	self->irc_tolower = irc_tolower; +	self->irc_strxfrm = irc_strxfrm; + +	self->irc_chantypes         = xstrdup ("#&"); +	self->irc_idchan_prefixes   = xstrdup (""); +	self->irc_statusmsg         = xstrdup (""); + +	self->irc_chanuser_prefixes = xstrdup ("@+"); +	self->irc_chanuser_modes    = xstrdup ("ov");  	str_map_init (&self->irc_users);  	self->irc_users.key_xfrm = irc_strxfrm; @@ -1119,8 +1137,12 @@ 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); +	free (self->irc_chantypes); +	free (self->irc_idchan_prefixes); +	free (self->irc_statusmsg); + +	free (self->irc_chanuser_prefixes); +	free (self->irc_chanuser_modes);  	str_map_free (&self->irc_users);  	str_map_free (&self->irc_channels); @@ -3731,7 +3753,6 @@ irc_is_highlight (struct server *s, const char *message)  // --- Input handling ----------------------------------------------------------  // TODO: we will need a proper mode parser; to be shared with kike -// TODO: we alse definitely need to parse server capability messages  static void  irc_handle_join (struct server *s, const struct irc_message *msg) @@ -4430,7 +4451,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]; -		const char *nick = item + strspn (item, s->irc_channel_modes); +		const char *nick = item + strspn (item, s->irc_chanuser_modes);  		struct channel_user *channel_user = str_map_find (&map, nick);  		if (!channel_user)  		{ @@ -4479,11 +4500,72 @@ irc_handle_isupport_prefix (struct server *s, char *value)  	if (*modes++ != '(' || !prefixes++ || strlen (value) != 2 * n_prefixes--)  		return; -	free (s->irc_channel_modes); -	free (s->irc_channel_prefixes); +	free (s->irc_chanuser_modes); +	free (s->irc_chanuser_prefixes); + +	s->irc_chanuser_modes    = xstrndup (modes,    n_prefixes); +	s->irc_chanuser_prefixes = xstrndup (prefixes, n_prefixes); +} + +static void +irc_handle_isupport_casemapping (struct server *s, char *value) +{ +	// TODO: reinitialize hashtables with the new tolower() and strxfrm(), +	//   note that collisions may arise on reconnecting + +	if      (!strcmp (value, "ascii")) +	{ +		s->irc_tolower = tolower_ascii; +		s->irc_strxfrm = tolower_ascii_strxfrm; +	} +	else if (!strcmp (value, "rfc1459")) +	{ +		s->irc_tolower = irc_tolower; +		s->irc_strxfrm = irc_strxfrm; +	} +	else if (!strcmp (value, "rfc1459-strict")) +	{ +		// TODO: implement +		s->irc_tolower = irc_tolower; +		s->irc_strxfrm = irc_strxfrm; +	} +} + +static void +irc_handle_isupport_chantypes (struct server *s, char *value) +{ +	free (s->irc_chantypes); +	s->irc_chantypes = xstrdup (value); +} + +static void +irc_handle_isupport_idchan (struct server *s, char *value) +{ +	struct str prefixes; +	str_init (&prefixes); + +	struct str_vector v; +	str_vector_init (&v); +	split_str_ignore_empty (value, ',', &v); +	for (size_t i = 0; i < v.len; i++) +	{ +		// Not using or validating the numeric part +		const char *pair = v.vector[i]; +		const char *colon = strchr (pair, ':'); +		if (colon) +			str_append_data (&prefixes, pair, colon - pair); +	} +	str_vector_free (&v); + +	free (s->irc_idchan_prefixes); +	s->irc_idchan_prefixes = str_steal (&prefixes); +} -	s->irc_channel_modes    = xstrndup (modes,    n_prefixes); -	s->irc_channel_prefixes = xstrndup (prefixes, n_prefixes); +static void +irc_handle_isupport_statusmsg (struct server *s, char *value) +{ +	free (s->irc_statusmsg); +	s->irc_statusmsg = xstrdup (value);  }  static void @@ -4522,14 +4604,22 @@ irc_handle_rpl_isupport (struct server *s, const struct irc_message *msg)  		str_init (&value_unescaped);  		unescape_isupport_value (value, &value_unescaped); -		if (!strcmp (param, "PREFIX")) -			irc_handle_isupport_prefix (s, value_unescaped.str); +		if      (!strcmp (param, "PREFIX")) +			irc_handle_isupport_prefix      (s, value_unescaped.str); +		else if (!strcmp (param, "CASEMAPPING")) +			irc_handle_isupport_casemapping (s, value_unescaped.str); +		else if (!strcmp (param, "CHANTYPES")) +			irc_handle_isupport_chantypes   (s, value_unescaped.str); +		else if (!strcmp (param, "IDCHAN")) +			irc_handle_isupport_idchan      (s, value_unescaped.str); +		else if (!strcmp (param, "STATUSMSG")) +			irc_handle_isupport_statusmsg   (s, value_unescaped.str); + +		// TODO: also parse MODES, TARGMAX, CHANMODES and make use of them +		//   to split client commands as necessary  		str_free (&value_unescaped);  	} - -	// TODO: initialize key_strxfrm according to server properties; -	//   note that collisions may arise on reconnecting  }  static void | 
