From 004ce33a22ae09f1802290ac752d4b62ecbeac9b Mon Sep 17 00:00:00 2001 From: Iain Lane Date: Fri, 4 Jun 2021 13:30:27 +0100 Subject: [PATCH] utils: Don't strip modifiers when stripping encoding We have some locales which are dupes if we do this, for example ca_ES.UTF-8 and ca_ES.UTF-8@valencia. The latter of these should become ca_ES@valencia in the output. That is what `locale -a` shows. Previously `as_locale_strip_encoding ()` modified the passed-in string in place. However, in the one place where don't `g_strdup ()` the string before passing to this function, it is the key in a `GHashTable`. We can't do this, and only get away with it because the hash table isn't touched after this call. Fix the function to instead return a newly allocated string, and drop the `g_strdup` calls from the other call sites. Add a small test for this function too. https://github.com/ximion/appstream-generator/issues/92 --- src/as-context.c | 2 +- src/as-utils-private.h | 5 ++++- src/as-utils.c | 20 +++++++++++++------- src/as-yaml.c | 2 +- tests/test-misc.c | 18 ++++++++++++++++++ 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/as-context.c b/src/as-context.c index cade065d3..9ce9b83f4 100644 --- a/src/as-context.c +++ b/src/as-context.c @@ -513,7 +513,7 @@ as_context_localized_ht_set (AsContext *ctx, GHashTable *lht, const gchar *value if (selected_locale == NULL) selected_locale = "C"; - locale_noenc = as_locale_strip_encoding (g_strdup (selected_locale)); + locale_noenc = as_locale_strip_encoding (selected_locale); g_hash_table_insert (lht, g_ref_string_new_intern (locale_noenc), g_strdup (value)); diff --git a/src/as-utils-private.h b/src/as-utils-private.h index 110e006d7..5dbeb2d35 100644 --- a/src/as-utils-private.h +++ b/src/as-utils-private.h @@ -97,7 +97,10 @@ AS_INTERNAL_VISIBLE gboolean as_copy_file (const gchar *source, const gchar *destination, GError **error); gboolean as_is_cruft_locale (const gchar *locale); -gchar *as_locale_strip_encoding (gchar *locale); + +AS_INTERNAL_VISIBLE +gchar *as_locale_strip_encoding (const gchar *locale); + gchar *as_utils_locale_to_language (const gchar *locale); gchar *as_get_current_arch (void); diff --git a/src/as-utils.c b/src/as-utils.c index 66f8a8222..4f2479291 100644 --- a/src/as-utils.c +++ b/src/as-utils.c @@ -776,16 +776,22 @@ as_is_cruft_locale (const gchar *locale) * as_locale_strip_encoding: * * Remove the encoding from a locale string. - * The function modifies the string directly. + * The function returns a newly allocated string. */ gchar* -as_locale_strip_encoding (gchar *locale) +as_locale_strip_encoding (const gchar *locale) { - gchar *tmp; - tmp = g_strstr_len (locale, -1, ".UTF-8"); - if (tmp != NULL) - *tmp = '\0'; - return locale; + static const char tail[] = ".UTF-8"; + gchar *ret; + g_autoptr(GString) str = NULL; + + str = g_string_new (locale); + g_string_replace (str, tail, "", 1); + + ret = g_string_free (str, FALSE); + str = NULL; + + return ret; } /** diff --git a/src/as-yaml.c b/src/as-yaml.c index 701429975..b284cdffb 100644 --- a/src/as-yaml.c +++ b/src/as-yaml.c @@ -509,7 +509,7 @@ as_yaml_set_localized_table (AsContext *ctx, GNode *node, GHashTable *l10n_table for (GNode *n = node->children; n != NULL; n = n->next) { const gchar *locale = as_yaml_get_node_locale (ctx, n); if (locale != NULL) { - g_autofree gchar *locale_noenc = as_locale_strip_encoding (g_strdup (locale)); + g_autofree gchar *locale_noenc = as_locale_strip_encoding (locale); g_hash_table_insert (l10n_table, g_ref_string_new_intern (locale_noenc), g_strdup (as_yaml_node_get_value (n))); diff --git a/tests/test-misc.c b/tests/test-misc.c index 4e9bca8de..0d7bdce50 100644 --- a/tests/test-misc.c +++ b/tests/test-misc.c @@ -21,6 +21,7 @@ #include #include "appstream.h" #include "as-news-convert.h" +#include "as-utils-private.h" #include "as-test-utils.h" @@ -192,6 +193,22 @@ test_readwrite_text_news () g_free (tmp); } +static void +test_locale_strip_encoding () +{ + g_autofree gchar *c = NULL; + g_autofree gchar *cutf8 = NULL; + g_autofree gchar *cutf8valencia = NULL; + + c = as_locale_strip_encoding ("C"); + cutf8 = as_locale_strip_encoding ("C.UTF-8"); + cutf8valencia = as_locale_strip_encoding ("C.UTF-8@valencia"); + + g_assert_cmpstr (c, ==, "C"); + g_assert_cmpstr (cutf8, ==, "C"); + g_assert_cmpstr (cutf8valencia, ==, "C@valencia"); +} + int main (int argc, char **argv) { @@ -214,6 +231,7 @@ main (int argc, char **argv) g_test_add_func ("/AppStream/Misc/YAMLNews", test_readwrite_yaml_news); g_test_add_func ("/AppStream/Misc/TextNews", test_readwrite_text_news); + g_test_add_func ("/AppStream/Misc/StripLocaleEncoding", test_locale_strip_encoding); ret = g_test_run (); g_free (datadir);