Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020, 2021 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file json/i18n.c
18 : * @brief helper functions for i18n in JSON processing
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h" /* UNNECESSARY? */
22 : #include <gnunet/gnunet_util_lib.h>
23 : #include "taler/taler_util.h"
24 : #include "taler/taler_json_lib.h"
25 :
26 :
27 : const json_t *
28 0 : TALER_JSON_extract_i18n (const json_t *object,
29 : const char *language_pattern,
30 : const char *field)
31 : {
32 : const json_t *ret;
33 : json_t *i18n;
34 0 : double quality = 0.0;
35 :
36 0 : ret = json_object_get (object,
37 : field);
38 0 : if (NULL == ret)
39 0 : return NULL; /* field MUST exist in object */
40 : {
41 : char *name;
42 :
43 0 : GNUNET_asprintf (&name,
44 : "%s_i18n",
45 : field);
46 0 : i18n = json_object_get (object,
47 : name);
48 0 : GNUNET_free (name);
49 : }
50 0 : if (NULL == i18n)
51 0 : return ret;
52 : {
53 : const char *key;
54 : json_t *value;
55 :
56 0 : json_object_foreach (i18n, key, value) {
57 0 : double q = TALER_pattern_matches (language_pattern,
58 : key);
59 0 : if (q > quality)
60 : {
61 0 : quality = q;
62 0 : ret = value;
63 : }
64 : }
65 : }
66 0 : return ret;
67 : }
68 :
69 :
70 : /**
71 : * Check that @a tag is a valid language tag. Accepted are a
72 : * two- or three-letter language code (ISO 639-1, 639-2 or 639-3),
73 : * optionally followed by '_' or '-' and a two-letter country code
74 : * (ISO 3166-1 alpha-2) or a three-digit region code (UN M.49).
75 : * We do not care about capitalization. For the syntax, see the
76 : * GNU Gettext manual, including appendix A for rare language
77 : * codes.
78 : *
79 : * @param tag language tag to check
80 : * @return true if @a tag is well-formed
81 : */
82 : static bool
83 0 : check_language_tag (const char *tag)
84 : {
85 0 : size_t len = strlen (tag);
86 0 : size_t off = 0;
87 :
88 0 : while ( (off < len) &&
89 0 : (0 != isalpha ((unsigned char) tag[off])) )
90 0 : off++;
91 0 : if ( (off < 2) ||
92 : (off > 3) )
93 0 : return false; /* language code must have 2 or 3 letters */
94 0 : if (off == len)
95 0 : return true; /* language code without country code */
96 0 : if ( ('_' != tag[off]) &&
97 0 : ('-' != tag[off]) )
98 0 : return false;
99 0 : off++;
100 0 : if (2 == len - off)
101 : {
102 0 : return ( (0 != isalpha ((unsigned char) tag[off])) &&
103 0 : (0 != isalpha ((unsigned char) tag[off + 1])) );
104 : }
105 0 : if (3 == len - off)
106 : {
107 0 : return ( (0 != isdigit ((unsigned char) tag[off])) &&
108 0 : (0 != isdigit ((unsigned char) tag[off + 1])) &&
109 0 : (0 != isdigit ((unsigned char) tag[off + 2])) );
110 : }
111 0 : return false;
112 : }
113 :
114 :
115 : bool
116 153 : TALER_JSON_check_i18n (const json_t *i18n)
117 : {
118 : const char *field;
119 : json_t *member;
120 :
121 153 : if (! json_is_object (i18n))
122 0 : return false;
123 153 : json_object_foreach ((json_t *) i18n, field, member)
124 : {
125 0 : if (! json_is_string (member))
126 0 : return false;
127 0 : if (! check_language_tag (field))
128 0 : return false;
129 : }
130 153 : return true;
131 : }
132 :
133 :
134 : /* end of i18n.c */
|