qulogic/pidgin

Parents 1407a0aac0bf
Children 95d36c221e21
IRCv3: Update the signals so that handlers can inhibit the message from being displayed

This was mainly added for DCC neogotiation, but could be useful in other ways.

Testing Done:
Sent `CTCP VERSION` from irssi to a nick and a channel. Also sent `CTCP VERSION` from pidgin 3 to a nick and channel.

Bugs closed: PIDGIN-17721

Reviewed at https://reviews.imfreedom.org/r/2858/
--- a/libpurple/protocols/ircv3/purpleircv3connection.c Mon Dec 04 02:13:29 2023 -0600
+++ b/libpurple/protocols/ircv3/purpleircv3connection.c Mon Dec 04 02:20:09 2023 -0600
@@ -401,6 +401,57 @@
}
/******************************************************************************
+ * Default Handlers
+ *****************************************************************************/
+static gboolean
+purple_ircv3_connection_ctcp_request_default_handler(G_GNUC_UNUSED PurpleIRCv3Connection *connection,
+ G_GNUC_UNUSED PurpleConversation *conversation,
+ PurpleMessage *message,
+ const char *command,
+ const char *params)
+{
+ char *contents = NULL;
+
+ if(!purple_strempty(params)) {
+ contents = g_strdup_printf(_("requested CTCP %s: %s"), command,
+ params);
+ } else {
+ contents = g_strdup_printf(_("requested CTCP %s"),
+ command);
+ }
+
+ purple_message_set_contents(message, contents);
+
+ g_clear_pointer(&contents, g_free);
+
+ return FALSE;
+}
+
+static gboolean
+purple_ircv3_connection_ctcp_response_default_handler(G_GNUC_UNUSED PurpleIRCv3Connection *connection,
+ G_GNUC_UNUSED PurpleConversation *conversation,
+ PurpleMessage *message,
+ const char *command,
+ const char *params)
+{
+ char *contents = NULL;
+
+ if(!purple_strempty(params)) {
+ contents = g_strdup_printf(_("CTCP %s response: %s"), command,
+ params);
+ } else {
+ contents = g_strdup_printf(_("CTCP %s response was empty"),
+ command);
+ }
+
+ purple_message_set_contents(message, contents);
+
+ g_clear_pointer(&contents, g_free);
+
+ return FALSE;
+}
+
+/******************************************************************************
* GObject Implementation
*****************************************************************************/
static void
@@ -595,46 +646,67 @@
/**
* PurpleIRCv3Connection::ctcp-request:
* @connection: The instance.
+ * @conversation: The conversation.
+ * @message: The message.
* @command: The CTCP command.
* @params: (nullable): The CTCP parameters.
*
* This signal is emitted after a CTCP request has been received.
*
+ * Signal handlers should return TRUE if they fully handled the request and
+ * do not want it echoed out to the user.
+ *
+ * Handlers may also modify the message. For example, the CTCP ACTION
+ * command has its message contents replaced with just the CTCP parameters
+ * and sets the [property@Message:action] to %TRUE and then returns %TRUE.
+ *
* Since: 3.0.0
*/
signals[SIG_CTCP_REQUEST] = g_signal_new_class_handler(
"ctcp-request",
G_OBJECT_CLASS_TYPE(klass),
G_SIGNAL_RUN_LAST,
- NULL,
+ G_CALLBACK(purple_ircv3_connection_ctcp_request_default_handler),
+ g_signal_accumulator_true_handled,
NULL,
NULL,
- NULL,
- G_TYPE_NONE,
- 2,
+ G_TYPE_BOOLEAN,
+ 4,
+ PURPLE_TYPE_CONVERSATION,
+ PURPLE_TYPE_MESSAGE,
G_TYPE_STRING,
G_TYPE_STRING);
/**
* PurpleIRCv3Connection::ctcp-response:
* @connection: The instance.
+ * @conversation: The conversation.
+ * @message: The message.
* @command: The CTCP command.
* @params: (nullable): The CTCP parameters.
*
* This signal is emitted after a CTCP response has been received.
*
+ * Signal handlers should return TRUE if they fully handled the response
+ * and do not want it echoed out to the user.
+ *
+ * Handlers may modify @conversation or @message to depending on their
+ * needs.
+ *
* Since: 3.0.0
*/
signals[SIG_CTCP_RESPONSE] = g_signal_new_class_handler(
"ctcp-response",
G_OBJECT_CLASS_TYPE(klass),
G_SIGNAL_RUN_LAST,
- NULL,
+ G_CALLBACK(purple_ircv3_connection_ctcp_response_default_handler),
+ g_signal_accumulator_true_handled,
NULL,
NULL,
- NULL,
- G_TYPE_NONE,
- 2,
+ G_TYPE_BOOLEAN,
+ 4,
+ PURPLE_TYPE_CONVERSATION,
+ PURPLE_TYPE_MESSAGE,
G_TYPE_STRING,
G_TYPE_STRING);
}
@@ -659,28 +731,44 @@
g_type_class_unref(hack);
}
-void
+gboolean
purple_ircv3_connection_emit_ctcp_request(PurpleIRCv3Connection *connection,
+ PurpleConversation *conversation,
+ PurpleMessage *message,
const char *command,
const char *parameters)
{
- g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection));
- g_return_if_fail(!purple_strempty(command));
+ gboolean ret = FALSE;
- g_signal_emit(connection, signals[SIG_CTCP_REQUEST], 0, command,
- parameters);
+ g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), FALSE);
+ g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), FALSE);
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), FALSE);
+ g_return_val_if_fail(!purple_strempty(command), FALSE);
+
+ g_signal_emit(connection, signals[SIG_CTCP_REQUEST], 0, conversation,
+ message, command, parameters, &ret);
+
+ return ret;
}
-void
+gboolean
purple_ircv3_connection_emit_ctcp_response(PurpleIRCv3Connection *connection,
+ PurpleConversation *conversation,
+ PurpleMessage *message,
const char *command,
const char *parameters)
{
- g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection));
- g_return_if_fail(!purple_strempty(command));
+ gboolean ret = FALSE;
- g_signal_emit(connection, signals[SIG_CTCP_RESPONSE], 0, command,
- parameters);
+ g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), FALSE);
+ g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), FALSE);
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), FALSE);
+ g_return_val_if_fail(!purple_strempty(command), FALSE);
+
+ g_signal_emit(connection, signals[SIG_CTCP_RESPONSE], 0, conversation,
+ message, command, parameters, &ret);
+
+ return ret;
}
/******************************************************************************
--- a/libpurple/protocols/ircv3/purpleircv3connection.h Mon Dec 04 02:13:29 2023 -0600
+++ b/libpurple/protocols/ircv3/purpleircv3connection.h Mon Dec 04 02:20:09 2023 -0600
@@ -65,28 +65,46 @@
/**
* purple_ircv3_connection_emit_ctcp_request:
* @connection: The instance.
+ * @conversation: The conversation.
+ * @message: The message.
* @command: The CTCP command.
* @parameters: (nullable): The CTCP parameters.
*
* Emits the [signal@Connection:ctcp-request] signal with the given @command
- * and @parameters.
+ * and @parameters which originated from @message in @conversation.
+ *
+ * The message may be modified by a signal handler. For example, the default
+ * handler will output an internationalized string that describes what command
+ * was requested.
+ *
+ * Returns: %TRUE if the request was handled and the message should not be
+ * echoed, otherwise %FALSE.
*
* Since: 3.0.0
*/
-G_GNUC_INTERNAL void purple_ircv3_connection_emit_ctcp_request(PurpleIRCv3Connection *connection, const char *command, const char *parameters);
+G_GNUC_INTERNAL gboolean purple_ircv3_connection_emit_ctcp_request(PurpleIRCv3Connection *connection, PurpleConversation *conversation, PurpleMessage *message, const char *command, const char *parameters);
/**
* purple_ircv3_connection_emit_ctcp_response:
* @connection: The instance.
+ * @conversation: The conversation.
+ * @message: The message.
* @command: The CTCP command.
* @parameters: (nullable): The CTCP parameters.
*
* Emits the [signal@Connection:ctcp-response] signal with the given @command
- * and @parameters.
+ * and @parameters which originated from @message in @conversation.
+ *
+ * The message may be modified by a signal handler. For example, the default
+ * handler will output an internationalized string that describes what the
+ * response was.
+ *
+ * Returns: %TRUE if the request was handled and the message should not be
+ * echoed, otherwise %FALSE.
*
* Since: 3.0.0
*/
-G_GNUC_INTERNAL void purple_ircv3_connection_emit_ctcp_response(PurpleIRCv3Connection *connection, const char *command, const char *parameters);
+G_GNUC_INTERNAL gboolean purple_ircv3_connection_emit_ctcp_response(PurpleIRCv3Connection *connection, PurpleConversation *conversation, PurpleMessage *message, const char *command, const char *parameters);
/**
* purple_ircv3_connection_writef:
--- a/libpurple/protocols/ircv3/purpleircv3ctcp.c Mon Dec 04 02:13:29 2023 -0600
+++ b/libpurple/protocols/ircv3/purpleircv3ctcp.c Mon Dec 04 02:20:09 2023 -0600
@@ -25,79 +25,66 @@
/******************************************************************************
* Internal API
*****************************************************************************/
-void
+gboolean
purple_ircv3_ctcp_handle(PurpleIRCv3Connection *connection,
+ PurpleConversation *conversation,
PurpleMessage *message)
{
- const char *contents = NULL;
-
- g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection));
- g_return_if_fail(PURPLE_IS_MESSAGE(message));
+ PurpleMessageFlags flags;
+ char *command = NULL;
+ char *params = NULL;
+ char *ptr = NULL;
+ const char *contents = NULL;
+ gboolean ret = FALSE;
- contents = purple_message_get_contents(message);
- if(contents != NULL && contents[0] == PURPLE_IRCV3_CTCP_DELIMITER) {
- PurpleMessageFlags flags;
- char *command = NULL;
- char *contents = NULL;
- char *params = NULL;
- char *ptr = NULL;
-
- /* Move past the delimiter. */
- contents += 1;
+ g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), FALSE);
+ g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), FALSE);
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), FALSE);
- /* Find the delimiter for the command. */
- ptr = g_strstr_len(contents, -1, " ");
-
- /* If we don't have a space, then we have no parameters. */
- if(ptr == NULL) {
- size_t len = strlen(contents);
+ contents = purple_message_get_contents(message);
+ if(contents == NULL || contents[0] != PURPLE_IRCV3_CTCP_DELIMITER) {
+ return FALSE;
+ }
- command = g_strdup(contents);
- if(command[len - 1] == PURPLE_IRCV3_CTCP_DELIMITER) {
- command[len - 1] = '\0';
- }
- } else {
- size_t len = 0;
+ /* Move past the delimiter. */
+ contents += 1;
- command = g_strndup(contents, ptr - contents);
+ /* Find the delimiter for the command. */
+ ptr = g_strstr_len(contents, -1, " ");
+
+ /* If we don't have a space, then we have no parameters. */
+ if(ptr == NULL) {
+ size_t len = strlen(contents);
- params = g_strdup(ptr + 1);
- len = strlen(params);
- if(params[len - 1] == PURPLE_IRCV3_CTCP_DELIMITER) {
- params[len - 1] = '\0';
- }
- }
+ command = g_strdup(contents);
+ if(command[len - 1] == PURPLE_IRCV3_CTCP_DELIMITER) {
+ command[len - 1] = '\0';
+ }
+ } else {
+ size_t len = 0;
- flags = purple_message_get_flags(message);
- if(flags & PURPLE_MESSAGE_NOTIFY) {
- if(!purple_strempty(params)) {
- contents = g_strdup_printf(_("CTCP %s response: %s"), command,
- params);
- } else {
- contents = g_strdup_printf(_("CTCP %s response was empty"),
- command);
- }
+ command = g_strndup(contents, ptr - contents);
+
+ params = g_strdup(ptr + 1);
+ len = strlen(params);
+ if(params[len - 1] == PURPLE_IRCV3_CTCP_DELIMITER) {
+ params[len - 1] = '\0';
+ }
+ }
- purple_ircv3_connection_emit_ctcp_response(connection, command,
- params);
- } else {
- if(!purple_strempty(params)) {
- contents = g_strdup_printf(_("requested CTCP %s: %s"), command,
- params);
- } else {
- contents = g_strdup_printf(_("requested CTCP %s"), command);
- }
+ flags = purple_message_get_flags(message);
+ if(flags & PURPLE_MESSAGE_NOTIFY) {
+ ret = purple_ircv3_connection_emit_ctcp_response(connection,
+ conversation, message,
+ command, params);
+ } else {
+ ret = purple_ircv3_connection_emit_ctcp_request(connection, conversation,
+ message, command,
+ params);
+ }
- purple_ircv3_connection_emit_ctcp_request(connection, command,
- params);
- }
+ g_clear_pointer(&command, g_free);
+ g_clear_pointer(&params, g_free);
- if(!purple_strempty(contents)) {
- purple_message_set_contents(message, contents);
- }
-
- g_clear_pointer(&contents, g_free);
- g_clear_pointer(&command, g_free);
- g_clear_pointer(&params, g_free);
- }
+ return ret;
}
--- a/libpurple/protocols/ircv3/purpleircv3ctcp.h Mon Dec 04 02:13:29 2023 -0600
+++ b/libpurple/protocols/ircv3/purpleircv3ctcp.h Mon Dec 04 02:20:09 2023 -0600
@@ -34,15 +34,18 @@
/**
* purple_ircv3_ctcp_handle: (skip)
- * @connection: The connection instance.
- * @message: The message instance.
+ * @connection: The connection.
+ * @conversation: The conversation.
+ * @message: The message.
*
* Check if @message is a CTCP message and handles it accordingly.
*
+ * Returns: %TRUE if the message was a CTCP message and %FALSE otherwise.
+ *
* Since: 3.0.0
*/
G_GNUC_INTERNAL
-void purple_ircv3_ctcp_handle(PurpleIRCv3Connection *connection, PurpleMessage *message);
+gboolean purple_ircv3_ctcp_handle(PurpleIRCv3Connection *connection, PurpleConversation *conversation, PurpleMessage *message);
G_END_DECLS
--- a/libpurple/protocols/ircv3/purpleircv3messagehandlers.c Mon Dec 04 02:13:29 2023 -0600
+++ b/libpurple/protocols/ircv3/purpleircv3messagehandlers.c Mon Dec 04 02:20:09 2023 -0600
@@ -229,9 +229,9 @@
g_date_time_unref(dt);
/* Check if this is a CTCP message. */
- purple_ircv3_ctcp_handle(connection, message);
-
- purple_conversation_write_message(conversation, message);
+ if(!purple_ircv3_ctcp_handle(connection, conversation, message)) {
+ purple_conversation_write_message(conversation, message);
+ }
g_clear_pointer(&nick, g_free);
g_clear_object(&message);