# HG changeset patch
# Node ID 1697fab3b016
# Parent  67bd91ac4fab
diff --git a/libpurple/protocols/ircv3/purpleircv3connection.c b/libpurple/protocols/ircv3/purpleircv3connection.c
--- a/libpurple/protocols/ircv3/purpleircv3connection.c
+++ b/libpurple/protocols/ircv3/purpleircv3connection.c
@@ -22,6 +22,7 @@
 
 #include "purpleircv3constants.h"
 #include "purpleircv3core.h"
+#include "purpleircv3ctcp.h"
 #include "purpleircv3formatting.h"
 #include "purpleircv3parser.h"
 
@@ -293,6 +294,9 @@
 
 	g_signal_emit(connection, signals[SIG_REGISTRATION_COMPLETE], 0);
 
+	/* Add our supported CTCP commands. */
+	purple_ircv3_ctcp_add_default_handlers(connection);
+
 	/* Now that registration is complete, rejoin any channels that the
 	 * conversation manager has for us.
 	 */
diff --git a/libpurple/protocols/ircv3/purpleircv3constants.h b/libpurple/protocols/ircv3/purpleircv3constants.h
--- a/libpurple/protocols/ircv3/purpleircv3constants.h
+++ b/libpurple/protocols/ircv3/purpleircv3constants.h
@@ -24,6 +24,15 @@
 #define PURPLE_IRCV3_CONSTANTS_H
 
 /**
+ * PURPLE_IRCV3_CTCP_ACTION:
+ *
+ * A constant representing the CTCP ACTION command.
+ *
+ * Since: 3.0.0
+ */
+#define PURPLE_IRCV3_CTCP_ACTION ("ACTION") PURPLE_IRCV3_AVAILABLE_MACRO_IN_3_0
+
+/**
  * PURPLE_IRCV3_CTCP_DELIMITER:
  *
  * The delimiter used for CTCP messages.
@@ -33,6 +42,15 @@
 #define PURPLE_IRCV3_CTCP_DELIMITER (0x1) PURPLE_IRCV3_AVAILABLE_MACRO_IN_3_0
 
 /**
+ * PURPLE_IRCV3_CTCP_VERSION:
+ *
+ * A constant representing the CTCP VERSION command.
+ *
+ * Since: 3.0.0
+ */
+#define PURPLE_IRCV3_CTCP_VERSION ("VERSION") PURPLE_IRCV3_AVAILABLE_MACRO_IN_3_0
+
+/**
  * PURPLE_IRCV3_ERR_NICKLOCKED:
  *
  * A constant for the IRC %NICKLOCKED error.
diff --git a/libpurple/protocols/ircv3/purpleircv3ctcp.h b/libpurple/protocols/ircv3/purpleircv3ctcp.h
--- a/libpurple/protocols/ircv3/purpleircv3ctcp.h
+++ b/libpurple/protocols/ircv3/purpleircv3ctcp.h
@@ -47,6 +47,17 @@
 G_GNUC_INTERNAL
 gboolean purple_ircv3_ctcp_handle(PurpleIRCv3Connection *connection, PurpleConversation *conversation, PurpleMessage *message);
 
+/**
+ * purple_ircv3_ctcp_add_default_handlers: (skip)
+ * @connection: The connection.
+ *
+ * Adds handlers for the CTCP command that we support directly.
+ *
+ * Since: 3.0.0
+ */
+G_GNUC_INTERNAL
+void purple_ircv3_ctcp_add_default_handlers(PurpleIRCv3Connection *connection);
+
 G_END_DECLS
 
 #endif /* PURPLE_IRCV3_CTCP_H */
diff --git a/libpurple/protocols/ircv3/purpleircv3ctcp.c b/libpurple/protocols/ircv3/purpleircv3ctcp.c
--- a/libpurple/protocols/ircv3/purpleircv3ctcp.c
+++ b/libpurple/protocols/ircv3/purpleircv3ctcp.c
@@ -21,6 +21,66 @@
 #include "purpleircv3ctcp.h"
 
 #include "purpleircv3constants.h"
+#include "purpleircv3source.h"
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+purple_ircv3_ctcp_respond(PurpleIRCv3Connection *connection,
+                          PurpleMessage *message,
+                          const char *response)
+{
+	const char *author = NULL;
+	char *nick = NULL;
+
+	author = purple_message_get_author(message);
+	purple_ircv3_source_parse(author, &nick, NULL, NULL);
+	if(!purple_strempty(nick)) {
+		PurpleContact *contact = NULL;
+
+		contact = purple_ircv3_connection_find_or_create_contact(connection,
+		                                                         nick);
+
+		if(PURPLE_IS_CONTACT(contact)) {
+			const char *id = NULL;
+
+			id = purple_contact_info_get_id(PURPLE_CONTACT_INFO(contact));
+
+			purple_ircv3_connection_writef(connection, "%s %s :%s",
+			                               PURPLE_IRCV3_MSG_NOTICE,
+			                               id,
+			                               response);
+		}
+	}
+
+	g_clear_pointer(&nick, g_free);
+}
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static gboolean
+purple_ircv3_ctcp_handler(PurpleIRCv3Connection *connection,
+                          PurpleConversation *conversation,
+                          PurpleMessage *message,
+                          const char *command,
+                          const char *params,
+                          G_GNUC_UNUSED gpointer data)
+{
+	if(purple_strequal(command, PURPLE_IRCV3_CTCP_ACTION)) {
+		purple_message_set_contents(message, params);
+		purple_message_set_action(message, TRUE);
+
+		purple_conversation_write_message(conversation, message);
+
+		return TRUE;
+	} else if(purple_strequal(command, PURPLE_IRCV3_CTCP_VERSION)) {
+		purple_ircv3_ctcp_respond(connection, message, "Purple3 IRCv3");
+	}
+
+	return FALSE;
+}
 
 /******************************************************************************
  * Internal API
@@ -88,3 +148,9 @@
 
 	return ret;
 }
+
+void
+purple_ircv3_ctcp_add_default_handlers(PurpleIRCv3Connection *connection) {
+	g_signal_connect(connection, "ctcp-request",
+	                 G_CALLBACK(purple_ircv3_ctcp_handler), NULL);
+}
