From 1e764ab76de16241852dd53546bcbf9452bf1fc3 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 1 Apr 2025 12:56:52 +0200 Subject: [PATCH 1/6] More const correctness Signed-off-by: Steffen Jaeckel --- src/config/preferences.c | 2 +- src/config/preferences.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/preferences.c b/src/config/preferences.c index cb5faea6a..d306066b9 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -600,7 +600,7 @@ prefs_get_string_with_locale(preference_t pref, gchar* locale) * @param new_value The new string value to set. Pass NULL to remove the key. */ void -prefs_set_string(preference_t pref, gchar* new_value) +prefs_set_string(preference_t pref, const gchar* new_value) { const char* group = _get_group(pref); const char* key = _get_key(pref); diff --git a/src/config/preferences.h b/src/config/preferences.h index 40dd48b44..e59041495 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -331,7 +331,7 @@ gboolean prefs_get_boolean(preference_t pref); void prefs_set_boolean(preference_t pref, gboolean value); gchar* prefs_get_string(preference_t pref); gchar* prefs_get_string_with_locale(preference_t pref, gchar* locale); -void prefs_set_string(preference_t pref, gchar* new_value); +void prefs_set_string(preference_t pref, const gchar* new_value); void prefs_set_string_with_option(preference_t pref, char* option, char* value); void prefs_set_string_list_with_option(preference_t pref, char* option, const gchar* const* values); From 9c2b3f6579db1a7c1c0a338379eabb57d32f485c Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 1 Apr 2025 10:48:04 +0200 Subject: [PATCH 2/6] Re-factor `cmd_time()` Instead of c&p'ing the same code again and again, put everything in a struct and loop over it. This also fixes `vcard` not being in included in `all`. Fixes: f934c5b59f ("Add vCard support") Signed-off-by: Steffen Jaeckel --- src/command/cmd_funcs.c | 243 +++++++--------------------------------- 1 file changed, 40 insertions(+), 203 deletions(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index ec8ce90dd..19ef48894 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -5297,217 +5297,54 @@ cmd_wrap(ProfWin* window, const char* const command, gchar** args) gboolean cmd_time(ProfWin* window, const char* const command, gchar** args) { - if (g_strcmp0(args[0], "lastactivity") == 0) { - if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_LASTACTIVITY); - cons_show("Last activity time format: '%s'.", format); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_LASTACTIVITY, args[2]); - cons_show("Last activity time format set to '%s'.", args[2]); - ui_redraw(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - cons_show("Last activity time cannot be disabled."); - ui_redraw(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "statusbar") == 0) { - if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_STATUSBAR); - cons_show("Status bar time format: '%s'.", format); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_STATUSBAR, args[2]); - cons_show("Status bar time format set to '%s'.", args[2]); - ui_redraw(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - prefs_set_string(PREF_TIME_STATUSBAR, "off"); - cons_show("Status bar time display disabled."); - ui_redraw(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "console") == 0) { - if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_CONSOLE); - cons_show("Console time format: '%s'.", format); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_CONSOLE, args[2]); - cons_show("Console time format set to '%s'.", args[2]); - wins_resize_all(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - prefs_set_string(PREF_TIME_CONSOLE, "off"); - cons_show("Console time display disabled."); - wins_resize_all(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "chat") == 0) { - if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_CHAT); - cons_show("Chat time format: '%s'.", format); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_CHAT, args[2]); - cons_show("Chat time format set to '%s'.", args[2]); - wins_resize_all(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - prefs_set_string(PREF_TIME_CHAT, "off"); - cons_show("Chat time display disabled."); - wins_resize_all(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "muc") == 0) { - if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_MUC); - cons_show("MUC time format: '%s'.", format); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_MUC, args[2]); - cons_show("MUC time format set to '%s'.", args[2]); - wins_resize_all(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - prefs_set_string(PREF_TIME_MUC, "off"); - cons_show("MUC time display disabled."); - wins_resize_all(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "config") == 0) { - if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_CONFIG); - cons_show("config time format: '%s'.", format); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_CONFIG, args[2]); - cons_show("config time format set to '%s'.", args[2]); - wins_resize_all(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - prefs_set_string(PREF_TIME_CONFIG, "off"); - cons_show("config time display disabled."); - wins_resize_all(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "private") == 0) { - if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_PRIVATE); - cons_show("Private chat time format: '%s'.", format); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_PRIVATE, args[2]); - cons_show("Private chat time format set to '%s'.", args[2]); - wins_resize_all(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - prefs_set_string(PREF_TIME_PRIVATE, "off"); - cons_show("Private chat time display disabled."); - wins_resize_all(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "xml") == 0) { - if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_XMLCONSOLE); - cons_show("XML Console time format: '%s'.", format); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_XMLCONSOLE, args[2]); - cons_show("XML Console time format set to '%s'.", args[2]); - wins_resize_all(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - prefs_set_string(PREF_TIME_XMLCONSOLE, "off"); - cons_show("XML Console time display disabled."); - wins_resize_all(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "all") == 0) { - if (args[1] == NULL) { - cons_time_setting(); - return TRUE; - } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_CONSOLE, args[2]); - cons_show("Console time format set to '%s'.", args[2]); - prefs_set_string(PREF_TIME_CHAT, args[2]); - cons_show("Chat time format set to '%s'.", args[2]); - prefs_set_string(PREF_TIME_MUC, args[2]); - cons_show("MUC time format set to '%s'.", args[2]); - prefs_set_string(PREF_TIME_CONFIG, args[2]); - cons_show("config time format set to '%s'.", args[2]); - prefs_set_string(PREF_TIME_PRIVATE, args[2]); - cons_show("Private chat time format set to '%s'.", args[2]); - prefs_set_string(PREF_TIME_XMLCONSOLE, args[2]); - cons_show("XML Console time format set to '%s'.", args[2]); - wins_resize_all(); - return TRUE; - } else if (g_strcmp0(args[1], "off") == 0) { - prefs_set_string(PREF_TIME_CONSOLE, "off"); - cons_show("Console time display disabled."); - prefs_set_string(PREF_TIME_CHAT, "off"); - cons_show("Chat time display disabled."); - prefs_set_string(PREF_TIME_MUC, "off"); - cons_show("MUC time display disabled."); - prefs_set_string(PREF_TIME_CONFIG, "off"); - cons_show("config time display disabled."); - prefs_set_string(PREF_TIME_PRIVATE, "off"); - cons_show("config time display disabled."); - prefs_set_string(PREF_TIME_XMLCONSOLE, "off"); - cons_show("XML Console time display disabled."); - ui_redraw(); - return TRUE; - } else { - cons_bad_cmd_usage(command); - return TRUE; - } - } else if (g_strcmp0(args[0], "vcard") == 0) { + const struct time_preferences + { + preference_t pref; + const char *name, *description; + } time_prefs[] = { + { .pref = PREF_TIME_LASTACTIVITY, .name = "lastactivity", .description = "Last activity" }, + { .pref = PREF_TIME_CONSOLE, .name = "console", .description = "Console" }, + { .pref = PREF_TIME_STATUSBAR, .name = "statusbar", .description = "Status bar" }, + { .pref = PREF_TIME_CHAT, .name = "chat", .description = "Chat" }, + { .pref = PREF_TIME_MUC, .name = "muc", .description = "MUC" }, + { .pref = PREF_TIME_CONFIG, .name = "config", .description = "Config" }, + { .pref = PREF_TIME_PRIVATE, .name = "private", .description = "Private chat" }, + { .pref = PREF_TIME_XMLCONSOLE, .name = "xml", .description = "XML Console" }, + { .pref = PREF_TIME_VCARD, .name = "vcard", .description = "vCard" }, + }; + gboolean redraw = FALSE; + gboolean set_all = g_strcmp0(args[0], "all") == 0; + for (size_t n = 0; n < ARRAY_SIZE(time_prefs); ++n) { + if (!set_all && g_strcmp0(args[0], time_prefs[n].name) != 0) + continue; + const struct time_preferences* tp = &time_prefs[n]; if (args[1] == NULL) { - auto_gchar gchar* format = prefs_get_string(PREF_TIME_VCARD); - cons_show("vCard time format: %s", format); - return TRUE; + if (set_all) { + cons_time_setting(); + return TRUE; + } + auto_gchar gchar* format = prefs_get_string(tp->pref); + cons_show("%s time format: '%s'.", tp->description, format); } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_TIME_VCARD, args[2]); - cons_show("vCard time format set to '%s'.", args[2]); - ui_redraw(); - return TRUE; + prefs_set_string(tp->pref, args[2]); + cons_show("%s time format set to '%s'.", tp->description, args[2]); + redraw = TRUE; } else if (g_strcmp0(args[1], "off") == 0) { - cons_show("vCard time cannot be disabled."); - ui_redraw(); - return TRUE; + if (tp->pref == PREF_TIME_LASTACTIVITY) { + cons_show("%s time display cannot be disabled.", tp->description); + } else { + prefs_set_string(tp->pref, "off"); + cons_show("%s time display disabled.", tp->description); + redraw = TRUE; + } } else { cons_bad_cmd_usage(command); return TRUE; } - } else { - cons_bad_cmd_usage(command); - return TRUE; } + if (redraw) + ui_redraw(); + return TRUE; } gboolean From 3bf72210e1650a00a7ee3f434c3be0d6258b5b5e Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 1 Apr 2025 12:19:47 +0200 Subject: [PATCH 3/6] Add `iso8601` when setting a time format Instead of manually typing the format-string, one can now simply use `iso8601`. Signed-off-by: Steffen Jaeckel --- src/command/cmd_defs.c | 6 ++++-- src/command/cmd_funcs.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 8c3c3d248..591b3d486 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -1190,7 +1190,8 @@ static const struct cmd_t command_defs[] = { "Time formats are strings supported by g_date_time_format. " "See https://developer.gnome.org/glib/stable/glib-GDateTime.html#g-date-time-format for more details. " "Setting the format to an unsupported string, will display the string. " - "If the format contains spaces, it must be surrounded with double quotes.") + "If the format contains spaces, it must be surrounded with double quotes. " + "It is possible to pass format as 'iso8601' in order to set the time format according to ISO-8601 (only local time, without Time zone designator).") CMD_ARGS( { "console set ", "Set time format for console window." }, { "console off", "Do not show time in console window." }, @@ -1216,7 +1217,8 @@ static const struct cmd_t command_defs[] = { "/time xml off", "/time statusbar set %H:%M", "/time lastactivity set \"%d-%m-%y %H:%M:%S\"", - "/time all set \"%d-%m-%y %H:%M:%S\"") + "/time all set \"%d-%m-%y %H:%M:%S\"", + "/time all set iso8601") }, { CMD_PREAMBLE("/inpblock", diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 19ef48894..7bc19040a 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -5326,7 +5326,20 @@ cmd_time(ProfWin* window, const char* const command, gchar** args) auto_gchar gchar* format = prefs_get_string(tp->pref); cons_show("%s time format: '%s'.", tp->description, format); } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(tp->pref, args[2]); + const struct format_strings + { + const char *name, *format; + } format_strings[] = { + { .name = "iso8601", .format = "%Y-%m-%dT%H:%M:%S" }, + }; + const gchar* set_arg = args[2]; + for (size_t m = 0; m < ARRAY_SIZE(format_strings); ++m) { + if (g_strcmp0(args[2], format_strings[m].name) == 0) { + set_arg = format_strings[m].format; + break; + } + } + prefs_set_string(tp->pref, set_arg); cons_show("%s time format set to '%s'.", tp->description, args[2]); redraw = TRUE; } else if (g_strcmp0(args[1], "off") == 0) { From a6f125058964da28378e68711d598a6f10dd4f15 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 1 Apr 2025 12:51:50 +0200 Subject: [PATCH 4/6] Fix memleak `end_date` only gets free'd if `chatwin_db_history()` is called, which is not always the case. Signed-off-by: Steffen Jaeckel --- src/ui/window.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ui/window.c b/src/ui/window.c index 71b1cd7d0..88271b344 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -701,12 +701,13 @@ win_page_down(ProfWin* window, int scroll_size) auto_gchar gchar* start = g_date_time_format_iso8601(last_entry->time); GDateTime* now = g_date_time_new_now_local(); gchar* end_date = g_date_time_format_iso8601(now); + g_date_time_unref(now); if (*scroll_state != WIN_SCROLL_REACHED_BOTTOM && !chatwin_db_history((ProfChatWin*)window, start, end_date, FALSE)) { *scroll_state = WIN_SCROLL_REACHED_BOTTOM; + } else if (*scroll_state == WIN_SCROLL_REACHED_BOTTOM) { + g_free(end_date); } - g_date_time_unref(now); - int offset = last_entry->y_end_pos - 1; *page_start = offset - page_space + scroll_size; } From 5efec675fd6598ca066f7dea73df0a6f4cb496d4 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 1 Apr 2025 17:05:31 +0200 Subject: [PATCH 5/6] No need to always get a fresh list of keys or values. > The returned data is valid until changes to the hash release those keys. As of the doc of `g_hash_table_get_keys()` [0]. > The returned data is valid until hash_table is modified. As of the doc of `g_hash_table_get_values()` [1]. Use this property and create the lists when modifying the hashtable. The `keys` list is most of the time used sorted, so sort it immediately. In the cases where it was not used sorted, it does not matter. This started off by looking into whether this can be improved. `g_hash_table_foreach()` is discouraged to be used and proposes to use a `GHashTableIter`. Since our lists are not modified very often it does not really make sense, so I decided to keep using lists, but allocating those lists statically instead of per invocation. Instead of using a list, we could maybe use the `GArray` version, but I am not sure whether it wouldn't be even better to replace the `GHashTable` all along to store the `windows` instead. [0] https://docs.gtk.org/glib/type_func.HashTable.get_keys.html [1] https://docs.gtk.org/glib/type_func.HashTable.get_values.html Signed-off-by: Steffen Jaeckel --- src/ui/window_list.c | 168 ++++++++++++------------------------------- 1 file changed, 47 insertions(+), 121 deletions(-) diff --git a/src/ui/window_list.c b/src/ui/window_list.c index 79e58a2b5..7ddf4bf5c 100644 --- a/src/ui/window_list.c +++ b/src/ui/window_list.c @@ -57,6 +57,7 @@ #endif static GHashTable* windows; +static GList *keys, *values; static int current; static Autocomplete wins_ac; static Autocomplete wins_close_ac; @@ -64,13 +65,35 @@ static Autocomplete wins_close_ac; static int _wins_cmp_num(gconstpointer a, gconstpointer b); static int _wins_get_next_available_num(GList* used); +static void +_wins_htable_update(void) +{ + if (values) + g_list_free(values); + if (keys) + g_list_free(keys); + keys = g_hash_table_get_keys(windows); + keys = g_list_sort(keys, _wins_cmp_num); + values = g_hash_table_get_values(windows); +} + +static gboolean +_wins_htable_insert(GHashTable* hash_table, + gpointer key, + gpointer value) +{ + gboolean ret = g_hash_table_insert(hash_table, key, value); + _wins_htable_update(); + return ret; +} + void wins_init(void) { windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)win_free); ProfWin* console = win_create_console(); - g_hash_table_insert(windows, GINT_TO_POINTER(1), console); + _wins_htable_insert(windows, GINT_TO_POINTER(1), console); current = 1; @@ -98,7 +121,6 @@ wins_chat_exists(const char* const barejid) ProfChatWin* wins_get_chat(const char* const barejid) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -106,14 +128,12 @@ wins_get_chat(const char* const barejid) if (window->type == WIN_CHAT) { ProfChatWin* chatwin = (ProfChatWin*)window; if (g_strcmp0(chatwin->barejid, barejid) == 0) { - g_list_free(values); return chatwin; } } curr = g_list_next(curr); } - g_list_free(values); return NULL; } @@ -127,7 +147,6 @@ GList* wins_get_chat_unsubscribed(void) { GList* result = NULL; - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -142,14 +161,12 @@ wins_get_chat_unsubscribed(void) curr = g_list_next(curr); } - g_list_free(values); return result; } ProfConfWin* wins_get_conf(const char* const roomjid) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -157,21 +174,18 @@ wins_get_conf(const char* const roomjid) if (window->type == WIN_CONFIG) { ProfConfWin* confwin = (ProfConfWin*)window; if (g_strcmp0(confwin->roomjid, roomjid) == 0) { - g_list_free(values); return confwin; } } curr = g_list_next(curr); } - g_list_free(values); return NULL; } ProfMucWin* wins_get_muc(const char* const roomjid) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -179,21 +193,18 @@ wins_get_muc(const char* const roomjid) if (window->type == WIN_MUC) { ProfMucWin* mucwin = (ProfMucWin*)window; if (g_strcmp0(mucwin->roomjid, roomjid) == 0) { - g_list_free(values); return mucwin; } } curr = g_list_next(curr); } - g_list_free(values); return NULL; } ProfPrivateWin* wins_get_private(const char* const fulljid) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -201,21 +212,18 @@ wins_get_private(const char* const fulljid) if (window->type == WIN_PRIVATE) { ProfPrivateWin* privatewin = (ProfPrivateWin*)window; if (g_strcmp0(privatewin->fulljid, fulljid) == 0) { - g_list_free(values); return privatewin; } } curr = g_list_next(curr); } - g_list_free(values); return NULL; } ProfPluginWin* wins_get_plugin(const char* const tag) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -223,14 +231,12 @@ wins_get_plugin(const char* const tag) if (window->type == WIN_PLUGIN) { ProfPluginWin* pluginwin = (ProfPluginWin*)window; if (g_strcmp0(pluginwin->tag, tag) == 0) { - g_list_free(values); return pluginwin; } } curr = g_list_next(curr); } - g_list_free(values); return NULL; } @@ -254,7 +260,6 @@ wins_get_private_chats(const char* const roomjid) GList* result = NULL; GString* prefix = g_string_new(roomjid); g_string_append(prefix, "/"); - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -268,7 +273,6 @@ wins_get_private_chats(const char* const roomjid) curr = g_list_next(curr); } - g_list_free(values); g_string_free(prefix, TRUE); return result; } @@ -332,7 +336,7 @@ wins_get_current(void) GList* wins_get_nums(void) { - return g_hash_table_get_keys(windows); + return g_list_copy(keys); } void @@ -431,11 +435,7 @@ wins_get_by_string(const char* str) ProfWin* wins_get_next(void) { - // get and sort win nums - GList* keys = g_hash_table_get_keys(windows); - keys = g_list_sort(keys, _wins_cmp_num); GList* curr = keys; - // find our place in the list while (curr) { if (current == GPOINTER_TO_INT(curr->data)) { @@ -448,23 +448,16 @@ wins_get_next(void) curr = g_list_next(curr); if (curr) { int next = GPOINTER_TO_INT(curr->data); - g_list_free(keys); return wins_get_by_num(next); - // otherwise return the first window (console) - } else { - g_list_free(keys); - return wins_get_console(); } + // otherwise return the first window (console) + return wins_get_console(); } ProfWin* wins_get_previous(void) { - // get and sort win nums - GList* keys = g_hash_table_get_keys(windows); - keys = g_list_sort(keys, _wins_cmp_num); GList* curr = keys; - // find our place in the list while (curr) { if (current == GPOINTER_TO_INT(curr->data)) { @@ -477,33 +470,27 @@ wins_get_previous(void) curr = g_list_previous(curr); if (curr) { int previous = GPOINTER_TO_INT(curr->data); - g_list_free(keys); return wins_get_by_num(previous); - // otherwise return the last window - } else { - int new_num = GPOINTER_TO_INT(g_list_last(keys)->data); - g_list_free(keys); - return wins_get_by_num(new_num); } + // otherwise return the last window + int new_num = GPOINTER_TO_INT(g_list_last(keys)->data); + return wins_get_by_num(new_num); } int wins_get_num(ProfWin* window) { - GList* keys = g_hash_table_get_keys(windows); GList* curr = keys; while (curr) { gconstpointer num_p = curr->data; ProfWin* curr_win = g_hash_table_lookup(windows, num_p); if (curr_win == window) { - g_list_free(keys); return GPOINTER_TO_INT(num_p); } curr = g_list_next(curr); } - g_list_free(keys); return -1; } @@ -596,6 +583,7 @@ wins_close_by_num(int i) } g_hash_table_remove(windows, GINT_TO_POINTER(i)); + _wins_htable_update(); status_bar_inactive(i); } } @@ -615,11 +603,9 @@ wins_is_current(ProfWin* window) ProfWin* wins_new_xmlconsole(void) { - GList* keys = g_hash_table_get_keys(windows); int result = _wins_get_next_available_num(keys); - g_list_free(keys); ProfWin* newwin = win_create_xmlconsole(); - g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin); + _wins_htable_insert(windows, GINT_TO_POINTER(result), newwin); autocomplete_add(wins_ac, "xmlconsole"); autocomplete_add(wins_close_ac, "xmlconsole"); return newwin; @@ -628,11 +614,9 @@ wins_new_xmlconsole(void) ProfWin* wins_new_chat(const char* const barejid) { - GList* keys = g_hash_table_get_keys(windows); int result = _wins_get_next_available_num(keys); - g_list_free(keys); ProfWin* newwin = win_create_chat(barejid); - g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin); + _wins_htable_insert(windows, GINT_TO_POINTER(result), newwin); autocomplete_add(wins_ac, barejid); autocomplete_add(wins_close_ac, barejid); @@ -653,11 +637,9 @@ wins_new_chat(const char* const barejid) ProfWin* wins_new_muc(const char* const roomjid) { - GList* keys = g_hash_table_get_keys(windows); int result = _wins_get_next_available_num(keys); - g_list_free(keys); ProfWin* newwin = win_create_muc(roomjid); - g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin); + _wins_htable_insert(windows, GINT_TO_POINTER(result), newwin); autocomplete_add(wins_ac, roomjid); autocomplete_add(wins_close_ac, roomjid); newwin->urls_ac = autocomplete_new(); @@ -669,11 +651,9 @@ wins_new_muc(const char* const roomjid) ProfWin* wins_new_config(const char* const roomjid, DataForm* form, ProfConfWinCallback submit, ProfConfWinCallback cancel, const void* userdata) { - GList* keys = g_hash_table_get_keys(windows); int result = _wins_get_next_available_num(keys); - g_list_free(keys); ProfWin* newwin = win_create_config(roomjid, form, submit, cancel, userdata); - g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin); + _wins_htable_insert(windows, GINT_TO_POINTER(result), newwin); return newwin; } @@ -681,11 +661,9 @@ wins_new_config(const char* const roomjid, DataForm* form, ProfConfWinCallback s ProfWin* wins_new_private(const char* const fulljid) { - GList* keys = g_hash_table_get_keys(windows); int result = _wins_get_next_available_num(keys); - g_list_free(keys); ProfWin* newwin = win_create_private(fulljid); - g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin); + _wins_htable_insert(windows, GINT_TO_POINTER(result), newwin); autocomplete_add(wins_ac, fulljid); autocomplete_add(wins_close_ac, fulljid); newwin->urls_ac = autocomplete_new(); @@ -697,11 +675,9 @@ wins_new_private(const char* const fulljid) ProfWin* wins_new_plugin(const char* const plugin_name, const char* const tag) { - GList* keys = g_hash_table_get_keys(windows); int result = _wins_get_next_available_num(keys); - g_list_free(keys); ProfWin* newwin = win_create_plugin(plugin_name, tag); - g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin); + _wins_htable_insert(windows, GINT_TO_POINTER(result), newwin); autocomplete_add(wins_ac, tag); autocomplete_add(wins_close_ac, tag); return newwin; @@ -710,11 +686,9 @@ wins_new_plugin(const char* const plugin_name, const char* const tag) ProfWin* wins_new_vcard(vCard* vcard) { - GList* keys = g_hash_table_get_keys(windows); int result = _wins_get_next_available_num(keys); - g_list_free(keys); ProfWin* newwin = win_create_vcard(vcard); - g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin); + _wins_htable_insert(windows, GINT_TO_POINTER(result), newwin); return newwin; } @@ -722,18 +696,15 @@ wins_new_vcard(vCard* vcard) gboolean wins_do_notify_remind(void) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { ProfWin* window = curr->data; if (win_notify_remind(window)) { - g_list_free(values); return TRUE; } curr = g_list_next(curr); } - g_list_free(values); return FALSE; } @@ -741,7 +712,6 @@ int wins_get_total_unread(void) { int result = 0; - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -749,21 +719,18 @@ wins_get_total_unread(void) result += win_unread(window); curr = g_list_next(curr); } - g_list_free(values); return result; } void wins_resize_all(void) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { ProfWin* window = curr->data; win_resize(window); curr = g_list_next(curr); } - g_list_free(values); ProfWin* current_win = wins_get_current(); win_update_virtual(current_win); @@ -795,7 +762,6 @@ wins_show_subwin(ProfWin* window) ProfXMLWin* wins_get_xmlconsole(void) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -803,20 +769,17 @@ wins_get_xmlconsole(void) if (window->type == WIN_XML) { ProfXMLWin* xmlwin = (ProfXMLWin*)window; assert(xmlwin->memcheck == PROFXMLWIN_MEMCHECK); - g_list_free(values); return xmlwin; } curr = g_list_next(curr); } - g_list_free(values); return NULL; } ProfVcardWin* wins_get_vcard(void) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -824,13 +787,11 @@ wins_get_vcard(void) if (window->type == WIN_VCARD) { ProfVcardWin* vcardwin = (ProfVcardWin*)window; assert(vcardwin->memcheck == PROFVCARDWIN_MEMCHECK); - g_list_free(values); return vcardwin; } curr = g_list_next(curr); } - g_list_free(values); return NULL; } @@ -838,7 +799,6 @@ GSList* wins_get_chat_recipients(void) { GSList* result = NULL; - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -849,7 +809,6 @@ wins_get_chat_recipients(void) } curr = g_list_next(curr); } - g_list_free(values); return result; } @@ -857,7 +816,6 @@ GSList* wins_get_prune_wins(void) { GSList* result = NULL; - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -867,14 +825,12 @@ wins_get_prune_wins(void) } curr = g_list_next(curr); } - g_list_free(values); return result; } void wins_lost_connection(void) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -889,13 +845,11 @@ wins_lost_connection(void) } curr = g_list_next(curr); } - g_list_free(values); } void wins_reestablished_connection(void) { - GList* values = g_hash_table_get_values(windows); GList* curr = values; while (curr) { @@ -928,7 +882,6 @@ wins_reestablished_connection(void) } curr = g_list_next(curr); } - g_list_free(values); } void @@ -943,7 +896,7 @@ wins_swap(int source_win, int target_win) // target window empty if (target == NULL) { g_hash_table_steal(windows, GINT_TO_POINTER(source_win)); - g_hash_table_insert(windows, GINT_TO_POINTER(target_win), source); + _wins_htable_insert(windows, GINT_TO_POINTER(target_win), source); status_bar_inactive(source_win); auto_char char* identifier = win_get_tab_identifier(source); if (win_unread(source) > 0) { @@ -961,7 +914,7 @@ wins_swap(int source_win, int target_win) g_hash_table_steal(windows, GINT_TO_POINTER(source_win)); g_hash_table_steal(windows, GINT_TO_POINTER(target_win)); g_hash_table_insert(windows, GINT_TO_POINTER(source_win), target); - g_hash_table_insert(windows, GINT_TO_POINTER(target_win), source); + _wins_htable_insert(windows, GINT_TO_POINTER(target_win), source); auto_char char* source_identifier = win_get_tab_identifier(source); auto_char char* target_identifier = win_get_tab_identifier(target); if (win_unread(source) > 0) { @@ -1011,16 +964,9 @@ _wins_get_next_available_num(GList* used) if (g_list_length(used) == 1) { return 2; } else { - GList* sorted = NULL; GList* curr = used; - while (curr) { - sorted = g_list_insert_sorted(sorted, curr->data, _wins_cmp_num); - curr = g_list_next(curr); - } - int result = 0; int last_num = 1; - curr = sorted; // skip console curr = g_list_next(curr); while (curr) { @@ -1031,7 +977,6 @@ _wins_get_next_available_num(GList* used) if (result == 10) { result = 0; } - g_list_free(sorted); return (result); } else { @@ -1047,7 +992,6 @@ _wins_get_next_available_num(GList* used) result = 0; } - g_list_free(sorted); return result; } } @@ -1056,10 +1000,6 @@ gboolean wins_tidy(void) { gboolean tidy_required = FALSE; - // check for gaps - GList* keys = g_hash_table_get_keys(windows); - keys = g_list_sort(keys, _wins_cmp_num); - // get last used GList* last = g_list_last(keys); int last_num = GPOINTER_TO_INT(last->data); @@ -1104,13 +1044,12 @@ wins_tidy(void) g_hash_table_destroy(windows); windows = new_windows; + _wins_htable_update(); current = 1; ProfWin* console = wins_get_console(); ui_focus_win(console); - g_list_free(keys); return TRUE; } else { - g_list_free(keys); return FALSE; } } @@ -1123,9 +1062,6 @@ wins_create_summary(gboolean unread) } GSList* result = NULL; - - GList* keys = g_hash_table_get_keys(windows); - keys = g_list_sort(keys, _wins_cmp_num); GList* curr = keys; while (curr) { @@ -1149,8 +1085,6 @@ wins_create_summary(gboolean unread) curr = g_list_next(curr); } - g_list_free(keys); - return result; } @@ -1159,8 +1093,6 @@ wins_create_summary_attention() { GSList* result = NULL; - GList* keys = g_hash_table_get_keys(windows); - keys = g_list_sort(keys, _wins_cmp_num); GList* curr = keys; while (curr) { @@ -1193,8 +1125,6 @@ wins_create_summary_attention() curr = g_list_next(curr); } - g_list_free(keys); - return result; } @@ -1225,6 +1155,11 @@ win_close_reset_search_attempts(void) void wins_destroy(void) { + if (values) + g_list_free(values); + if (keys) + g_list_free(keys); + values = keys = NULL; g_hash_table_destroy(windows); windows = NULL; autocomplete_free(wins_ac); @@ -1237,9 +1172,7 @@ ProfWin* wins_get_next_unread(void) { // get and sort win nums - GList* values = g_hash_table_get_keys(windows); - values = g_list_sort(values, _wins_cmp_num); - GList* curr = values; + GList* curr = keys; while (curr) { int curr_win_num = GPOINTER_TO_INT(curr->data); @@ -1247,14 +1180,12 @@ wins_get_next_unread(void) // test if window has unread messages if (win_unread(window) > 0) { - g_list_free(values); return window; } curr = g_list_next(curr); } - g_list_free(values); return NULL; } @@ -1262,8 +1193,6 @@ ProfWin* wins_get_next_attention(void) { // get and sort win nums - GList* values = g_hash_table_get_values(windows); - values = g_list_sort(values, _wins_cmp_num); GList* curr = values; ProfWin* current_window = wins_get_by_num(current); @@ -1283,7 +1212,6 @@ wins_get_next_attention(void) while (current_window && curr) { ProfWin* window = curr->data; if (win_has_attention(window)) { - g_list_free(values); return window; } curr = g_list_next(curr); @@ -1297,13 +1225,11 @@ wins_get_next_attention(void) break; } if (win_has_attention(window)) { - g_list_free(values); return window; } curr = g_list_next(curr); } - g_list_free(values); return NULL; } From ed44d7ad96fdc0896d1a9cbf4b309ea8179f5c4c Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Wed, 9 Apr 2025 16:40:33 +0200 Subject: [PATCH 6/6] Fix handling of roster pushes We must only return early in cases where we received a roster push with 1. a `from` attribute 2. that `from` is not our bare JID The server sends roster pushes without `from` attribute and we must accept them. Fixes #2035 Fixes: bac24601da ("Introduce `equals_our_barejid()`") Signed-off-by: Steffen Jaeckel --- src/xmpp/roster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c index dac0d7358..a760a8884 100644 --- a/src/xmpp/roster.c +++ b/src/xmpp/roster.c @@ -201,7 +201,7 @@ roster_set_handler(xmpp_stanza_t* const stanza) // if from attribute exists and it is not current users barejid, ignore push const char* from = xmpp_stanza_get_from(stanza); - if (!equals_our_barejid(from)) { + if (from && !equals_our_barejid(from)) { log_warning("Received alleged roster push from: %s", from); return; }