Bumping manifests a=b2g-bump
[gecko.git] / netwerk / dns / nameprep.c
blob039797885dc63d6a156dadf8a4999e41cef88bf4
1 /*
2 * Copyright (c) 2001,2002 Japan Network Information Center.
3 * All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set forth bellow.
6 *
7 * LICENSE TERMS AND CONDITIONS
8 *
9 * The following License Terms and Conditions apply, unless a different
10 * license is obtained from Japan Network Information Center ("JPNIC"),
11 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
12 * Chiyoda-ku, Tokyo 101-0047, Japan.
14 * 1. Use, Modification and Redistribution (including distribution of any
15 * modified or derived work) in source and/or binary forms is permitted
16 * under this License Terms and Conditions.
18 * 2. Redistribution of source code must retain the copyright notices as they
19 * appear in each source code file, this License Terms and Conditions.
21 * 3. Redistribution in binary form must reproduce the Copyright Notice,
22 * this License Terms and Conditions, in the documentation and/or other
23 * materials provided with the distribution. For the purposes of binary
24 * distribution the "Copyright Notice" refers to the following language:
25 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
27 * 4. The name of JPNIC may not be used to endorse or promote products
28 * derived from this Software without specific prior written approval of
29 * JPNIC.
31 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
34 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
38 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
45 #include <stdlib.h>
46 #include <string.h>
48 #include "nsIDNKitInterface.h"
50 #define UCS_MAX 0x7fffffff
51 #define UNICODE_MAX 0x10ffff
55 * Load NAMEPREP compiled tables.
57 #include "nameprepdata.c"
60 * Define mapping/checking functions for each version of the draft.
63 #define VERSION id11
64 #include "nameprep_template.c"
65 #undef VERSION
67 typedef const char *(*nameprep_mapproc)(uint32_t v);
68 typedef int (*nameprep_checkproc)(uint32_t v);
69 typedef idn_biditype_t (*nameprep_biditypeproc)(uint32_t v);
71 static struct idn_nameprep {
72 char *version;
73 nameprep_mapproc map_proc;
74 nameprep_checkproc prohibited_proc;
75 nameprep_checkproc unassigned_proc;
76 nameprep_biditypeproc biditype_proc;
77 } nameprep_versions[] = {
78 #define MAKE_NAMEPREP_HANDLE(version, id) \
79 { version, \
80 compose_sym2(nameprep_map_, id), \
81 compose_sym2(nameprep_prohibited_, id), \
82 compose_sym2(nameprep_unassigned_, id), \
83 compose_sym2(nameprep_biditype_, id), }
84 MAKE_NAMEPREP_HANDLE("nameprep-11", id11),
85 { NULL, NULL, NULL, NULL, NULL },
88 static idn_result_t idn_nameprep_check(nameprep_checkproc proc,
89 const uint32_t *str,
90 const uint32_t **found);
92 idn_result_t
93 idn_nameprep_create(const char *version, idn_nameprep_t *handlep) {
94 idn_nameprep_t handle;
96 assert(handlep != NULL);
98 TRACE(("idn_nameprep_create(version=%-.50s)\n",
99 version == NULL ? "<NULL>" : version));
101 if (version == NULL)
102 version = IDN_NAMEPREP_CURRENT;
105 * Lookup table for the specified version. Since the number of
106 * versions won't be large (I don't want see draft-23 or such :-),
107 * simple linear search is OK.
109 for (handle = nameprep_versions; handle->version != NULL; handle++) {
110 if (strcmp(handle->version, version) == 0) {
111 *handlep = handle;
112 return (idn_success);
115 return (idn_notfound);
118 void
119 idn_nameprep_destroy(idn_nameprep_t handle) {
120 assert(handle != NULL);
122 TRACE(("idn_nameprep_destroy()\n"));
124 /* Nothing to do. */
127 idn_result_t
128 idn_nameprep_map(idn_nameprep_t handle, const uint32_t *from,
129 uint32_t *to, size_t tolen) {
130 assert(handle != NULL && from != NULL && to != NULL);
132 TRACE(("idn_nameprep_map(ctx=%s, from=\"%s\")\n",
133 handle->version, idn__debug_ucs4xstring(from, 50)));
135 while (*from != '\0') {
136 uint32_t v = *from;
137 const char *mapped;
139 if (v > UCS_MAX) {
140 /* This cannot happen, but just in case.. */
141 return (idn_invalid_codepoint);
142 } else if (v > UNICODE_MAX) {
143 /* No mapping is possible. */
144 mapped = NULL;
145 } else {
146 /* Try mapping. */
147 mapped = (*handle->map_proc)(v);
150 if (mapped == NULL) {
151 /* No mapping. Just copy verbatim. */
152 if (tolen < 1)
153 return (idn_buffer_overflow);
154 *to++ = v;
155 tolen--;
156 } else {
157 const unsigned char *mappeddata;
158 size_t mappedlen;
160 mappeddata = (const unsigned char *)mapped + 1;
161 mappedlen = *mapped;
163 if (tolen < (mappedlen + 3) / 4)
164 return (idn_buffer_overflow);
165 tolen -= (mappedlen + 3) / 4;
166 while (mappedlen >= 4) {
167 *to = *mappeddata++;
168 *to |= *mappeddata++ << 8;
169 *to |= *mappeddata++ << 16;
170 *to |= *mappeddata++ << 24;
171 mappedlen -= 4;
172 to++;
174 if (mappedlen > 0) {
175 *to = *mappeddata++;
176 *to |= (mappedlen >= 2) ?
177 *mappeddata++ << 8: 0;
178 *to |= (mappedlen >= 3) ?
179 *mappeddata++ << 16: 0;
180 to++;
183 from++;
185 if (tolen == 0)
186 return (idn_buffer_overflow);
187 *to = '\0';
188 return (idn_success);
191 idn_result_t
192 idn_nameprep_isprohibited(idn_nameprep_t handle, const uint32_t *str,
193 const uint32_t **found) {
194 assert(handle != NULL && str != NULL && found != NULL);
196 TRACE(("idn_nameprep_isprohibited(ctx=%s, str=\"%s\")\n",
197 handle->version, idn__debug_ucs4xstring(str, 50)));
199 return (idn_nameprep_check(handle->prohibited_proc, str, found));
202 idn_result_t
203 idn_nameprep_isunassigned(idn_nameprep_t handle, const uint32_t *str,
204 const uint32_t **found) {
205 assert(handle != NULL && str != NULL && found != NULL);
207 TRACE(("idn_nameprep_isunassigned(handle->version, str=\"%s\")\n",
208 handle->version, idn__debug_ucs4xstring(str, 50)));
210 return (idn_nameprep_check(handle->unassigned_proc, str, found));
213 static idn_result_t
214 idn_nameprep_check(nameprep_checkproc proc, const uint32_t *str,
215 const uint32_t **found) {
216 uint32_t v;
218 while (*str != '\0') {
219 v = *str;
221 if (v > UCS_MAX) {
222 /* This cannot happen, but just in case.. */
223 return (idn_invalid_codepoint);
224 } else if (v > UNICODE_MAX) {
225 /* It is invalid.. */
226 *found = str;
227 return (idn_success);
228 } else if ((*proc)(v)) {
229 *found = str;
230 return (idn_success);
232 str++;
234 *found = NULL;
235 return (idn_success);
238 idn_result_t
239 idn_nameprep_isvalidbidi(idn_nameprep_t handle, const uint32_t *str,
240 const uint32_t **found) {
241 uint32_t v;
242 idn_biditype_t first_char;
243 idn_biditype_t last_char;
244 int found_r_al;
246 assert(handle != NULL && str != NULL && found != NULL);
248 TRACE(("idn_nameprep_isvalidbidi(ctx=%s, str=\"%s\")\n",
249 handle->version, idn__debug_ucs4xstring(str, 50)));
251 if (*str == '\0') {
252 *found = NULL;
253 return (idn_success);
257 * check first character's type and initialize variables.
259 found_r_al = 0;
260 if (*str > UCS_MAX) {
261 /* This cannot happen, but just in case.. */
262 return (idn_invalid_codepoint);
263 } else if (*str > UNICODE_MAX) {
264 /* It is invalid.. */
265 *found = str;
266 return (idn_success);
268 first_char = last_char = (*(handle->biditype_proc))(*str);
269 if (first_char == idn_biditype_r_al) {
270 found_r_al = 1;
272 str++;
275 * see whether string is valid or not.
277 while (*str != '\0') {
278 v = *str;
280 if (v > UCS_MAX) {
281 /* This cannot happen, but just in case.. */
282 return (idn_invalid_codepoint);
283 } else if (v > UNICODE_MAX) {
284 /* It is invalid.. */
285 *found = str;
286 return (idn_success);
287 } else {
288 last_char = (*(handle->biditype_proc))(v);
289 if (found_r_al && last_char == idn_biditype_l) {
290 *found = str;
291 return (idn_success);
293 if (first_char != idn_biditype_r_al && last_char == idn_biditype_r_al) {
294 *found = str;
295 return (idn_success);
297 if (last_char == idn_biditype_r_al) {
298 found_r_al = 1;
301 str++;
304 if (found_r_al) {
305 if (last_char != idn_biditype_r_al) {
306 *found = str - 1;
307 return (idn_success);
311 *found = NULL;
312 return (idn_success);
315 idn_result_t
316 idn_nameprep_createproc(const char *parameter, void **handlep) {
317 return idn_nameprep_create(parameter, (idn_nameprep_t *)handlep);
320 void
321 idn_nameprep_destroyproc(void *handle) {
322 idn_nameprep_destroy((idn_nameprep_t)handle);
325 idn_result_t
326 idn_nameprep_mapproc(void *handle, const uint32_t *from,
327 uint32_t *to, size_t tolen) {
328 return idn_nameprep_map((idn_nameprep_t)handle, from, to, tolen);
331 idn_result_t
332 idn_nameprep_prohibitproc(void *handle, const uint32_t *str,
333 const uint32_t **found) {
334 return idn_nameprep_isprohibited((idn_nameprep_t)handle, str, found);
337 idn_result_t
338 idn_nameprep_unassignedproc(void *handle, const uint32_t *str,
339 const uint32_t **found) {
340 return idn_nameprep_isunassigned((idn_nameprep_t)handle, str, found);
343 idn_result_t
344 idn_nameprep_bidiproc(void *handle, const uint32_t *str,
345 const uint32_t **found) {
346 return idn_nameprep_isvalidbidi((idn_nameprep_t)handle, str, found);