2 * Copyright (c) 2001,2002 Japan Network Information Center.
5 * By using this file, you agree to the terms and conditions set forth bellow.
7 * LICENSE TERMS AND CONDITIONS
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
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.
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.
64 #include "nameprep_template.c"
67 typedef const char *(*nameprep_mapproc
)(PRUint32 v
);
68 typedef int (*nameprep_checkproc
)(PRUint32 v
);
69 typedef idn_biditype_t (*nameprep_biditypeproc
)(PRUint32 v
);
71 static struct idn_nameprep
{
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) \
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
,
90 const PRUint32
**found
);
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
));
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) {
112 return (idn_success
);
115 return (idn_notfound
);
119 idn_nameprep_destroy(idn_nameprep_t handle
) {
120 assert(handle
!= NULL
);
122 TRACE(("idn_nameprep_destroy()\n"));
128 idn_nameprep_map(idn_nameprep_t handle
, const PRUint32
*from
,
129 PRUint32
*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') {
140 /* This cannot happen, but just in case.. */
141 return (idn_invalid_codepoint
);
142 } else if (v
> UNICODE_MAX
) {
143 /* No mapping is possible. */
147 mapped
= (*handle
->map_proc
)(v
);
150 if (mapped
== NULL
) {
151 /* No mapping. Just copy verbatim. */
153 return (idn_buffer_overflow
);
157 const unsigned char *mappeddata
;
160 mappeddata
= (const unsigned char *)mapped
+ 1;
163 if (tolen
< (mappedlen
+ 3) / 4)
164 return (idn_buffer_overflow
);
165 tolen
-= (mappedlen
+ 3) / 4;
166 while (mappedlen
>= 4) {
168 *to
|= *mappeddata
++ << 8;
169 *to
|= *mappeddata
++ << 16;
170 *to
|= *mappeddata
++ << 24;
176 *to
|= (mappedlen
>= 2) ?
177 *mappeddata
++ << 8: 0;
178 *to
|= (mappedlen
>= 3) ?
179 *mappeddata
++ << 16: 0;
186 return (idn_buffer_overflow
);
188 return (idn_success
);
192 idn_nameprep_isprohibited(idn_nameprep_t handle
, const PRUint32
*str
,
193 const PRUint32
**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
));
203 idn_nameprep_isunassigned(idn_nameprep_t handle
, const PRUint32
*str
,
204 const PRUint32
**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
));
214 idn_nameprep_check(nameprep_checkproc proc
, const PRUint32
*str
,
215 const PRUint32
**found
) {
218 while (*str
!= '\0') {
222 /* This cannot happen, but just in case.. */
223 return (idn_invalid_codepoint
);
224 } else if (v
> UNICODE_MAX
) {
225 /* It is invalid.. */
227 return (idn_success
);
228 } else if ((*proc
)(v
)) {
230 return (idn_success
);
235 return (idn_success
);
239 idn_nameprep_isvalidbidi(idn_nameprep_t handle
, const PRUint32
*str
,
240 const PRUint32
**found
) {
242 idn_biditype_t first_char
;
243 idn_biditype_t last_char
;
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)));
253 return (idn_success
);
257 * check first character's type and initialize variables.
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.. */
266 return (idn_success
);
268 first_char
= last_char
= (*(handle
->biditype_proc
))(*str
);
269 if (first_char
== idn_biditype_r_al
) {
275 * see whether string is valid or not.
277 while (*str
!= '\0') {
281 /* This cannot happen, but just in case.. */
282 return (idn_invalid_codepoint
);
283 } else if (v
> UNICODE_MAX
) {
284 /* It is invalid.. */
286 return (idn_success
);
288 last_char
= (*(handle
->biditype_proc
))(v
);
289 if (found_r_al
&& last_char
== idn_biditype_l
) {
291 return (idn_success
);
293 if (first_char
!= idn_biditype_r_al
&& last_char
== idn_biditype_r_al
) {
295 return (idn_success
);
297 if (last_char
== idn_biditype_r_al
) {
305 if (last_char
!= idn_biditype_r_al
) {
307 return (idn_success
);
312 return (idn_success
);
316 idn_nameprep_createproc(const char *parameter
, void **handlep
) {
317 return idn_nameprep_create(parameter
, (idn_nameprep_t
*)handlep
);
321 idn_nameprep_destroyproc(void *handle
) {
322 idn_nameprep_destroy((idn_nameprep_t
)handle
);
326 idn_nameprep_mapproc(void *handle
, const PRUint32
*from
,
327 PRUint32
*to
, size_t tolen
) {
328 return idn_nameprep_map((idn_nameprep_t
)handle
, from
, to
, tolen
);
332 idn_nameprep_prohibitproc(void *handle
, const PRUint32
*str
,
333 const PRUint32
**found
) {
334 return idn_nameprep_isprohibited((idn_nameprep_t
)handle
, str
, found
);
338 idn_nameprep_unassignedproc(void *handle
, const PRUint32
*str
,
339 const PRUint32
**found
) {
340 return idn_nameprep_isunassigned((idn_nameprep_t
)handle
, str
, found
);
344 idn_nameprep_bidiproc(void *handle
, const PRUint32
*str
,
345 const PRUint32
**found
) {
346 return idn_nameprep_isvalidbidi((idn_nameprep_t
)handle
, str
, found
);