diff options
| author | Přemysl Janouch <p.janouch@gmail.com> | 2015-06-12 20:29:21 +0200 | 
|---|---|---|
| committer | Přemysl Janouch <p.janouch@gmail.com> | 2015-06-12 20:29:21 +0200 | 
| commit | bf01fb7aa3101d061dc9271e6f863f5b634ca408 (patch) | |
| tree | d90d321b435b2a57c9ce93051ffc4adc60b68069 /kike.c | |
| parent | 20fc6c17d1bd776087d274b319977d265a8c0656 (diff) | |
| download | xK-bf01fb7aa3101d061dc9271e6f863f5b634ca408.tar.gz xK-bf01fb7aa3101d061dc9271e6f863f5b634ca408.tar.xz xK-bf01fb7aa3101d061dc9271e6f863f5b634ca408.zip | |
kike: implement the multi-prefix capability
Diffstat (limited to 'kike.c')
| -rw-r--r-- | kike.c | 83 | 
1 files changed, 67 insertions, 16 deletions
| @@ -293,6 +293,11 @@ enum  	IRC_USER_MODE_RX_SERVER_NOTICES  = (1 << 4)  }; +enum +{ +	IRC_CAP_MULTI_PREFIX             = (1 << 0), +}; +  struct client  {  	LIST_HEADER (struct client) @@ -314,6 +319,7 @@ struct client  	bool half_closed;                   ///< Closing link: conn. is half-closed  	unsigned long cap_version;          ///< CAP protocol version +	unsigned caps;                      ///< Enabled capabilities  	bool ssl_rx_want_tx;                ///< SSL_read() wants to write  	bool ssl_tx_want_rx;                ///< SSL_write() wants to read @@ -1140,20 +1146,53 @@ irc_handle_cap (const struct irc_message *msg, struct client *c)  				subcommand, "Ignoring invalid protocol version number");  		c->cap_negotiating = true; -		// TODO: actually implement a few capabilities -		client_send (c, "CAP %s LS :", target); +		client_send (c, "CAP %s LS :multi-prefix", target);  	}  	else if (!irc_strcmp (subcommand, "LIST"))  	{ -		// TODO: list currently enabled capabilities -		client_send (c, "CAP %s LIST :", target); +		struct str_vector caps; +		str_vector_init (&caps); + +		if (c->caps & IRC_CAP_MULTI_PREFIX) +			str_vector_add (&caps, "multi-prefix"); + +		char *caps_str = join_str_vector (&caps, ' '); +		str_vector_free (&caps); +		client_send (c, "CAP %s LIST :%s", target, caps_str); +		free (caps_str);  	}  	else if (!irc_strcmp (subcommand, "REQ"))  	{  		c->cap_negotiating = true; -		// TODO: process the capability change request, "-" disables -		if (v.len) + +		unsigned new_caps = c->caps; +		bool success = true; +		for (size_t i = 0; i < v.len; i++) +		{ +			bool neg = false; +			const char *name = v.vector[i]; +			if (*name == '-') +			{ +				neg = true; +				name++; +			} +			unsigned cap = 0; +			if (!strcmp (name, "multi-prefix")) +				cap = IRC_CAP_MULTI_PREFIX; +			else +				success = false; + +			if (neg) +				new_caps &= ~cap; +			else +				new_caps |=  cap; +		} + +		if (success) +		{ +			c->caps = new_caps;  			client_send (c, "CAP %s NAK :%s", target, params); +		}  		else  			client_send (c, "CAP %s ACK :%s", target, params);  	} @@ -1944,6 +1983,26 @@ irc_handle_list (const struct irc_message *msg, struct client *c)  }  static void +irc_append_prefixes (struct client *c, struct channel_user *user, +	struct str *output) +{ +	struct str prefixes; +	str_init (&prefixes); + +	if (user->modes & IRC_CHAN_MODE_OPERATOR)  str_append_c (&prefixes, '@'); +	if (user->modes & IRC_CHAN_MODE_VOICE)     str_append_c (&prefixes, '+'); + +	if (prefixes.len) +	{ +		if (c->caps & IRC_CAP_MULTI_PREFIX) +			str_append   (output, prefixes.str); +		else +			str_append_c (output, prefixes.str[0]); +	} +	str_free (&prefixes); +} + +static void  irc_send_rpl_namreply (struct client *c, const struct channel *chan)  {  	struct str_vector nicks; @@ -1963,10 +2022,7 @@ irc_send_rpl_namreply (struct client *c, const struct channel *chan)  		struct str result;  		str_init (&result); -		if (iter->modes & IRC_CHAN_MODE_OPERATOR) -			str_append_c (&result, '@'); -		else if (iter->modes & IRC_CHAN_MODE_VOICE) -			str_append_c (&result, '+'); +		irc_append_prefixes (c, iter, &result);  		str_append (&result, iter->c->nickname);  		str_vector_add_owned (&nicks, str_steal (&result));  	} @@ -2029,12 +2085,7 @@ irc_send_rpl_whoreply (struct client *c, const struct channel *chan,  	struct channel_user *user;  	if (chan && (user = channel_get_user (chan, target))) -	{ -		if (user->modes & IRC_CHAN_MODE_OPERATOR) -			str_append_c (&chars, '@'); -		else if (user->modes & IRC_CHAN_MODE_VOICE) -			str_append_c (&chars, '+'); -	} +		irc_append_prefixes (c, user, &chars);  	irc_send_reply (c, IRC_RPL_WHOREPLY, chan ? chan->name : "*",  		target->username, target->hostname, target->ctx->server_name, | 
