commit a369995a792e3a9618c5c8f8e6b257f406df9f5f
parent f194a76d391d9a3c7c0d7a0070759fc1809ad082
Author: Christian Grothoff <grothoff@gnunet.org>
Date: Sun, 16 Aug 2026 08:28:56 +0200
better language code check
Diffstat:
| M | src/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;
}