etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / contrib / idn / idnkit-1.0-src / lib / res.c
blob490550ec8b50f0d1c471d65c1342f62a1a363239
1 /* $NetBSD: res.c,v 1.4 2014/12/10 04:37:55 christos Exp $ */
3 #ifndef lint
4 static char *rcsid = "Id: res.c,v 1.1 2003/06/04 00:26:10 marka Exp ";
5 #endif
7 /*
8 * Copyright (c) 2000,2002 Japan Network Information Center.
9 * All rights reserved.
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
35 * JPNIC.
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.
50 #include <config.h>
52 #include <stddef.h>
53 #include <stdlib.h>
54 #include <string.h>
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>
66 #include <idn/res.h>
67 #include <idn/util.h>
68 #include <idn/debug.h>
69 #include <idn/ucs4.h>
71 #ifndef IDN_UTF8_ENCODING_NAME
72 #define IDN_UTF8_ENCODING_NAME "UTF-8" /* by IANA */
73 #endif
75 #ifndef WITHOUT_ICONV
76 #define ENCODE_MASK \
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 | \
80 IDN_UNDOIFERR)
81 #define DECODE_MASK \
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)
85 #else
86 #define ENCODE_MASK \
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)
90 #define DECODE_MASK \
91 (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
92 IDN_UNASCHECK | IDN_BIDICHECK | IDN_IDNCONV | IDN_ASCCHECK | \
93 IDN_RTCHECK | IDN_DECODE_QUERY)
94 #endif
96 #define MAX_LABEL_LENGTH 63
99 * label to convert.
101 typedef struct labellist * labellist_t;
102 struct labellist {
103 unsigned long *name;
104 size_t name_length;
105 unsigned long *undo_name;
106 labellist_t next;
107 labellist_t previous;
108 int dot_followed;
111 typedef idn_result_t (*res_insnproc_t)(idn_resconf_t ctx,
112 labellist_t label);
114 static void idn_res_initialize(void);
115 static idn_result_t copy_verbatim(const char *from, char *to,
116 size_t tolen);
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,
127 unsigned long *name,
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,
135 labellist_t label);
136 #endif
137 static idn_result_t label_idnencode_ace(idn_resconf_t ctx,
138 labellist_t label);
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,
148 labellist_t label);
149 static idn_result_t label_lencheck_nonace(idn_resconf_t ctx,
150 labellist_t label);
151 static idn_result_t label_rtcheck(idn_resconf_t ctx, idn_action_t actions,
152 labellist_t label,
153 const unsigned long *original_name);
155 static int initialized;
156 static int enabled;
158 void
159 idn_res_enable(int on_off) {
160 if (!initialized) {
161 idn_res_initialize();
164 if (on_off == 0) {
165 enabled = 0;
166 } else {
167 enabled = 1;
171 static void
172 idn_res_initialize(void) {
173 if (!initialized) {
174 char *value = getenv("IDN_DISABLE");
176 if (value == NULL) {
177 enabled = 1;
178 } else {
179 enabled = 0;
181 initialized = 1;
185 idn_result_t
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;
191 idn_result_t r;
192 labellist_t labels = NULL, l;
193 unsigned long *buffer = NULL;
194 size_t buffer_length;
195 int from_is_root;
196 int idn_is_ace;
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",
206 actions));
207 r = idn_invalid_action;
208 goto ret;
211 if (!initialized)
212 idn_res_initialize();
213 if (!enabled || actions == 0) {
214 r = copy_verbatim(from, to, tolen);
215 goto ret;
216 } else if (tolen <= 0) {
217 r = idn_buffer_overflow;
218 goto ret;
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);
226 #else
227 actions |= (IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | \
228 IDN_NORMALIZE | IDN_PROHCHECK | IDN_BIDICHECK | \
229 IDN_IDNCONV | IDN_LENCHECK);
230 #endif
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;
240 goto ret;
242 #endif
244 idn_converter = idn_resconf_getidnconverter(ctx);
245 if (idn_converter != NULL &&
246 idn_converter_isasciicompatible(idn_converter))
247 idn_is_ace = 1;
248 else
249 idn_is_ace = 0;
251 buffer_length = tolen * 2;
253 for (;;) {
254 void *new_buffer;
256 new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
257 if (new_buffer == NULL) {
258 r = idn_nomemory;
259 goto ret;
261 buffer = (unsigned long *)new_buffer;
263 if (actions & IDN_LOCALCONV) {
264 r = idn_converter_convtoucs4(local_converter, from,
265 buffer, buffer_length);
266 } else {
267 r = idn_ucs4_utf8toucs4(from, buffer, buffer_length);
269 if (r == idn_success)
270 break;
271 else if (r != idn_buffer_overflow)
272 goto ret;
274 buffer_length *= 2;
277 if (*buffer == '\0') {
278 if (tolen <= 0) {
279 r = idn_buffer_overflow;
280 goto ret;
282 *to = '\0';
283 r = idn_success;
284 goto ret;
288 * Delimiter map.
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)
300 goto ret;
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)
313 goto ret;
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)
325 goto ret;
329 if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
330 if (actions & IDN_MAP) {
331 r = label_map(ctx, l);
332 if (r != idn_success)
333 goto ret;
335 if (actions & IDN_NORMALIZE) {
336 r = label_normalize(ctx, l);
337 if (r != idn_success)
338 goto ret;
340 if (actions & IDN_PROHCHECK) {
341 r = label_prohcheck(ctx, l);
342 if (r == idn_prohibited &&
343 (actions & IDN_UNDOIFERR)) {
344 labellist_undo(l);
345 continue;
346 } else if (r != idn_success) {
347 goto ret;
350 if (actions & IDN_UNASCHECK) {
351 r = label_unascheck(ctx, l);
352 if (r == idn_prohibited &&
353 (actions & IDN_UNDOIFERR)) {
354 labellist_undo(l);
355 continue;
356 } else if (r != idn_success) {
357 goto ret;
360 if (actions & IDN_BIDICHECK) {
361 r = label_bidicheck(ctx, l);
362 if (r == idn_prohibited &&
363 (actions & IDN_UNDOIFERR)) {
364 labellist_undo(l);
365 continue;
366 } else if (r != idn_success) {
367 goto ret;
372 if (actions & IDN_ASCCHECK) {
373 r = label_asccheck(ctx, l);
374 if (r == idn_prohibited && (actions & IDN_UNDOIFERR)) {
375 labellist_undo(l);
376 continue;
377 } else if (r != idn_success) {
378 goto ret;
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)
386 goto ret;
390 if (!from_is_root && (actions & IDN_LENCHECK)) {
391 if (idn_is_ace)
392 r = label_lencheck_ace(ctx, l);
393 else
394 r = label_lencheck_nonace(ctx, l);
395 if (r == idn_invalid_length &&
396 (actions & IDN_UNDOIFERR)) {
397 labellist_undo(l);
398 continue;
399 } else if (r != idn_success) {
400 goto ret;
406 * Concat a list of labels to a name.
408 for (;;) {
409 void *new_buffer;
411 new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
412 if (new_buffer == NULL) {
413 r = idn_nomemory;
414 goto ret;
416 buffer = (unsigned long *)new_buffer;
418 r = labellist_getnamelist(labels, buffer, buffer_length);
419 if (r == idn_success)
420 break;
421 else if (r != idn_buffer_overflow)
422 goto ret;
424 buffer_length *= 2;
427 if ((actions & IDN_IDNCONV) && idn_converter != NULL && !idn_is_ace) {
428 r = idn_converter_convfromucs4(idn_converter, buffer, to,
429 tolen);
430 } else {
431 r = idn_ucs4_ucs4toutf8(buffer, to, tolen);
434 ret:
435 if (r == idn_success) {
436 TRACE(("idn_res_encodename(): success (to=\"%s\")\n",
437 idn__debug_xstring(to, 50)));
438 } else {
439 TRACE(("idn_res_encodename(): %s\n", idn_result_tostring(r)));
441 free(buffer);
442 if (local_converter != NULL)
443 idn_converter_destroy(local_converter);
444 if (idn_converter != NULL)
445 idn_converter_destroy(idn_converter);
446 if (labels != NULL)
447 labellist_destroy(labels);
448 return (r);
451 idn_result_t
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;
457 idn_result_t r;
458 labellist_t labels = NULL, l;
459 unsigned long *buffer = NULL;
460 unsigned long *saved_name = NULL;
461 size_t buffer_length;
462 int idn_is_ace;
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",
472 actions));
473 r = idn_invalid_action;
474 goto ret;
477 if (!initialized)
478 idn_res_initialize();
479 if (!enabled || actions == 0) {
480 r = copy_verbatim(from, to, tolen);
481 goto ret;
482 } else if (tolen <= 0) {
483 r = idn_buffer_overflow;
484 goto ret;
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);
492 #else
493 actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \
494 IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \
495 IDN_RTCHECK);
496 #endif
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;
506 goto ret;
508 #endif
510 idn_converter = idn_resconf_getidnconverter(ctx);
511 if (idn_converter != NULL &&
512 idn_converter_isasciicompatible(idn_converter))
513 idn_is_ace = 1;
514 else
515 idn_is_ace = 0;
517 buffer_length = tolen * 2;
519 TRACE(("res idndecode(name=\"%s\")\n", idn__debug_xstring(from, 50)));
521 for (;;) {
522 void *new_buffer;
524 new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
525 if (new_buffer == NULL) {
526 r = idn_nomemory;
527 goto ret;
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);
535 } else {
536 r = idn_ucs4_utf8toucs4(from, buffer, buffer_length);
538 if (r == idn_success)
539 break;
540 else if (r != idn_buffer_overflow)
541 goto ret;
543 buffer_length *= 2;
546 if (*buffer == '\0') {
547 if (tolen <= 0) {
548 r = idn_buffer_overflow;
549 goto ret;
551 *to = '\0';
552 r = idn_success;
553 goto ret;
557 * Delimiter map.
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)
569 goto ret;
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)
580 goto ret;
583 * Perform conversions and tests.
585 for (l = labellist_tail(labels); l != NULL;
586 l = labellist_previous(l)) {
588 free(saved_name);
589 saved_name = NULL;
591 if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
592 if (actions & IDN_MAP) {
593 r = label_map(ctx, l);
594 if (r != idn_success)
595 goto ret;
597 if (actions & IDN_NORMALIZE) {
598 r = label_normalize(ctx, l);
599 if (r != idn_success)
600 goto ret;
602 if (actions & IDN_PROHCHECK) {
603 r = label_prohcheck(ctx, l);
604 if (r == idn_prohibited) {
605 labellist_undo(l);
606 continue;
607 } else if (r != idn_success) {
608 goto ret;
611 if (actions & IDN_UNASCHECK) {
612 r = label_unascheck(ctx, l);
613 if (r == idn_prohibited) {
614 labellist_undo(l);
615 continue;
616 } else if (r != idn_success) {
617 goto ret;
620 if (actions & IDN_BIDICHECK) {
621 r = label_bidicheck(ctx, l);
622 if (r == idn_prohibited) {
623 labellist_undo(l);
624 continue;
625 } else if (r != idn_success) {
626 goto ret;
631 if ((actions & IDN_IDNCONV) && idn_is_ace) {
632 saved_name = idn_ucs4_strdup(labellist_getname(l));
633 if (saved_name == NULL) {
634 r = idn_nomemory;
635 goto ret;
637 r = label_idndecode(ctx, l);
638 if (r == idn_invalid_encoding) {
639 labellist_undo(l);
640 continue;
641 } else if (r != idn_success) {
642 goto ret;
645 if ((actions & IDN_RTCHECK) && saved_name != NULL) {
646 r = label_rtcheck(ctx, actions, l, saved_name);
647 if (r == idn_invalid_encoding) {
648 labellist_undo(l);
649 continue;
650 } else if (r != idn_success) {
651 goto ret;
655 #ifndef WITHOUT_ICONV
656 if (actions & IDN_LOCALCONV) {
657 r = label_localdecodecheck(ctx, l);
658 if (r != idn_success)
659 goto ret;
661 #endif
665 * Concat a list of labels to a name.
667 for (;;) {
668 void *new_buffer;
670 new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
671 if (new_buffer == NULL) {
672 r = idn_nomemory;
673 goto ret;
675 buffer = (unsigned long *)new_buffer;
677 r = labellist_getnamelist(labels, buffer, buffer_length);
678 if (r == idn_success)
679 break;
680 else if (r != idn_buffer_overflow)
681 goto ret;
683 buffer_length *= 2;
686 if (actions & IDN_LOCALCONV) {
687 r = idn_converter_convfromucs4(local_converter, buffer, to,
688 tolen);
689 } else {
690 r = idn_ucs4_ucs4toutf8(buffer, to, tolen);
693 ret:
694 if (r == idn_success) {
695 TRACE(("idn_res_decodename(): success (to=\"%s\")\n",
696 idn__debug_xstring(to, 50)));
697 } else {
698 TRACE(("idn_res_decodename(): %s\n", idn_result_tostring(r)));
700 free(saved_name);
701 free(buffer);
702 if (local_converter != NULL)
703 idn_converter_destroy(local_converter);
704 if (idn_converter != NULL)
705 idn_converter_destroy(idn_converter);
706 if (labels != NULL)
707 labellist_destroy(labels);
708 return (r);
711 idn_result_t
712 idn_res_decodename2(idn_resconf_t ctx, idn_action_t actions, const char *from,
713 char *to, size_t tolen, const char *auxencoding) {
714 #ifdef WITHOUT_ICONV
715 return idn_failure;
717 #else /* WITHOUT_ICONV */
718 idn_result_t r;
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>"));
732 if (!initialized)
733 idn_res_initialize();
734 if (!enabled || actions == 0) {
735 r = copy_verbatim(from, to, tolen);
736 goto ret;
737 } else if (tolen <= 0) {
738 r = idn_buffer_overflow;
739 goto ret;
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) {
754 goto ret;
757 aux_converter = idn_resconf_getauxidnconverter(ctx);
758 if (aux_converter == NULL) {
759 r = idn_failure;
760 goto ret;
763 buffer_length = tolen * 2;
764 for (;;) {
765 void *new_buffer;
767 new_buffer = realloc(buffer_ucs4,
768 sizeof(*buffer_ucs4) * buffer_length);
769 if (new_buffer == NULL) {
770 r = idn_nomemory;
771 goto ret;
773 buffer_ucs4 = (unsigned long *)new_buffer;
775 r = idn_converter_convtoucs4(aux_converter, from,
776 buffer_ucs4,
777 buffer_length);
778 if (r == idn_success)
779 break;
780 else if (r != idn_buffer_overflow)
781 goto ret;
783 buffer_length *= 2;
786 if (*buffer_ucs4 == '\0') {
787 if (tolen <= 0) {
788 r = idn_buffer_overflow;
789 goto ret;
791 *to = '\0';
792 r = idn_success;
793 goto ret;
797 * Convert `buffer_ucs4' to UTF-8.
799 buffer_length = tolen * 2;
800 for (;;) {
801 void *new_buffer;
803 new_buffer = realloc(buffer_utf8,
804 sizeof(*buffer_utf8) * buffer_length);
805 if (new_buffer == NULL) {
806 r = idn_nomemory;
807 goto ret;
809 buffer_utf8 = (char *)new_buffer;
810 r = idn_ucs4_ucs4toutf8(buffer_ucs4, buffer_utf8,
811 buffer_length);
813 if (r == idn_success)
814 break;
815 else if (r != idn_buffer_overflow)
816 goto ret;
818 buffer_length *= 2;
821 if (*buffer_utf8 == '\0') {
822 if (tolen <= 0) {
823 r = idn_buffer_overflow;
824 goto ret;
826 *to = '\0';
827 r = idn_success;
828 goto ret;
831 r = idn_res_decodename(ctx, actions, buffer_utf8, to, tolen);
833 ret:
834 if (r == idn_success) {
835 TRACE(("idn_res_decodename2(): success (to=\"%s\")\n",
836 idn__debug_xstring(to, 50)));
837 } else {
838 TRACE(("idn_res_decodename2(): %s\n", idn_result_tostring(r)));
840 free(buffer_ucs4);
841 free(buffer_utf8);
842 if (aux_converter != NULL)
843 idn_converter_destroy(aux_converter);
845 return (r);
847 #endif /* WITHOUT_ICONV */
850 static idn_result_t
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);
860 static idn_result_t
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;
867 idn_result_t r;
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) {
878 r = idn_nomemory;
879 goto ret;
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) {
894 r = idn_nomemory;
895 goto ret;
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) {
903 r = idn_nomemory;
904 goto ret;
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;
915 if (*endp == '.')
916 name = endp + 1;
917 else
918 name = endp;
921 *labelp = head_label;
922 r = idn_success;
924 ret:
925 if (r != idn_success) {
926 if (new_label != NULL) {
927 free(new_label->name);
928 free(new_label->undo_name);
929 free(new_label);
931 if (head_label != NULL)
932 labellist_destroy(head_label);
934 return (r);
938 static void
939 labellist_destroy(labellist_t label) {
940 labellist_t l, l_next;
942 for (l = label; l != NULL; l = l_next) {
943 l_next = l->next;
944 free(l->name);
945 free(l->undo_name);
946 free(l);
950 static idn_result_t
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) {
978 labellist_t l;
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 */
987 return (l->name);
990 static idn_result_t
991 labellist_getnamelist(labellist_t label, unsigned long *name,
992 size_t name_length) {
993 static const unsigned long dot_string[] = {0x002e, 0x0000}; /* "." */
994 size_t length;
995 labellist_t l;
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);
1004 *name = '\0';
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);
1014 static void
1015 labellist_undo(labellist_t label) {
1016 size_t length;
1018 length = idn_ucs4_strlen(label->undo_name) + 1;
1019 memcpy(label->name, label->undo_name, sizeof(long) * length);
1022 static labellist_t
1023 labellist_tail(labellist_t label) {
1024 labellist_t l;
1026 if (label == NULL)
1027 return (NULL);
1028 for (l = label; l->next != NULL; l = l->next)
1029 ; /* nothing to be done */
1030 return (l);
1033 static labellist_t
1034 labellist_previous(labellist_t label) {
1035 return (label->previous);
1038 #ifndef WITHOUT_ICONV
1040 static idn_result_t
1041 label_localdecodecheck(idn_resconf_t ctx, labellist_t label) {
1042 idn_converter_t local_converter = NULL;
1043 const unsigned long *from;
1044 char *to = NULL;
1045 size_t to_length;
1046 idn_result_t r;
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) {
1055 r = idn_success;
1056 goto ret;
1059 for (;;) {
1060 char *new_buffer;
1062 new_buffer = (char *)realloc(to, to_length);
1063 if (new_buffer == NULL) {
1064 r = idn_nomemory;
1065 goto ret;
1067 to = new_buffer;
1068 r = idn_converter_convfromucs4(local_converter, from, to,
1069 to_length);
1070 if (r == idn_success)
1071 break;
1072 else if (r == idn_nomapping) {
1073 r = label_idnencode_ace(ctx, label);
1074 if (r != idn_success)
1075 goto ret;
1076 break;
1077 } else if (r != idn_buffer_overflow) {
1078 goto ret;
1080 to_length *= 2;
1083 r = idn_success;
1084 ret:
1085 TRACE(("res ucs4tolocal_check(): %s\n", idn_result_tostring(r)));
1086 if (local_converter != NULL)
1087 idn_converter_destroy(local_converter);
1088 free(to);
1089 return (r);
1092 #endif /* !WITHOUT_ICONV */
1094 static idn_result_t
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;
1101 idn_result_t r;
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) {
1110 r = idn_success;
1111 goto ret;
1114 for (;;) {
1115 char *new_buffer;
1117 new_buffer = (char *) realloc(ascii_from, from_length);
1118 if (new_buffer == NULL) {
1119 r = idn_nomemory;
1120 goto ret;
1122 ascii_from = new_buffer;
1123 r = idn_ucs4_ucs4toutf8(from, ascii_from, from_length);
1124 if (r == idn_success)
1125 break;
1126 else if (r != idn_buffer_overflow)
1127 goto ret;
1128 from_length *= 2;
1131 to = NULL;
1132 to_length = from_length;
1134 for (;;) {
1135 unsigned long *new_buffer;
1137 new_buffer = (unsigned long *)
1138 realloc(to, sizeof(long) * to_length);
1139 if (new_buffer == NULL) {
1140 r = idn_nomemory;
1141 goto ret;
1143 to = new_buffer;
1144 r = idn_converter_convtoucs4(idn_converter, ascii_from, to,
1145 to_length);
1146 if (r == idn_success)
1147 break;
1148 else if (r != idn_buffer_overflow)
1149 goto ret;
1150 to_length *= 2;
1153 r = labellist_setname(label, to);
1154 ret:
1155 if (r == idn_success) {
1156 TRACE(("res idntoucs4(): success (label=\"%s\")\n",
1157 idn__debug_ucs4xstring(labellist_getname(label),
1158 50)));
1159 } else {
1160 TRACE(("res idntoucs4(): %s\n", idn_result_tostring(r)));
1162 if (idn_converter != NULL)
1163 idn_converter_destroy(idn_converter);
1164 free(to);
1165 free(ascii_from);
1166 return (r);
1169 static idn_result_t
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;
1175 size_t to_length;
1176 idn_result_t r;
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) {
1184 r = idn_success;
1185 goto ret;
1188 ascii_to = NULL;
1189 to_length = idn_ucs4_strlen(from) * 4 + 16; /* add mergin */
1191 for (;;) {
1192 char *new_buffer;
1194 new_buffer = (char *) realloc(ascii_to, to_length);
1195 if (new_buffer == NULL) {
1196 r = idn_nomemory;
1197 goto ret;
1199 ascii_to = new_buffer;
1200 r = idn_converter_convfromucs4(idn_converter, from, ascii_to,
1201 to_length);
1202 if (r == idn_success)
1203 break;
1204 else if (r != idn_buffer_overflow)
1205 goto ret;
1206 to_length *= 2;
1209 for (;;) {
1210 unsigned long *new_buffer;
1212 new_buffer = (unsigned long *)
1213 realloc(to, sizeof(long) * to_length);
1214 if (new_buffer == NULL) {
1215 r = idn_nomemory;
1216 goto ret;
1218 to = new_buffer;
1219 r = idn_ucs4_utf8toucs4(ascii_to, to, to_length);
1220 if (r == idn_success)
1221 break;
1222 else if (r != idn_buffer_overflow)
1223 goto ret;
1224 to_length *= 2;
1227 if (r != idn_success)
1228 goto ret;
1230 r = labellist_setname(label, to);
1231 ret:
1232 if (r == idn_success) {
1233 TRACE(("res ucs4toidn(): success (label=\"%s\")\n",
1234 idn__debug_ucs4xstring(labellist_getname(label),
1235 50)));
1236 } else {
1237 TRACE(("res ucs4toidn(): %s\n", idn_result_tostring(r)));
1239 if (idn_converter != NULL)
1240 idn_converter_destroy(idn_converter);
1241 free(to);
1242 free(ascii_to);
1243 return (r);
1246 static idn_result_t
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;
1251 size_t to_length;
1252 idn_mapselector_t local_mapper;
1253 idn_result_t r;
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) {
1263 r = idn_success;
1264 goto ret;
1267 if (tld == from)
1268 tld = idn_mapselector_getdefaulttld();
1269 to_length = idn_ucs4_strlen(from) + 1 + 15; /* 15 for margin */
1271 for (;;) {
1272 unsigned long *new_buffer;
1274 new_buffer = (unsigned long *)
1275 realloc(to, sizeof(long) * to_length);
1276 if (new_buffer == NULL) {
1277 r = idn_nomemory;
1278 goto ret;
1280 to = new_buffer;
1281 r = idn_mapselector_map2(local_mapper, from, tld, to,
1282 to_length);
1283 if (r == idn_success)
1284 break;
1285 else if (r != idn_buffer_overflow)
1286 goto ret;
1287 to_length *= 2;
1290 r = labellist_setname(label, to);
1291 ret:
1292 if (r == idn_success) {
1293 TRACE(("res localmap(): success (label=\"%s\")\n",
1294 idn__debug_ucs4xstring(labellist_getname(label),
1295 50)));
1296 } else {
1297 TRACE(("res localmap(): %s\n", idn_result_tostring(r)));
1299 if (local_mapper != NULL)
1300 idn_mapselector_destroy(local_mapper);
1301 free(to);
1302 return (r);
1305 static idn_result_t
1306 label_map(idn_resconf_t ctx, labellist_t label) {
1307 const unsigned long *from;
1308 unsigned long *to = NULL;
1309 size_t to_length;
1310 idn_mapper_t mapper;
1311 idn_result_t r;
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) {
1318 r = idn_success;
1319 goto ret;
1321 to_length = idn_ucs4_strlen(from) + 1 + 15; /* 15 for margin */
1323 for (;;) {
1324 unsigned long *new_buffer;
1326 new_buffer = (unsigned long *)
1327 realloc(to, sizeof(long) * to_length);
1328 if (new_buffer == NULL) {
1329 r = idn_nomemory;
1330 goto ret;
1332 to = new_buffer;
1333 r = idn_mapper_map(mapper, from, to, to_length);
1334 if (r == idn_success)
1335 break;
1336 else if (r != idn_buffer_overflow)
1337 goto ret;
1338 to_length *= 2;
1341 r = labellist_setname(label, to);
1342 ret:
1343 if (r == idn_success) {
1344 TRACE(("res map(): success (label=\"%s\")\n",
1345 idn__debug_ucs4xstring(labellist_getname(label),
1346 50)));
1347 } else {
1348 TRACE(("res map(): %s\n", idn_result_tostring(r)));
1350 if (mapper != NULL)
1351 idn_mapper_destroy(mapper);
1352 free(to);
1353 return (r);
1356 static idn_result_t
1357 label_normalize(idn_resconf_t ctx, labellist_t label) {
1358 const unsigned long *from;
1359 unsigned long *to = NULL;
1360 size_t to_length;
1361 idn_normalizer_t normalizer;
1362 idn_result_t r;
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) {
1370 r = idn_success;
1371 goto ret;
1373 to_length = idn_ucs4_strlen(from) + 1 + 15; /* 15 for margin */
1375 for (;;) {
1376 unsigned long *new_buffer;
1378 new_buffer = (unsigned long *)
1379 realloc(to, sizeof(long) * to_length);
1380 if (new_buffer == NULL) {
1381 r = idn_nomemory;
1382 goto ret;
1384 to = new_buffer;
1385 r = idn_normalizer_normalize(normalizer, from, to, to_length);
1386 if (r == idn_success)
1387 break;
1388 else if (r != idn_buffer_overflow)
1389 goto ret;
1390 to_length *= 2;
1393 r = labellist_setname(label, to);
1394 ret:
1395 if (r == idn_success) {
1396 TRACE(("res normalize(): success (label=\"%s\")\n",
1397 idn__debug_ucs4xstring(labellist_getname(label),
1398 50)));
1399 } else {
1400 TRACE(("res normalize(): %s\n", idn_result_tostring(r)));
1402 if (normalizer != NULL)
1403 idn_normalizer_destroy(normalizer);
1404 free(to);
1405 return (r);
1408 static idn_result_t
1409 label_prohcheck(idn_resconf_t ctx, labellist_t label) {
1410 const unsigned long *name, *found;
1411 idn_checker_t prohibit_checker;
1412 idn_result_t r;
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) {
1420 r = idn_success;
1421 goto ret;
1424 r = idn_checker_lookup(prohibit_checker, name, &found);
1425 idn_checker_destroy(prohibit_checker);
1426 if (r == idn_success && found != NULL)
1427 r = idn_prohibited;
1429 ret:
1430 TRACE(("res prohcheck(): %s\n", idn_result_tostring(r)));
1431 return (r);
1434 static idn_result_t
1435 label_unascheck(idn_resconf_t ctx, labellist_t label) {
1436 const unsigned long *name, *found;
1437 idn_checker_t unassigned_checker;
1438 idn_result_t r;
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) {
1446 r = idn_success;
1447 goto ret;
1450 r = idn_checker_lookup(unassigned_checker, name, &found);
1451 idn_checker_destroy(unassigned_checker);
1452 if (r == idn_success && found != NULL)
1453 r = idn_prohibited;
1455 ret:
1456 TRACE(("res unascheck(): %s\n", idn_result_tostring(r)));
1457 return (r);
1460 static idn_result_t
1461 label_bidicheck(idn_resconf_t ctx, labellist_t label) {
1462 const unsigned long *name, *found;
1463 idn_checker_t bidi_checker;
1464 idn_result_t r;
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) {
1472 r = idn_success;
1473 goto ret;
1476 r = idn_checker_lookup(bidi_checker, name, &found);
1477 idn_checker_destroy(bidi_checker);
1478 if (r == idn_success && found != NULL)
1479 r = idn_prohibited;
1481 ret:
1482 TRACE(("res bidicheck(): %s\n", idn_result_tostring(r)));
1483 return (r);
1486 static idn_result_t
1487 label_asccheck(idn_resconf_t ctx, labellist_t label) {
1488 const unsigned long *name, *n;
1489 idn_result_t r;
1491 name = labellist_getname(label);
1492 TRACE(("res asccheck(label=\"%s\")\n",
1493 idn__debug_ucs4xstring(name, 50)));
1495 if (*name == '-') {
1496 r = idn_prohibited;
1497 goto ret;
1500 for (n = name; *n != '\0'; n++) {
1501 if (*n <= '\177') {
1502 if ((*n < '0' || *n > '9') &&
1503 (*n < 'A' || *n > 'Z') &&
1504 (*n < 'a' || *n > 'z') &&
1505 *n != '-') {
1506 r = idn_prohibited;
1507 goto ret;
1512 if (n > name && *(n - 1) == '-') {
1513 r = idn_prohibited;
1514 goto ret;
1517 r = idn_success;
1518 ret:
1519 TRACE(("res asccheck(): %s\n", idn_result_tostring(r)));
1520 return (r);
1523 static idn_result_t
1524 label_lencheck_ace(idn_resconf_t ctx, labellist_t label) {
1525 const unsigned long *name;
1526 size_t name_length;
1527 idn_result_t r;
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;
1536 goto ret;
1539 r = idn_success;
1540 ret:
1541 TRACE(("res lencheck(): %s\n", idn_result_tostring(r)));
1542 return (r);
1545 static idn_result_t
1546 label_lencheck_nonace(idn_resconf_t ctx, labellist_t label) {
1547 idn_converter_t idn_converter;
1548 const unsigned long *from;
1549 size_t to_length;
1550 idn_result_t r;
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);
1561 for (;;) {
1562 void *new_buffer;
1564 new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
1565 if (new_buffer == NULL) {
1566 r = idn_nomemory;
1567 goto ret;
1569 buffer = (char *)new_buffer;
1571 if (idn_converter != NULL) {
1572 r = idn_converter_convfromucs4(idn_converter, from,
1573 buffer, buffer_length);
1574 } else {
1575 r = idn_ucs4_ucs4toutf8(from, buffer, buffer_length);
1577 if (r == idn_success)
1578 break;
1579 else if (r != idn_buffer_overflow)
1580 goto ret;
1582 buffer_length *= 2;
1585 to_length = strlen(buffer);
1586 if (to_length == 0 || to_length > MAX_LABEL_LENGTH) {
1587 r = idn_invalid_length;
1588 goto ret;
1591 r = idn_success;
1592 ret:
1593 TRACE(("res lencheck(): %s\n", idn_result_tostring(r)));
1594 if (idn_converter != NULL)
1595 idn_converter_destroy(idn_converter);
1596 free(buffer);
1597 return (r);
1600 static idn_result_t
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;
1606 idn_result_t r;
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)
1615 goto ret;
1616 if (rt_label == NULL) {
1617 if (*original_name == '\0')
1618 r = idn_success;
1619 else
1620 r = idn_invalid_encoding;
1621 goto ret;
1624 if (!idn__util_ucs4isasciirange(labellist_getname(rt_label))) {
1625 r = label_map(ctx, rt_label);
1626 if (r != idn_success)
1627 goto ret;
1628 r = label_normalize(ctx, rt_label);
1629 if (r != idn_success)
1630 goto ret;
1631 r = label_prohcheck(ctx, rt_label);
1632 if (r != idn_success)
1633 goto ret;
1634 if (actions & IDN_UNASCHECK) {
1635 r = label_unascheck(ctx, rt_label);
1636 if (r != idn_success)
1637 goto ret;
1639 r = label_bidicheck(ctx, rt_label);
1640 if (r != idn_success)
1641 goto ret;
1644 if (actions & IDN_ASCCHECK) {
1645 r = label_asccheck(ctx, rt_label);
1646 if (r != idn_success)
1647 goto ret;
1649 if (!idn__util_ucs4isasciirange(labellist_getname(rt_label))) {
1650 r = label_idnencode_ace(ctx, rt_label);
1651 if (r != idn_success)
1652 goto ret;
1654 r = label_lencheck_ace(ctx, rt_label);
1655 if (r != idn_success)
1656 goto ret;
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;
1664 goto ret;
1667 r = idn_success;
1668 ret:
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);
1674 return (r);
1677 const char *
1678 idn__res_actionstostring(idn_action_t actions) {
1679 static char buf[100];
1681 buf[0] = '\0';
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");
1695 else {
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");
1724 if (buf[0] == '|')
1725 return (buf + 1);
1726 else
1727 return (buf);