Mon, 21 Sep 2020 20:23:22 -0500
Cleanup some GG utility functions
* Remove unused `ggp_int64_compare`.
* Inline `ggp_list_copy_to_slist_deep`.
It's only used once.
* Rewrite `ggp_message_format_to_gg` using `GString`.
This may not be the best, but it's better than the implementation with `GList`.
* Use a string list pref to save gg server history.
This removes the need for gg to do the conversion to/from plain strings itself,
and thus removes the need for the `ggp_str*_list` functions.
* Embed `ggp_list_truncate` directly where used, and in simplified form.
* Embed `ggp_password_validate` at its caller.
There's only one use of it.
Testing Done:
Compile only.
Reviewed at https://reviews.imfreedom.org/r/117/
--- a/libpurple/protocols/gg/message-prpl.c Mon Sep 21 20:15:51 2020 -0500 +++ b/libpurple/protocols/gg/message-prpl.c Mon Sep 21 20:23:22 2020 -0500 @@ -309,13 +309,14 @@ msg->text = text_new; } -gchar * ggp_message_format_to_gg(PurpleConversation *conv, const gchar *text) +gchar * +ggp_message_format_to_gg(PurpleConversation *conv, const gchar *text) { gchar *text_new, *tmp; - GList *rt = NULL; /* reformatted text */ + GString *reformatted_text = NULL; GMatchInfo *match; guint pos = 0; - GList *pending_objects = NULL; + GString *pending_objects = NULL; GList *font_stack = NULL; static int html_sizes_pt[7] = { 7, 8, 9, 10, 12, 14, 16 }; @@ -346,6 +347,8 @@ text_new = g_strdup_printf("%s<eom></eom>", text_new); g_free(tmp); + reformatted_text = g_string_new(NULL); + pending_objects = g_string_new(NULL); g_regex_match(global_data.re_html_tag, text_new, 0, &match); while (g_match_info_matches(match)) { int m_start, m_end, m_pos; @@ -370,76 +373,80 @@ "uknown tag %s\n", tag_str); } - /* closing *all* formatting-related tags (GG11 weirness) + /* closing *all* formatting-related tags (GG11 weirdness) * and adding pending objects */ - if ((text_before && (font_changed || pending_objects)) || - (tag == GGP_HTML_TAG_EOM && tag_close)) - { + if ((text_before && (font_changed || pending_objects->len > 0)) || + (tag == GGP_HTML_TAG_EOM && tag_close)) { font_changed = FALSE; if (in_any_tag) { in_any_tag = FALSE; - if (font_current->s && !GGP_GG11_FORCE_COMPAT) - rt = g_list_prepend(rt, - g_strdup("</s>")); - if (font_current->u) - rt = g_list_prepend(rt, - g_strdup("</u>")); - if (font_current->i) - rt = g_list_prepend(rt, - g_strdup("</i>")); - if (font_current->b) - rt = g_list_prepend(rt, - g_strdup("</b>")); - rt = g_list_prepend(rt, g_strdup("</span>")); + if (font_current->s && !GGP_GG11_FORCE_COMPAT) { + g_string_append(reformatted_text, "</s>"); + } + if (font_current->u) { + g_string_append(reformatted_text, "</u>"); + } + if (font_current->i) { + g_string_append(reformatted_text, "</i>"); + } + if (font_current->b) { + g_string_append(reformatted_text, "</b>"); + } + g_string_append(reformatted_text, "</span>"); } - if (pending_objects) { - rt = g_list_concat(pending_objects, rt); - pending_objects = NULL; + if (pending_objects->len > 0) { + g_string_append(reformatted_text, pending_objects->str); + g_string_truncate(pending_objects, 0); } } /* opening formatting-related tags again */ if (text_before && !in_any_tag) { - gchar *style; - GList *styles = NULL; gboolean has_size = (font_new->size > 0 && font_new->size <= 7 && font_new->size != 3); + gboolean has_style = + has_size || font_new->face || + (font_new->bgcolor >= 0 && !GGP_GG11_FORCE_COMPAT) || + font_new->color >= 0; - if (has_size) - styles = g_list_append(styles, g_strdup_printf( - "font-size:%dpt;", - html_sizes_pt[font_new->size - 1])); - if (font_new->face) - styles = g_list_append(styles, g_strdup_printf( - "font-family:%s;", font_new->face)); - if (font_new->bgcolor >= 0 && !GGP_GG11_FORCE_COMPAT) - styles = g_list_append(styles, g_strdup_printf( - "background-color:#%06x;", - font_new->bgcolor)); - if (font_new->color >= 0) - styles = g_list_append(styles, g_strdup_printf( - "color:#%06x;", font_new->color)); + if (has_style) { + g_string_append(reformatted_text, "<span style=\""); - if (styles) { - gchar *combined = ggp_strjoin_list(" ", styles); - g_list_free_full(styles, g_free); - style = g_strdup_printf(" style=\"%s\"", - combined); - g_free(combined); - } else - style = g_strdup(""); - rt = g_list_prepend(rt, g_strdup_printf("<span%s>", - style)); - g_free(style); + if (has_size) { + g_string_append_printf(reformatted_text, "font-size:%dpt;", + html_sizes_pt[font_new->size - 1]); + } + if (font_new->face) { + g_string_append_printf(reformatted_text, "font-family:%s;", + font_new->face); + } + if (font_new->bgcolor >= 0 && !GGP_GG11_FORCE_COMPAT) { + g_string_append_printf(reformatted_text, + "background-color:#%06x;", + font_new->bgcolor); + } + if (font_new->color >= 0) { + g_string_append_printf(reformatted_text, "color:#%06x;", + font_new->color); + } - if (font_new->b) - rt = g_list_prepend(rt, g_strdup("<b>")); - if (font_new->i) - rt = g_list_prepend(rt, g_strdup("<i>")); - if (font_new->u) - rt = g_list_prepend(rt, g_strdup("<u>")); - if (font_new->s && !GGP_GG11_FORCE_COMPAT) - rt = g_list_prepend(rt, g_strdup("<s>")); + g_string_append(reformatted_text, "\">"); + } else { + g_string_append(reformatted_text, "<span>"); + } + + if (font_new->b) { + g_string_append(reformatted_text, "<b>"); + } + if (font_new->i) { + g_string_append(reformatted_text, "<i>"); + } + if (font_new->u) { + g_string_append(reformatted_text, "<u>"); + } + if (font_new->s && !GGP_GG11_FORCE_COMPAT) { + g_string_append(reformatted_text, "<s>"); + } ggp_font_free(font_current); font_current = font_new; @@ -448,8 +455,8 @@ in_any_tag = TRUE; } if (text_before) { - rt = g_list_prepend(rt, - g_strndup(text_new + pos, m_start - pos)); + g_string_append_len(reformatted_text, text_new + pos, + m_start - pos); } /* set formatting of a following text */ @@ -480,10 +487,9 @@ res = ggp_image_prepare(conv, image, &id); if (res == GGP_IMAGE_PREPARE_OK) { - pending_objects = g_list_prepend( - pending_objects, g_strdup_printf( - "<img name=\"" GGP_IMAGE_ID_FORMAT - "\">", id)); + g_string_append_printf(pending_objects, + "<img name=\"" GGP_IMAGE_ID_FORMAT "\">", + id); } else if (res == GGP_IMAGE_PREPARE_TOO_BIG) { purple_conversation_write_system_message(conv, _("Image is too large, please try " @@ -541,9 +547,9 @@ font_stack = g_list_prepend(font_stack, ggp_font_clone(font_new)); - if (tag == GGP_HTML_TAG_DIV) - pending_objects = g_list_prepend( - pending_objects, g_strdup("<br>")); + if (tag == GGP_HTML_TAG_DIV) { + g_string_append(pending_objects, "<br>"); + } style = g_hash_table_lookup(attribs, "style"); if (style) @@ -583,11 +589,9 @@ else font_new = ggp_font_clone(font_base); } else if (tag == GGP_HTML_TAG_BR) { - pending_objects = g_list_prepend(pending_objects, - g_strdup("<br>")); + g_string_append(pending_objects, "<br>"); } else if (tag == GGP_HTML_TAG_HR) { - pending_objects = g_list_prepend(pending_objects, - g_strdup("<br><span>---</span><br>")); + g_string_append(pending_objects, "<br><span>---</span><br>"); } else if (tag == GGP_HTML_TAG_A || tag == GGP_HTML_TAG_EOM) { /* do nothing */ } else if (tag == GGP_HTML_TAG_UNKNOWN) { @@ -616,10 +620,9 @@ g_list_free_full(font_stack, ggp_font_free); /* combining reformatted text info one string */ - rt = g_list_reverse(rt); g_free(text_new); - text_new = ggp_strjoin_list("", rt); - g_list_free_full(rt, g_free); + g_string_free(pending_objects, TRUE); + text_new = g_string_free(reformatted_text, FALSE); if (purple_debug_is_verbose()) purple_debug_info("gg", "reformatted text: [%s]", text_new);
--- a/libpurple/protocols/gg/servconn.c Mon Sep 21 20:15:51 2020 -0500 +++ b/libpurple/protocols/gg/servconn.c Mon Sep 21 20:23:22 2020 -0500 @@ -44,14 +44,18 @@ void ggp_servconn_setup(PurpleAccountOption *server_option) { - purple_prefs_add_string(GGP_SERVCONN_HISTORY_PREF, ""); + GList *extra; + purple_prefs_add_string_list(GGP_SERVCONN_HISTORY_PREF, NULL); global_data.server_option = server_option; - global_data.server_history = ggp_strsplit_list(purple_prefs_get_string( - GGP_SERVCONN_HISTORY_PREF), ";", GGP_SERVCONN_HISTORY_MAXLEN + 1); - global_data.server_history = ggp_list_truncate( - global_data.server_history, GGP_SERVCONN_HISTORY_MAXLEN, - g_free); + global_data.server_history = + purple_prefs_get_string_list(GGP_SERVCONN_HISTORY_PREF); + extra = g_list_nth(global_data.server_history, GGP_SERVCONN_HISTORY_MAXLEN); + if (extra != NULL) { + /* Truncate the list to the maximum. */ + extra->prev->next = NULL; + g_list_free_full(extra, g_free); + } purple_account_option_string_set_hints(global_data.server_option, ggp_servconn_get_servers()); @@ -65,7 +69,6 @@ void ggp_servconn_add_server(const gchar *server) { GList *old_entry; - gchar *joined; old_entry = g_list_find_custom(global_data.server_history, server, (GCompareFunc)g_strcmp0); @@ -77,21 +80,32 @@ global_data.server_history = g_list_prepend(global_data.server_history, g_strdup(server)); - global_data.server_history = ggp_list_truncate( - global_data.server_history, GGP_SERVCONN_HISTORY_MAXLEN, - g_free); + old_entry = + g_list_nth(global_data.server_history, GGP_SERVCONN_HISTORY_MAXLEN); + if (old_entry != NULL) { + /* Truncate the list to the maximum. */ + old_entry->prev->next = NULL; + g_list_free_full(old_entry, g_free); + } - joined = ggp_strjoin_list(";", global_data.server_history); - purple_prefs_set_string(GGP_SERVCONN_HISTORY_PREF, joined); - g_free(joined); + purple_prefs_set_string_list(GGP_SERVCONN_HISTORY_PREF, + global_data.server_history); purple_account_option_string_set_hints(global_data.server_option, ggp_servconn_get_servers()); } -GSList * ggp_servconn_get_servers(void) +GSList * +ggp_servconn_get_servers(void) { - return ggp_list_copy_to_slist_deep(global_data.server_history, - (GCopyFunc)g_strdup, NULL); + GSList *new_list = NULL; + GList *it; + + it = g_list_first(global_data.server_history); + while (it) { + new_list = g_slist_append(new_list, g_strdup(it->data)); + it = g_list_next(it); + } + return new_list; } void
--- a/libpurple/protocols/gg/utils.c Mon Sep 21 20:15:51 2020 -0500 +++ b/libpurple/protocols/gg/utils.c Mon Sep 21 20:23:22 2020 -0500 @@ -102,15 +102,6 @@ return ggp_convert(src, "CP1250", "UTF-8"); } -gboolean ggp_password_validate(const gchar *password) -{ - const int len = strlen(password); - if (len < 6 || len > 15) - return FALSE; - return g_regex_match_simple("^[ a-zA-Z0-9~`!@#$%^&*()_+=[\\]{};':\",./?" - "<>\\\\|-]+$", password, 0, 0); -} - gchar * ggp_utf8_strndup(const gchar *str, gsize n) { size_t raw_len; @@ -134,60 +125,6 @@ return g_strndup(str, raw_len); } -GSList * ggp_list_copy_to_slist_deep(GList *list, GCopyFunc func, - gpointer user_data) -{ - GSList *new_list = NULL; - GList *it; - - it = g_list_first(list); - while (it) { - new_list = g_slist_append(new_list, func(it->data, user_data)); - it = g_list_next(it); - } - return new_list; -} - -GList * ggp_strsplit_list(const gchar *string, const gchar *delimiter, - gint max_tokens) -{ - gchar **splitted, **it; - GList *list = NULL; - - it = splitted = g_strsplit(string, delimiter, max_tokens); - while (*it) { - list = g_list_append(list, *it); - it++; - } - g_free(splitted); - - return list; -} - -gchar * ggp_strjoin_list(const gchar *separator, GList *list) -{ - gchar **str_array; - gchar *joined; - gint list_len, i; - GList *it; - - list_len = g_list_length(list); - str_array = g_new(gchar*, list_len + 1); - - it = g_list_first(list); - i = 0; - while (it) { - str_array[i++] = it->data; - it = g_list_next(it); - } - str_array[i] = NULL; - - joined = g_strjoinv(separator, str_array); - g_free(str_array); - - return joined; -} - const gchar * ggp_ipv4_to_str(uint32_t raw_ip) { static gchar buff[INET_ADDRSTRLEN]; @@ -202,16 +139,6 @@ return buff; } -GList * ggp_list_truncate(GList *list, guint length, GDestroyNotify free_func) -{ - while (g_list_length(list) > length) { - GList *last = g_list_last(list); - free_func(last->data); - list = g_list_delete_link(list, last); - } - return list; -} - gchar * ggp_free_if_equal(gchar *str, const gchar *pattern) { if (g_strcmp0(str, pattern) == 0) { @@ -228,18 +155,6 @@ return ptr; } -gint ggp_int64_compare(gconstpointer _a, gconstpointer _b) -{ - const int64_t *ap = _a, *bp = _b; - const int64_t a = *ap, b = *bp; - if (a == b) - return 0; - if (a < b) - return -1; - else - return 1; -} - JsonParser * ggp_json_parse(const gchar *data) { JsonParser *parser;
--- a/libpurple/protocols/gg/utils.h Mon Sep 21 20:15:51 2020 -0500 +++ b/libpurple/protocols/gg/utils.h Mon Sep 21 20:23:22 2020 -0500 @@ -81,28 +81,14 @@ */ gchar * ggp_convert_from_cp1250(const gchar *src); -gboolean ggp_password_validate(const gchar *password); - gchar * ggp_utf8_strndup(const gchar *str, gsize n); -GSList * ggp_list_copy_to_slist_deep(GList *list, GCopyFunc func, - gpointer user_data); - -GList * ggp_strsplit_list(const gchar *string, const gchar *delimiter, - gint max_tokens); - -gchar * ggp_strjoin_list(const gchar *separator, GList *list); - const gchar * ggp_ipv4_to_str(uint32_t raw_ip); -GList * ggp_list_truncate(GList *list, guint length, GDestroyNotify free_func); - gchar * ggp_free_if_equal(gchar *str, const gchar *pattern); uint64_t * ggp_uint64dup(uint64_t val); -gint ggp_int64_compare(gconstpointer a, gconstpointer b); - JsonParser * ggp_json_parse(const gchar *data); #endif /* PURPLE_GG_UTILS_H */
--- a/libpurple/protocols/gg/validator.c Mon Sep 21 20:15:51 2020 -0500 +++ b/libpurple/protocols/gg/validator.c Mon Sep 21 20:23:22 2020 -0500 @@ -44,8 +44,16 @@ value = purple_request_field_string_get_value(field); - if (value != NULL && ggp_password_validate(value)) - return TRUE; + if (value != NULL) { + size_t len = strlen(value); + if (6 <= len && len <= 15) { + if (g_regex_match_simple( + "^[ a-zA-Z0-9~`!@#$%^&*()_+=[\\]{};':\",./?<>\\\\|-]+$", + value, 0, 0)) { + return TRUE; + } + } + } if (errmsg) *errmsg = g_strdup(_("Password can contain 6-15 alphanumeric characters"));