1 /* $NetBSD: res.c,v 1.4 2014/12/10 04:37:55 christos Exp $ */
4 static char *rcsid
= "Id: res.c,v 1.1 2003/06/04 00:26:10 marka Exp ";
8 * Copyright (c) 2000,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.
56 #include <idn/result.h>
57 #include <idn/assert.h>
58 #include <idn/logmacro.h>
59 #include <idn/converter.h>
60 #include <idn/normalizer.h>
61 #include <idn/checker.h>
62 #include <idn/mapper.h>
63 #include <idn/mapselector.h>
64 #include <idn/delimitermap.h>
65 #include <idn/resconf.h>
68 #include <idn/debug.h>
71 #ifndef IDN_UTF8_ENCODING_NAME
72 #define IDN_UTF8_ENCODING_NAME "UTF-8" /* by IANA */
77 (IDN_LOCALCONV | IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | \
78 IDN_NORMALIZE | IDN_PROHCHECK | IDN_UNASCHECK | IDN_BIDICHECK | \
79 IDN_ASCCHECK | IDN_IDNCONV | IDN_LENCHECK | IDN_ENCODE_QUERY | \
82 (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
83 IDN_UNASCHECK | IDN_BIDICHECK | IDN_IDNCONV | IDN_ASCCHECK | \
84 IDN_RTCHECK | IDN_LOCALCONV | IDN_DECODE_QUERY)
87 (IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | IDN_NORMALIZE | \
88 IDN_PROHCHECK | IDN_UNASCHECK | IDN_BIDICHECK | IDN_ASCCHECK | \
89 IDN_IDNCONV | IDN_LENCHECK | IDN_ENCODE_QUERY | IDN_UNDOIFERR)
91 (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
92 IDN_UNASCHECK | IDN_BIDICHECK | IDN_IDNCONV | IDN_ASCCHECK | \
93 IDN_RTCHECK | IDN_DECODE_QUERY)
96 #define MAX_LABEL_LENGTH 63
101 typedef struct labellist
* labellist_t
;
105 unsigned long *undo_name
;
107 labellist_t previous
;
111 typedef idn_result_t (*res_insnproc_t
)(idn_resconf_t ctx
,
114 static void idn_res_initialize(void);
115 static idn_result_t
copy_verbatim(const char *from
, char *to
,
117 static idn_result_t
labellist_create(const unsigned long *name
,
118 labellist_t
*labelp
);
119 static void labellist_destroy(labellist_t label
);
120 static idn_result_t
labellist_setname(labellist_t label
,
121 const unsigned long *name
);
122 static const unsigned long *
123 labellist_getname(labellist_t label
);
124 static const unsigned long *
125 labellist_gettldname(labellist_t label
);
126 static idn_result_t
labellist_getnamelist(labellist_t label
,
128 size_t label_length
);
129 static void labellist_undo(labellist_t label
);
130 static labellist_t
labellist_tail(labellist_t label
);
131 static labellist_t
labellist_previous(labellist_t label
);
133 #ifndef WITHOUT_ICONV
134 static idn_result_t
label_localdecodecheck(idn_resconf_t ctx
,
137 static idn_result_t
label_idnencode_ace(idn_resconf_t ctx
,
139 static idn_result_t
label_idndecode(idn_resconf_t ctx
, labellist_t label
);
140 static idn_result_t
label_localmap(idn_resconf_t ctx
, labellist_t label
);
141 static idn_result_t
label_map(idn_resconf_t ctx
, labellist_t label
);
142 static idn_result_t
label_normalize(idn_resconf_t ctx
, labellist_t label
);
143 static idn_result_t
label_prohcheck(idn_resconf_t ctx
, labellist_t label
);
144 static idn_result_t
label_unascheck(idn_resconf_t ctx
, labellist_t label
);
145 static idn_result_t
label_bidicheck(idn_resconf_t ctx
, labellist_t label
);
146 static idn_result_t
label_asccheck(idn_resconf_t ctx
, labellist_t label
);
147 static idn_result_t
label_lencheck_ace(idn_resconf_t ctx
,
149 static idn_result_t
label_lencheck_nonace(idn_resconf_t ctx
,
151 static idn_result_t
label_rtcheck(idn_resconf_t ctx
, idn_action_t actions
,
153 const unsigned long *original_name
);
155 static int initialized
;
159 idn_res_enable(int on_off
) {
161 idn_res_initialize();
172 idn_res_initialize(void) {
174 char *value
= getenv("IDN_DISABLE");
186 idn_res_encodename(idn_resconf_t ctx
, idn_action_t actions
, const char *from
,
187 char *to
, size_t tolen
) {
188 idn_converter_t local_converter
= NULL
;
189 idn_converter_t idn_converter
= NULL
;
190 idn_delimitermap_t delimiter_mapper
;
192 labellist_t labels
= NULL
, l
;
193 unsigned long *buffer
= NULL
;
194 size_t buffer_length
;
198 assert(ctx
!= NULL
&& from
!= NULL
&& to
!= NULL
);
200 TRACE(("idn_res_encodename(actions=%s, from=\"%s\", tolen=%d)\n",
201 idn__res_actionstostring(actions
),
202 idn__debug_xstring(from
, 50), (int)tolen
));
204 if (actions
& ~ENCODE_MASK
) {
205 WARNING(("idn_res_encodename: invalid actions 0x%x\n",
207 r
= idn_invalid_action
;
212 idn_res_initialize();
213 if (!enabled
|| actions
== 0) {
214 r
= copy_verbatim(from
, to
, tolen
);
216 } else if (tolen
<= 0) {
217 r
= idn_buffer_overflow
;
221 if (actions
& IDN_ENCODE_QUERY
) {
222 #ifndef WITHOUT_ICONV
223 actions
|= (IDN_LOCALCONV
| IDN_DELIMMAP
| IDN_LOCALMAP
| \
224 IDN_MAP
| IDN_NORMALIZE
| IDN_PROHCHECK
| \
225 IDN_BIDICHECK
| IDN_IDNCONV
| IDN_LENCHECK
);
227 actions
|= (IDN_DELIMMAP
| IDN_LOCALMAP
| IDN_MAP
| \
228 IDN_NORMALIZE
| IDN_PROHCHECK
| IDN_BIDICHECK
| \
229 IDN_IDNCONV
| IDN_LENCHECK
);
234 * Convert `from' to UCS4.
236 local_converter
= idn_resconf_getlocalconverter(ctx
);
237 #ifndef WITHOUT_ICONV
238 if (local_converter
== NULL
) {
239 r
= idn_invalid_name
;
244 idn_converter
= idn_resconf_getidnconverter(ctx
);
245 if (idn_converter
!= NULL
&&
246 idn_converter_isasciicompatible(idn_converter
))
251 buffer_length
= tolen
* 2;
256 new_buffer
= realloc(buffer
, sizeof(*buffer
) * buffer_length
);
257 if (new_buffer
== NULL
) {
261 buffer
= (unsigned long *)new_buffer
;
263 if (actions
& IDN_LOCALCONV
) {
264 r
= idn_converter_convtoucs4(local_converter
, from
,
265 buffer
, buffer_length
);
267 r
= idn_ucs4_utf8toucs4(from
, buffer
, buffer_length
);
269 if (r
== idn_success
)
271 else if (r
!= idn_buffer_overflow
)
277 if (*buffer
== '\0') {
279 r
= idn_buffer_overflow
;
290 if (actions
& IDN_DELIMMAP
) {
291 TRACE(("res delimitermap(name=\"%s\")\n",
292 idn__debug_ucs4xstring(buffer
, 50)));
294 delimiter_mapper
= idn_resconf_getdelimitermap(ctx
);
295 if (delimiter_mapper
!= NULL
) {
296 r
= idn_delimitermap_map(delimiter_mapper
, buffer
,
297 buffer
, buffer_length
);
298 idn_delimitermap_destroy(delimiter_mapper
);
299 if (r
!= idn_success
)
302 TRACE(("res delimitermap(): success (name=\"%s\")\n",
303 idn__debug_ucs4xstring(buffer
, 50)));
306 from_is_root
= (buffer
[0] == '.' && buffer
[1] == '\0');
309 * Split the name into a list of labels.
311 r
= labellist_create(buffer
, &labels
);
312 if (r
!= idn_success
)
316 * Perform conversions and tests.
318 for (l
= labellist_tail(labels
); l
!= NULL
;
319 l
= labellist_previous(l
)) {
321 if (!idn__util_ucs4isasciirange(labellist_getname(l
))) {
322 if (actions
& IDN_LOCALMAP
) {
323 r
= label_localmap(ctx
, l
);
324 if (r
!= idn_success
)
329 if (!idn__util_ucs4isasciirange(labellist_getname(l
))) {
330 if (actions
& IDN_MAP
) {
331 r
= label_map(ctx
, l
);
332 if (r
!= idn_success
)
335 if (actions
& IDN_NORMALIZE
) {
336 r
= label_normalize(ctx
, l
);
337 if (r
!= idn_success
)
340 if (actions
& IDN_PROHCHECK
) {
341 r
= label_prohcheck(ctx
, l
);
342 if (r
== idn_prohibited
&&
343 (actions
& IDN_UNDOIFERR
)) {
346 } else if (r
!= idn_success
) {
350 if (actions
& IDN_UNASCHECK
) {
351 r
= label_unascheck(ctx
, l
);
352 if (r
== idn_prohibited
&&
353 (actions
& IDN_UNDOIFERR
)) {
356 } else if (r
!= idn_success
) {
360 if (actions
& IDN_BIDICHECK
) {
361 r
= label_bidicheck(ctx
, l
);
362 if (r
== idn_prohibited
&&
363 (actions
& IDN_UNDOIFERR
)) {
366 } else if (r
!= idn_success
) {
372 if (actions
& IDN_ASCCHECK
) {
373 r
= label_asccheck(ctx
, l
);
374 if (r
== idn_prohibited
&& (actions
& IDN_UNDOIFERR
)) {
377 } else if (r
!= idn_success
) {
382 if (!idn__util_ucs4isasciirange(labellist_getname(l
))) {
383 if ((actions
& IDN_IDNCONV
) && idn_is_ace
) {
384 r
= label_idnencode_ace(ctx
, l
);
385 if (r
!= idn_success
)
390 if (!from_is_root
&& (actions
& IDN_LENCHECK
)) {
392 r
= label_lencheck_ace(ctx
, l
);
394 r
= label_lencheck_nonace(ctx
, l
);
395 if (r
== idn_invalid_length
&&
396 (actions
& IDN_UNDOIFERR
)) {
399 } else if (r
!= idn_success
) {
406 * Concat a list of labels to a name.
411 new_buffer
= realloc(buffer
, sizeof(*buffer
) * buffer_length
);
412 if (new_buffer
== NULL
) {
416 buffer
= (unsigned long *)new_buffer
;
418 r
= labellist_getnamelist(labels
, buffer
, buffer_length
);
419 if (r
== idn_success
)
421 else if (r
!= idn_buffer_overflow
)
427 if ((actions
& IDN_IDNCONV
) && idn_converter
!= NULL
&& !idn_is_ace
) {
428 r
= idn_converter_convfromucs4(idn_converter
, buffer
, to
,
431 r
= idn_ucs4_ucs4toutf8(buffer
, to
, tolen
);
435 if (r
== idn_success
) {
436 TRACE(("idn_res_encodename(): success (to=\"%s\")\n",
437 idn__debug_xstring(to
, 50)));
439 TRACE(("idn_res_encodename(): %s\n", idn_result_tostring(r
)));
442 if (local_converter
!= NULL
)
443 idn_converter_destroy(local_converter
);
444 if (idn_converter
!= NULL
)
445 idn_converter_destroy(idn_converter
);
447 labellist_destroy(labels
);
452 idn_res_decodename(idn_resconf_t ctx
, idn_action_t actions
, const char *from
,
453 char *to
, size_t tolen
) {
454 idn_converter_t local_converter
= NULL
;
455 idn_converter_t idn_converter
= NULL
;
456 idn_delimitermap_t delimiter_mapper
;
458 labellist_t labels
= NULL
, l
;
459 unsigned long *buffer
= NULL
;
460 unsigned long *saved_name
= NULL
;
461 size_t buffer_length
;
464 assert(ctx
!= NULL
&& from
!= NULL
&& to
!= NULL
);
466 TRACE(("idn_res_decodename(actions=%s, from=\"%s\", tolen=%d)\n",
467 idn__res_actionstostring(actions
),
468 idn__debug_xstring(from
, 50), (int)tolen
));
470 if (actions
& ~DECODE_MASK
) {
471 WARNING(("idn_res_decodename: invalid actions 0x%x\n",
473 r
= idn_invalid_action
;
478 idn_res_initialize();
479 if (!enabled
|| actions
== 0) {
480 r
= copy_verbatim(from
, to
, tolen
);
482 } else if (tolen
<= 0) {
483 r
= idn_buffer_overflow
;
487 if (actions
& IDN_DECODE_QUERY
) {
488 #ifndef WITHOUT_ICONV
489 actions
|= (IDN_DELIMMAP
| IDN_MAP
| IDN_NORMALIZE
| \
490 IDN_PROHCHECK
| IDN_BIDICHECK
| IDN_IDNCONV
| \
491 IDN_RTCHECK
| IDN_LOCALCONV
);
493 actions
|= (IDN_DELIMMAP
| IDN_MAP
| IDN_NORMALIZE
| \
494 IDN_PROHCHECK
| IDN_BIDICHECK
| IDN_IDNCONV
| \
500 * Convert `from' to UCS4.
502 local_converter
= idn_resconf_getlocalconverter(ctx
);
503 #ifndef WITHOUT_ICONV
504 if (local_converter
== NULL
) {
505 r
= idn_invalid_name
;
510 idn_converter
= idn_resconf_getidnconverter(ctx
);
511 if (idn_converter
!= NULL
&&
512 idn_converter_isasciicompatible(idn_converter
))
517 buffer_length
= tolen
* 2;
519 TRACE(("res idndecode(name=\"%s\")\n", idn__debug_xstring(from
, 50)));
524 new_buffer
= realloc(buffer
, sizeof(*buffer
) * buffer_length
);
525 if (new_buffer
== NULL
) {
529 buffer
= (unsigned long *)new_buffer
;
531 if ((actions
& IDN_IDNCONV
) &&
532 idn_converter
!= NULL
&& !idn_is_ace
) {
533 r
= idn_converter_convtoucs4(idn_converter
, from
,
534 buffer
, buffer_length
);
536 r
= idn_ucs4_utf8toucs4(from
, buffer
, buffer_length
);
538 if (r
== idn_success
)
540 else if (r
!= idn_buffer_overflow
)
546 if (*buffer
== '\0') {
548 r
= idn_buffer_overflow
;
559 if (actions
& IDN_DELIMMAP
) {
560 TRACE(("res delimitermap(name=\"%s\")\n",
561 idn__debug_ucs4xstring(buffer
, 50)));
563 delimiter_mapper
= idn_resconf_getdelimitermap(ctx
);
564 if (delimiter_mapper
!= NULL
) {
565 r
= idn_delimitermap_map(delimiter_mapper
, buffer
,
566 buffer
, buffer_length
);
567 idn_delimitermap_destroy(delimiter_mapper
);
568 if (r
!= idn_success
)
571 TRACE(("res delimitermap(): success (name=\"%s\")\n",
572 idn__debug_ucs4xstring(buffer
, 50)));
576 * Split the name into a list of labels.
578 r
= labellist_create(buffer
, &labels
);
579 if (r
!= idn_success
)
583 * Perform conversions and tests.
585 for (l
= labellist_tail(labels
); l
!= NULL
;
586 l
= labellist_previous(l
)) {
591 if (!idn__util_ucs4isasciirange(labellist_getname(l
))) {
592 if (actions
& IDN_MAP
) {
593 r
= label_map(ctx
, l
);
594 if (r
!= idn_success
)
597 if (actions
& IDN_NORMALIZE
) {
598 r
= label_normalize(ctx
, l
);
599 if (r
!= idn_success
)
602 if (actions
& IDN_PROHCHECK
) {
603 r
= label_prohcheck(ctx
, l
);
604 if (r
== idn_prohibited
) {
607 } else if (r
!= idn_success
) {
611 if (actions
& IDN_UNASCHECK
) {
612 r
= label_unascheck(ctx
, l
);
613 if (r
== idn_prohibited
) {
616 } else if (r
!= idn_success
) {
620 if (actions
& IDN_BIDICHECK
) {
621 r
= label_bidicheck(ctx
, l
);
622 if (r
== idn_prohibited
) {
625 } else if (r
!= idn_success
) {
631 if ((actions
& IDN_IDNCONV
) && idn_is_ace
) {
632 saved_name
= idn_ucs4_strdup(labellist_getname(l
));
633 if (saved_name
== NULL
) {
637 r
= label_idndecode(ctx
, l
);
638 if (r
== idn_invalid_encoding
) {
641 } else if (r
!= idn_success
) {
645 if ((actions
& IDN_RTCHECK
) && saved_name
!= NULL
) {
646 r
= label_rtcheck(ctx
, actions
, l
, saved_name
);
647 if (r
== idn_invalid_encoding
) {
650 } else if (r
!= idn_success
) {
655 #ifndef WITHOUT_ICONV
656 if (actions
& IDN_LOCALCONV
) {
657 r
= label_localdecodecheck(ctx
, l
);
658 if (r
!= idn_success
)
665 * Concat a list of labels to a name.
670 new_buffer
= realloc(buffer
, sizeof(*buffer
) * buffer_length
);
671 if (new_buffer
== NULL
) {
675 buffer
= (unsigned long *)new_buffer
;
677 r
= labellist_getnamelist(labels
, buffer
, buffer_length
);
678 if (r
== idn_success
)
680 else if (r
!= idn_buffer_overflow
)
686 if (actions
& IDN_LOCALCONV
) {
687 r
= idn_converter_convfromucs4(local_converter
, buffer
, to
,
690 r
= idn_ucs4_ucs4toutf8(buffer
, to
, tolen
);
694 if (r
== idn_success
) {
695 TRACE(("idn_res_decodename(): success (to=\"%s\")\n",
696 idn__debug_xstring(to
, 50)));
698 TRACE(("idn_res_decodename(): %s\n", idn_result_tostring(r
)));
702 if (local_converter
!= NULL
)
703 idn_converter_destroy(local_converter
);
704 if (idn_converter
!= NULL
)
705 idn_converter_destroy(idn_converter
);
707 labellist_destroy(labels
);
712 idn_res_decodename2(idn_resconf_t ctx
, idn_action_t actions
, const char *from
,
713 char *to
, size_t tolen
, const char *auxencoding
) {
717 #else /* WITHOUT_ICONV */
719 idn_converter_t aux_converter
= NULL
;
720 unsigned long *buffer_ucs4
= NULL
;
721 char *buffer_utf8
= NULL
;
722 size_t buffer_length
;
724 assert(ctx
!= NULL
&& from
!= NULL
&& to
!= NULL
);
726 TRACE(("idn_res_decodename2(actions=%s, from=\"%s\", tolen=%d, "
727 "auxencoding=\"%s\")\n",
728 idn__res_actionstostring(actions
),
729 idn__debug_xstring(from
, 50), (int)tolen
,
730 (auxencoding
!= NULL
) ? auxencoding
: "<null>"));
733 idn_res_initialize();
734 if (!enabled
|| actions
== 0) {
735 r
= copy_verbatim(from
, to
, tolen
);
737 } else if (tolen
<= 0) {
738 r
= idn_buffer_overflow
;
742 if (auxencoding
== NULL
||
743 strcmp(auxencoding
, IDN_UTF8_ENCODING_NAME
) == 0 ||
744 strcmp(auxencoding
, "UTF-8") == 0) {
745 return idn_res_decodename(ctx
, actions
, from
, to
, tolen
);
749 * Convert `from' to UCS4.
751 r
= idn_resconf_setauxidnconvertername(ctx
, auxencoding
,
752 IDN_CONVERTER_DELAYEDOPEN
);
753 if (r
!= idn_success
) {
757 aux_converter
= idn_resconf_getauxidnconverter(ctx
);
758 if (aux_converter
== NULL
) {
763 buffer_length
= tolen
* 2;
767 new_buffer
= realloc(buffer_ucs4
,
768 sizeof(*buffer_ucs4
) * buffer_length
);
769 if (new_buffer
== NULL
) {
773 buffer_ucs4
= (unsigned long *)new_buffer
;
775 r
= idn_converter_convtoucs4(aux_converter
, from
,
778 if (r
== idn_success
)
780 else if (r
!= idn_buffer_overflow
)
786 if (*buffer_ucs4
== '\0') {
788 r
= idn_buffer_overflow
;
797 * Convert `buffer_ucs4' to UTF-8.
799 buffer_length
= tolen
* 2;
803 new_buffer
= realloc(buffer_utf8
,
804 sizeof(*buffer_utf8
) * buffer_length
);
805 if (new_buffer
== NULL
) {
809 buffer_utf8
= (char *)new_buffer
;
810 r
= idn_ucs4_ucs4toutf8(buffer_ucs4
, buffer_utf8
,
813 if (r
== idn_success
)
815 else if (r
!= idn_buffer_overflow
)
821 if (*buffer_utf8
== '\0') {
823 r
= idn_buffer_overflow
;
831 r
= idn_res_decodename(ctx
, actions
, buffer_utf8
, to
, tolen
);
834 if (r
== idn_success
) {
835 TRACE(("idn_res_decodename2(): success (to=\"%s\")\n",
836 idn__debug_xstring(to
, 50)));
838 TRACE(("idn_res_decodename2(): %s\n", idn_result_tostring(r
)));
842 if (aux_converter
!= NULL
)
843 idn_converter_destroy(aux_converter
);
847 #endif /* WITHOUT_ICONV */
851 copy_verbatim(const char *from
, char *to
, size_t tolen
) {
852 size_t fromlen
= strlen(from
);
854 if (fromlen
+ 1 > tolen
)
855 return (idn_buffer_overflow
);
856 (void)memcpy(to
, from
, fromlen
+ 1);
857 return (idn_success
);
861 labellist_create(const unsigned long *name
, labellist_t
*labelp
) {
862 size_t length
, malloc_length
;
863 labellist_t head_label
= NULL
;
864 labellist_t tail_label
= NULL
;
865 labellist_t new_label
= NULL
;
866 const unsigned long *endp
= NULL
;
869 while (*name
!= '\0') {
870 for (endp
= name
; *endp
!= '.' && *endp
!= '\0'; endp
++)
871 ; /* nothing to be done */
872 length
= (endp
- name
) + 1;
873 malloc_length
= length
+ 15; /* add 15 for margin */
875 new_label
= (labellist_t
)
876 malloc(sizeof(struct labellist
));
877 if (new_label
== NULL
) {
881 if (head_label
== NULL
)
882 head_label
= new_label
;
884 new_label
->name
= NULL
;
885 new_label
->undo_name
= NULL
;
886 new_label
->name_length
= malloc_length
;
887 new_label
->next
= NULL
;
888 new_label
->previous
= NULL
;
889 new_label
->dot_followed
= (*endp
== '.');
891 new_label
->name
= (unsigned long *)
892 malloc(sizeof(long) * malloc_length
);
893 if (new_label
->name
== NULL
) {
897 memcpy(new_label
->name
, name
, sizeof(long) * length
);
898 *(new_label
->name
+ length
- 1) = '\0';
900 new_label
->undo_name
= (unsigned long *)
901 malloc(sizeof(long) * malloc_length
);
902 if (new_label
->undo_name
== NULL
) {
906 memcpy(new_label
->undo_name
, name
, sizeof(long) * length
);
907 *(new_label
->undo_name
+ length
- 1) = '\0';
909 if (tail_label
!= NULL
) {
910 tail_label
->next
= new_label
;
911 new_label
->previous
= tail_label
;
913 tail_label
= new_label
;
921 *labelp
= head_label
;
925 if (r
!= idn_success
) {
926 if (new_label
!= NULL
) {
927 free(new_label
->name
);
928 free(new_label
->undo_name
);
931 if (head_label
!= NULL
)
932 labellist_destroy(head_label
);
939 labellist_destroy(labellist_t label
) {
940 labellist_t l
, l_next
;
942 for (l
= label
; l
!= NULL
; l
= l_next
) {
951 labellist_setname(labellist_t label
, const unsigned long *name
) {
952 unsigned long *new_name
;
953 size_t length
, new_length
;
955 length
= idn_ucs4_strlen(name
) + 1;
956 new_length
= length
+ 15; /* add 15 for margin */
958 if (label
->name_length
< new_length
) {
959 new_name
= (unsigned long *)
960 realloc(label
->name
, sizeof(long) * new_length
);
961 if (new_name
== NULL
)
962 return (idn_nomemory
);
963 label
->name
= new_name
;
964 label
->name_length
= new_length
;
966 memcpy(label
->name
, name
, sizeof(long) * length
);
968 return (idn_success
);
971 static const unsigned long *
972 labellist_getname(labellist_t label
) {
973 return (label
->name
);
976 static const unsigned long *
977 labellist_gettldname(labellist_t label
) {
980 if (label
->previous
== NULL
&& label
->next
== NULL
&&
981 !label
->dot_followed
)
982 return (idn_mapselector_getnotld());
984 for (l
= label
; l
->next
!= NULL
; l
= l
->next
)
985 ; /* nothing to be done */
991 labellist_getnamelist(labellist_t label
, unsigned long *name
,
992 size_t name_length
) {
993 static const unsigned long dot_string
[] = {0x002e, 0x0000}; /* "." */
997 for (l
= label
, length
= 0; l
!= NULL
; l
= l
->next
)
998 length
+= idn_ucs4_strlen(l
->name
) + 1; /* name + `.' */
999 length
++; /* for NUL */
1001 if (name_length
< length
)
1002 return (idn_buffer_overflow
);
1005 for (l
= label
; l
!= NULL
; l
= l
->next
) {
1006 idn_ucs4_strcat(name
, l
->name
);
1007 name
+= idn_ucs4_strlen(name
);
1008 if (l
->dot_followed
)
1009 idn_ucs4_strcat(name
, dot_string
);
1011 return (idn_success
);
1015 labellist_undo(labellist_t label
) {
1018 length
= idn_ucs4_strlen(label
->undo_name
) + 1;
1019 memcpy(label
->name
, label
->undo_name
, sizeof(long) * length
);
1023 labellist_tail(labellist_t label
) {
1028 for (l
= label
; l
->next
!= NULL
; l
= l
->next
)
1029 ; /* nothing to be done */
1034 labellist_previous(labellist_t label
) {
1035 return (label
->previous
);
1038 #ifndef WITHOUT_ICONV
1041 label_localdecodecheck(idn_resconf_t ctx
, labellist_t label
) {
1042 idn_converter_t local_converter
= NULL
;
1043 const unsigned long *from
;
1048 from
= labellist_getname(label
);
1049 to_length
= idn_ucs4_strlen(from
) + 1 + 15; /* 15 for margin */
1050 TRACE(("res ucs4tolocal_check(label=\"%s\")\n",
1051 idn__debug_ucs4xstring(from
, 50)));
1053 local_converter
= idn_resconf_getlocalconverter(ctx
);
1054 if (local_converter
== NULL
) {
1062 new_buffer
= (char *)realloc(to
, to_length
);
1063 if (new_buffer
== NULL
) {
1068 r
= idn_converter_convfromucs4(local_converter
, from
, to
,
1070 if (r
== idn_success
)
1072 else if (r
== idn_nomapping
) {
1073 r
= label_idnencode_ace(ctx
, label
);
1074 if (r
!= idn_success
)
1077 } else if (r
!= idn_buffer_overflow
) {
1085 TRACE(("res ucs4tolocal_check(): %s\n", idn_result_tostring(r
)));
1086 if (local_converter
!= NULL
)
1087 idn_converter_destroy(local_converter
);
1092 #endif /* !WITHOUT_ICONV */
1095 label_idndecode(idn_resconf_t ctx
, labellist_t label
) {
1096 idn_converter_t idn_converter
= NULL
;
1097 const unsigned long *from
;
1098 char *ascii_from
= NULL
;
1099 unsigned long *to
= NULL
;
1100 size_t from_length
, to_length
;
1103 from
= labellist_getname(label
);
1104 from_length
= idn_ucs4_strlen(from
) + 1;
1105 TRACE(("res idntoucs4(label=\"%s\")\n",
1106 idn__debug_ucs4xstring(from
, 50)));
1108 idn_converter
= idn_resconf_getidnconverter(ctx
);
1109 if (idn_converter
== NULL
) {
1117 new_buffer
= (char *) realloc(ascii_from
, from_length
);
1118 if (new_buffer
== NULL
) {
1122 ascii_from
= new_buffer
;
1123 r
= idn_ucs4_ucs4toutf8(from
, ascii_from
, from_length
);
1124 if (r
== idn_success
)
1126 else if (r
!= idn_buffer_overflow
)
1132 to_length
= from_length
;
1135 unsigned long *new_buffer
;
1137 new_buffer
= (unsigned long *)
1138 realloc(to
, sizeof(long) * to_length
);
1139 if (new_buffer
== NULL
) {
1144 r
= idn_converter_convtoucs4(idn_converter
, ascii_from
, to
,
1146 if (r
== idn_success
)
1148 else if (r
!= idn_buffer_overflow
)
1153 r
= labellist_setname(label
, to
);
1155 if (r
== idn_success
) {
1156 TRACE(("res idntoucs4(): success (label=\"%s\")\n",
1157 idn__debug_ucs4xstring(labellist_getname(label
),
1160 TRACE(("res idntoucs4(): %s\n", idn_result_tostring(r
)));
1162 if (idn_converter
!= NULL
)
1163 idn_converter_destroy(idn_converter
);
1170 label_idnencode_ace(idn_resconf_t ctx
, labellist_t label
) {
1171 idn_converter_t idn_converter
= NULL
;
1172 const unsigned long *from
;
1173 char *ascii_to
= NULL
;
1174 unsigned long *to
= NULL
;
1178 from
= labellist_getname(label
);
1179 TRACE(("res ucs4toidn(label=\"%s\")\n",
1180 idn__debug_ucs4xstring(from
, 50)));
1182 idn_converter
= idn_resconf_getidnconverter(ctx
);
1183 if (idn_converter
== NULL
) {
1189 to_length
= idn_ucs4_strlen(from
) * 4 + 16; /* add mergin */
1194 new_buffer
= (char *) realloc(ascii_to
, to_length
);
1195 if (new_buffer
== NULL
) {
1199 ascii_to
= new_buffer
;
1200 r
= idn_converter_convfromucs4(idn_converter
, from
, ascii_to
,
1202 if (r
== idn_success
)
1204 else if (r
!= idn_buffer_overflow
)
1210 unsigned long *new_buffer
;
1212 new_buffer
= (unsigned long *)
1213 realloc(to
, sizeof(long) * to_length
);
1214 if (new_buffer
== NULL
) {
1219 r
= idn_ucs4_utf8toucs4(ascii_to
, to
, to_length
);
1220 if (r
== idn_success
)
1222 else if (r
!= idn_buffer_overflow
)
1227 if (r
!= idn_success
)
1230 r
= labellist_setname(label
, to
);
1232 if (r
== idn_success
) {
1233 TRACE(("res ucs4toidn(): success (label=\"%s\")\n",
1234 idn__debug_ucs4xstring(labellist_getname(label
),
1237 TRACE(("res ucs4toidn(): %s\n", idn_result_tostring(r
)));
1239 if (idn_converter
!= NULL
)
1240 idn_converter_destroy(idn_converter
);
1247 label_localmap(idn_resconf_t ctx
, labellist_t label
) {
1248 const unsigned long *from
;
1249 const unsigned long *tld
;
1250 unsigned long *to
= NULL
;
1252 idn_mapselector_t local_mapper
;
1255 from
= labellist_getname(label
);
1256 tld
= labellist_gettldname(label
);
1257 TRACE(("res localmap(label=\"%s\", tld=\"%s\")\n",
1258 idn__debug_ucs4xstring(from
, 50),
1259 idn__debug_ucs4xstring(tld
, 50)));
1261 local_mapper
= idn_resconf_getlocalmapselector(ctx
);
1262 if (local_mapper
== NULL
) {
1268 tld
= idn_mapselector_getdefaulttld();
1269 to_length
= idn_ucs4_strlen(from
) + 1 + 15; /* 15 for margin */
1272 unsigned long *new_buffer
;
1274 new_buffer
= (unsigned long *)
1275 realloc(to
, sizeof(long) * to_length
);
1276 if (new_buffer
== NULL
) {
1281 r
= idn_mapselector_map2(local_mapper
, from
, tld
, to
,
1283 if (r
== idn_success
)
1285 else if (r
!= idn_buffer_overflow
)
1290 r
= labellist_setname(label
, to
);
1292 if (r
== idn_success
) {
1293 TRACE(("res localmap(): success (label=\"%s\")\n",
1294 idn__debug_ucs4xstring(labellist_getname(label
),
1297 TRACE(("res localmap(): %s\n", idn_result_tostring(r
)));
1299 if (local_mapper
!= NULL
)
1300 idn_mapselector_destroy(local_mapper
);
1306 label_map(idn_resconf_t ctx
, labellist_t label
) {
1307 const unsigned long *from
;
1308 unsigned long *to
= NULL
;
1310 idn_mapper_t mapper
;
1313 from
= labellist_getname(label
);
1314 TRACE(("res map(label=\"%s\")\n", idn__debug_ucs4xstring(from
, 50)));
1316 mapper
= idn_resconf_getmapper(ctx
);
1317 if (mapper
== NULL
) {
1321 to_length
= idn_ucs4_strlen(from
) + 1 + 15; /* 15 for margin */
1324 unsigned long *new_buffer
;
1326 new_buffer
= (unsigned long *)
1327 realloc(to
, sizeof(long) * to_length
);
1328 if (new_buffer
== NULL
) {
1333 r
= idn_mapper_map(mapper
, from
, to
, to_length
);
1334 if (r
== idn_success
)
1336 else if (r
!= idn_buffer_overflow
)
1341 r
= labellist_setname(label
, to
);
1343 if (r
== idn_success
) {
1344 TRACE(("res map(): success (label=\"%s\")\n",
1345 idn__debug_ucs4xstring(labellist_getname(label
),
1348 TRACE(("res map(): %s\n", idn_result_tostring(r
)));
1351 idn_mapper_destroy(mapper
);
1357 label_normalize(idn_resconf_t ctx
, labellist_t label
) {
1358 const unsigned long *from
;
1359 unsigned long *to
= NULL
;
1361 idn_normalizer_t normalizer
;
1364 from
= labellist_getname(label
);
1365 TRACE(("res normalzie(label=\"%s\")\n",
1366 idn__debug_ucs4xstring(from
, 50)));
1368 normalizer
= idn_resconf_getnormalizer(ctx
);
1369 if (normalizer
== NULL
) {
1373 to_length
= idn_ucs4_strlen(from
) + 1 + 15; /* 15 for margin */
1376 unsigned long *new_buffer
;
1378 new_buffer
= (unsigned long *)
1379 realloc(to
, sizeof(long) * to_length
);
1380 if (new_buffer
== NULL
) {
1385 r
= idn_normalizer_normalize(normalizer
, from
, to
, to_length
);
1386 if (r
== idn_success
)
1388 else if (r
!= idn_buffer_overflow
)
1393 r
= labellist_setname(label
, to
);
1395 if (r
== idn_success
) {
1396 TRACE(("res normalize(): success (label=\"%s\")\n",
1397 idn__debug_ucs4xstring(labellist_getname(label
),
1400 TRACE(("res normalize(): %s\n", idn_result_tostring(r
)));
1402 if (normalizer
!= NULL
)
1403 idn_normalizer_destroy(normalizer
);
1409 label_prohcheck(idn_resconf_t ctx
, labellist_t label
) {
1410 const unsigned long *name
, *found
;
1411 idn_checker_t prohibit_checker
;
1414 name
= labellist_getname(label
);
1415 TRACE(("res prohcheck(label=\"%s\")\n",
1416 idn__debug_ucs4xstring(name
, 50)));
1418 prohibit_checker
= idn_resconf_getprohibitchecker(ctx
);
1419 if (prohibit_checker
== NULL
) {
1424 r
= idn_checker_lookup(prohibit_checker
, name
, &found
);
1425 idn_checker_destroy(prohibit_checker
);
1426 if (r
== idn_success
&& found
!= NULL
)
1430 TRACE(("res prohcheck(): %s\n", idn_result_tostring(r
)));
1435 label_unascheck(idn_resconf_t ctx
, labellist_t label
) {
1436 const unsigned long *name
, *found
;
1437 idn_checker_t unassigned_checker
;
1440 name
= labellist_getname(label
);
1441 TRACE(("res unascheck(label=\"%s\")\n",
1442 idn__debug_ucs4xstring(name
, 50)));
1444 unassigned_checker
= idn_resconf_getunassignedchecker(ctx
);
1445 if (unassigned_checker
== NULL
) {
1450 r
= idn_checker_lookup(unassigned_checker
, name
, &found
);
1451 idn_checker_destroy(unassigned_checker
);
1452 if (r
== idn_success
&& found
!= NULL
)
1456 TRACE(("res unascheck(): %s\n", idn_result_tostring(r
)));
1461 label_bidicheck(idn_resconf_t ctx
, labellist_t label
) {
1462 const unsigned long *name
, *found
;
1463 idn_checker_t bidi_checker
;
1466 name
= labellist_getname(label
);
1467 TRACE(("res bidicheck(label=\"%s\")\n",
1468 idn__debug_ucs4xstring(name
, 50)));
1470 bidi_checker
= idn_resconf_getbidichecker(ctx
);
1471 if (bidi_checker
== NULL
) {
1476 r
= idn_checker_lookup(bidi_checker
, name
, &found
);
1477 idn_checker_destroy(bidi_checker
);
1478 if (r
== idn_success
&& found
!= NULL
)
1482 TRACE(("res bidicheck(): %s\n", idn_result_tostring(r
)));
1487 label_asccheck(idn_resconf_t ctx
, labellist_t label
) {
1488 const unsigned long *name
, *n
;
1491 name
= labellist_getname(label
);
1492 TRACE(("res asccheck(label=\"%s\")\n",
1493 idn__debug_ucs4xstring(name
, 50)));
1500 for (n
= name
; *n
!= '\0'; n
++) {
1502 if ((*n
< '0' || *n
> '9') &&
1503 (*n
< 'A' || *n
> 'Z') &&
1504 (*n
< 'a' || *n
> 'z') &&
1512 if (n
> name
&& *(n
- 1) == '-') {
1519 TRACE(("res asccheck(): %s\n", idn_result_tostring(r
)));
1524 label_lencheck_ace(idn_resconf_t ctx
, labellist_t label
) {
1525 const unsigned long *name
;
1529 name
= labellist_getname(label
);
1530 name_length
= idn_ucs4_strlen(name
);
1531 TRACE(("res lencheck(label=\"%s\")\n",
1532 idn__debug_ucs4xstring(name
, 50)));
1534 if (name_length
== 0 || name_length
> MAX_LABEL_LENGTH
) {
1535 r
= idn_invalid_length
;
1541 TRACE(("res lencheck(): %s\n", idn_result_tostring(r
)));
1546 label_lencheck_nonace(idn_resconf_t ctx
, labellist_t label
) {
1547 idn_converter_t idn_converter
;
1548 const unsigned long *from
;
1551 char *buffer
= NULL
;
1552 size_t buffer_length
;
1554 from
= labellist_getname(label
);
1555 TRACE(("res lencheck(label=\"%s\")\n",
1556 idn__debug_ucs4xstring(from
, 50)));
1558 buffer_length
= idn_ucs4_strlen(from
) * 4 + 16; /* 16 for margin */
1559 idn_converter
= idn_resconf_getidnconverter(ctx
);
1564 new_buffer
= realloc(buffer
, sizeof(*buffer
) * buffer_length
);
1565 if (new_buffer
== NULL
) {
1569 buffer
= (char *)new_buffer
;
1571 if (idn_converter
!= NULL
) {
1572 r
= idn_converter_convfromucs4(idn_converter
, from
,
1573 buffer
, buffer_length
);
1575 r
= idn_ucs4_ucs4toutf8(from
, buffer
, buffer_length
);
1577 if (r
== idn_success
)
1579 else if (r
!= idn_buffer_overflow
)
1585 to_length
= strlen(buffer
);
1586 if (to_length
== 0 || to_length
> MAX_LABEL_LENGTH
) {
1587 r
= idn_invalid_length
;
1593 TRACE(("res lencheck(): %s\n", idn_result_tostring(r
)));
1594 if (idn_converter
!= NULL
)
1595 idn_converter_destroy(idn_converter
);
1601 label_rtcheck(idn_resconf_t ctx
, idn_action_t actions
, labellist_t label
,
1602 const unsigned long *original_name
) {
1603 labellist_t rt_label
= NULL
;
1604 const unsigned long *rt_name
;
1605 const unsigned long *cur_name
;
1608 cur_name
= labellist_getname(label
);
1609 TRACE(("res rtcheck(label=\"%s\", org_label=\"%s\")\n",
1610 idn__debug_ucs4xstring(cur_name
, 50),
1611 idn__debug_ucs4xstring(original_name
, 50)));
1613 r
= labellist_create(cur_name
, &rt_label
);
1614 if (r
!= idn_success
)
1616 if (rt_label
== NULL
) {
1617 if (*original_name
== '\0')
1620 r
= idn_invalid_encoding
;
1624 if (!idn__util_ucs4isasciirange(labellist_getname(rt_label
))) {
1625 r
= label_map(ctx
, rt_label
);
1626 if (r
!= idn_success
)
1628 r
= label_normalize(ctx
, rt_label
);
1629 if (r
!= idn_success
)
1631 r
= label_prohcheck(ctx
, rt_label
);
1632 if (r
!= idn_success
)
1634 if (actions
& IDN_UNASCHECK
) {
1635 r
= label_unascheck(ctx
, rt_label
);
1636 if (r
!= idn_success
)
1639 r
= label_bidicheck(ctx
, rt_label
);
1640 if (r
!= idn_success
)
1644 if (actions
& IDN_ASCCHECK
) {
1645 r
= label_asccheck(ctx
, rt_label
);
1646 if (r
!= idn_success
)
1649 if (!idn__util_ucs4isasciirange(labellist_getname(rt_label
))) {
1650 r
= label_idnencode_ace(ctx
, rt_label
);
1651 if (r
!= idn_success
)
1654 r
= label_lencheck_ace(ctx
, rt_label
);
1655 if (r
!= idn_success
)
1657 rt_name
= labellist_getname(rt_label
);
1659 if (idn_ucs4_strcasecmp(rt_name
, original_name
) != 0) {
1660 TRACE(("res rtcheck(): round trip failed, org =\"%s\", rt=\"%s\"\n",
1661 idn__debug_ucs4xstring(original_name
, 50),
1662 idn__debug_ucs4xstring(rt_name
, 50)));
1663 r
= idn_invalid_encoding
;
1669 if (r
!= idn_nomemory
&& r
!= idn_success
)
1670 r
= idn_invalid_encoding
;
1671 TRACE(("res rtcheck(): %s\n", idn_result_tostring(r
)));
1672 if (rt_label
!= NULL
)
1673 labellist_destroy(rt_label
);
1678 idn__res_actionstostring(idn_action_t actions
) {
1679 static char buf
[100];
1683 if (actions
== IDN_ENCODE_QUERY
)
1684 strcpy(buf
, "encode-query");
1685 else if (actions
== IDN_DECODE_QUERY
)
1686 strcpy(buf
, "decode-query");
1687 else if (actions
== IDN_ENCODE_APP
)
1688 strcpy(buf
, "encode-app");
1689 else if (actions
== IDN_DECODE_APP
)
1690 strcpy(buf
, "decode-app");
1691 else if (actions
== IDN_ENCODE_STORED
)
1692 strcpy(buf
, "encode-stored");
1693 else if (actions
== IDN_DECODE_STORED
)
1694 strcpy(buf
, "decode-stored");
1696 if (actions
& IDN_LOCALCONV
)
1697 strcat(buf
, "|localconv");
1698 if (actions
& IDN_DELIMMAP
)
1699 strcat(buf
, "|delimmap");
1700 if (actions
& IDN_LOCALMAP
)
1701 strcat(buf
, "|localmap");
1703 if (actions
& IDN_MAP
)
1704 strcat(buf
, "|map");
1705 if (actions
& IDN_NORMALIZE
)
1706 strcat(buf
, "|normalize");
1707 if (actions
& IDN_PROHCHECK
)
1708 strcat(buf
, "|prohcheck");
1709 if (actions
& IDN_UNASCHECK
)
1710 strcat(buf
, "|unascheck");
1711 if (actions
& IDN_BIDICHECK
)
1712 strcat(buf
, "|bidicheck");
1714 if (actions
& IDN_IDNCONV
)
1715 strcat(buf
, "|idnconv");
1716 if (actions
& IDN_ASCCHECK
)
1717 strcat(buf
, "|asccheck");
1718 if (actions
& IDN_LENCHECK
)
1719 strcat(buf
, "|lencheck");
1720 if (actions
& IDN_RTCHECK
)
1721 strcat(buf
, "|rtcheck");