diff --git a/app/flatpak-builtins-config.c b/app/flatpak-builtins-config.c index 5d24dc73..8b4855fd 100644 --- a/app/flatpak-builtins-config.c +++ b/app/flatpak-builtins-config.c @@ -68,49 +68,73 @@ looks_like_a_language (const char *s) } static gboolean -looks_like_a_region (const char *s) +looks_like_a_territory (const char *s) { - g_auto(GStrv) locale = g_strsplit (s, "_", 3); - int i; - int len; + gsize len = strlen (s); + gsize i; - if (!looks_like_a_language(locale[0])) + if (len < 2) return FALSE; - if (locale[1] != NULL) + for (i = 0; i < len; i++) { - len = strlen (locale[1]); - - // This can be either GB or Latn - if (len < 2 || len > 4) + if (!g_ascii_isalpha (s[i]) || !g_ascii_isupper (s[i])) return FALSE; - - for (i = 0; i < len; i++) - { - if ((locale[2] == NULL) && (!g_ascii_isalpha (locale[1][i]) || !g_ascii_isupper (locale[1][i]))) - return FALSE; - else if (!g_ascii_isalpha (locale[1][i])) - return FALSE; - } } - if (g_strv_length (locale) > 2) + return TRUE; +} + +static gboolean +looks_like_a_codeset_or_modifier (const char *s) +{ + gsize len = strlen (s); + gsize i; + + if (len < 1) + return FALSE; + + for (i = 0; i < len; i++) { - len = strlen (locale[2]); - - if (len < 2 || len > 3) + if (!g_ascii_isalnum (s[i]) && s[i] != '-') return FALSE; - - for (i = 0; i < len; i++) - { - if (!g_ascii_isalpha (locale[2][i]) || !g_ascii_isupper (locale[2][i])) - return FALSE; - } } return TRUE; } +static gboolean +looks_like_a_locale (const char *s) +{ + g_autofree gchar *locale = g_strdup (s); + gchar *language, *territory, *codeset, *modifier; + + modifier = strchr (locale, '@'); + if (modifier != NULL) + *modifier++ = '\0'; + + codeset = strchr (locale, '.'); + if (codeset != NULL) + *codeset++ = '\0'; + + territory = strchr (locale, '_'); + if (territory != NULL) + *territory++ = '\0'; + + language = locale; + + if (!looks_like_a_language (language)) + return FALSE; + if (territory != NULL && !looks_like_a_territory (territory)) + return FALSE; + if (codeset != NULL && !looks_like_a_codeset_or_modifier (codeset)) + return FALSE; + if (modifier != NULL && !looks_like_a_codeset_or_modifier (modifier)) + return FALSE; + + return TRUE; +} + static char * parse_locale (const char *value, GError **error) { @@ -120,7 +144,7 @@ parse_locale (const char *value, GError **error) strs = g_strsplit (value, ";", 0); for (i = 0; strs[i]; i++) { - if (!looks_like_a_language (strs[i]) && !looks_like_a_region (strs[i])) + if (!looks_like_a_language (strs[i]) && !looks_like_a_locale (strs[i])) { flatpak_fail (error, _("'%s' does not look like a language/locale code"), strs[i]); return NULL; diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index 6a68da43..65a07922 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -14607,9 +14607,10 @@ flatpak_dir_get_default_locale_languages (FlatpakDir *self) extra_languages = flatpak_dir_get_config_strv (self, "xa.extra-languages"); for (i = 0; extra_languages != NULL && extra_languages[i] != NULL; i++) { - g_auto(GStrv) locales = g_strsplit (extra_languages[i], "_", -1); - g_free (extra_languages[i]); - extra_languages[i] = g_strdup (locales[0]); + /* Strip the locale, modifier or codeset, if present. */ + gchar *match = strpbrk (extra_languages[i], "._@"); + if (match != NULL) + *match = '\0'; } if (flatpak_dir_is_user (self)) diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c index ad730671..d6935b1d 100644 --- a/common/flatpak-installation.c +++ b/common/flatpak-installation.c @@ -1687,12 +1687,15 @@ flatpak_installation_get_default_languages (FlatpakInstallation *self, * @self: a #FlatpakInstallation * @error: return location for a #GError * - * Like flatpak_installation_get_default_languages() but includes region - * information (e.g. en_US rather than en) which may be included in the - * xa.extra-languages configuration. + * Like flatpak_installation_get_default_languages() but includes territory + * information (e.g. `en_US` rather than `en`) which may be included in the + * `xa.extra-languages` configuration. + * + * Strings returned by this function are in the format specified by + * [`setlocale()`](man:setlocale): `language[_territory][.codeset][@modifier]`. * * Returns: (array zero-terminated=1) (element-type utf8) (transfer full): - * A possibly empty array of language and locale strings, or %NULL on error. + * A possibly empty array of locale strings, or %NULL on error. * Since: 1.5.1 */ char **