From 9237852b262226fe74fe893909c6b30a699d3779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Wed, 12 Jul 2023 18:58:51 +0200 Subject: [PATCH] irc: build dynamically the list of CTCPs supported in reply to "CTCP CLIENTINFO" (issue #1974) --- ChangeLog.adoc | 1 + src/plugins/irc/irc-ctcp.c | 126 ++++++++++++++++++- tests/unit/plugins/irc/test-irc-ctcp.cpp | 42 ++++++- tests/unit/plugins/irc/test-irc-protocol.cpp | 12 +- 4 files changed, 171 insertions(+), 10 deletions(-) diff --git a/ChangeLog.adoc b/ChangeLog.adoc index 54526d6a8a3..bb34b59c21c 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -24,6 +24,7 @@ New features:: * irc: display commands 716/717 in private buffer (if present) (issue #146) * irc: create default options irc.ctcp.* when file irc.conf is created (issue #1974) * irc: evaluate options irc.ctcp.* (issue #1974) + * irc: build dynamically the list of CTCPs supported in reply to "CTCP CLIENTINFO" (issue #1974) * irc: remove Git revision and compilation date from CTCP VERSION/FINGER reply (issue #1974) * trigger: add options `-o`, `-ol`, `-i` and `-il` in command `/trigger list` (issue #1953) diff --git a/src/plugins/irc/irc-ctcp.c b/src/plugins/irc/irc-ctcp.c index ead48458da7..16872894555 100644 --- a/src/plugins/irc/irc-ctcp.c +++ b/src/plugins/irc/irc-ctcp.c @@ -427,6 +427,123 @@ irc_ctcp_reply_to_nick (struct t_irc_server *server, weechat_arraylist_free (list_messages); } +/* + * Compares two CTCPs in arraylist. + */ + +int +irc_ctcp_list_ctcp_cmp_cb (void *data, struct t_arraylist *arraylist, + void *pointer1, void *pointer2) +{ + /* make C compiler happy */ + (void) data; + (void) arraylist; + + return weechat_strcasecmp ((const char *)pointer1, (const char *)pointer2); +} + +/* + * Frees a CTCP in arraylist. + */ + +void +irc_ctcp_list_ctcp_free_cb (void *data, struct t_arraylist *arraylist, + void *pointer) +{ + /* make C compiler happy */ + (void) data; + (void) arraylist; + + free (pointer); +} + +/* + * Returns list of supported/configured CTCP replies, aggregation of these + * lists: + * + * - list of default CTCP replies (if not blocked) + * - list of CTCP replies defined in options irc.ctcp.* (if not blocked) + * - other CTCP: ACTION, DCC, PING. + * + * The list returned is a string with multiple CTCP (upper case) separated by + * spaces. + * + * Note: result must be freed after use. + */ + +char * +irc_ctcp_get_supported_ctcp (struct t_irc_server *server) +{ + struct t_arraylist *list_ctcp; + struct t_hdata *hdata_config_section, *hdata_config_option; + struct t_config_option *ptr_option; + const char *reply, *ptr_name; + char *ctcp_upper, **result; + int i, list_size; + + list_ctcp = weechat_arraylist_new (16, 1, 0, + &irc_ctcp_list_ctcp_cmp_cb, NULL, + &irc_ctcp_list_ctcp_free_cb, NULL); + if (!list_ctcp) + return NULL; + + /* add default CTCPs */ + for (i = 0; irc_ctcp_default_reply[i].name; i++) + { + reply = irc_ctcp_get_reply (server, irc_ctcp_default_reply[i].name); + if (reply && reply[0]) + { + weechat_arraylist_add (list_ctcp, + strdup (irc_ctcp_default_reply[i].name)); + } + } + + /* add customized CTCPs */ + hdata_config_section = weechat_hdata_get ("config_section"); + hdata_config_option = weechat_hdata_get ("config_option"); + ptr_option = weechat_hdata_pointer (hdata_config_section, + irc_config_section_ctcp, + "options"); + while (ptr_option) + { + ptr_name = weechat_hdata_string (hdata_config_option, ptr_option, "name"); + if (ptr_name) + { + reply = irc_ctcp_get_reply (server, ptr_name); + if (reply && reply[0]) + weechat_arraylist_add (list_ctcp, strdup (ptr_name)); + } + ptr_option = weechat_hdata_move (hdata_config_option, ptr_option, 1); + } + + /* add other CTCPs */ + weechat_arraylist_add (list_ctcp, strdup ("action")); + weechat_arraylist_add (list_ctcp, strdup ("dcc")); + weechat_arraylist_add (list_ctcp, strdup ("ping")); + + result = weechat_string_dyn_alloc (128); + if (result) + { + list_size = weechat_arraylist_size (list_ctcp); + for (i = 0; i < list_size; i++) + { + ctcp_upper = weechat_string_toupper ( + (const char *)weechat_arraylist_get (list_ctcp, i)); + if (ctcp_upper) + { + if (*result[0]) + weechat_string_dyn_concat (result, " ", -1); + weechat_string_dyn_concat (result, ctcp_upper, -1); + free (ctcp_upper); + } + } + } + + weechat_arraylist_free (list_ctcp); + + return (result) ? weechat_string_dyn_free (result, 0) : NULL; +} + /* * Evaluates CTCP reply format. * @@ -458,9 +575,12 @@ irc_ctcp_eval_reply (struct t_irc_server *server, const char *format) * $clientinfo: supported CTCP, example: * ACTION DCC CLIENTINFO FINGER PING SOURCE TIME USERINFO VERSION */ - weechat_hashtable_set (extra_vars, "clientinfo", - "ACTION DCC CLIENTINFO FINGER PING SOURCE TIME " - "USERINFO VERSION"); + info = irc_ctcp_get_supported_ctcp (server); + if (info) + { + weechat_hashtable_set (extra_vars, "clientinfo", info); + free (info); + } info_version = weechat_info_get ("version", ""); info_version_git = weechat_info_get ("version_git", ""); diff --git a/tests/unit/plugins/irc/test-irc-ctcp.cpp b/tests/unit/plugins/irc/test-irc-ctcp.cpp index 4267aff07e8..6fd4a67753b 100644 --- a/tests/unit/plugins/irc/test-irc-ctcp.cpp +++ b/tests/unit/plugins/irc/test-irc-ctcp.cpp @@ -31,6 +31,8 @@ extern "C" #include "src/plugins/irc/irc-config.h" #include "src/plugins/irc/irc-ctcp.h" #include "src/plugins/irc/irc-server.h" + +extern char *irc_ctcp_get_supported_ctcp (struct t_irc_server *server); } TEST_GROUP(IrcCtcp) @@ -109,6 +111,44 @@ TEST(IrcCtcp, IrcCtcpReplyToNick) /* TODO: write tests */ } +/* + * Tests functions: + * irc_ctcp_get_supported_ctcp + */ + +TEST(IrcCtcp, IrcCtcpGetSupportedCtcp) +{ + struct t_irc_server *server; + struct t_config_option *ptr_option; + char *str; + + server = irc_server_alloc ("server"); + CHECK(server); + + WEE_TEST_STR("ACTION CLIENTINFO DCC FINGER PING SOURCE TIME USERINFO VERSION", + irc_ctcp_get_supported_ctcp (server)); + + config_file_option_set_with_string ("irc.ctcp.version", ""); + WEE_TEST_STR("ACTION CLIENTINFO DCC FINGER PING SOURCE TIME USERINFO", + irc_ctcp_get_supported_ctcp (server)); + + config_file_option_set_with_string ("irc.ctcp.time", ""); + WEE_TEST_STR("ACTION CLIENTINFO DCC FINGER PING SOURCE USERINFO", + irc_ctcp_get_supported_ctcp (server)); + + config_file_option_set_with_string ("irc.ctcp.version", "test"); + WEE_TEST_STR("ACTION CLIENTINFO DCC FINGER PING SOURCE USERINFO VERSION", + irc_ctcp_get_supported_ctcp (server)); + + config_file_search_with_string ("irc.ctcp.version", NULL, NULL, &ptr_option, NULL); + config_file_option_unset (ptr_option); + + config_file_search_with_string ("irc.ctcp.time", NULL, NULL, &ptr_option, NULL); + config_file_option_unset (ptr_option); + + irc_server_free (server); +} + /* * Tests functions: * irc_ctcp_eval_reply @@ -139,7 +179,7 @@ TEST(IrcCtcp, IrcCtcpEvalReply) WEE_TEST_STR("abc", irc_ctcp_eval_reply (server, "abc")); /* ${clientinfo} */ - WEE_TEST_STR("ACTION DCC CLIENTINFO FINGER PING SOURCE TIME USERINFO VERSION", + WEE_TEST_STR("ACTION CLIENTINFO DCC FINGER PING SOURCE TIME USERINFO VERSION", irc_ctcp_eval_reply (server, "${clientinfo}")); /* ${version} */ diff --git a/tests/unit/plugins/irc/test-irc-protocol.cpp b/tests/unit/plugins/irc/test-irc-protocol.cpp index 6061e5169f5..a1c7ab49590 100644 --- a/tests/unit/plugins/irc/test-irc-protocol.cpp +++ b/tests/unit/plugins/irc/test-irc-protocol.cpp @@ -2953,9 +2953,9 @@ TEST(IrcProtocolWithServer, privmsg) { CHECK_SRV("--", "CTCP requested by alice: CLIENTINFO", "irc_privmsg,irc_ctcp,host_user@host,log1"); - CHECK_SRV("--", "CTCP reply to alice: CLIENTINFO ACTION DCC " - "CLIENTINFO FINGER PING SOURCE TIME USERINFO VERSION", - "irc_privmsg,irc_ctcp,irc_ctcp_reply,self_msg,notify_none," + CHECK_SRV("--", "CTCP reply to alice: CLIENTINFO ACTION CLIENTINFO " + "DCC FINGER PING SOURCE TIME USERINFO VERSION", + "irc_privmsg,irc_ctcp,irc_ctcp_reply,self_msg,notify_none," "no_highlight,log1"); } else @@ -2970,9 +2970,9 @@ TEST(IrcProtocolWithServer, privmsg) RECV(":alice!user@host PRIVMSG alice :\01CLIENTINFO\01"); CHECK_SRV("--", "CTCP requested by alice: CLIENTINFO", "irc_privmsg,irc_ctcp,host_user@host,log1"); - CHECK_SRV("--", "CTCP reply to alice: CLIENTINFO ACTION DCC " - "CLIENTINFO FINGER PING SOURCE TIME USERINFO VERSION", - "irc_privmsg,irc_ctcp,irc_ctcp_reply,self_msg,notify_none," + CHECK_SRV("--", "CTCP reply to alice: CLIENTINFO ACTION CLIENTINFO " + "DCC FINGER PING SOURCE TIME USERINFO VERSION", + "irc_privmsg,irc_ctcp,irc_ctcp_reply,self_msg,notify_none," "no_highlight,log1"); }