Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package weechat for openSUSE:Factory checked in at 2025-11-26 17:14:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/weechat (Old) and /work/SRC/openSUSE:Factory/.weechat.new.14147 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "weechat" Wed Nov 26 17:14:44 2025 rev:88 rq:1319853 version:4.7.2 Changes: -------- --- /work/SRC/openSUSE:Factory/weechat/weechat.changes 2025-11-24 14:16:01.150551644 +0100 +++ /work/SRC/openSUSE:Factory/.weechat.new.14147/weechat.changes 2025-11-26 17:14:56.368932986 +0100 @@ -1,0 +2,13 @@ +Tue Nov 25 00:21:56 UTC 2025 - Hunter Wardlaw <[email protected]> + +- Update to 4.7.2: + + Fixed + * api: fix file descriptor leak in hook_url when a timeout occurs + or if the hook is removed during the transfer (#2284) + * irc: fix colors in messages 367 (ban mask), 728 (quiet mask) and + MODE (#2286) + * irc: fix reset of color when multiple modes are set with + command /mode + +------------------------------------------------------------------- Old: ---- weechat-4.7.1.tar.xz weechat-4.7.1.tar.xz.asc New: ---- weechat-4.7.2.tar.xz weechat-4.7.2.tar.xz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ weechat.spec ++++++ --- /var/tmp/diff_new_pack.iipNQ4/_old 2025-11-26 17:14:58.673030122 +0100 +++ /var/tmp/diff_new_pack.iipNQ4/_new 2025-11-26 17:14:58.697031133 +0100 @@ -17,7 +17,7 @@ Name: weechat -Version: 4.7.1 +Version: 4.7.2 Release: 0 Summary: Multi-protocol extensible Chat Client License: GPL-3.0-or-later ++++++ weechat-4.7.1.tar.xz -> weechat-4.7.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/CHANGELOG.md new/weechat-4.7.2/CHANGELOG.md --- old/weechat-4.7.1/CHANGELOG.md 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/CHANGELOG.md 2025-11-23 11:34:17.000000000 +0100 @@ -6,6 +6,14 @@ # WeeChat ChangeLog +## Version 4.7.2 (2025-11-23) + +### Fixed + +- api: fix file descriptor leak in hook_url when a timeout occurs or if the hook is removed during the transfer ([#2284](https://github.com/weechat/weechat/issues/2284)) +- irc: fix colors in messages 367 (ban mask), 728 (quiet mask) and MODE ([#2286](https://github.com/weechat/weechat/issues/2286)) +- irc: fix reset of color when multiple modes are set with command `/mode` + ## Version 4.7.1 (2025-08-16) ### Fixed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/doc/en/weechat_plugin_api.en.adoc new/weechat-4.7.2/doc/en/weechat_plugin_api.en.adoc --- old/weechat-4.7.1/doc/en/weechat_plugin_api.en.adoc 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/doc/en/weechat_plugin_api.en.adoc 2025-11-23 11:34:17.000000000 +0100 @@ -11064,6 +11064,16 @@ *** _headers_: HTTP headers in response *** _output_: standard output (set only if _file_out_ was not set in options) *** _error_: error message (set only in case of error) +*** _error_code_: error code (integer, set only in case of error): +**** `1`: invalid URL +**** `2`: transfer error (Curl error) +**** `3`: not enough memory +**** `4`: file error +**** `5`: transfer stopped (hook removed during the transfer) +**** `6`: transfer timeout +**** `100`: thread creation error +*** _error_code_pthread_: return code of function _pthread_create_ + (integer, set only if _error_code_ is `100`) ** return value: *** _WEECHAT_RC_OK_ *** _WEECHAT_RC_ERROR_ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/doc/fr/weechat_plugin_api.fr.adoc new/weechat-4.7.2/doc/fr/weechat_plugin_api.fr.adoc --- old/weechat-4.7.1/doc/fr/weechat_plugin_api.fr.adoc 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/doc/fr/weechat_plugin_api.fr.adoc 2025-11-23 11:34:17.000000000 +0100 @@ -11270,6 +11270,16 @@ *** _output_ : sortie standard (défini seulement si _file_out_ n'était pas défini dans les options) *** _error_ : message d'erreur (défini seulement en cas d'erreur) +*** _error_code_ : code d'erreur (entier, défini seulement en cas d'erreur) : +**** `1` : URL invalide +**** `2` : erreur de transfert (erreur Curl) +**** `3` : mémoire insuffisante +**** `4` : erreur de fichier +**** `5` : transfert stoppé (hook supprimé durant le transfert) +**** `6` : délai d'attente dépassé pour le transfert ("timeout") +**** `100` : erreur de création du thread +*** _error_code_pthread_ : code retour de la fonction _pthread_create_ + (entier, défini seulement si _error_code_ vaut `100`) ** valeur de retour : *** _WEECHAT_RC_OK_ *** _WEECHAT_RC_ERROR_ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/doc/it/weechat_plugin_api.it.adoc new/weechat-4.7.2/doc/it/weechat_plugin_api.it.adoc --- old/weechat-4.7.1/doc/it/weechat_plugin_api.it.adoc 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/doc/it/weechat_plugin_api.it.adoc 2025-11-23 11:34:17.000000000 +0100 @@ -11475,6 +11475,16 @@ *** _headers_: HTTP headers in response *** _output_: standard output (set only if _file_out_ was not set in options) *** _error_: error message (set only in case of error) +*** _error_code_: error code (integer, set only in case of error): +**** `1`: invalid URL +**** `2`: transfer error (Curl error) +**** `3`: not enough memory +**** `4`: file error +**** `5`: transfer stopped (hook removed during the transfer) +**** `6`: transfer timeout +**** `100`: thread creation error +*** _error_code_pthread_: return code of function _pthread_create_ + (integer, set only if _error_code_ is `100`) ** return value: *** _WEECHAT_RC_OK_ *** _WEECHAT_RC_ERROR_ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/doc/ja/weechat_plugin_api.ja.adoc new/weechat-4.7.2/doc/ja/weechat_plugin_api.ja.adoc --- old/weechat-4.7.1/doc/ja/weechat_plugin_api.ja.adoc 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/doc/ja/weechat_plugin_api.ja.adoc 2025-11-23 11:34:17.000000000 +0100 @@ -11209,6 +11209,16 @@ *** _headers_: HTTP headers in response *** _output_: standard output (set only if _file_out_ was not set in options) *** _error_: error message (set only in case of error) +*** _error_code_: error code (integer, set only in case of error): +**** `1`: invalid URL +**** `2`: transfer error (Curl error) +**** `3`: not enough memory +**** `4`: file error +**** `5`: transfer stopped (hook removed during the transfer) +**** `6`: transfer timeout +**** `100`: thread creation error +*** _error_code_pthread_: return code of function _pthread_create_ + (integer, set only if _error_code_ is `100`) ** return value: *** _WEECHAT_RC_OK_ *** _WEECHAT_RC_ERROR_ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/doc/sr/weechat_plugin_api.sr.adoc new/weechat-4.7.2/doc/sr/weechat_plugin_api.sr.adoc --- old/weechat-4.7.1/doc/sr/weechat_plugin_api.sr.adoc 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/doc/sr/weechat_plugin_api.sr.adoc 2025-11-23 11:34:17.000000000 +0100 @@ -10781,6 +10781,16 @@ *** _headers_: HTTP заглавља у одзиву *** _output_: стандардни излаз (поставља се само ако у опцијама није постављено _file_out_) *** _error_: порука о грешки (поставља се само у случају грешке) +*** _error_code_: error code (integer, set only in case of error): +**** `1`: invalid URL +**** `2`: transfer error (Curl error) +**** `3`: not enough memory +**** `4`: file error +**** `5`: transfer stopped (hook removed during the transfer) +**** `6`: transfer timeout +**** `100`: thread creation error +*** _error_code_pthread_: return code of function _pthread_create_ + (integer, set only if _error_code_ is `100`) ** повратна вредност: *** _WEECHAT_RC_OK_ *** _WEECHAT_RC_ERROR_ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/src/core/core-url.c new/weechat-4.7.2/src/core/core-url.c --- old/weechat-4.7.1/src/core/core-url.c 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/src/core/core-url.c 2025-11-23 11:34:17.000000000 +0100 @@ -37,6 +37,7 @@ #include "core-infolist.h" #include "core-proxy.h" #include "core-string.h" +#include "core-util.h" #include "../plugins/plugin.h" @@ -653,7 +654,9 @@ URL_DEF_OPTION(SSLENGINE_DEFAULT, LONG, NULL), URL_DEF_OPTION(CAPATH, STRING, NULL), URL_DEF_OPTION(SSL_SESSIONID_CACHE, LONG, NULL), +#if LIBCURL_VERSION_NUM < 0x081100 /* < 8.17.0 */ URL_DEF_OPTION(KRBLEVEL, STRING, NULL), +#endif URL_DEF_OPTION(KEYPASSWD, STRING, NULL), URL_DEF_OPTION(ISSUERCERT, STRING, NULL), URL_DEF_OPTION(CRLFILE, STRING, NULL), @@ -1046,31 +1049,46 @@ * output | stdout (set only if "file_out" was not set in options) * error | error message (set only in case of error) * + * If timeout is 0, the function blocks until the end of the transfer. + * If timeout (in milliseconds) is > 0, the function returns an error in the + * output hashtable if the timeout is reached while the transfer is still + * active. + * + * If stop_download is not NULL, it is checked regularly, and as soon as the + * pointed integer becomes different from 0 (set by the caller of this function), + * the download is immediately stopped with an error. + * * Returns: * 0: OK * 1: invalid URL * 2: error downloading URL * 3: not enough memory * 4: file error + * 5: transfer stopped by the caller + * 6: transfer timeout */ int weeurl_download (const char *url, struct t_hashtable *options, - struct t_hashtable *output) + long timeout, struct t_hashtable *output, + int *stop_transfer) { CURL *curl; + CURLM *multi; + CURLMcode curl_mc; struct t_url_file url_file[2]; char *url_file_option[2] = { "file_in", "file_out" }; char *url_file_mode[2] = { "rb", "wb" }; - char url_error[CURL_ERROR_SIZE + 1], url_error_code[12]; + char url_error[4096], url_error_code[12]; char **string_headers, **string_output; char str_response_code[32]; CURLoption url_file_opt_func[2] = { CURLOPT_READFUNCTION, CURLOPT_WRITEFUNCTION }; CURLoption url_file_opt_data[2] = { CURLOPT_READDATA, CURLOPT_WRITEDATA }; void *url_file_opt_cb[2] = { &weeurl_read_stream, &weeurl_write_stream }; struct t_proxy *ptr_proxy; - int rc, curl_rc, i, output_to_file; + int rc, i, output_to_file, still_running; long response_code; + struct timeval tv_now, tv_end; rc = 0; @@ -1169,44 +1187,120 @@ /* set error buffer */ curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, url_error); - /* perform action! */ - curl_rc = curl_easy_perform (curl); - if (curl_rc == CURLE_OK) + /* compute end time for transfer, according to the timeout */ + if (timeout > 0) { - if (output) - { - curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response_code); - snprintf (str_response_code, sizeof (str_response_code), - "%ld", response_code); - hashtable_set (output, "response_code", str_response_code); - } + gettimeofday (&tv_end, NULL); + util_timeval_add (&tv_end, ((long long)timeout) * 1000); } else { - if (output) + tv_end.tv_sec = 0; + tv_end.tv_usec = 0; + } + + /* start the transfer */ + multi = curl_multi_init (); + curl_multi_add_handle (multi, curl); + while (1) + { + curl_mc = curl_multi_perform (multi, &still_running); + + if ((curl_mc == CURLM_OK) && still_running) + curl_mc = curl_multi_poll (multi, NULL, 0, 5, NULL); + + if (curl_mc != CURLM_OK) + { + if (output) + { + snprintf (url_error_code, sizeof (url_error_code), "%d", curl_mc); + if (!url_error[0]) + { + snprintf (url_error, sizeof (url_error), + "%s", _("transfer error")); + } + } + else + { + /* + * URL transfer done in a forked process: display error on stderr, + * which will be sent to the hook_process callback + */ + fprintf (stderr, + _("curl error %d (%s) (URL: \"%s\")\n"), + curl_mc, url_error, url); + } + rc = 2; + break; + } + if (!still_running) + { + /* transfer OK */ + if (output) + { + curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response_code); + snprintf (str_response_code, sizeof (str_response_code), + "%ld", response_code); + hashtable_set (output, "response_code", str_response_code); + } + break; + } + if (stop_transfer && *stop_transfer) { - snprintf (url_error_code, sizeof (url_error_code), "%d", curl_rc); - if (!url_error[0]) + /* transfer stopped by the caller */ + if (output) + { + if (!url_error[0]) + snprintf (url_error, sizeof (url_error), "transfer stopped"); + } + else { - snprintf (url_error, sizeof (url_error), - "%s", _("transfer error")); + /* + * URL transfer done in a forked process: display error on stderr, + * which will be sent to the hook_process callback + */ + fprintf (stderr, + _("transfer stopped (URL: \"%s\")\n"), + url); } + rc = 5; + break; } - else + if (tv_end.tv_sec > 0) { - /* - * URL transfer done in a forked process: display error on stderr, - * which will be sent to the hook_process callback - */ - fprintf (stderr, - _("curl error %d (%s) (URL: \"%s\")\n"), - curl_rc, url_error, url); + /* timeout reached? */ + gettimeofday (&tv_now, NULL); + if (util_timeval_cmp (&tv_now, &tv_end) >= 0) + { + if (output) + { + if (!url_error[0]) + { + snprintf (url_error, sizeof (url_error), + URL_ERROR_TIMEOUT " (%.3fs)", + ((float)timeout) / 1000); + } + } + else + { + /* + * URL transfer done in a forked process: display error on stderr, + * which will be sent to the hook_process callback + */ + fprintf (stderr, + _("transfer timeout reached (%.3fs) (URL: \"%s\")\n"), + ((float)timeout) / 1000, url); + } + rc = 6; + break; + } } - rc = 2; } /* cleanup */ + curl_multi_remove_handle (multi, curl); curl_easy_cleanup (curl); + curl_multi_cleanup (multi); end: for (i = 0; i < 2; i++) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/src/core/core-url.h new/weechat-4.7.2/src/core/core-url.h --- old/weechat-4.7.1/src/core/core-url.h 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/src/core/core-url.h 2025-11-23 11:34:17.000000000 +0100 @@ -24,6 +24,8 @@ #include <stdio.h> +#define URL_ERROR_TIMEOUT "transfer timeout reached" + struct t_hashtable; struct t_infolist; @@ -61,7 +63,8 @@ extern struct t_url_option url_options[]; extern int weeurl_download (const char *url, struct t_hashtable *options, - struct t_hashtable *output); + long timeout, struct t_hashtable *output, + int *stop_transfer); extern int weeurl_option_add_to_infolist (struct t_infolist *infolist, struct t_url_option *option); extern void weeurl_init (void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/src/core/hook/hook-process.c new/weechat-4.7.2/src/core/hook/hook-process.c --- old/weechat-4.7.1/src/core/hook/hook-process.c 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/src/core/hook/hook-process.c 2025-11-23 11:34:17.000000000 +0100 @@ -279,7 +279,9 @@ } rc = weeurl_download (ptr_url, HOOK_PROCESS(hook_process, options), - NULL); /* output */ + 0, /* timeout */ + NULL, /* output */ + NULL); /* stop_download */ } else if (strncmp (HOOK_PROCESS(hook_process, command), "func:", 5) == 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/src/core/hook/hook-url.c new/weechat-4.7.2/src/core/hook/hook-url.c --- old/weechat-4.7.1/src/core/hook/hook-url.c 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/src/core/hook/hook-url.c 2025-11-23 11:34:17.000000000 +0100 @@ -137,7 +137,9 @@ url_rc = weeurl_download (HOOK_URL(hook, url), HOOK_URL(hook, options), - HOOK_URL(hook, output)); + HOOK_URL(hook, timeout), + HOOK_URL(hook, output), + &(HOOK_URL(hook, stop_transfer))); if (url_rc != 0) { @@ -159,7 +161,7 @@ { struct t_hook *hook; const char *ptr_error; - char str_error[1024], str_error_code[12]; + char str_error[1024]; /* make C compiler happy */ (void) data; @@ -192,11 +194,10 @@ if (!hashtable_has_key (HOOK_URL(hook, output), "error_code")) { snprintf (str_error, sizeof (str_error), - "transfer timeout reached (%.3fs)", + URL_ERROR_TIMEOUT " (%.3fs)", ((float)HOOK_URL(hook, timeout)) / 1000); - snprintf (str_error_code, sizeof (str_error_code), "6"); hashtable_set (HOOK_URL(hook, output), "error", str_error); - hashtable_set (HOOK_URL(hook, output), "error_code", str_error_code); + hashtable_set (HOOK_URL(hook, output), "error_code", "6"); } hook_url_run_callback (hook); if (weechat_debug_core >= 1) @@ -224,7 +225,7 @@ { int rc, timeout, max_calls; long interval; - char str_error[1024], str_error_code[12], str_error_code_pthread[12]; + char str_error[1024], str_error_code_pthread[12]; HOOK_URL(hook, thread_running) = 1; @@ -235,11 +236,10 @@ { snprintf (str_error, sizeof (str_error), "error calling pthread_create (%d)", rc); - snprintf (str_error_code, sizeof (str_error_code), "5"); snprintf (str_error_code_pthread, sizeof (str_error_code_pthread), "%d", rc); hashtable_set (HOOK_URL(hook, output), "error", str_error); - hashtable_set (HOOK_URL(hook, output), "error_code", str_error_code); + hashtable_set (HOOK_URL(hook, output), "error_code", "100"); hashtable_set (HOOK_URL(hook, output), "error_code_pthread", str_error_code_pthread); hook_url_run_callback (hook); @@ -265,7 +265,7 @@ { if (timeout <= 100) { - interval = timeout; + interval = timeout + 50; max_calls = 1; } else @@ -274,6 +274,7 @@ max_calls = timeout / 100; if (timeout % 100 == 0) max_calls++; + max_calls++; } } HOOK_URL(hook, hook_timer) = hook_timer (hook->plugin, @@ -323,6 +324,7 @@ new_hook_url->url = strdup (url); new_hook_url->options = (options) ? hashtable_dup (options) : NULL; new_hook_url->timeout = timeout; + new_hook_url->stop_transfer = 0; new_hook_url->thread_id = 0; new_hook_url->thread_created = 0; new_hook_url->thread_running = 0; @@ -366,6 +368,26 @@ if (!hook || !hook->hook_data) return; + /* stop transfer if it's still active */ + if (HOOK_URL(hook, thread_created) && HOOK_URL(hook, thread_running)) + { + HOOK_URL(hook, stop_transfer) = 1; + usleep (10000); + if (!hashtable_has_key (HOOK_URL(hook, output), "error_code")) + { + hashtable_set (HOOK_URL(hook, output), "error", "transfer stopped"); + hashtable_set (HOOK_URL(hook, output), "error_code", "5"); + } + hook_url_run_callback (hook); + if (weechat_debug_core >= 1) + { + gui_chat_printf ( + NULL, + _("End of URL transfer '%s', transfer stopped"), + HOOK_URL(hook, url)); + } + } + if (HOOK_URL(hook, url)) { free (HOOK_URL(hook, url)); @@ -421,6 +443,8 @@ return 0; if (!infolist_new_var_integer (item, "timeout", (int)(HOOK_URL(hook, timeout)))) return 0; + if (!infolist_new_var_integer (item, "stop_transfer", HOOK_URL(hook, stop_transfer))) + return 0; if (!infolist_new_var_integer (item, "thread_created", (int)(HOOK_URL(hook, thread_created)))) return 0; if (!infolist_new_var_integer (item, "thread_running", (int)(HOOK_URL(hook, thread_running)))) @@ -451,6 +475,7 @@ hashtable_get_string (HOOK_URL(hook, options), "keys_values")); log_printf (" timeout . . . . . . . : %ld", HOOK_URL(hook, timeout)); + log_printf (" stop_transfer . . . . : %d", HOOK_URL(hook, stop_transfer)); log_printf (" thread_created. . . . : %d", (int)HOOK_URL(hook, thread_created)); log_printf (" thread_running. . . . : %d", (int)HOOK_URL(hook, thread_running)); log_printf (" hook_timer. . . . . . : %p", HOOK_URL(hook, hook_timer)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/src/core/hook/hook-url.h new/weechat-4.7.2/src/core/hook/hook-url.h --- old/weechat-4.7.1/src/core/hook/hook-url.h 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/src/core/hook/hook-url.h 2025-11-23 11:34:17.000000000 +0100 @@ -41,6 +41,7 @@ char *url; /* URL */ struct t_hashtable *options; /* URL options (see doc) */ long timeout; /* timeout (ms) (0 = no timeout) */ + int stop_transfer; /* 1 is used to stop transfer now */ pthread_t thread_id; /* thread id */ int thread_created; /* thread created */ int thread_running; /* 1 if thread is running */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/src/plugins/irc/irc-mode.c new/weechat-4.7.2/src/plugins/irc/irc-mode.c --- old/weechat-4.7.1/src/plugins/irc/irc-mode.c 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/src/plugins/irc/irc-mode.c 2025-11-23 11:34:17.000000000 +0100 @@ -28,6 +28,7 @@ #include "../weechat-plugin.h" #include "irc.h" +#include "irc-color.h" #include "irc-mode.h" #include "irc-config.h" #include "irc-server.h" @@ -37,18 +38,24 @@ /* - * Gets mode arguments: skip colons before arguments. + * Gets mode arguments: skips colons before arguments and converts IRC color + * codes into WeeChat color codes, so that the result can be displayed in a + * buffer. */ char * -irc_mode_get_arguments (const char *arguments) +irc_mode_get_arguments_colors (const char *arguments) { - char **argv, **argv2, *new_arguments; + char **argv, **new_arguments; int argc, i; if (!arguments || !arguments[0]) return strdup (""); + new_arguments = weechat_string_dyn_alloc (1024); + if (!new_arguments) + return NULL; + argv = weechat_string_split (arguments, " ", NULL, WEECHAT_STRING_SPLIT_STRIP_LEFT | WEECHAT_STRING_SPLIT_STRIP_RIGHT @@ -57,26 +64,20 @@ if (!argv) return strdup (""); - argv2 = malloc (sizeof (*argv) * (argc + 1)); - if (!argv2) - { - weechat_string_free_split (argv); - return strdup ("");; - } - for (i = 0; i < argc; i++) { - argv2[i] = (argv[i][0] == ':') ? argv[i] + 1 : argv[i]; + if ((*new_arguments)[0]) + weechat_string_dyn_concat (new_arguments, " ", -1); + weechat_string_dyn_concat ( + new_arguments, + (argv[i][0] == ':') ? IRC_COLOR_MSG(argv[i] + 1) : IRC_COLOR_MSG(argv[i]), + -1); + weechat_string_dyn_concat (new_arguments, IRC_COLOR_RESET, -1); } - argv2[argc] = NULL; - - new_arguments = weechat_string_rebuild_split_string ( - (const char **)argv2, " ", 0, -1); weechat_string_free_split (argv); - free (argv2); - return new_arguments; + return weechat_string_dyn_free (new_arguments, 0); } /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/src/plugins/irc/irc-mode.h new/weechat-4.7.2/src/plugins/irc/irc-mode.h --- old/weechat-4.7.1/src/plugins/irc/irc-mode.h 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/src/plugins/irc/irc-mode.h 2025-11-23 11:34:17.000000000 +0100 @@ -25,7 +25,7 @@ struct t_irc_server; struct t_irc_channel; -extern char *irc_mode_get_arguments (const char *arguments); +extern char *irc_mode_get_arguments_colors (const char *arguments); extern char irc_mode_get_chanmode_type (struct t_irc_server *server, char chanmode); extern int irc_mode_channel_set (struct t_irc_server *server, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/src/plugins/irc/irc-protocol.c new/weechat-4.7.2/src/plugins/irc/irc-protocol.c --- old/weechat-4.7.1/src/plugins/irc/irc-protocol.c 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/src/plugins/irc/irc-protocol.c 2025-11-23 11:34:17.000000000 +0100 @@ -2178,7 +2178,7 @@ } ptr_nick = irc_nick_search (ctxt->server, ptr_channel, ctxt->nick); ptr_buffer = (ptr_channel) ? ptr_channel->buffer : ctxt->server->buffer; - modes_args = irc_mode_get_arguments (msg_modes_args); + modes_args = irc_mode_get_arguments_colors (msg_modes_args); weechat_printf_datetime_tags ( irc_msgbuffer_get_target_buffer (ctxt->server, NULL, ctxt->command, NULL, ptr_buffer), @@ -6811,7 +6811,7 @@ IRC_COLOR_CHAT_DELIMITERS, str_number, IRC_COLOR_CHAT_HOST, - ctxt->params[2], /* banmask */ + IRC_COLOR_MSG(ctxt->params[2]), /* banmask */ IRC_COLOR_RESET, (nick_address[0]) ? nick_address : "?", weechat_util_get_time_string (&datetime)); @@ -6834,7 +6834,7 @@ IRC_COLOR_CHAT_DELIMITERS, str_number, IRC_COLOR_CHAT_HOST, - ctxt->params[2], /* banmask */ + IRC_COLOR_MSG(ctxt->params[2]), /* banmask */ IRC_COLOR_RESET, (nick_address[0]) ? nick_address : "?"); } @@ -6857,7 +6857,7 @@ IRC_COLOR_CHAT_DELIMITERS, str_number, IRC_COLOR_CHAT_HOST, - ctxt->params[2], /* banmask */ + IRC_COLOR_MSG(ctxt->params[2]), /* banmask */ IRC_COLOR_RESET); } @@ -7386,7 +7386,7 @@ IRC_COLOR_CHAT_DELIMITERS, str_number, IRC_COLOR_CHAT_HOST, - ctxt->params[3], /* quietmask */ + IRC_COLOR_MSG(ctxt->params[3]), /* quietmask */ IRC_COLOR_RESET, (nick_address[0]) ? nick_address : "?", weechat_util_get_time_string (&datetime)); @@ -7409,7 +7409,7 @@ IRC_COLOR_CHAT_DELIMITERS, str_number, IRC_COLOR_CHAT_HOST, - ctxt->params[3], /* quietmask */ + IRC_COLOR_MSG(ctxt->params[3]), /* quietmask */ IRC_COLOR_RESET, (nick_address[0]) ? nick_address : "?"); } @@ -7432,7 +7432,7 @@ IRC_COLOR_CHAT_DELIMITERS, str_number, IRC_COLOR_CHAT_HOST, - ctxt->params[3], /* quietmask */ + IRC_COLOR_MSG(ctxt->params[3]), /* quietmask */ IRC_COLOR_RESET); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/tests/unit/plugins/irc/test-irc-mode.cpp new/weechat-4.7.2/tests/unit/plugins/irc/test-irc-mode.cpp --- old/weechat-4.7.1/tests/unit/plugins/irc/test-irc-mode.cpp 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/tests/unit/plugins/irc/test-irc-mode.cpp 2025-11-23 11:34:17.000000000 +0100 @@ -25,11 +25,13 @@ extern "C" { +#include "src/gui/gui-color.h" +#include "src/plugins/irc/irc-color.h" #include "src/plugins/irc/irc-mode.h" } #define WEE_CHECK_GET_ARGS(__result, __arguments) \ - str = irc_mode_get_arguments (__arguments); \ + str = irc_mode_get_arguments_colors (__arguments); \ STRCMP_EQUAL(__result, str); \ free (str); @@ -44,23 +46,93 @@ TEST(IrcMode, GetArguments) { - char *str; + char *str, string[1024], expected[1024]; /* invalid arguments */ - WEE_CHECK_GET_ARGS("", irc_mode_get_arguments (NULL)); - WEE_CHECK_GET_ARGS("", irc_mode_get_arguments ("")); - WEE_CHECK_GET_ARGS("", irc_mode_get_arguments (" ")); + WEE_CHECK_GET_ARGS("", NULL); + WEE_CHECK_GET_ARGS("", ""); + WEE_CHECK_GET_ARGS("", " "); /* simple arguments */ - WEE_CHECK_GET_ARGS("abc", irc_mode_get_arguments ("abc")); - WEE_CHECK_GET_ARGS("abc def", irc_mode_get_arguments ("abc def")); - WEE_CHECK_GET_ARGS("abc def ghi", irc_mode_get_arguments ("abc def ghi")); + snprintf (string, sizeof (string), "abc%c02_blue", IRC_COLOR_COLOR_CHAR); + snprintf (expected, sizeof (expected), + "abc%s_blue%s", + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset")); + WEE_CHECK_GET_ARGS(expected, string); + snprintf (string, sizeof (string), + "abc%c02_blue def%c02_blue", + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR); + snprintf (expected, sizeof (expected), + "abc%s_blue%s def%s_blue%s", + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset"), + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset")); + WEE_CHECK_GET_ARGS(expected, string); + snprintf (string, sizeof (string), + "abc%c02_blue def%c02_blue ghi%c02_blue", + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR); + snprintf (expected, sizeof (expected), + "abc%s_blue%s def%s_blue%s ghi%s_blue%s", + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset"), + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset"), + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset")); + WEE_CHECK_GET_ARGS(expected, string); /* some arguments starting with a colon */ - WEE_CHECK_GET_ARGS("abc", irc_mode_get_arguments (":abc")); - WEE_CHECK_GET_ARGS("abc def", irc_mode_get_arguments (":abc def")); - WEE_CHECK_GET_ARGS("abc def", irc_mode_get_arguments ("abc :def")); - WEE_CHECK_GET_ARGS("abc def ghi", irc_mode_get_arguments ("abc :def ghi")); - WEE_CHECK_GET_ARGS("abc def ghi", irc_mode_get_arguments ("abc :def :ghi")); - WEE_CHECK_GET_ARGS("abc def ghi", irc_mode_get_arguments (":abc :def :ghi")); + snprintf (string, sizeof (string), ":abc%c02_blue", IRC_COLOR_COLOR_CHAR); + snprintf (expected, sizeof (expected), + "abc%s_blue%s", + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset")); + WEE_CHECK_GET_ARGS(expected, string); + snprintf (string, sizeof (string), + ":abc%c02_blue def%c02_blue", + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR); + snprintf (expected, sizeof (expected), + "abc%s_blue%s def%s_blue%s", + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset"), + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset")); + WEE_CHECK_GET_ARGS(expected, string); + snprintf (string, sizeof (string), + "abc%c02_blue :def%c02_blue", + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR); + WEE_CHECK_GET_ARGS(expected, string); + snprintf (string, sizeof (string), + "abc%c02_blue :def%c02_blue ghi%c02_blue", + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR); + snprintf (expected, sizeof (expected), + "abc%s_blue%s def%s_blue%s ghi%s_blue%s", + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset"), + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset"), + gui_color_get_custom ("|blue"), + gui_color_get_custom ("reset")); + WEE_CHECK_GET_ARGS(expected, string); + snprintf (string, sizeof (string), + "abc%c02_blue :def%c02_blue :ghi%c02_blue", + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR); + WEE_CHECK_GET_ARGS(expected, string); + snprintf (string, sizeof (string), + ":abc%c02_blue :def%c02_blue :ghi%c02_blue", + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR, + IRC_COLOR_COLOR_CHAR); + WEE_CHECK_GET_ARGS(expected, string); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/tests/unit/plugins/irc/test-irc-protocol.cpp new/weechat-4.7.2/tests/unit/plugins/irc/test-irc-protocol.cpp --- old/weechat-4.7.1/tests/unit/plugins/irc/test-irc-protocol.cpp 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/tests/unit/plugins/irc/test-irc-protocol.cpp 2025-11-23 11:34:17.000000000 +0100 @@ -2316,6 +2316,22 @@ "irc_mode,nick_admin,host_user@host,log3"); STRCMP_EQUAL(NULL, ptr_channel->modes); + /* bans added on channel */ + RECV(":admin!user@host MODE #test +bb " + "bob!user_\00304red@host_\00304red " + "carol!user_\00304red@host_\00304red"); + CHECK_CHAN("--", "Mode #test [+bb bob!user_red@host_red " + "carol!user_red@host_red] by admin", + "irc_mode,nick_admin,host_user@host,log3"); + + /* bans removed from channel */ + RECV(":admin!user@host MODE #test -bb " + "bob!user_\00304red@host_\00304red " + "carol!user_\00304red@host_\00304red"); + CHECK_CHAN("--", "Mode #test [-bb bob!user_red@host_red " + "carol!user_red@host_red] by admin", + "irc_mode,nick_admin,host_user@host,log3"); + /* nick mode '@' on channel #test */ RECV(":admin!user@host MODE #test +o alice "); CHECK_CHAN("--", "Mode #test [+o alice] by admin", @@ -5600,30 +5616,32 @@ RECV(":server 367 alice #test"); CHECK_ERROR_PARAMS("367", 2, 3); - RECV(":server 367 alice #test nick1!user1@host1"); - CHECK_CHAN("--", "[#test] [1] nick1!user1@host1 banned", + RECV(":server 367 alice #test nick1!user1@host1_\00304red"); + CHECK_CHAN("--", "[#test] [1] nick1!user1@host1_red banned", "irc_367,irc_numeric,nick_server,log3"); - RECV(":server 367 alice #test nick1!user1@host1 nick2!user2@host2 "); + RECV(":server 367 alice #test nick1!user1_\00304red@host1_\00304red " + "nick2!user2_\00304red@host2_\00304red "); CHECK_CHAN("--", - "[#test] [2] nick1!user1@host1 banned by nick2 (user2@host2)", + "[#test] [2] nick1!user1_red@host1_red banned by nick2 (user2_red@host2_red)", "irc_367,irc_numeric,nick_server,log3"); - RECV(":server 367 alice #test nick1!user1@host1 nick2!user2@host2 " - "1205585109 "); + RECV(":server 367 alice #test nick1!user1_\00304red@host1_\00304red " + "nick2!user2_\00304red@host2_\00304red 1205585109 "); CHECK_CHAN("--", - "[#test] [3] nick1!user1@host1 banned " - "by nick2 (user2@host2) on Sat, 15 Mar 2008 12:45:09", + "[#test] [3] nick1!user1_red@host1_red banned " + "by nick2 (user2_red@host2_red) on Sat, 15 Mar 2008 12:45:09", "irc_367,irc_numeric,nick_server,log3"); /* channel not found */ - RECV(":server 367 alice #xyz nick1!user1@host1"); - CHECK_SRV("--", "[#xyz] nick1!user1@host1 banned", + RECV(":server 367 alice #xyz nick1!user1_\00304red@host1_\00304red"); + CHECK_SRV("--", "[#xyz] nick1!user1_red@host1_red banned", "irc_367,irc_numeric,nick_server,log3"); - RECV(":server 367 alice #xyz nick1!user1@host1 nick2!user2@host2"); - CHECK_SRV("--", "[#xyz] nick1!user1@host1 banned by nick2 (user2@host2)", + RECV(":server 367 alice #xyz nick1!user1_\00304red@host1_\00304red " + "nick2!user2_\00304red@host2_\00304red"); + CHECK_SRV("--", "[#xyz] nick1!user1_red@host1_red banned by nick2 (user2_red@host2_red)", "irc_367,irc_numeric,nick_server,log3"); - RECV(":server 367 alice #xyz nick1!user1@host1 nick2!user2@host2 " - "1205585109"); - CHECK_SRV("--", "[#xyz] nick1!user1@host1 banned by nick2 (user2@host2) " + RECV(":server 367 alice #xyz nick1!user1_\00304red@host1_\00304red " + "nick2!user2_\00304red@host2_\00304red 1205585109"); + CHECK_SRV("--", "[#xyz] nick1!user1_red@host1_red banned by nick2 (user2_red@host2_red) " "on Sat, 15 Mar 2008 12:45:09", "irc_367,irc_numeric,nick_server,log3"); } @@ -7208,29 +7226,30 @@ RECV(":server 728 alice #test q"); CHECK_ERROR_PARAMS("728", 3, 4); - RECV(":server 728 alice #test q nick1!user1@host1"); - CHECK_CHAN("--", "[#test] nick1!user1@host1 quieted", + RECV(":server 728 alice #test q nick1!user1_\00304red@host1_\00304red"); + CHECK_CHAN("--", "[#test] nick1!user1_red@host1_red quieted", "irc_728,irc_numeric,nick_server,log3"); - RECV(":server 728 alice #test q nick1!user1@host1 alice!user@host"); - CHECK_CHAN("--", "[#test] nick1!user1@host1 quieted by alice (user@host)", + RECV(":server 728 alice #test q nick1!user1_\00304red@host1_\00304red " + "alice!user_\00304red@host_\00304red"); + CHECK_CHAN("--", "[#test] nick1!user1_red@host1_red quieted by alice (user_red@host_red)", "irc_728,irc_numeric,nick_server,log3"); - RECV(":server 728 alice #test q nick1!user1@host1 alice!user@host " - "1351350090 "); + RECV(":server 728 alice #test q nick1!user1_\00304red@host1_\00304red " + "alice!user_\00304red@host_\00304red 1351350090 "); CHECK_CHAN("--", - "[#test] nick1!user1@host1 quieted by alice (user@host) " + "[#test] nick1!user1_red@host1_red quieted by alice (user_red@host_red) " "on Sat, 27 Oct 2012 15:01:30", "irc_728,irc_numeric,nick_server,log3"); /* channel not found */ - RECV(":server 728 alice #xyz q nick1!user1@host1"); - CHECK_SRV("--", "[#xyz] nick1!user1@host1 quieted", + RECV(":server 728 alice #xyz q nick1!user1_\00304red@host1_\00304red"); + CHECK_SRV("--", "[#xyz] nick1!user1_red@host1_red quieted", "irc_728,irc_numeric,nick_server,log3"); - RECV(":server 728 alice #xyz q nick1!user1@host1 alice!user@host"); - CHECK_SRV("--", "[#xyz] nick1!user1@host1 quieted by alice (user@host)", + RECV(":server 728 alice #xyz q nick1!user1_\00304red@host1_\00304red alice!user_\00304red@host_\00304red"); + CHECK_SRV("--", "[#xyz] nick1!user1_red@host1_red quieted by alice (user_red@host_red)", "irc_728,irc_numeric,nick_server,log3"); - RECV(":server 728 alice #xyz q nick1!user1@host1 alice!user@host " + RECV(":server 728 alice #xyz q nick1!user1_\00304red@host1_\00304red alice!user_\00304red@host_\00304red " "1351350090 "); - CHECK_SRV("--", "[#xyz] nick1!user1@host1 quieted by alice (user@host) " + CHECK_SRV("--", "[#xyz] nick1!user1_red@host1_red quieted by alice (user_red@host_red) " "on Sat, 27 Oct 2012 15:01:30", "irc_728,irc_numeric,nick_server,log3"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.7.1/version.sh new/weechat-4.7.2/version.sh --- old/weechat-4.7.1/version.sh 2025-08-16 21:49:19.000000000 +0200 +++ new/weechat-4.7.2/version.sh 2025-11-23 11:34:17.000000000 +0100 @@ -41,8 +41,8 @@ # devel-number the devel version as hex number ("0x04010000" for "4.1.0-dev") # -weechat_stable="4.7.1" -weechat_devel="4.7.1" +weechat_stable="4.7.2" +weechat_devel="4.7.2" stable_major=$(echo "${weechat_stable}" | cut -d"." -f1) stable_minor=$(echo "${weechat_stable}" | cut -d"." -f2)
