summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2021-05-24 02:53:28 +0100
committerGitHub <noreply@github.com>2021-05-23 20:53:28 -0500
commit37118a4d2b70c11a76c732346975c2745d3cc4c6 (patch)
treeb43cd4aa33f016b8826bdf420887cdb55551ee11
parent6199635e7fbd220860e9b650b6d3fe63f60d4f80 (diff)
Implement support for the IRCv3 account-tag specification. (#2572)
Co-authored-by: Patrick <tingping@tingping.se>
-rw-r--r--src/common/hexchat.h1
-rw-r--r--src/common/inbound.c3
-rw-r--r--src/common/proto-irc.c19
-rw-r--r--src/common/proto-irc.h4
-rw-r--r--src/common/server.c1
-rw-r--r--src/common/userlist.c12
6 files changed, 35 insertions, 5 deletions
diff --git a/src/common/hexchat.h b/src/common/hexchat.h
index f7cacfcc..f9ca006b 100644
--- a/src/common/hexchat.h
+++ b/src/common/hexchat.h
@@ -569,6 +569,7 @@ typedef struct server
 	unsigned int have_idmsg:1;		/* freenode's IDENTIFY-MSG */
 	unsigned int have_accnotify:1; /* cap account-notify */
 	unsigned int have_extjoin:1;	/* cap extended-join */
+	unsigned int have_account_tag:1;	/* cap account-tag */
 	unsigned int have_server_time:1;	/* cap server-time */
 	unsigned int have_sasl:1;		/* SASL capability */
 	unsigned int have_except:1;	/* ban exemptions +e */
diff --git a/src/common/inbound.c b/src/common/inbound.c
index 3a26dce9..7175b2ae 100644
--- a/src/common/inbound.c
+++ b/src/common/inbound.c
@@ -1671,6 +1671,8 @@ inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable)
 			serv->have_server_time = enable;
 		else if (!strcmp (extension, "away-notify"))
 			serv->have_awaynotify = enable;
+		else if (!strcmp (extension, "account-tag"))
+			serv->have_account_tag = enable;
 		else if (!strcmp (extension, "sasl"))
 		{
 			serv->have_sasl = enable;
@@ -1726,6 +1728,7 @@ static const char * const supported_caps[] = {
 	"chghost",
 	"setname",
 	"invite-notify",
+	"account-tag",
 
 	/* ZNC */
 	"znc.in/server-time-iso",
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index 57eda88a..cfe76361 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -1010,6 +1010,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 						 const message_tags_data *tags_data)
 {
 	server *serv = sess->server;
+	char *account;
 	char ip[128], nick[NICKLEN];
 	char *text, *ex;
 	int len = strlen (type);
@@ -1028,6 +1029,14 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 		ex[0] = '!';
 	}
 
+
+	/** Update the account for this message's source. */
+	if (serv->have_account_tag)
+	{
+		account = tags_data->account && *tags_data->account ? tags_data->account : "*";
+		inbound_account (serv, nick, account, tags_data);
+	}
+
 	if (len == 4)
 	{
 		guint32 t;
@@ -1522,6 +1531,9 @@ handle_message_tags (server *serv, const char *tags_str,
 		*value = '\0';
 		value++;
 
+		if (serv->have_account_tag && !strcmp (key, "account"))
+			tags_data->account = g_strdup (value);
+
 		if (serv->have_server_time && !strcmp (key, "time"))
 			handle_message_tag_time (value, tags_data);
 	}
@@ -1619,10 +1631,17 @@ irc_inline (server *serv, char *buf, int len)
 	}
 
 xit:
+	message_tags_data_free (&tags_data);
 	g_free (pdibuf);
 }
 
 void
+message_tags_data_free (message_tags_data *tags_data)
+{
+	g_clear_pointer (&tags_data->account, g_free);
+}
+
+void
 proto_fill_her_up (server *serv)
 {
 	serv->p_inline = irc_inline;
diff --git a/src/common/proto-irc.h b/src/common/proto-irc.h
index 6c075795..0f72c644 100644
--- a/src/common/proto-irc.h
+++ b/src/common/proto-irc.h
@@ -25,6 +25,7 @@
 
 #define MESSAGE_TAGS_DATA_INIT			\
 	{									\
+		NULL, /* account name */		\
 		(time_t)0, /* timestamp */		\
 	}
 
@@ -36,9 +37,12 @@
  */
 typedef struct 
 {
+	char *account;
 	time_t timestamp;
 } message_tags_data;
 
+void message_tags_data_free (message_tags_data *tags_data);
+
 void proto_fill_her_up (server *serv);
 
 #endif
diff --git a/src/common/server.c b/src/common/server.c
index c6fa1ced..5c645eb5 100644
--- a/src/common/server.c
+++ b/src/common/server.c
@@ -1784,6 +1784,7 @@ server_set_defaults (server *serv)
 	serv->have_idmsg = FALSE;
 	serv->have_accnotify = FALSE;
 	serv->have_extjoin = FALSE;
+	serv->have_account_tag = FALSE;
 	serv->have_server_time = FALSE;
 	serv->have_sasl = FALSE;
 	serv->have_except = FALSE;
diff --git a/src/common/userlist.c b/src/common/userlist.c
index 17719ff6..5f2d67f2 100644
--- a/src/common/userlist.c
+++ b/src/common/userlist.c
@@ -101,13 +101,15 @@ userlist_set_account (struct session *sess, char *nick, char *account)
 	user = userlist_find (sess, nick);
 	if (user)
 	{
-		g_free (user->account);
-			
 		if (strcmp (account, "*") == 0)
-			user->account = NULL;
-		else
+		{
+			g_clear_pointer (&user->account, g_free);
+		} else if (g_strcmp0 (user->account, account))
+		{
+			g_free (user->account);
 			user->account = g_strdup (account);
-			
+		}
+
 		/* gui doesnt currently reflect login status, maybe later
 		fe_userlist_rehash (sess, user); */
 	}