diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2023-07-12 18:28:29 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2023-07-12 18:58:30 +0200 |
commit | f46f75997518a2bf1f37718a8255e2be2be1e961 (patch) | |
tree | f3a32bb015e0820b2071e205a4d1900ee0805c86 /src/plugins | |
parent | 5d222c8d5c419bf3e0e62a15809cabe95793b691 (diff) | |
download | weechat-f46f75997518a2bf1f37718a8255e2be2be1e961.zip |
irc: evaluate options irc.ctcp.* (issue #1974)
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/irc/irc-config.c | 59 | ||||
-rw-r--r-- | src/plugins/irc/irc-config.h | 2 | ||||
-rw-r--r-- | src/plugins/irc/irc-ctcp.c | 239 | ||||
-rw-r--r-- | src/plugins/irc/irc-ctcp.h | 5 |
4 files changed, 185 insertions, 120 deletions
diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c index 0fde4767b..36c564f94 100644 --- a/src/plugins/irc/irc-config.c +++ b/src/plugins/irc/irc-config.c @@ -1594,15 +1594,19 @@ irc_config_ctcp_create_option_cb (const void *pointer, void *data, config_file, section, option_name, "string", _("format for CTCP reply or empty string for blocking " - "CTCP (no reply), following variables are replaced: " - "$version (WeeChat version), " - "$compilation (compilation date), " - "$osinfo (info about OS), " - "$site (WeeChat site), " - "$download (WeeChat site, download page), " - "$time (current date and time as text), " - "$username (username on server), " - "$realname (realname on server)"), + "CTCP (no reply); content is evaluated, see /help eval; " + "following variables are replaced: " + "${clientinfo}: list of supported CTCP, " + "${version}: WeeChat version, " + "${git}: Git version, " + "${versiongit}: WeeChat version and Git version, " + "${compilation}: compilation date, " + "${osinfo}: info about OS, " + "${site}: WeeChat site, " + "${download}: WeeChat site, download page, " + "${time}: current date and time as text, " + "${username}: username on server, " + "${realname}: realname on server"), NULL, 0, 0, default_value, value, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); rc = (ptr_option) ? @@ -2796,8 +2800,8 @@ irc_config_update_cb (const void *pointer, void *data, int version_read, struct t_hashtable *data_read) { - const char *ptr_section, *ptr_option; - char *new_option, *pos_option; + const char *ptr_section, *ptr_option, *ptr_value; + char *new_option, *pos_option, *new_value; int changes; /* make C compiler happy */ @@ -2871,6 +2875,39 @@ irc_config_update_cb (const void *pointer, void *data, } } + if (version_read < 3) + { + /* + * changes in v3: + * - options "irc.ctcp.*" are now evaluated + * (eg: "$version" -> "${version"}) + */ + ptr_section = weechat_hashtable_get (data_read, "section"); + ptr_option = weechat_hashtable_get (data_read, "option"); + ptr_value = weechat_hashtable_get (data_read, "value"); + if (ptr_section + && ptr_option + && ptr_value + && ptr_value[0] + && (strcmp (ptr_section, "ctcp") == 0)) + { + new_value = irc_ctcp_convert_legacy_format (ptr_value); + if (new_value && (strcmp (ptr_value, new_value) != 0)) + { + weechat_printf ( + NULL, + _("IRC CTCP format converted for \"%s\": \"%s\" => \"%s\""), + ptr_option, + ptr_value, + new_value); + weechat_hashtable_set (data_read, "value", new_value); + changes++; + } + if (new_value) + free (new_value); + } + } + return (changes) ? data_read : NULL; } diff --git a/src/plugins/irc/irc-config.h b/src/plugins/irc/irc-config.h index 51f845f19..3a9e8b899 100644 --- a/src/plugins/irc/irc-config.h +++ b/src/plugins/irc/irc-config.h @@ -23,7 +23,7 @@ #define IRC_CONFIG_NAME "irc" #define IRC_CONFIG_PRIO_NAME (TO_STR(IRC_PLUGIN_PRIORITY) "|" IRC_CONFIG_NAME) -#define IRC_CONFIG_VERSION 2 +#define IRC_CONFIG_VERSION 3 enum t_irc_config_look_server_buffer { diff --git a/src/plugins/irc/irc-ctcp.c b/src/plugins/irc/irc-ctcp.c index 7f5a11a25..ead48458d 100644 --- a/src/plugins/irc/irc-ctcp.c +++ b/src/plugins/irc/irc-ctcp.c @@ -41,17 +41,67 @@ struct t_irc_ctcp_reply irc_ctcp_default_reply[] = -{ { "clientinfo", "$clientinfo" }, - { "finger", "WeeChat $version" }, - { "source", "$download" }, - { "time", "$time" }, - { "userinfo", "$username ($realname)" }, - { "version", "WeeChat $version" }, +{ { "clientinfo", "${clientinfo}" }, + { "finger", "WeeChat ${version}" }, + { "source", "${download}" }, + { "time", "${time}" }, + { "userinfo", "${username} (${realname})" }, + { "version", "WeeChat ${version}" }, { NULL, NULL }, }; /* + * Converts old CTCP format, by converting format "$xxx" to "${xxx}" + * (new CTCP formats are evaluated). + * + * Note: result must be freed after use. + */ + +char * +irc_ctcp_convert_legacy_format (const char *format) +{ + int i; + char *str, *str2, old_format[256], new_format[256]; + char *ctcp_legacy_vars[] = { + "clientinfo", + "versiongit", + "version", + "git", + "osinfo", + "site", + "download", + "username", + "realname", + "date", + "time", + NULL, + }; + + if (!format) + return NULL; + + str = strdup (format);; + str2 = NULL; + + for (i = 0; ctcp_legacy_vars[i]; i++) + { + snprintf (old_format, sizeof (old_format), + "$%s", + ctcp_legacy_vars[i]); + snprintf (new_format, sizeof (new_format), + "${%s}", + ctcp_legacy_vars[i]); + str2 = weechat_string_replace (str, old_format, new_format); + if (str) + free (str); + str = str2; + } + + return str; +} + +/* * Gets default reply for a CTCP query. * * Returns NULL if CTCP is unknown. @@ -378,44 +428,58 @@ end: } /* - * Replaces variables in CTCP format. + * Evaluates CTCP reply format. * * Note: result must be freed after use. */ char * -irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) +irc_ctcp_eval_reply (struct t_irc_server *server, const char *format) { - char *res, *temp, *username, *realname, *info, *info2; + struct t_hashtable *extra_vars; + char *info, *info_version, *info_version_git, *username, *realname; + char buf[4096], *value; time_t now; struct tm *local_time; - char buf[4096]; struct utsname *buf_uname; + if (!server || !format) + return NULL; + + extra_vars = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (!extra_vars) + return NULL; + /* * $clientinfo: supported CTCP, example: * ACTION DCC CLIENTINFO FINGER PING SOURCE TIME USERINFO VERSION */ - temp = weechat_string_replace ( - format, "$clientinfo", - "ACTION DCC CLIENTINFO FINGER PING SOURCE TIME USERINFO VERSION"); - if (!temp) - return NULL; - res = temp; + weechat_hashtable_set (extra_vars, "clientinfo", + "ACTION DCC CLIENTINFO FINGER PING SOURCE TIME " + "USERINFO VERSION"); + + info_version = weechat_info_get ("version", ""); + info_version_git = weechat_info_get ("version_git", ""); + + /* + * $version: WeeChat version, examples: + * 0.3.9 + * 0.4.0-dev + */ + if (info_version) + weechat_hashtable_set (extra_vars, "version", info_version); /* * $git: git version (output of "git describe" for a development version * only, empty string if unknown), example: * v0.3.9-104-g7eb5cc4 */ - info = weechat_info_get ("version_git", ""); - temp = weechat_string_replace (res, "$git", info); - free (res); - if (info) - free (info); - if (!temp) - return NULL; - res = temp; + if (info_version_git) + weechat_hashtable_set (extra_vars, "git", info_version_git); /* * $versiongit: WeeChat version + git version (if known), examples: @@ -423,49 +487,24 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) * 0.4.0-dev * 0.4.0-dev (git: v0.3.9-104-g7eb5cc4) */ - info = weechat_info_get ("version_git", ""); - info2 = weechat_info_get ("version", ""); - snprintf (buf, sizeof (buf), "%s%s%s%s", - info2, - (info && info[0]) ? " (git: " : "", - (info && info[0]) ? info : "", - (info && info[0]) ? ")" : ""); - temp = weechat_string_replace (res, "$versiongit", buf); - free (res); - if (info) - free (info); - if (info2) - free (info2); - if (!temp) - return NULL; - res = temp; - - /* - * $version: WeeChat version, examples: - * 0.3.9 - * 0.4.0-dev - */ - info = weechat_info_get ("version", ""); - temp = weechat_string_replace (res, "$version", info); - free (res); - if (info) - free (info); - if (!temp) - return NULL; - res = temp; + if (info_version && info_version_git) + { + snprintf (buf, sizeof (buf), "%s (git: %s)", + info_version, + info_version_git); + weechat_hashtable_set (extra_vars, "versiongit", buf); + } /* * $compilation: compilation date, example: * Dec 16 2012 */ info = weechat_info_get ("date", ""); - temp = weechat_string_replace (res, "$compilation", info); - free (res); if (info) + { + weechat_hashtable_set (extra_vars, "compilation", info); free (info); - if (!temp) - return NULL; - res = temp; + } /* * $osinfo: info about OS, example: @@ -476,19 +515,15 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) { if (uname (buf_uname) >= 0) { - snprintf (buf, sizeof (buf), "%s %s / %s", - buf_uname->sysname, buf_uname->release, + snprintf (buf, sizeof (buf), + "%s %s / %s", + buf_uname->sysname, + buf_uname->release, buf_uname->machine); - temp = weechat_string_replace (res, "$osinfo", buf); - free (res); - if (!temp) - { - free (buf_uname); - return NULL; - } - res = temp; + weechat_hashtable_set (extra_vars, "osinfo", buf); } - free (buf_uname); + if (buf_uname) + free (buf_uname); } /* @@ -496,26 +531,22 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) * https://weechat.org/ */ info = weechat_info_get ("weechat_site", ""); - temp = weechat_string_replace (res, "$site", info); - free (res); if (info) + { + weechat_hashtable_set (extra_vars, "site", info); free (info); - if (!temp) - return NULL; - res = temp; + } /* * $download: WeeChat download page, example: * https://weechat.org/download/ */ info = weechat_info_get ("weechat_site_download", ""); - temp = weechat_string_replace (res, "$download", info); - free (res); if (info) + { + weechat_hashtable_set (extra_vars, "download", info); free (info); - if (!temp) - return NULL; - res = temp; + } /* * $time: local date/time of user, example: @@ -529,11 +560,7 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) local_time) == 0) buf[0] = '\0'; setlocale (LC_ALL, ""); - temp = weechat_string_replace (res, "$time", buf); - free (res); - if (!temp) - return NULL; - res = temp; + weechat_hashtable_set (extra_vars, "time", buf); /* * $username: user name, example: @@ -544,11 +571,7 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME)); if (username) { - temp = weechat_string_replace (res, "$username", username); - free (res); - if (!temp) - return NULL; - res = temp; + weechat_hashtable_set (extra_vars, "username", username); free (username); } @@ -561,16 +584,20 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME)); if (realname) { - temp = weechat_string_replace (res, "$realname", realname); - free (res); - if (!temp) - return NULL; - res = temp; + weechat_hashtable_set (extra_vars, "realname", realname); free (realname); } - /* return result */ - return res; + value = weechat_string_eval_expression (format, NULL, extra_vars, NULL); + + if (info_version) + free (info_version); + if (info_version_git) + free (info_version_git); + + weechat_hashtable_free (extra_vars); + + return value; } /* @@ -1048,7 +1075,7 @@ irc_ctcp_recv (struct t_irc_server *server, time_t date, const char *arguments, const char *message) { char *dup_arguments, *ptr_args, *pos_end, *pos_space, *pos_args; - char *nick_color, *decoded_reply; + char *nick_color, *reply_eval; const char *reply; struct t_irc_channel *ptr_channel; struct t_irc_nick *ptr_nick; @@ -1213,13 +1240,13 @@ irc_ctcp_recv (struct t_irc_server *server, time_t date, { if (reply) { - decoded_reply = irc_ctcp_replace_variables (server, reply); - if (decoded_reply) + reply_eval = irc_ctcp_eval_reply (server, reply); + if (reply_eval) { irc_ctcp_reply_to_nick (server, tags, command, channel, nick, ptr_args + 1, - decoded_reply); - free (decoded_reply); + reply_eval); + free (reply_eval); } } else @@ -1246,13 +1273,13 @@ irc_ctcp_recv (struct t_irc_server *server, time_t date, if (reply[0]) { - decoded_reply = irc_ctcp_replace_variables (server, reply); - if (decoded_reply) + reply_eval = irc_ctcp_eval_reply (server, reply); + if (reply_eval) { irc_ctcp_reply_to_nick (server, tags, command, channel, nick, ptr_args + 1, - decoded_reply); - free (decoded_reply); + reply_eval); + free (reply_eval); } } } diff --git a/src/plugins/irc/irc-ctcp.h b/src/plugins/irc/irc-ctcp.h index c2b165f05..2a7eb24f2 100644 --- a/src/plugins/irc/irc-ctcp.h +++ b/src/plugins/irc/irc-ctcp.h @@ -33,6 +33,7 @@ struct t_irc_ctcp_reply extern struct t_irc_ctcp_reply irc_ctcp_default_reply[]; +extern char *irc_ctcp_convert_legacy_format (const char *format); extern const char *irc_ctcp_get_default_reply (const char *ctcp); extern const char *irc_ctcp_get_reply (struct t_irc_server *server, const char *ctcp); @@ -43,8 +44,8 @@ extern void irc_ctcp_display_reply_from_nick (struct t_irc_server *server, const char *nick, const char *address, const char *arguments); -extern char *irc_ctcp_replace_variables (struct t_irc_server *server, - const char *format); +extern char *irc_ctcp_eval_reply (struct t_irc_server *server, + const char *format); extern void irc_ctcp_recv (struct t_irc_server *server, time_t date, struct t_hashtable *tags, const char *command, struct t_irc_channel *channel, const char *target, |