1 /* $NetBSD: nameprep.c,v 1.4 2014/12/10 04:37:55 christos Exp $ */
4 static char *rcsid
= "Id: nameprep.c,v 1.1 2003/06/04 00:25:56 marka Exp ";
8 * Copyright (c) 2001,2002 Japan Network Information Center.
11 * By using this file, you agree to the terms and conditions set forth bellow.
13 * LICENSE TERMS AND CONDITIONS
15 * The following License Terms and Conditions apply, unless a different
16 * license is obtained from Japan Network Information Center ("JPNIC"),
17 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
18 * Chiyoda-ku, Tokyo 101-0047, Japan.
20 * 1. Use, Modification and Redistribution (including distribution of any
21 * modified or derived work) in source and/or binary forms is permitted
22 * under this License Terms and Conditions.
24 * 2. Redistribution of source code must retain the copyright notices as they
25 * appear in each source code file, this License Terms and Conditions.
27 * 3. Redistribution in binary form must reproduce the Copyright Notice,
28 * this License Terms and Conditions, in the documentation and/or other
29 * materials provided with the distribution. For the purposes of binary
30 * distribution the "Copyright Notice" refers to the following language:
31 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
33 * 4. The name of JPNIC may not be used to endorse or promote products
34 * derived from this Software without specific prior written approval of
37 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
40 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
55 #include <idn/result.h>
56 #include <idn/assert.h>
58 #include <idn/logmacro.h>
59 #include <idn/debug.h>
60 #include <idn/nameprep.h>
62 #define UCS_MAX 0x7fffffff
63 #define UNICODE_MAX 0x10ffff
67 * Load NAMEPREP compiled tables.
69 #include "nameprepdata.c"
72 * Define mapping/checking functions for each version of the draft.
75 #define VERSION rfc3491
76 #include "nameprep_template.c"
79 typedef const char *(*nameprep_mapproc
)(unsigned long v
);
80 typedef int (*nameprep_checkproc
)(unsigned long v
);
81 typedef idn_biditype_t (*nameprep_biditypeproc
)(unsigned long v
);
83 static struct idn_nameprep
{
85 nameprep_mapproc map_proc
;
86 nameprep_checkproc prohibited_proc
;
87 nameprep_checkproc unassigned_proc
;
88 nameprep_biditypeproc biditype_proc
;
89 } nameprep_versions
[] = {
90 #define MAKE_NAMEPREP_HANDLE(version, id) \
92 compose_sym2(nameprep_map_, id), \
93 compose_sym2(nameprep_prohibited_, id), \
94 compose_sym2(nameprep_unassigned_, id), \
95 compose_sym2(nameprep_biditype_, id), }
96 MAKE_NAMEPREP_HANDLE("RFC3491", rfc3491
),
100 static idn_result_t
idn_nameprep_check(nameprep_checkproc proc
,
101 const unsigned long *str
,
102 const unsigned long **found
);
105 idn_nameprep_create(const char *version
, idn_nameprep_t
*handlep
) {
106 idn_nameprep_t handle
;
108 assert(handlep
!= NULL
);
110 TRACE(("idn_nameprep_create(version=%-.50s)\n",
111 version
== NULL
? "<NULL>" : version
));
114 version
= IDN_NAMEPREP_CURRENT
;
117 * Lookup table for the specified version. Since the number of
118 * versions won't be large (I don't want see draft-23 or such :-),
119 * simple linear search is OK.
121 for (handle
= nameprep_versions
; handle
->version
!= NULL
; handle
++) {
122 if (strcmp(handle
->version
, version
) == 0) {
124 return (idn_success
);
127 return (idn_notfound
);
131 idn_nameprep_destroy(idn_nameprep_t handle
) {
132 assert(handle
!= NULL
);
134 TRACE(("idn_nameprep_destroy()\n"));
140 idn_nameprep_map(idn_nameprep_t handle
, const unsigned long *from
,
141 unsigned long *to
, size_t tolen
) {
142 assert(handle
!= NULL
&& from
!= NULL
&& to
!= NULL
);
144 TRACE(("idn_nameprep_map(ctx=%s, from=\"%s\")\n",
145 handle
->version
, idn__debug_ucs4xstring(from
, 50)));
147 while (*from
!= '\0') {
148 unsigned long v
= *from
;
152 /* This cannot happen, but just in case.. */
153 return (idn_invalid_codepoint
);
154 } else if (v
> UNICODE_MAX
) {
155 /* No mapping is possible. */
159 mapped
= (*handle
->map_proc
)(v
);
162 if (mapped
== NULL
) {
163 /* No mapping. Just copy verbatim. */
165 return (idn_buffer_overflow
);
169 const unsigned char *mappeddata
;
172 mappeddata
= (const unsigned char *)mapped
+ 1;
175 if (tolen
< (mappedlen
+ 3) / 4)
176 return (idn_buffer_overflow
);
177 tolen
-= (mappedlen
+ 3) / 4;
178 while (mappedlen
>= 4) {
180 *to
|= *mappeddata
++ << 8;
181 *to
|= *mappeddata
++ << 16;
182 *to
|= *mappeddata
++ << 24;
188 *to
|= (mappedlen
>= 2) ?
189 *mappeddata
++ << 8: 0;
190 *to
|= (mappedlen
>= 3) ?
191 *mappeddata
++ << 16: 0;
198 return (idn_buffer_overflow
);
200 return (idn_success
);
204 idn_nameprep_isprohibited(idn_nameprep_t handle
, const unsigned long *str
,
205 const unsigned long **found
) {
206 assert(handle
!= NULL
&& str
!= NULL
&& found
!= NULL
);
208 TRACE(("idn_nameprep_isprohibited(ctx=%s, str=\"%s\")\n",
209 handle
->version
, idn__debug_ucs4xstring(str
, 50)));
211 return (idn_nameprep_check(handle
->prohibited_proc
, str
, found
));
215 idn_nameprep_isunassigned(idn_nameprep_t handle
, const unsigned long *str
,
216 const unsigned long **found
) {
217 assert(handle
!= NULL
&& str
!= NULL
&& found
!= NULL
);
219 TRACE(("idn_nameprep_isunassigned(handle->version, str=\"%s\")\n",
220 handle
->version
, idn__debug_ucs4xstring(str
, 50)));
222 return (idn_nameprep_check(handle
->unassigned_proc
, str
, found
));
226 idn_nameprep_check(nameprep_checkproc proc
, const unsigned long *str
,
227 const unsigned long **found
) {
230 while (*str
!= '\0') {
234 /* This cannot happen, but just in case.. */
235 return (idn_invalid_codepoint
);
236 } else if (v
> UNICODE_MAX
) {
237 /* It is invalid.. */
239 return (idn_success
);
240 } else if ((*proc
)(v
)) {
242 return (idn_success
);
247 return (idn_success
);
251 idn_nameprep_isvalidbidi(idn_nameprep_t handle
, const unsigned long *str
,
252 const unsigned long **found
) {
254 idn_biditype_t first_char
;
255 idn_biditype_t last_char
;
258 assert(handle
!= NULL
&& str
!= NULL
&& found
!= NULL
);
260 TRACE(("idn_nameprep_isvalidbidi(ctx=%s, str=\"%s\")\n",
261 handle
->version
, idn__debug_ucs4xstring(str
, 50)));
265 return (idn_success
);
269 * check first character's type and initialize variables.
272 if (*str
> UCS_MAX
) {
273 /* This cannot happen, but just in case.. */
274 return (idn_invalid_codepoint
);
275 } else if (*str
> UNICODE_MAX
) {
276 /* It is invalid.. */
278 return (idn_success
);
280 first_char
= last_char
= (*(handle
->biditype_proc
))(*str
);
281 if (first_char
== idn_biditype_r_al
) {
287 * see whether string is valid or not.
289 while (*str
!= '\0') {
293 /* This cannot happen, but just in case.. */
294 return (idn_invalid_codepoint
);
295 } else if (v
> UNICODE_MAX
) {
296 /* It is invalid.. */
298 return (idn_success
);
300 last_char
= (*(handle
->biditype_proc
))(v
);
301 if (found_r_al
&& last_char
== idn_biditype_l
) {
303 return (idn_success
);
305 if (first_char
!= idn_biditype_r_al
&& last_char
== idn_biditype_r_al
) {
307 return (idn_success
);
309 if (last_char
== idn_biditype_r_al
) {
317 if (last_char
!= idn_biditype_r_al
) {
319 return (idn_success
);
324 return (idn_success
);
328 idn_nameprep_createproc(const char *parameter
, void **handlep
) {
329 return idn_nameprep_create(parameter
, (idn_nameprep_t
*)handlep
);
333 idn_nameprep_destroyproc(void *handle
) {
334 idn_nameprep_destroy((idn_nameprep_t
)handle
);
338 idn_nameprep_mapproc(void *handle
, const unsigned long *from
,
339 unsigned long *to
, size_t tolen
) {
340 return idn_nameprep_map((idn_nameprep_t
)handle
, from
, to
, tolen
);
344 idn_nameprep_prohibitproc(void *handle
, const unsigned long *str
,
345 const unsigned long **found
) {
346 return idn_nameprep_isprohibited((idn_nameprep_t
)handle
, str
, found
);
350 idn_nameprep_unassignedproc(void *handle
, const unsigned long *str
,
351 const unsigned long **found
) {
352 return idn_nameprep_isunassigned((idn_nameprep_t
)handle
, str
, found
);
356 idn_nameprep_bidiproc(void *handle
, const unsigned long *str
,
357 const unsigned long **found
) {
358 return idn_nameprep_isvalidbidi((idn_nameprep_t
)handle
, str
, found
);