# HG changeset patch
# Node ID 053e689919b8d23938ba6a563d435339b472609f
# Parent  2d095091213ec37a52042f5d30b644bbd8d4d4ff
diff --git a/ibis-cli/ibiscli.c b/ibis-cli/ibiscli.c
--- a/ibis-cli/ibiscli.c
+++ b/ibis-cli/ibiscli.c
@@ -110,7 +110,7 @@
 	timestamp = g_date_time_format(now, "%H:%M:%S");
 	g_date_time_unref(now);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_print("%s %s%s", timestamp, prefix, serialized);
 
diff --git a/ibis/ibisclient.c b/ibis/ibisclient.c
--- a/ibis/ibisclient.c
+++ b/ibis/ibisclient.c
@@ -73,6 +73,11 @@
 	char *realname;
 	char *username;
 
+	/* This keeps track of whether or not the message tags capability has been
+	 * negotiated.
+	 */
+	gboolean message_tags_negotiated;
+
 	/* The name of the server detected from the source of the CAP or
 	 * RPL_WELCOME messages.
 	 */
@@ -343,6 +348,15 @@
 }
 
 static void
+ibis_client_ack_message_tags_cb(G_GNUC_UNUSED IbisCapabilities *capabilities,
+                                G_GNUC_UNUSED const char *name, gpointer data)
+{
+	IbisClient *client = data;
+
+	client->message_tags_negotiated = TRUE;
+}
+
+static void
 ibis_client_network_feature_cb(IbisFeatures *features, const char *name,
                                gpointer data)
 {
@@ -357,6 +371,25 @@
 }
 
 /******************************************************************************
+ * IbisClient default handlers
+ *****************************************************************************/
+static gboolean
+ibis_client_writing_message_default_handler(IbisClient *client,
+                                            IbisMessage *message)
+{
+	const char *command = NULL;
+
+	command = ibis_message_get_command(message);
+	if(ibis_str_equal(command, IBIS_MSG_TAGMSG)) {
+		if(!client->message_tags_negotiated) {
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+/******************************************************************************
  * GObject Implementation
  *****************************************************************************/
 G_DEFINE_FINAL_TYPE(IbisClient, ibis_client, G_TYPE_OBJECT)
@@ -461,7 +494,13 @@
 
 static void
 ibis_client_init(IbisClient *client) {
+	client->message_tags_negotiated = FALSE;
+
 	client->capabilities = ibis_capabilities_new();
+	g_signal_connect_object(client->capabilities,
+	                        "ack::" IBIS_CAPABILITY_MESSAGE_TAGS,
+	                        G_CALLBACK(ibis_client_ack_message_tags_cb),
+	                        client, 0);
 
 	client->features = ibis_features_new();
 	g_signal_connect_object(client->features, "changed::" IBIS_FEATURE_NETWORK,
@@ -672,7 +711,7 @@
 		"writing-message",
 		G_OBJECT_CLASS_TYPE(klass),
 		G_SIGNAL_DETAILED | G_SIGNAL_RUN_LAST,
-		NULL,
+		G_CALLBACK(ibis_client_writing_message_default_handler),
 		g_signal_accumulator_true_handled,
 		NULL,
 		NULL,
@@ -1030,7 +1069,7 @@
 		return;
 	}
 
-	bytes = ibis_message_serialize(message);
+	bytes = ibis_message_serialize(message, client->message_tags_negotiated);
 
 	g_object_set_data(G_OBJECT(message), "ibis-client", client);
 
diff --git a/ibis/ibismessage.c b/ibis/ibismessage.c
--- a/ibis/ibismessage.c
+++ b/ibis/ibismessage.c
@@ -107,10 +107,10 @@
 }
 
 static GString *
-ibis_message_serialize_internal(IbisMessage *message) {
+ibis_message_serialize_internal(IbisMessage *message, gboolean include_tags) {
 	GString *str = g_string_new("");
 
-	if(IBIS_IS_TAGS(message->tags)) {
+	if(include_tags && IBIS_IS_TAGS(message->tags)) {
 		char *tag_data = ibis_tags_serialize(message->tags);
 
 		g_string_append(str, tag_data);
@@ -619,17 +619,25 @@
 }
 
 GBytes *
-ibis_message_serialize(IbisMessage *message) {
+ibis_message_serialize(IbisMessage *message, gboolean include_tags) {
+	GString *str = NULL;
+
 	g_return_val_if_fail(IBIS_IS_MESSAGE(message), NULL);
 
-	return g_string_free_to_bytes(ibis_message_serialize_internal(message));
+	str = ibis_message_serialize_internal(message, include_tags);
+
+	return g_string_free_to_bytes(str);
 }
 
 char *
-ibis_message_serialize_to_string(IbisMessage *message) {
+ibis_message_serialize_to_string(IbisMessage *message, gboolean include_tags) {
+	GString *str = NULL;
+
 	g_return_val_if_fail(IBIS_IS_MESSAGE(message), NULL);
 
-	return g_string_free_and_steal(ibis_message_serialize_internal(message));
+	str = ibis_message_serialize_internal(message, include_tags);
+
+	return g_string_free_and_steal(str);
 }
 
 GError *
diff --git a/ibis/ibismessage.h b/ibis/ibismessage.h
--- a/ibis/ibismessage.h
+++ b/ibis/ibismessage.h
@@ -255,9 +255,14 @@
 /**
  * ibis_message_serialize:
  * @message: The instance.
+ * @include_tags: Whether or not tags should be included.
  *
  * Serializes @message into a [type@GLib.Bytes].
  *
+ * If @include_tags is %FALSE, the tags will not be added to the output. This
+ * only should be set %TRUE if the message-tags capability has been negotiated
+ * with the server.
+ *
  * This output does include the trailing `\r\n`.
  *
  * Returns: (transfer full): The serialized message.
@@ -265,14 +270,19 @@
  * Since: 0.1
  */
 IBIS_AVAILABLE_IN_0_1
-GBytes *ibis_message_serialize(IbisMessage *message);
+GBytes *ibis_message_serialize(IbisMessage *message, gboolean include_tags);
 
 /**
  * ibis_message_serialize_to_string:
  * @message: The instance.
+ * @include_tags: Whether or not tags should be included.
  *
  * Serializes @message into a string.
  *
+ * If @include_tags is %FALSE, the tags will not be added to the output. This
+ * only should be set %TRUE if the message-tags capability has been negotiated
+ * with the server.
+ *
  * This string does include the trailing `\r\n`.
  *
  * Returns: (transfer full): The serialized message.
@@ -280,7 +290,7 @@
  * Since: 0.1
  */
 IBIS_AVAILABLE_IN_0_1
-char *ibis_message_serialize_to_string(IbisMessage *message);
+char *ibis_message_serialize_to_string(IbisMessage *message, gboolean include_tags);
 
 /**
  * ibis_message_get_error:
diff --git a/ibis/tests/test_message.c b/ibis/tests/test_message.c
--- a/ibis/tests/test_message.c
+++ b/ibis/tests/test_message.c
@@ -294,7 +294,7 @@
 
 	message = g_object_new(IBIS_TYPE_MESSAGE, NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "");
 
@@ -309,7 +309,7 @@
 
 	message = g_object_new(IBIS_TYPE_MESSAGE, "source", "source", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":source\r\n");
 
@@ -324,7 +324,48 @@
 
 	message = ibis_message_new("command");
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
+	g_assert_cmpstr(serialized, ==, "COMMAND\r\n");
+
+	g_clear_pointer(&serialized, g_free);
+	g_assert_finalize_object(message);
+}
+
+static void
+test_ibis_message_serialize_with_tags(void) {
+	IbisMessage *message = NULL;
+	IbisTags *tags = NULL;
+	char *serialized = NULL;
+
+	message = ibis_message_new("command");
+
+	tags = ibis_tags_new();
+	ibis_tags_add(tags, "foo", "bar");
+	ibis_message_set_tags(message, tags);
+	g_clear_object(&tags);
+
+	serialized = ibis_message_serialize_to_string(message, TRUE);
+	g_assert_cmpstr(serialized, ==, "@foo=bar COMMAND\r\n");
+
+	g_clear_pointer(&serialized, g_free);
+	g_assert_finalize_object(message);
+}
+
+
+static void
+test_ibis_message_serialize_no_tags(void) {
+	IbisMessage *message = NULL;
+	IbisTags *tags = NULL;
+	char *serialized = NULL;
+
+	message = ibis_message_new("command");
+
+	tags = ibis_tags_new();
+	ibis_tags_add(tags, "foo", "bar");
+	ibis_message_set_tags(message, tags);
+	g_clear_object(&tags);
+
+	serialized = ibis_message_serialize_to_string(message, FALSE);
 	g_assert_cmpstr(serialized, ==, "COMMAND\r\n");
 
 	g_clear_pointer(&serialized, g_free);
@@ -339,7 +380,7 @@
 	message = g_object_new(IBIS_TYPE_MESSAGE, NULL);
 	ibis_message_set_params(message, "foo", "bar", "baz", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "foo bar baz\r\n");
 
@@ -355,7 +396,7 @@
 	message = g_object_new(IBIS_TYPE_MESSAGE, NULL);
 	ibis_message_set_params(message, "", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":\r\n");
 
@@ -371,7 +412,7 @@
 	message = g_object_new(IBIS_TYPE_MESSAGE, NULL);
 	ibis_message_set_params(message, ":foo", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "::foo\r\n");
 
@@ -387,7 +428,7 @@
 	message = g_object_new(IBIS_TYPE_MESSAGE, NULL);
 	ibis_message_set_params(message, "I'm in space!!!!", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":I'm in space!!!!\r\n");
 
@@ -407,7 +448,7 @@
 	ibis_message_set_ctcp_message(message, ctcp_message);
 	g_clear_object(&ctcp_message);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 	g_assert_cmpstr(serialized, ==, "PRIVMSG :\001VERSION\001\r\n");
 	g_clear_pointer(&serialized, g_free);
 
@@ -429,7 +470,7 @@
 	ibis_message_set_ctcp_message(message, ctcp_message);
 	g_clear_object(&ctcp_message);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 	g_assert_cmpstr(serialized, ==,
 	                "PRIVMSG :\001ACTION slaps grim with a large trout\001\r\n");
 
@@ -451,7 +492,7 @@
 	ibis_message_set_ctcp_message(message, ctcp_message);
 	g_clear_object(&ctcp_message);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==,
 	                "PRIVMSG :\001DCC SEND pidgin.ico ::1 0\001\r\n");
@@ -474,7 +515,7 @@
 	ibis_message_set_ctcp_message(message, ctcp_message);
 	g_clear_object(&ctcp_message);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==,
 	                "PRIVMSG :\001DCC SEND pidgin.ico ::1 0\001\r\n");
@@ -494,7 +535,7 @@
 	message = ibis_message_new("foo");
 	ibis_message_set_params(message, "bar", "baz", "asdf", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "FOO bar baz asdf\r\n");
 
@@ -510,7 +551,7 @@
 	message = ibis_message_new(IBIS_MSG_AWAY);
 	ibis_message_set_source(message, "src");
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 	g_assert_cmpstr(serialized, ==, ":src AWAY\r\n");
 
 	g_clear_pointer(&serialized, g_free);
@@ -526,7 +567,7 @@
 	ibis_message_set_source(message, "src");
 	ibis_message_set_params(message, "", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 	g_assert_cmpstr(serialized, ==, ":src AWAY :\r\n");
 
 	g_clear_pointer(&serialized, g_free);
@@ -542,7 +583,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "bar", "baz", "asdf", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":coolguy FOO bar baz asdf\r\n");
 
@@ -558,7 +599,7 @@
 	message = ibis_message_new("foo");
 	ibis_message_set_params(message, "bar", "baz", "asdf quux", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "FOO bar baz :asdf quux\r\n");
 
@@ -574,7 +615,7 @@
 	message = ibis_message_new("foo");
 	ibis_message_set_params(message, "bar", "baz", "", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "FOO bar baz :\r\n");
 
@@ -590,7 +631,7 @@
 	message = ibis_message_new("foo");
 	ibis_message_set_params(message, "bar", "baz", ":asdf", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "FOO bar baz ::asdf\r\n");
 
@@ -607,7 +648,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "bar", "baz", "asdf quux", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":coolguy FOO bar baz :asdf quux\r\n");
 
@@ -625,7 +666,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "bar", "baz", "  asdf quux ", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":coolguy FOO bar baz :  asdf quux \r\n");
 
@@ -642,7 +683,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "bar", "lol :)", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":coolguy PRIVMSG bar :lol :)\r\n");
 
@@ -659,7 +700,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "bar", "baz", "", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":coolguy FOO bar baz :\r\n");
 
@@ -677,7 +718,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "bar", "baz", "  ", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":coolguy FOO bar baz :  \r\n");
 
@@ -694,7 +735,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "b\tar", "baz", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, ":coolguy FOO b\tar baz\r\n");
 
@@ -716,7 +757,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "bar", "baz", "  ", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "@asd :coolguy FOO bar baz :  \r\n");
 
@@ -739,7 +780,7 @@
 	ibis_message_set_source(message, "coolguy");
 	ibis_message_set_params(message, "bar", "baz", "  ", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "@asd :coolguy FOO bar baz :  \r\n");
 
@@ -761,7 +802,7 @@
 	message = ibis_message_new("foo");
 	ibis_message_set_tags(message, tags);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==, "@a=b\\\\and\\nk;d=gh\\:764 FOO\r\n");
 
@@ -784,7 +825,7 @@
 	ibis_message_set_tags(message, tags);
 	ibis_message_set_params(message, "par1", "par2", NULL);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==,
 	                "@a=b\\\\and\\nk;d=gh\\:764 FOO par1 par2\r\n");
@@ -806,7 +847,7 @@
 	message = ibis_message_new("COMMAND");
 	ibis_message_set_tags(message, tags);
 
-	serialized = ibis_message_serialize_to_string(message);
+	serialized = ibis_message_serialize_to_string(message, TRUE);
 
 	g_assert_cmpstr(serialized, ==,
 	                "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND\r\n");
@@ -854,6 +895,10 @@
 	                test_ibis_message_serialize_source);
 	g_test_add_func("/ibis/message/serialize/command",
 	                test_ibis_message_serialize_command);
+	g_test_add_func("/ibis/message/serialize/tags",
+	                test_ibis_message_serialize_with_tags);
+	g_test_add_func("/ibis/message/serialize/no-tags",
+	                test_ibis_message_serialize_no_tags);
 	g_test_add_func("/ibis/message/serialize/parameters/normal",
 	                test_ibis_message_serialize_parameters_normal);
 	g_test_add_func("/ibis/message/serialize/parameters/last_empty",
