exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit a369995a792e3a9618c5c8f8e6b257f406df9f5f
parent f194a76d391d9a3c7c0d7a0070759fc1809ad082
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Sun, 16 Aug 2026 08:28:56 +0200

better language code check

Diffstat:
Msrc/json/i18n.c | 92++++++++++++++++++++++++++++++++++++++++----------------------------------------
1 file changed, 46 insertions(+), 46 deletions(-)

diff --git a/src/json/i18n.c b/src/json/i18n.c @@ -67,6 +67,51 @@ TALER_JSON_extract_i18n (const json_t *object, } +/** + * Check that @a tag is a valid language tag. Accepted are a + * two- or three-letter language code (ISO 639-1, 639-2 or 639-3), + * optionally followed by '_' or '-' and a two-letter country code + * (ISO 3166-1 alpha-2) or a three-digit region code (UN M.49). + * We do not care about capitalization. For the syntax, see the + * GNU Gettext manual, including appendix A for rare language + * codes. + * + * @param tag language tag to check + * @return true if @a tag is well-formed + */ +static bool +check_language_tag (const char *tag) +{ + size_t len = strlen (tag); + size_t off = 0; + + while ( (off < len) && + (0 != isalpha ((unsigned char) tag[off])) ) + off++; + if ( (off < 2) || + (off > 3) ) + return false; /* language code must have 2 or 3 letters */ + if (off == len) + return true; /* language code without country code */ + if ( ('_' != tag[off]) && + ('-' != tag[off]) ) + return false; + off++; + if (2 == len - off) + { + return ( (0 != isalpha ((unsigned char) tag[off])) && + (0 != isalpha ((unsigned char) tag[off + 1])) ); + } + if (3 == len - off) + { + return ( (0 != isdigit ((unsigned char) tag[off])) && + (0 != isdigit ((unsigned char) tag[off + 1])) && + (0 != isdigit ((unsigned char) tag[off + 2])) ); + } + return false; +} + + bool TALER_JSON_check_i18n (const json_t *i18n) { @@ -79,53 +124,8 @@ TALER_JSON_check_i18n (const json_t *i18n) { if (! json_is_string (member)) return false; - /* Field name must be either of format "en_UK" - or just "en"; we do not care about capitalization; - for syntax, see GNU Gettext manual, including - appendix A for rare language codes. */ - switch (strlen (field)) - { - case 0: - case 1: + if (! check_language_tag (field)) return false; - case 2: - if (! isalpha ((unsigned char) field[0])) - return false; - if (! isalpha ((unsigned char) field[1])) - return false; - break; - case 3: - case 4: - return false; - case 5: - if (! isalpha ((unsigned char) field[0])) - return false; - if (! isalpha ((unsigned char) field[1])) - return false; - if ('_' != field[2]) - return false; - if (! isalpha ((unsigned char) field[3])) - return false; - if (! isalpha ((unsigned char) field[4])) - return false; - break; - case 6: - if (! isalpha ((unsigned char) field[0])) - return false; - if (! isalpha ((unsigned char) field[1])) - return false; - if ('_' != field[2]) - return false; - if (! isalpha ((unsigned char) field[3])) - return false; - if (! isalpha ((unsigned char) field[4])) - return false; - if (! isalpha ((unsigned char) field[5])) - return false; - break; - default: - return false; - } } return true; }