xref: /minix3/external/bsd/bind/dist/contrib/idn/idnkit-1.0-src/lib/res.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: res.c,v 1.4 2014/12/10 04:37:55 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek #ifndef lint
4*00b67f09SDavid van Moolenbroek static char *rcsid = "Id: res.c,v 1.1 2003/06/04 00:26:10 marka Exp ";
5*00b67f09SDavid van Moolenbroek #endif
6*00b67f09SDavid van Moolenbroek 
7*00b67f09SDavid van Moolenbroek /*
8*00b67f09SDavid van Moolenbroek  * Copyright (c) 2000,2002 Japan Network Information Center.
9*00b67f09SDavid van Moolenbroek  * All rights reserved.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * By using this file, you agree to the terms and conditions set forth bellow.
12*00b67f09SDavid van Moolenbroek  *
13*00b67f09SDavid van Moolenbroek  * 			LICENSE TERMS AND CONDITIONS
14*00b67f09SDavid van Moolenbroek  *
15*00b67f09SDavid van Moolenbroek  * The following License Terms and Conditions apply, unless a different
16*00b67f09SDavid van Moolenbroek  * license is obtained from Japan Network Information Center ("JPNIC"),
17*00b67f09SDavid van Moolenbroek  * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
18*00b67f09SDavid van Moolenbroek  * Chiyoda-ku, Tokyo 101-0047, Japan.
19*00b67f09SDavid van Moolenbroek  *
20*00b67f09SDavid van Moolenbroek  * 1. Use, Modification and Redistribution (including distribution of any
21*00b67f09SDavid van Moolenbroek  *    modified or derived work) in source and/or binary forms is permitted
22*00b67f09SDavid van Moolenbroek  *    under this License Terms and Conditions.
23*00b67f09SDavid van Moolenbroek  *
24*00b67f09SDavid van Moolenbroek  * 2. Redistribution of source code must retain the copyright notices as they
25*00b67f09SDavid van Moolenbroek  *    appear in each source code file, this License Terms and Conditions.
26*00b67f09SDavid van Moolenbroek  *
27*00b67f09SDavid van Moolenbroek  * 3. Redistribution in binary form must reproduce the Copyright Notice,
28*00b67f09SDavid van Moolenbroek  *    this License Terms and Conditions, in the documentation and/or other
29*00b67f09SDavid van Moolenbroek  *    materials provided with the distribution.  For the purposes of binary
30*00b67f09SDavid van Moolenbroek  *    distribution the "Copyright Notice" refers to the following language:
31*00b67f09SDavid van Moolenbroek  *    "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
32*00b67f09SDavid van Moolenbroek  *
33*00b67f09SDavid van Moolenbroek  * 4. The name of JPNIC may not be used to endorse or promote products
34*00b67f09SDavid van Moolenbroek  *    derived from this Software without specific prior written approval of
35*00b67f09SDavid van Moolenbroek  *    JPNIC.
36*00b67f09SDavid van Moolenbroek  *
37*00b67f09SDavid van Moolenbroek  * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
38*00b67f09SDavid van Moolenbroek  *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39*00b67f09SDavid van Moolenbroek  *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
40*00b67f09SDavid van Moolenbroek  *    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JPNIC BE LIABLE
41*00b67f09SDavid van Moolenbroek  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42*00b67f09SDavid van Moolenbroek  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43*00b67f09SDavid van Moolenbroek  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44*00b67f09SDavid van Moolenbroek  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45*00b67f09SDavid van Moolenbroek  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46*00b67f09SDavid van Moolenbroek  *    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47*00b67f09SDavid van Moolenbroek  *    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
48*00b67f09SDavid van Moolenbroek  */
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek #include <config.h>
51*00b67f09SDavid van Moolenbroek 
52*00b67f09SDavid van Moolenbroek #include <stddef.h>
53*00b67f09SDavid van Moolenbroek #include <stdlib.h>
54*00b67f09SDavid van Moolenbroek #include <string.h>
55*00b67f09SDavid van Moolenbroek 
56*00b67f09SDavid van Moolenbroek #include <idn/result.h>
57*00b67f09SDavid van Moolenbroek #include <idn/assert.h>
58*00b67f09SDavid van Moolenbroek #include <idn/logmacro.h>
59*00b67f09SDavid van Moolenbroek #include <idn/converter.h>
60*00b67f09SDavid van Moolenbroek #include <idn/normalizer.h>
61*00b67f09SDavid van Moolenbroek #include <idn/checker.h>
62*00b67f09SDavid van Moolenbroek #include <idn/mapper.h>
63*00b67f09SDavid van Moolenbroek #include <idn/mapselector.h>
64*00b67f09SDavid van Moolenbroek #include <idn/delimitermap.h>
65*00b67f09SDavid van Moolenbroek #include <idn/resconf.h>
66*00b67f09SDavid van Moolenbroek #include <idn/res.h>
67*00b67f09SDavid van Moolenbroek #include <idn/util.h>
68*00b67f09SDavid van Moolenbroek #include <idn/debug.h>
69*00b67f09SDavid van Moolenbroek #include <idn/ucs4.h>
70*00b67f09SDavid van Moolenbroek 
71*00b67f09SDavid van Moolenbroek #ifndef IDN_UTF8_ENCODING_NAME
72*00b67f09SDavid van Moolenbroek #define IDN_UTF8_ENCODING_NAME "UTF-8"		/* by IANA */
73*00b67f09SDavid van Moolenbroek #endif
74*00b67f09SDavid van Moolenbroek 
75*00b67f09SDavid van Moolenbroek #ifndef WITHOUT_ICONV
76*00b67f09SDavid van Moolenbroek #define ENCODE_MASK \
77*00b67f09SDavid van Moolenbroek 	(IDN_LOCALCONV | IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | \
78*00b67f09SDavid van Moolenbroek 	 IDN_NORMALIZE | IDN_PROHCHECK | IDN_UNASCHECK | IDN_BIDICHECK | \
79*00b67f09SDavid van Moolenbroek 	 IDN_ASCCHECK | IDN_IDNCONV | IDN_LENCHECK | IDN_ENCODE_QUERY | \
80*00b67f09SDavid van Moolenbroek 	 IDN_UNDOIFERR)
81*00b67f09SDavid van Moolenbroek #define DECODE_MASK \
82*00b67f09SDavid van Moolenbroek 	(IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
83*00b67f09SDavid van Moolenbroek 	 IDN_UNASCHECK | IDN_BIDICHECK | IDN_IDNCONV | IDN_ASCCHECK | \
84*00b67f09SDavid van Moolenbroek 	 IDN_RTCHECK | IDN_LOCALCONV | IDN_DECODE_QUERY)
85*00b67f09SDavid van Moolenbroek #else
86*00b67f09SDavid van Moolenbroek #define ENCODE_MASK \
87*00b67f09SDavid van Moolenbroek 	(IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | IDN_NORMALIZE | \
88*00b67f09SDavid van Moolenbroek 	 IDN_PROHCHECK | IDN_UNASCHECK | IDN_BIDICHECK | IDN_ASCCHECK | \
89*00b67f09SDavid van Moolenbroek 	 IDN_IDNCONV | IDN_LENCHECK | IDN_ENCODE_QUERY | IDN_UNDOIFERR)
90*00b67f09SDavid van Moolenbroek #define DECODE_MASK \
91*00b67f09SDavid van Moolenbroek 	(IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
92*00b67f09SDavid van Moolenbroek 	 IDN_UNASCHECK | IDN_BIDICHECK | IDN_IDNCONV | IDN_ASCCHECK | \
93*00b67f09SDavid van Moolenbroek 	 IDN_RTCHECK | IDN_DECODE_QUERY)
94*00b67f09SDavid van Moolenbroek #endif
95*00b67f09SDavid van Moolenbroek 
96*00b67f09SDavid van Moolenbroek #define MAX_LABEL_LENGTH	63
97*00b67f09SDavid van Moolenbroek 
98*00b67f09SDavid van Moolenbroek /*
99*00b67f09SDavid van Moolenbroek  * label to convert.
100*00b67f09SDavid van Moolenbroek  */
101*00b67f09SDavid van Moolenbroek typedef struct labellist * labellist_t;
102*00b67f09SDavid van Moolenbroek struct labellist {
103*00b67f09SDavid van Moolenbroek 	unsigned long *name;
104*00b67f09SDavid van Moolenbroek 	size_t name_length;
105*00b67f09SDavid van Moolenbroek 	unsigned long *undo_name;
106*00b67f09SDavid van Moolenbroek 	labellist_t next;
107*00b67f09SDavid van Moolenbroek 	labellist_t previous;
108*00b67f09SDavid van Moolenbroek 	int dot_followed;
109*00b67f09SDavid van Moolenbroek };
110*00b67f09SDavid van Moolenbroek 
111*00b67f09SDavid van Moolenbroek typedef idn_result_t (*res_insnproc_t)(idn_resconf_t ctx,
112*00b67f09SDavid van Moolenbroek 				       labellist_t label);
113*00b67f09SDavid van Moolenbroek 
114*00b67f09SDavid van Moolenbroek static void		idn_res_initialize(void);
115*00b67f09SDavid van Moolenbroek static idn_result_t	copy_verbatim(const char *from, char *to,
116*00b67f09SDavid van Moolenbroek 				      size_t tolen);
117*00b67f09SDavid van Moolenbroek static idn_result_t	labellist_create(const unsigned long *name,
118*00b67f09SDavid van Moolenbroek 					 labellist_t *labelp);
119*00b67f09SDavid van Moolenbroek static void		labellist_destroy(labellist_t label);
120*00b67f09SDavid van Moolenbroek static idn_result_t	labellist_setname(labellist_t label,
121*00b67f09SDavid van Moolenbroek 					  const unsigned long *name);
122*00b67f09SDavid van Moolenbroek static const unsigned long *
123*00b67f09SDavid van Moolenbroek 			labellist_getname(labellist_t label);
124*00b67f09SDavid van Moolenbroek static const unsigned long *
125*00b67f09SDavid van Moolenbroek 			labellist_gettldname(labellist_t label);
126*00b67f09SDavid van Moolenbroek static idn_result_t	labellist_getnamelist(labellist_t label,
127*00b67f09SDavid van Moolenbroek 					      unsigned long *name,
128*00b67f09SDavid van Moolenbroek 					      size_t label_length);
129*00b67f09SDavid van Moolenbroek static void		labellist_undo(labellist_t label);
130*00b67f09SDavid van Moolenbroek static labellist_t	labellist_tail(labellist_t label);
131*00b67f09SDavid van Moolenbroek static labellist_t	labellist_previous(labellist_t label);
132*00b67f09SDavid van Moolenbroek 
133*00b67f09SDavid van Moolenbroek #ifndef WITHOUT_ICONV
134*00b67f09SDavid van Moolenbroek static idn_result_t	label_localdecodecheck(idn_resconf_t ctx,
135*00b67f09SDavid van Moolenbroek 					       labellist_t label);
136*00b67f09SDavid van Moolenbroek #endif
137*00b67f09SDavid van Moolenbroek static idn_result_t	label_idnencode_ace(idn_resconf_t ctx,
138*00b67f09SDavid van Moolenbroek 					    labellist_t label);
139*00b67f09SDavid van Moolenbroek static idn_result_t	label_idndecode(idn_resconf_t ctx, labellist_t label);
140*00b67f09SDavid van Moolenbroek static idn_result_t	label_localmap(idn_resconf_t ctx, labellist_t label);
141*00b67f09SDavid van Moolenbroek static idn_result_t	label_map(idn_resconf_t ctx, labellist_t label);
142*00b67f09SDavid van Moolenbroek static idn_result_t	label_normalize(idn_resconf_t ctx, labellist_t label);
143*00b67f09SDavid van Moolenbroek static idn_result_t	label_prohcheck(idn_resconf_t ctx, labellist_t label);
144*00b67f09SDavid van Moolenbroek static idn_result_t	label_unascheck(idn_resconf_t ctx, labellist_t label);
145*00b67f09SDavid van Moolenbroek static idn_result_t	label_bidicheck(idn_resconf_t ctx, labellist_t label);
146*00b67f09SDavid van Moolenbroek static idn_result_t	label_asccheck(idn_resconf_t ctx, labellist_t label);
147*00b67f09SDavid van Moolenbroek static idn_result_t	label_lencheck_ace(idn_resconf_t ctx,
148*00b67f09SDavid van Moolenbroek 					   labellist_t label);
149*00b67f09SDavid van Moolenbroek static idn_result_t	label_lencheck_nonace(idn_resconf_t ctx,
150*00b67f09SDavid van Moolenbroek 					      labellist_t label);
151*00b67f09SDavid van Moolenbroek static idn_result_t	label_rtcheck(idn_resconf_t ctx, idn_action_t actions,
152*00b67f09SDavid van Moolenbroek 				      labellist_t label,
153*00b67f09SDavid van Moolenbroek 				      const unsigned long *original_name);
154*00b67f09SDavid van Moolenbroek 
155*00b67f09SDavid van Moolenbroek static int initialized;
156*00b67f09SDavid van Moolenbroek static int enabled;
157*00b67f09SDavid van Moolenbroek 
158*00b67f09SDavid van Moolenbroek void
idn_res_enable(int on_off)159*00b67f09SDavid van Moolenbroek idn_res_enable(int on_off) {
160*00b67f09SDavid van Moolenbroek 	if (!initialized) {
161*00b67f09SDavid van Moolenbroek 		idn_res_initialize();
162*00b67f09SDavid van Moolenbroek 	}
163*00b67f09SDavid van Moolenbroek 
164*00b67f09SDavid van Moolenbroek 	if (on_off == 0) {
165*00b67f09SDavid van Moolenbroek 		enabled = 0;
166*00b67f09SDavid van Moolenbroek 	} else {
167*00b67f09SDavid van Moolenbroek 		enabled = 1;
168*00b67f09SDavid van Moolenbroek 	}
169*00b67f09SDavid van Moolenbroek }
170*00b67f09SDavid van Moolenbroek 
171*00b67f09SDavid van Moolenbroek static void
idn_res_initialize(void)172*00b67f09SDavid van Moolenbroek idn_res_initialize(void) {
173*00b67f09SDavid van Moolenbroek 	if (!initialized) {
174*00b67f09SDavid van Moolenbroek 		char *value = getenv("IDN_DISABLE");
175*00b67f09SDavid van Moolenbroek 
176*00b67f09SDavid van Moolenbroek 		if (value == NULL) {
177*00b67f09SDavid van Moolenbroek 			enabled = 1;
178*00b67f09SDavid van Moolenbroek 		} else {
179*00b67f09SDavid van Moolenbroek 			enabled = 0;
180*00b67f09SDavid van Moolenbroek 		}
181*00b67f09SDavid van Moolenbroek 		initialized = 1;
182*00b67f09SDavid van Moolenbroek 	}
183*00b67f09SDavid van Moolenbroek }
184*00b67f09SDavid van Moolenbroek 
185*00b67f09SDavid van Moolenbroek idn_result_t
idn_res_encodename(idn_resconf_t ctx,idn_action_t actions,const char * from,char * to,size_t tolen)186*00b67f09SDavid van Moolenbroek idn_res_encodename(idn_resconf_t ctx, idn_action_t actions, const char *from,
187*00b67f09SDavid van Moolenbroek 		    char *to, size_t tolen) {
188*00b67f09SDavid van Moolenbroek 	idn_converter_t local_converter = NULL;
189*00b67f09SDavid van Moolenbroek 	idn_converter_t idn_converter = NULL;
190*00b67f09SDavid van Moolenbroek 	idn_delimitermap_t delimiter_mapper;
191*00b67f09SDavid van Moolenbroek 	idn_result_t r;
192*00b67f09SDavid van Moolenbroek 	labellist_t labels = NULL, l;
193*00b67f09SDavid van Moolenbroek 	unsigned long *buffer = NULL;
194*00b67f09SDavid van Moolenbroek 	size_t buffer_length;
195*00b67f09SDavid van Moolenbroek 	int from_is_root;
196*00b67f09SDavid van Moolenbroek 	int idn_is_ace;
197*00b67f09SDavid van Moolenbroek 
198*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && from != NULL && to != NULL);
199*00b67f09SDavid van Moolenbroek 
200*00b67f09SDavid van Moolenbroek 	TRACE(("idn_res_encodename(actions=%s, from=\"%s\", tolen=%d)\n",
201*00b67f09SDavid van Moolenbroek 		idn__res_actionstostring(actions),
202*00b67f09SDavid van Moolenbroek 		idn__debug_xstring(from, 50), (int)tolen));
203*00b67f09SDavid van Moolenbroek 
204*00b67f09SDavid van Moolenbroek 	if (actions & ~ENCODE_MASK) {
205*00b67f09SDavid van Moolenbroek 		WARNING(("idn_res_encodename: invalid actions 0x%x\n",
206*00b67f09SDavid van Moolenbroek 			 actions));
207*00b67f09SDavid van Moolenbroek 		r = idn_invalid_action;
208*00b67f09SDavid van Moolenbroek 		goto ret;
209*00b67f09SDavid van Moolenbroek 	}
210*00b67f09SDavid van Moolenbroek 
211*00b67f09SDavid van Moolenbroek 	if (!initialized)
212*00b67f09SDavid van Moolenbroek 		idn_res_initialize();
213*00b67f09SDavid van Moolenbroek 	if (!enabled || actions == 0) {
214*00b67f09SDavid van Moolenbroek 		r = copy_verbatim(from, to, tolen);
215*00b67f09SDavid van Moolenbroek 		goto ret;
216*00b67f09SDavid van Moolenbroek 	} else if (tolen <= 0) {
217*00b67f09SDavid van Moolenbroek 		r = idn_buffer_overflow;
218*00b67f09SDavid van Moolenbroek 		goto ret;
219*00b67f09SDavid van Moolenbroek 	}
220*00b67f09SDavid van Moolenbroek 
221*00b67f09SDavid van Moolenbroek 	if (actions & IDN_ENCODE_QUERY) {
222*00b67f09SDavid van Moolenbroek #ifndef WITHOUT_ICONV
223*00b67f09SDavid van Moolenbroek 		actions |= (IDN_LOCALCONV | IDN_DELIMMAP | IDN_LOCALMAP | \
224*00b67f09SDavid van Moolenbroek 			    IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
225*00b67f09SDavid van Moolenbroek 			    IDN_BIDICHECK | IDN_IDNCONV | IDN_LENCHECK);
226*00b67f09SDavid van Moolenbroek #else
227*00b67f09SDavid van Moolenbroek 		actions |= (IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | \
228*00b67f09SDavid van Moolenbroek 			    IDN_NORMALIZE | IDN_PROHCHECK | IDN_BIDICHECK | \
229*00b67f09SDavid van Moolenbroek 			    IDN_IDNCONV | IDN_LENCHECK);
230*00b67f09SDavid van Moolenbroek #endif
231*00b67f09SDavid van Moolenbroek 	}
232*00b67f09SDavid van Moolenbroek 
233*00b67f09SDavid van Moolenbroek 	/*
234*00b67f09SDavid van Moolenbroek 	 * Convert `from' to UCS4.
235*00b67f09SDavid van Moolenbroek 	 */
236*00b67f09SDavid van Moolenbroek 	local_converter = idn_resconf_getlocalconverter(ctx);
237*00b67f09SDavid van Moolenbroek #ifndef WITHOUT_ICONV
238*00b67f09SDavid van Moolenbroek 	if (local_converter == NULL) {
239*00b67f09SDavid van Moolenbroek 		r = idn_invalid_name;
240*00b67f09SDavid van Moolenbroek 		goto ret;
241*00b67f09SDavid van Moolenbroek 	}
242*00b67f09SDavid van Moolenbroek #endif
243*00b67f09SDavid van Moolenbroek 
244*00b67f09SDavid van Moolenbroek 	idn_converter = idn_resconf_getidnconverter(ctx);
245*00b67f09SDavid van Moolenbroek 	if (idn_converter != NULL &&
246*00b67f09SDavid van Moolenbroek 	    idn_converter_isasciicompatible(idn_converter))
247*00b67f09SDavid van Moolenbroek 		idn_is_ace = 1;
248*00b67f09SDavid van Moolenbroek 	else
249*00b67f09SDavid van Moolenbroek 		idn_is_ace = 0;
250*00b67f09SDavid van Moolenbroek 
251*00b67f09SDavid van Moolenbroek 	buffer_length = tolen * 2;
252*00b67f09SDavid van Moolenbroek 
253*00b67f09SDavid van Moolenbroek 	for (;;) {
254*00b67f09SDavid van Moolenbroek 		void *new_buffer;
255*00b67f09SDavid van Moolenbroek 
256*00b67f09SDavid van Moolenbroek 		new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
257*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
258*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
259*00b67f09SDavid van Moolenbroek 			goto ret;
260*00b67f09SDavid van Moolenbroek 		}
261*00b67f09SDavid van Moolenbroek 		buffer = (unsigned long *)new_buffer;
262*00b67f09SDavid van Moolenbroek 
263*00b67f09SDavid van Moolenbroek 		if (actions & IDN_LOCALCONV) {
264*00b67f09SDavid van Moolenbroek 			r = idn_converter_convtoucs4(local_converter, from,
265*00b67f09SDavid van Moolenbroek 						     buffer, buffer_length);
266*00b67f09SDavid van Moolenbroek 		} else {
267*00b67f09SDavid van Moolenbroek 			r = idn_ucs4_utf8toucs4(from, buffer, buffer_length);
268*00b67f09SDavid van Moolenbroek 		}
269*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
270*00b67f09SDavid van Moolenbroek 			break;
271*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
272*00b67f09SDavid van Moolenbroek 			goto ret;
273*00b67f09SDavid van Moolenbroek 
274*00b67f09SDavid van Moolenbroek 		buffer_length *= 2;
275*00b67f09SDavid van Moolenbroek 	}
276*00b67f09SDavid van Moolenbroek 
277*00b67f09SDavid van Moolenbroek 	if (*buffer == '\0') {
278*00b67f09SDavid van Moolenbroek 		if (tolen <= 0) {
279*00b67f09SDavid van Moolenbroek 			r = idn_buffer_overflow;
280*00b67f09SDavid van Moolenbroek 			goto ret;
281*00b67f09SDavid van Moolenbroek 		}
282*00b67f09SDavid van Moolenbroek 		*to = '\0';
283*00b67f09SDavid van Moolenbroek 		r = idn_success;
284*00b67f09SDavid van Moolenbroek 		goto ret;
285*00b67f09SDavid van Moolenbroek 	}
286*00b67f09SDavid van Moolenbroek 
287*00b67f09SDavid van Moolenbroek 	/*
288*00b67f09SDavid van Moolenbroek 	 * Delimiter map.
289*00b67f09SDavid van Moolenbroek 	 */
290*00b67f09SDavid van Moolenbroek 	if (actions & IDN_DELIMMAP) {
291*00b67f09SDavid van Moolenbroek 		TRACE(("res delimitermap(name=\"%s\")\n",
292*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(buffer, 50)));
293*00b67f09SDavid van Moolenbroek 
294*00b67f09SDavid van Moolenbroek 		delimiter_mapper = idn_resconf_getdelimitermap(ctx);
295*00b67f09SDavid van Moolenbroek 		if (delimiter_mapper != NULL) {
296*00b67f09SDavid van Moolenbroek 			r = idn_delimitermap_map(delimiter_mapper, buffer,
297*00b67f09SDavid van Moolenbroek 						 buffer, buffer_length);
298*00b67f09SDavid van Moolenbroek 			idn_delimitermap_destroy(delimiter_mapper);
299*00b67f09SDavid van Moolenbroek 			if (r != idn_success)
300*00b67f09SDavid van Moolenbroek 				goto ret;
301*00b67f09SDavid van Moolenbroek 		}
302*00b67f09SDavid van Moolenbroek 		TRACE(("res delimitermap(): success (name=\"%s\")\n",
303*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(buffer, 50)));
304*00b67f09SDavid van Moolenbroek 	}
305*00b67f09SDavid van Moolenbroek 
306*00b67f09SDavid van Moolenbroek 	from_is_root = (buffer[0] == '.' && buffer[1] == '\0');
307*00b67f09SDavid van Moolenbroek 
308*00b67f09SDavid van Moolenbroek 	/*
309*00b67f09SDavid van Moolenbroek 	 * Split the name into a list of labels.
310*00b67f09SDavid van Moolenbroek 	 */
311*00b67f09SDavid van Moolenbroek 	r = labellist_create(buffer, &labels);
312*00b67f09SDavid van Moolenbroek 	if (r != idn_success)
313*00b67f09SDavid van Moolenbroek 		goto ret;
314*00b67f09SDavid van Moolenbroek 
315*00b67f09SDavid van Moolenbroek 	/*
316*00b67f09SDavid van Moolenbroek 	 * Perform conversions and tests.
317*00b67f09SDavid van Moolenbroek 	 */
318*00b67f09SDavid van Moolenbroek 	for (l = labellist_tail(labels); l != NULL;
319*00b67f09SDavid van Moolenbroek 	     l = labellist_previous(l)) {
320*00b67f09SDavid van Moolenbroek 
321*00b67f09SDavid van Moolenbroek 		if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
322*00b67f09SDavid van Moolenbroek 			if (actions & IDN_LOCALMAP) {
323*00b67f09SDavid van Moolenbroek 				r = label_localmap(ctx, l);
324*00b67f09SDavid van Moolenbroek 				if (r != idn_success)
325*00b67f09SDavid van Moolenbroek 					goto ret;
326*00b67f09SDavid van Moolenbroek 			}
327*00b67f09SDavid van Moolenbroek 		}
328*00b67f09SDavid van Moolenbroek 
329*00b67f09SDavid van Moolenbroek 		if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
330*00b67f09SDavid van Moolenbroek 			if (actions & IDN_MAP) {
331*00b67f09SDavid van Moolenbroek 				r = label_map(ctx, l);
332*00b67f09SDavid van Moolenbroek 				if (r != idn_success)
333*00b67f09SDavid van Moolenbroek 					goto ret;
334*00b67f09SDavid van Moolenbroek 			}
335*00b67f09SDavid van Moolenbroek 			if (actions & IDN_NORMALIZE) {
336*00b67f09SDavid van Moolenbroek 				r = label_normalize(ctx, l);
337*00b67f09SDavid van Moolenbroek 				if (r != idn_success)
338*00b67f09SDavid van Moolenbroek 					goto ret;
339*00b67f09SDavid van Moolenbroek 			}
340*00b67f09SDavid van Moolenbroek 			if (actions & IDN_PROHCHECK) {
341*00b67f09SDavid van Moolenbroek 				r = label_prohcheck(ctx, l);
342*00b67f09SDavid van Moolenbroek 				if (r == idn_prohibited &&
343*00b67f09SDavid van Moolenbroek 				    (actions & IDN_UNDOIFERR)) {
344*00b67f09SDavid van Moolenbroek 					labellist_undo(l);
345*00b67f09SDavid van Moolenbroek 					continue;
346*00b67f09SDavid van Moolenbroek 				} else if (r != idn_success) {
347*00b67f09SDavid van Moolenbroek 					goto ret;
348*00b67f09SDavid van Moolenbroek 				}
349*00b67f09SDavid van Moolenbroek 			}
350*00b67f09SDavid van Moolenbroek 			if (actions & IDN_UNASCHECK) {
351*00b67f09SDavid van Moolenbroek 				r = label_unascheck(ctx, l);
352*00b67f09SDavid van Moolenbroek 				if (r == idn_prohibited &&
353*00b67f09SDavid van Moolenbroek 				    (actions & IDN_UNDOIFERR)) {
354*00b67f09SDavid van Moolenbroek 					labellist_undo(l);
355*00b67f09SDavid van Moolenbroek 					continue;
356*00b67f09SDavid van Moolenbroek 				} else if (r != idn_success) {
357*00b67f09SDavid van Moolenbroek 					goto ret;
358*00b67f09SDavid van Moolenbroek 				}
359*00b67f09SDavid van Moolenbroek 			}
360*00b67f09SDavid van Moolenbroek 			if (actions & IDN_BIDICHECK) {
361*00b67f09SDavid van Moolenbroek 				r = label_bidicheck(ctx, l);
362*00b67f09SDavid van Moolenbroek 				if (r == idn_prohibited &&
363*00b67f09SDavid van Moolenbroek 				    (actions & IDN_UNDOIFERR)) {
364*00b67f09SDavid van Moolenbroek 					labellist_undo(l);
365*00b67f09SDavid van Moolenbroek 					continue;
366*00b67f09SDavid van Moolenbroek 				} else if (r != idn_success) {
367*00b67f09SDavid van Moolenbroek 					goto ret;
368*00b67f09SDavid van Moolenbroek 				}
369*00b67f09SDavid van Moolenbroek 			}
370*00b67f09SDavid van Moolenbroek 		}
371*00b67f09SDavid van Moolenbroek 
372*00b67f09SDavid van Moolenbroek 		if (actions & IDN_ASCCHECK) {
373*00b67f09SDavid van Moolenbroek 			r = label_asccheck(ctx, l);
374*00b67f09SDavid van Moolenbroek 			if (r == idn_prohibited && (actions & IDN_UNDOIFERR)) {
375*00b67f09SDavid van Moolenbroek 				labellist_undo(l);
376*00b67f09SDavid van Moolenbroek 				continue;
377*00b67f09SDavid van Moolenbroek 			} else if (r != idn_success) {
378*00b67f09SDavid van Moolenbroek 				goto ret;
379*00b67f09SDavid van Moolenbroek 			}
380*00b67f09SDavid van Moolenbroek 		}
381*00b67f09SDavid van Moolenbroek 
382*00b67f09SDavid van Moolenbroek 		if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
383*00b67f09SDavid van Moolenbroek 			if ((actions & IDN_IDNCONV) && idn_is_ace) {
384*00b67f09SDavid van Moolenbroek 				r = label_idnencode_ace(ctx, l);
385*00b67f09SDavid van Moolenbroek 				if (r != idn_success)
386*00b67f09SDavid van Moolenbroek 					goto ret;
387*00b67f09SDavid van Moolenbroek 			}
388*00b67f09SDavid van Moolenbroek 		}
389*00b67f09SDavid van Moolenbroek 
390*00b67f09SDavid van Moolenbroek 		if (!from_is_root && (actions & IDN_LENCHECK)) {
391*00b67f09SDavid van Moolenbroek 			if (idn_is_ace)
392*00b67f09SDavid van Moolenbroek 				r = label_lencheck_ace(ctx, l);
393*00b67f09SDavid van Moolenbroek 			else
394*00b67f09SDavid van Moolenbroek 				r = label_lencheck_nonace(ctx, l);
395*00b67f09SDavid van Moolenbroek 			if (r == idn_invalid_length &&
396*00b67f09SDavid van Moolenbroek 			    (actions & IDN_UNDOIFERR)) {
397*00b67f09SDavid van Moolenbroek 				labellist_undo(l);
398*00b67f09SDavid van Moolenbroek 				continue;
399*00b67f09SDavid van Moolenbroek 			} else if (r != idn_success) {
400*00b67f09SDavid van Moolenbroek 				goto ret;
401*00b67f09SDavid van Moolenbroek 			}
402*00b67f09SDavid van Moolenbroek 		}
403*00b67f09SDavid van Moolenbroek 	}
404*00b67f09SDavid van Moolenbroek 
405*00b67f09SDavid van Moolenbroek 	/*
406*00b67f09SDavid van Moolenbroek 	 * Concat a list of labels to a name.
407*00b67f09SDavid van Moolenbroek 	 */
408*00b67f09SDavid van Moolenbroek 	for (;;) {
409*00b67f09SDavid van Moolenbroek 		void *new_buffer;
410*00b67f09SDavid van Moolenbroek 
411*00b67f09SDavid van Moolenbroek 		new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
412*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
413*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
414*00b67f09SDavid van Moolenbroek 			goto ret;
415*00b67f09SDavid van Moolenbroek 		}
416*00b67f09SDavid van Moolenbroek 		buffer = (unsigned long *)new_buffer;
417*00b67f09SDavid van Moolenbroek 
418*00b67f09SDavid van Moolenbroek 		r = labellist_getnamelist(labels, buffer, buffer_length);
419*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
420*00b67f09SDavid van Moolenbroek 			break;
421*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
422*00b67f09SDavid van Moolenbroek 			goto ret;
423*00b67f09SDavid van Moolenbroek 
424*00b67f09SDavid van Moolenbroek 		buffer_length *= 2;
425*00b67f09SDavid van Moolenbroek 	}
426*00b67f09SDavid van Moolenbroek 
427*00b67f09SDavid van Moolenbroek 	if ((actions & IDN_IDNCONV) && idn_converter != NULL && !idn_is_ace) {
428*00b67f09SDavid van Moolenbroek 		r = idn_converter_convfromucs4(idn_converter, buffer, to,
429*00b67f09SDavid van Moolenbroek 					       tolen);
430*00b67f09SDavid van Moolenbroek 	} else {
431*00b67f09SDavid van Moolenbroek 		r = idn_ucs4_ucs4toutf8(buffer, to, tolen);
432*00b67f09SDavid van Moolenbroek 	}
433*00b67f09SDavid van Moolenbroek 
434*00b67f09SDavid van Moolenbroek ret:
435*00b67f09SDavid van Moolenbroek 	if (r == idn_success) {
436*00b67f09SDavid van Moolenbroek 		TRACE(("idn_res_encodename(): success (to=\"%s\")\n",
437*00b67f09SDavid van Moolenbroek 		       idn__debug_xstring(to, 50)));
438*00b67f09SDavid van Moolenbroek 	} else {
439*00b67f09SDavid van Moolenbroek 		TRACE(("idn_res_encodename(): %s\n", idn_result_tostring(r)));
440*00b67f09SDavid van Moolenbroek 	}
441*00b67f09SDavid van Moolenbroek 	free(buffer);
442*00b67f09SDavid van Moolenbroek 	if (local_converter != NULL)
443*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(local_converter);
444*00b67f09SDavid van Moolenbroek 	if (idn_converter != NULL)
445*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(idn_converter);
446*00b67f09SDavid van Moolenbroek 	if (labels != NULL)
447*00b67f09SDavid van Moolenbroek 		labellist_destroy(labels);
448*00b67f09SDavid van Moolenbroek 	return (r);
449*00b67f09SDavid van Moolenbroek }
450*00b67f09SDavid van Moolenbroek 
451*00b67f09SDavid van Moolenbroek idn_result_t
idn_res_decodename(idn_resconf_t ctx,idn_action_t actions,const char * from,char * to,size_t tolen)452*00b67f09SDavid van Moolenbroek idn_res_decodename(idn_resconf_t ctx, idn_action_t actions, const char *from,
453*00b67f09SDavid van Moolenbroek 		    char *to, size_t tolen) {
454*00b67f09SDavid van Moolenbroek 	idn_converter_t local_converter = NULL;
455*00b67f09SDavid van Moolenbroek 	idn_converter_t idn_converter = NULL;
456*00b67f09SDavid van Moolenbroek 	idn_delimitermap_t delimiter_mapper;
457*00b67f09SDavid van Moolenbroek 	idn_result_t r;
458*00b67f09SDavid van Moolenbroek 	labellist_t labels = NULL, l;
459*00b67f09SDavid van Moolenbroek 	unsigned long *buffer = NULL;
460*00b67f09SDavid van Moolenbroek 	unsigned long *saved_name = NULL;
461*00b67f09SDavid van Moolenbroek 	size_t buffer_length;
462*00b67f09SDavid van Moolenbroek 	int idn_is_ace;
463*00b67f09SDavid van Moolenbroek 
464*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && from != NULL && to != NULL);
465*00b67f09SDavid van Moolenbroek 
466*00b67f09SDavid van Moolenbroek 	TRACE(("idn_res_decodename(actions=%s, from=\"%s\", tolen=%d)\n",
467*00b67f09SDavid van Moolenbroek 		idn__res_actionstostring(actions),
468*00b67f09SDavid van Moolenbroek 		idn__debug_xstring(from, 50), (int)tolen));
469*00b67f09SDavid van Moolenbroek 
470*00b67f09SDavid van Moolenbroek 	if (actions & ~DECODE_MASK) {
471*00b67f09SDavid van Moolenbroek 		WARNING(("idn_res_decodename: invalid actions 0x%x\n",
472*00b67f09SDavid van Moolenbroek 			 actions));
473*00b67f09SDavid van Moolenbroek 		r = idn_invalid_action;
474*00b67f09SDavid van Moolenbroek 		goto ret;
475*00b67f09SDavid van Moolenbroek 	}
476*00b67f09SDavid van Moolenbroek 
477*00b67f09SDavid van Moolenbroek 	if (!initialized)
478*00b67f09SDavid van Moolenbroek 		idn_res_initialize();
479*00b67f09SDavid van Moolenbroek 	if (!enabled || actions == 0) {
480*00b67f09SDavid van Moolenbroek 		r = copy_verbatim(from, to, tolen);
481*00b67f09SDavid van Moolenbroek 		goto ret;
482*00b67f09SDavid van Moolenbroek 	} else if (tolen <= 0) {
483*00b67f09SDavid van Moolenbroek 		r = idn_buffer_overflow;
484*00b67f09SDavid van Moolenbroek 		goto ret;
485*00b67f09SDavid van Moolenbroek 	}
486*00b67f09SDavid van Moolenbroek 
487*00b67f09SDavid van Moolenbroek 	if (actions & IDN_DECODE_QUERY) {
488*00b67f09SDavid van Moolenbroek #ifndef WITHOUT_ICONV
489*00b67f09SDavid van Moolenbroek 		actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \
490*00b67f09SDavid van Moolenbroek 			    IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \
491*00b67f09SDavid van Moolenbroek 			    IDN_RTCHECK | IDN_LOCALCONV);
492*00b67f09SDavid van Moolenbroek #else
493*00b67f09SDavid van Moolenbroek 		actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \
494*00b67f09SDavid van Moolenbroek 			    IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \
495*00b67f09SDavid van Moolenbroek 			    IDN_RTCHECK);
496*00b67f09SDavid van Moolenbroek #endif
497*00b67f09SDavid van Moolenbroek 	}
498*00b67f09SDavid van Moolenbroek 
499*00b67f09SDavid van Moolenbroek 	/*
500*00b67f09SDavid van Moolenbroek 	 * Convert `from' to UCS4.
501*00b67f09SDavid van Moolenbroek 	 */
502*00b67f09SDavid van Moolenbroek 	local_converter = idn_resconf_getlocalconverter(ctx);
503*00b67f09SDavid van Moolenbroek #ifndef WITHOUT_ICONV
504*00b67f09SDavid van Moolenbroek 	if (local_converter == NULL) {
505*00b67f09SDavid van Moolenbroek 		r = idn_invalid_name;
506*00b67f09SDavid van Moolenbroek 		goto ret;
507*00b67f09SDavid van Moolenbroek 	}
508*00b67f09SDavid van Moolenbroek #endif
509*00b67f09SDavid van Moolenbroek 
510*00b67f09SDavid van Moolenbroek 	idn_converter = idn_resconf_getidnconverter(ctx);
511*00b67f09SDavid van Moolenbroek 	if (idn_converter != NULL &&
512*00b67f09SDavid van Moolenbroek 	    idn_converter_isasciicompatible(idn_converter))
513*00b67f09SDavid van Moolenbroek 		idn_is_ace = 1;
514*00b67f09SDavid van Moolenbroek 	else
515*00b67f09SDavid van Moolenbroek 		idn_is_ace = 0;
516*00b67f09SDavid van Moolenbroek 
517*00b67f09SDavid van Moolenbroek 	buffer_length = tolen * 2;
518*00b67f09SDavid van Moolenbroek 
519*00b67f09SDavid van Moolenbroek 	TRACE(("res idndecode(name=\"%s\")\n", idn__debug_xstring(from, 50)));
520*00b67f09SDavid van Moolenbroek 
521*00b67f09SDavid van Moolenbroek 	for (;;) {
522*00b67f09SDavid van Moolenbroek 		void *new_buffer;
523*00b67f09SDavid van Moolenbroek 
524*00b67f09SDavid van Moolenbroek 		new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
525*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
526*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
527*00b67f09SDavid van Moolenbroek 			goto ret;
528*00b67f09SDavid van Moolenbroek 		}
529*00b67f09SDavid van Moolenbroek 		buffer = (unsigned long *)new_buffer;
530*00b67f09SDavid van Moolenbroek 
531*00b67f09SDavid van Moolenbroek 		if ((actions & IDN_IDNCONV) &&
532*00b67f09SDavid van Moolenbroek 		     idn_converter != NULL && !idn_is_ace) {
533*00b67f09SDavid van Moolenbroek 			r = idn_converter_convtoucs4(idn_converter, from,
534*00b67f09SDavid van Moolenbroek 						     buffer, buffer_length);
535*00b67f09SDavid van Moolenbroek 		} else {
536*00b67f09SDavid van Moolenbroek 			r = idn_ucs4_utf8toucs4(from, buffer, buffer_length);
537*00b67f09SDavid van Moolenbroek 		}
538*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
539*00b67f09SDavid van Moolenbroek 			break;
540*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
541*00b67f09SDavid van Moolenbroek 			goto ret;
542*00b67f09SDavid van Moolenbroek 
543*00b67f09SDavid van Moolenbroek 		buffer_length *= 2;
544*00b67f09SDavid van Moolenbroek 	}
545*00b67f09SDavid van Moolenbroek 
546*00b67f09SDavid van Moolenbroek 	if (*buffer == '\0') {
547*00b67f09SDavid van Moolenbroek 		if (tolen <= 0) {
548*00b67f09SDavid van Moolenbroek 			r = idn_buffer_overflow;
549*00b67f09SDavid van Moolenbroek 			goto ret;
550*00b67f09SDavid van Moolenbroek 		}
551*00b67f09SDavid van Moolenbroek 		*to = '\0';
552*00b67f09SDavid van Moolenbroek 		r = idn_success;
553*00b67f09SDavid van Moolenbroek 		goto ret;
554*00b67f09SDavid van Moolenbroek 	}
555*00b67f09SDavid van Moolenbroek 
556*00b67f09SDavid van Moolenbroek 	/*
557*00b67f09SDavid van Moolenbroek 	 * Delimiter map.
558*00b67f09SDavid van Moolenbroek 	 */
559*00b67f09SDavid van Moolenbroek 	if (actions & IDN_DELIMMAP) {
560*00b67f09SDavid van Moolenbroek 		TRACE(("res delimitermap(name=\"%s\")\n",
561*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(buffer, 50)));
562*00b67f09SDavid van Moolenbroek 
563*00b67f09SDavid van Moolenbroek 		delimiter_mapper = idn_resconf_getdelimitermap(ctx);
564*00b67f09SDavid van Moolenbroek 		if (delimiter_mapper != NULL) {
565*00b67f09SDavid van Moolenbroek 			r = idn_delimitermap_map(delimiter_mapper, buffer,
566*00b67f09SDavid van Moolenbroek 						 buffer, buffer_length);
567*00b67f09SDavid van Moolenbroek 			idn_delimitermap_destroy(delimiter_mapper);
568*00b67f09SDavid van Moolenbroek 			if (r != idn_success)
569*00b67f09SDavid van Moolenbroek 				goto ret;
570*00b67f09SDavid van Moolenbroek 		}
571*00b67f09SDavid van Moolenbroek 		TRACE(("res delimitermap(): success (name=\"%s\")\n",
572*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(buffer, 50)));
573*00b67f09SDavid van Moolenbroek 	}
574*00b67f09SDavid van Moolenbroek 
575*00b67f09SDavid van Moolenbroek 	/*
576*00b67f09SDavid van Moolenbroek 	 * Split the name into a list of labels.
577*00b67f09SDavid van Moolenbroek 	 */
578*00b67f09SDavid van Moolenbroek 	r = labellist_create(buffer, &labels);
579*00b67f09SDavid van Moolenbroek 	if (r != idn_success)
580*00b67f09SDavid van Moolenbroek 		goto ret;
581*00b67f09SDavid van Moolenbroek 
582*00b67f09SDavid van Moolenbroek 	/*
583*00b67f09SDavid van Moolenbroek 	 * Perform conversions and tests.
584*00b67f09SDavid van Moolenbroek 	 */
585*00b67f09SDavid van Moolenbroek 	for (l = labellist_tail(labels); l != NULL;
586*00b67f09SDavid van Moolenbroek 	     l = labellist_previous(l)) {
587*00b67f09SDavid van Moolenbroek 
588*00b67f09SDavid van Moolenbroek 		free(saved_name);
589*00b67f09SDavid van Moolenbroek 		saved_name = NULL;
590*00b67f09SDavid van Moolenbroek 
591*00b67f09SDavid van Moolenbroek 		if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
592*00b67f09SDavid van Moolenbroek 			if (actions & IDN_MAP) {
593*00b67f09SDavid van Moolenbroek 				r = label_map(ctx, l);
594*00b67f09SDavid van Moolenbroek 				if (r != idn_success)
595*00b67f09SDavid van Moolenbroek 					goto ret;
596*00b67f09SDavid van Moolenbroek 			}
597*00b67f09SDavid van Moolenbroek 			if (actions & IDN_NORMALIZE) {
598*00b67f09SDavid van Moolenbroek 				r = label_normalize(ctx, l);
599*00b67f09SDavid van Moolenbroek 				if (r != idn_success)
600*00b67f09SDavid van Moolenbroek 					goto ret;
601*00b67f09SDavid van Moolenbroek 			}
602*00b67f09SDavid van Moolenbroek 			if (actions & IDN_PROHCHECK) {
603*00b67f09SDavid van Moolenbroek 				r = label_prohcheck(ctx, l);
604*00b67f09SDavid van Moolenbroek 				if (r == idn_prohibited) {
605*00b67f09SDavid van Moolenbroek 					labellist_undo(l);
606*00b67f09SDavid van Moolenbroek 					continue;
607*00b67f09SDavid van Moolenbroek 				} else if (r != idn_success) {
608*00b67f09SDavid van Moolenbroek 					goto ret;
609*00b67f09SDavid van Moolenbroek 				}
610*00b67f09SDavid van Moolenbroek 			}
611*00b67f09SDavid van Moolenbroek 			if (actions & IDN_UNASCHECK) {
612*00b67f09SDavid van Moolenbroek 				r = label_unascheck(ctx, l);
613*00b67f09SDavid van Moolenbroek 				if (r == idn_prohibited) {
614*00b67f09SDavid van Moolenbroek 					labellist_undo(l);
615*00b67f09SDavid van Moolenbroek 					continue;
616*00b67f09SDavid van Moolenbroek 				} else if (r != idn_success) {
617*00b67f09SDavid van Moolenbroek 					goto ret;
618*00b67f09SDavid van Moolenbroek 				}
619*00b67f09SDavid van Moolenbroek 			}
620*00b67f09SDavid van Moolenbroek 			if (actions & IDN_BIDICHECK) {
621*00b67f09SDavid van Moolenbroek 				r = label_bidicheck(ctx, l);
622*00b67f09SDavid van Moolenbroek 				if (r == idn_prohibited) {
623*00b67f09SDavid van Moolenbroek 					labellist_undo(l);
624*00b67f09SDavid van Moolenbroek 					continue;
625*00b67f09SDavid van Moolenbroek 				} else if (r != idn_success) {
626*00b67f09SDavid van Moolenbroek 					goto ret;
627*00b67f09SDavid van Moolenbroek 				}
628*00b67f09SDavid van Moolenbroek 			}
629*00b67f09SDavid van Moolenbroek 		}
630*00b67f09SDavid van Moolenbroek 
631*00b67f09SDavid van Moolenbroek 		if ((actions & IDN_IDNCONV) && idn_is_ace) {
632*00b67f09SDavid van Moolenbroek 			saved_name = idn_ucs4_strdup(labellist_getname(l));
633*00b67f09SDavid van Moolenbroek 			if (saved_name == NULL) {
634*00b67f09SDavid van Moolenbroek 				r = idn_nomemory;
635*00b67f09SDavid van Moolenbroek 				goto ret;
636*00b67f09SDavid van Moolenbroek 			}
637*00b67f09SDavid van Moolenbroek 			r = label_idndecode(ctx, l);
638*00b67f09SDavid van Moolenbroek 			if (r == idn_invalid_encoding) {
639*00b67f09SDavid van Moolenbroek 				labellist_undo(l);
640*00b67f09SDavid van Moolenbroek 				continue;
641*00b67f09SDavid van Moolenbroek 			} else if (r != idn_success) {
642*00b67f09SDavid van Moolenbroek 				goto ret;
643*00b67f09SDavid van Moolenbroek 			}
644*00b67f09SDavid van Moolenbroek 		}
645*00b67f09SDavid van Moolenbroek 		if ((actions & IDN_RTCHECK) && saved_name != NULL) {
646*00b67f09SDavid van Moolenbroek 			r = label_rtcheck(ctx, actions, l, saved_name);
647*00b67f09SDavid van Moolenbroek 			if (r == idn_invalid_encoding) {
648*00b67f09SDavid van Moolenbroek 				labellist_undo(l);
649*00b67f09SDavid van Moolenbroek 				continue;
650*00b67f09SDavid van Moolenbroek 			} else if (r != idn_success) {
651*00b67f09SDavid van Moolenbroek 				goto ret;
652*00b67f09SDavid van Moolenbroek 			}
653*00b67f09SDavid van Moolenbroek 		}
654*00b67f09SDavid van Moolenbroek 
655*00b67f09SDavid van Moolenbroek #ifndef WITHOUT_ICONV
656*00b67f09SDavid van Moolenbroek 		if (actions & IDN_LOCALCONV) {
657*00b67f09SDavid van Moolenbroek 			r = label_localdecodecheck(ctx, l);
658*00b67f09SDavid van Moolenbroek 			if (r != idn_success)
659*00b67f09SDavid van Moolenbroek 				goto ret;
660*00b67f09SDavid van Moolenbroek 		}
661*00b67f09SDavid van Moolenbroek #endif
662*00b67f09SDavid van Moolenbroek 	}
663*00b67f09SDavid van Moolenbroek 
664*00b67f09SDavid van Moolenbroek 	/*
665*00b67f09SDavid van Moolenbroek 	 * Concat a list of labels to a name.
666*00b67f09SDavid van Moolenbroek 	 */
667*00b67f09SDavid van Moolenbroek 	for (;;) {
668*00b67f09SDavid van Moolenbroek 		void *new_buffer;
669*00b67f09SDavid van Moolenbroek 
670*00b67f09SDavid van Moolenbroek 		new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
671*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
672*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
673*00b67f09SDavid van Moolenbroek 			goto ret;
674*00b67f09SDavid van Moolenbroek 		}
675*00b67f09SDavid van Moolenbroek 		buffer = (unsigned long *)new_buffer;
676*00b67f09SDavid van Moolenbroek 
677*00b67f09SDavid van Moolenbroek 		r = labellist_getnamelist(labels, buffer, buffer_length);
678*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
679*00b67f09SDavid van Moolenbroek 			break;
680*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
681*00b67f09SDavid van Moolenbroek 			goto ret;
682*00b67f09SDavid van Moolenbroek 
683*00b67f09SDavid van Moolenbroek 		buffer_length *= 2;
684*00b67f09SDavid van Moolenbroek 	}
685*00b67f09SDavid van Moolenbroek 
686*00b67f09SDavid van Moolenbroek 	if (actions & IDN_LOCALCONV) {
687*00b67f09SDavid van Moolenbroek 		r = idn_converter_convfromucs4(local_converter, buffer, to,
688*00b67f09SDavid van Moolenbroek 					       tolen);
689*00b67f09SDavid van Moolenbroek 	} else {
690*00b67f09SDavid van Moolenbroek 		r = idn_ucs4_ucs4toutf8(buffer, to, tolen);
691*00b67f09SDavid van Moolenbroek 	}
692*00b67f09SDavid van Moolenbroek 
693*00b67f09SDavid van Moolenbroek ret:
694*00b67f09SDavid van Moolenbroek 	if (r == idn_success) {
695*00b67f09SDavid van Moolenbroek 		TRACE(("idn_res_decodename(): success (to=\"%s\")\n",
696*00b67f09SDavid van Moolenbroek 		       idn__debug_xstring(to, 50)));
697*00b67f09SDavid van Moolenbroek 	} else {
698*00b67f09SDavid van Moolenbroek 		TRACE(("idn_res_decodename(): %s\n", idn_result_tostring(r)));
699*00b67f09SDavid van Moolenbroek 	}
700*00b67f09SDavid van Moolenbroek 	free(saved_name);
701*00b67f09SDavid van Moolenbroek 	free(buffer);
702*00b67f09SDavid van Moolenbroek 	if (local_converter != NULL)
703*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(local_converter);
704*00b67f09SDavid van Moolenbroek 	if (idn_converter != NULL)
705*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(idn_converter);
706*00b67f09SDavid van Moolenbroek 	if (labels != NULL)
707*00b67f09SDavid van Moolenbroek 		labellist_destroy(labels);
708*00b67f09SDavid van Moolenbroek 	return (r);
709*00b67f09SDavid van Moolenbroek }
710*00b67f09SDavid van Moolenbroek 
711*00b67f09SDavid van Moolenbroek idn_result_t
idn_res_decodename2(idn_resconf_t ctx,idn_action_t actions,const char * from,char * to,size_t tolen,const char * auxencoding)712*00b67f09SDavid van Moolenbroek idn_res_decodename2(idn_resconf_t ctx, idn_action_t actions, const char *from,
713*00b67f09SDavid van Moolenbroek 		    char *to, size_t tolen, const char *auxencoding) {
714*00b67f09SDavid van Moolenbroek #ifdef WITHOUT_ICONV
715*00b67f09SDavid van Moolenbroek 	return idn_failure;
716*00b67f09SDavid van Moolenbroek 
717*00b67f09SDavid van Moolenbroek #else /* WITHOUT_ICONV */
718*00b67f09SDavid van Moolenbroek 	idn_result_t r;
719*00b67f09SDavid van Moolenbroek 	idn_converter_t aux_converter = NULL;
720*00b67f09SDavid van Moolenbroek 	unsigned long *buffer_ucs4 = NULL;
721*00b67f09SDavid van Moolenbroek 	char *buffer_utf8 = NULL;
722*00b67f09SDavid van Moolenbroek 	size_t buffer_length;
723*00b67f09SDavid van Moolenbroek 
724*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && from != NULL && to != NULL);
725*00b67f09SDavid van Moolenbroek 
726*00b67f09SDavid van Moolenbroek 	TRACE(("idn_res_decodename2(actions=%s, from=\"%s\", tolen=%d, "
727*00b67f09SDavid van Moolenbroek 		"auxencoding=\"%s\")\n",
728*00b67f09SDavid van Moolenbroek 		idn__res_actionstostring(actions),
729*00b67f09SDavid van Moolenbroek 		idn__debug_xstring(from, 50), (int)tolen,
730*00b67f09SDavid van Moolenbroek 		(auxencoding != NULL) ? auxencoding : "<null>"));
731*00b67f09SDavid van Moolenbroek 
732*00b67f09SDavid van Moolenbroek 	if (!initialized)
733*00b67f09SDavid van Moolenbroek 		idn_res_initialize();
734*00b67f09SDavid van Moolenbroek 	if (!enabled || actions == 0) {
735*00b67f09SDavid van Moolenbroek 		r = copy_verbatim(from, to, tolen);
736*00b67f09SDavid van Moolenbroek 		goto ret;
737*00b67f09SDavid van Moolenbroek 	} else if (tolen <= 0) {
738*00b67f09SDavid van Moolenbroek 		r = idn_buffer_overflow;
739*00b67f09SDavid van Moolenbroek 		goto ret;
740*00b67f09SDavid van Moolenbroek 	}
741*00b67f09SDavid van Moolenbroek 
742*00b67f09SDavid van Moolenbroek 	if (auxencoding == NULL ||
743*00b67f09SDavid van Moolenbroek 	    strcmp(auxencoding, IDN_UTF8_ENCODING_NAME) == 0 ||
744*00b67f09SDavid van Moolenbroek 	    strcmp(auxencoding, "UTF-8") == 0) {
745*00b67f09SDavid van Moolenbroek 		return idn_res_decodename(ctx, actions, from, to, tolen);
746*00b67f09SDavid van Moolenbroek 	}
747*00b67f09SDavid van Moolenbroek 
748*00b67f09SDavid van Moolenbroek 	/*
749*00b67f09SDavid van Moolenbroek 	 * Convert `from' to UCS4.
750*00b67f09SDavid van Moolenbroek 	 */
751*00b67f09SDavid van Moolenbroek 	r = idn_resconf_setauxidnconvertername(ctx, auxencoding,
752*00b67f09SDavid van Moolenbroek 					       IDN_CONVERTER_DELAYEDOPEN);
753*00b67f09SDavid van Moolenbroek 	if (r != idn_success) {
754*00b67f09SDavid van Moolenbroek 		goto ret;
755*00b67f09SDavid van Moolenbroek 	}
756*00b67f09SDavid van Moolenbroek 
757*00b67f09SDavid van Moolenbroek 	aux_converter = idn_resconf_getauxidnconverter(ctx);
758*00b67f09SDavid van Moolenbroek 	if (aux_converter == NULL) {
759*00b67f09SDavid van Moolenbroek 		r = idn_failure;
760*00b67f09SDavid van Moolenbroek 		goto ret;
761*00b67f09SDavid van Moolenbroek 	}
762*00b67f09SDavid van Moolenbroek 
763*00b67f09SDavid van Moolenbroek 	buffer_length = tolen * 2;
764*00b67f09SDavid van Moolenbroek 	for (;;) {
765*00b67f09SDavid van Moolenbroek 		void *new_buffer;
766*00b67f09SDavid van Moolenbroek 
767*00b67f09SDavid van Moolenbroek 		new_buffer = realloc(buffer_ucs4,
768*00b67f09SDavid van Moolenbroek 				     sizeof(*buffer_ucs4) * buffer_length);
769*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
770*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
771*00b67f09SDavid van Moolenbroek 			goto ret;
772*00b67f09SDavid van Moolenbroek 		}
773*00b67f09SDavid van Moolenbroek 		buffer_ucs4 = (unsigned long *)new_buffer;
774*00b67f09SDavid van Moolenbroek 
775*00b67f09SDavid van Moolenbroek 		r = idn_converter_convtoucs4(aux_converter, from,
776*00b67f09SDavid van Moolenbroek 					     buffer_ucs4,
777*00b67f09SDavid van Moolenbroek 					     buffer_length);
778*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
779*00b67f09SDavid van Moolenbroek 			break;
780*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
781*00b67f09SDavid van Moolenbroek 			goto ret;
782*00b67f09SDavid van Moolenbroek 
783*00b67f09SDavid van Moolenbroek 		buffer_length *= 2;
784*00b67f09SDavid van Moolenbroek 	}
785*00b67f09SDavid van Moolenbroek 
786*00b67f09SDavid van Moolenbroek 	if (*buffer_ucs4 == '\0') {
787*00b67f09SDavid van Moolenbroek 		if (tolen <= 0) {
788*00b67f09SDavid van Moolenbroek 			r = idn_buffer_overflow;
789*00b67f09SDavid van Moolenbroek 			goto ret;
790*00b67f09SDavid van Moolenbroek 		}
791*00b67f09SDavid van Moolenbroek 		*to = '\0';
792*00b67f09SDavid van Moolenbroek 		r = idn_success;
793*00b67f09SDavid van Moolenbroek 		goto ret;
794*00b67f09SDavid van Moolenbroek 	}
795*00b67f09SDavid van Moolenbroek 
796*00b67f09SDavid van Moolenbroek 	/*
797*00b67f09SDavid van Moolenbroek 	 * Convert `buffer_ucs4' to UTF-8.
798*00b67f09SDavid van Moolenbroek 	 */
799*00b67f09SDavid van Moolenbroek 	buffer_length = tolen * 2;
800*00b67f09SDavid van Moolenbroek 	for (;;) {
801*00b67f09SDavid van Moolenbroek 		void *new_buffer;
802*00b67f09SDavid van Moolenbroek 
803*00b67f09SDavid van Moolenbroek 		new_buffer = realloc(buffer_utf8,
804*00b67f09SDavid van Moolenbroek 				     sizeof(*buffer_utf8) * buffer_length);
805*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
806*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
807*00b67f09SDavid van Moolenbroek 			goto ret;
808*00b67f09SDavid van Moolenbroek 		}
809*00b67f09SDavid van Moolenbroek 		buffer_utf8 = (char *)new_buffer;
810*00b67f09SDavid van Moolenbroek 		r = idn_ucs4_ucs4toutf8(buffer_ucs4, buffer_utf8,
811*00b67f09SDavid van Moolenbroek 					buffer_length);
812*00b67f09SDavid van Moolenbroek 
813*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
814*00b67f09SDavid van Moolenbroek 			break;
815*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
816*00b67f09SDavid van Moolenbroek 			goto ret;
817*00b67f09SDavid van Moolenbroek 
818*00b67f09SDavid van Moolenbroek 		buffer_length *= 2;
819*00b67f09SDavid van Moolenbroek 	}
820*00b67f09SDavid van Moolenbroek 
821*00b67f09SDavid van Moolenbroek 	if (*buffer_utf8 == '\0') {
822*00b67f09SDavid van Moolenbroek 		if (tolen <= 0) {
823*00b67f09SDavid van Moolenbroek 			r = idn_buffer_overflow;
824*00b67f09SDavid van Moolenbroek 			goto ret;
825*00b67f09SDavid van Moolenbroek 		}
826*00b67f09SDavid van Moolenbroek 		*to = '\0';
827*00b67f09SDavid van Moolenbroek 		r = idn_success;
828*00b67f09SDavid van Moolenbroek 		goto ret;
829*00b67f09SDavid van Moolenbroek 	}
830*00b67f09SDavid van Moolenbroek 
831*00b67f09SDavid van Moolenbroek 	r = idn_res_decodename(ctx, actions, buffer_utf8, to, tolen);
832*00b67f09SDavid van Moolenbroek 
833*00b67f09SDavid van Moolenbroek ret:
834*00b67f09SDavid van Moolenbroek 	if (r == idn_success) {
835*00b67f09SDavid van Moolenbroek 		TRACE(("idn_res_decodename2(): success (to=\"%s\")\n",
836*00b67f09SDavid van Moolenbroek 		       idn__debug_xstring(to, 50)));
837*00b67f09SDavid van Moolenbroek 	} else {
838*00b67f09SDavid van Moolenbroek 		TRACE(("idn_res_decodename2(): %s\n", idn_result_tostring(r)));
839*00b67f09SDavid van Moolenbroek 	}
840*00b67f09SDavid van Moolenbroek 	free(buffer_ucs4);
841*00b67f09SDavid van Moolenbroek 	free(buffer_utf8);
842*00b67f09SDavid van Moolenbroek 	if (aux_converter != NULL)
843*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(aux_converter);
844*00b67f09SDavid van Moolenbroek 
845*00b67f09SDavid van Moolenbroek 	return (r);
846*00b67f09SDavid van Moolenbroek 
847*00b67f09SDavid van Moolenbroek #endif /* WITHOUT_ICONV */
848*00b67f09SDavid van Moolenbroek }
849*00b67f09SDavid van Moolenbroek 
850*00b67f09SDavid van Moolenbroek static idn_result_t
copy_verbatim(const char * from,char * to,size_t tolen)851*00b67f09SDavid van Moolenbroek copy_verbatim(const char *from, char *to, size_t tolen) {
852*00b67f09SDavid van Moolenbroek 	size_t fromlen = strlen(from);
853*00b67f09SDavid van Moolenbroek 
854*00b67f09SDavid van Moolenbroek 	if (fromlen + 1 > tolen)
855*00b67f09SDavid van Moolenbroek 		return (idn_buffer_overflow);
856*00b67f09SDavid van Moolenbroek 	(void)memcpy(to, from, fromlen + 1);
857*00b67f09SDavid van Moolenbroek 	return (idn_success);
858*00b67f09SDavid van Moolenbroek }
859*00b67f09SDavid van Moolenbroek 
860*00b67f09SDavid van Moolenbroek static idn_result_t
labellist_create(const unsigned long * name,labellist_t * labelp)861*00b67f09SDavid van Moolenbroek labellist_create(const unsigned long *name, labellist_t *labelp) {
862*00b67f09SDavid van Moolenbroek 	size_t length, malloc_length;
863*00b67f09SDavid van Moolenbroek 	labellist_t head_label = NULL;
864*00b67f09SDavid van Moolenbroek 	labellist_t tail_label = NULL;
865*00b67f09SDavid van Moolenbroek 	labellist_t new_label = NULL;
866*00b67f09SDavid van Moolenbroek 	const unsigned long *endp = NULL;
867*00b67f09SDavid van Moolenbroek 	idn_result_t r;
868*00b67f09SDavid van Moolenbroek 
869*00b67f09SDavid van Moolenbroek 	while (*name != '\0') {
870*00b67f09SDavid van Moolenbroek 		for (endp = name; *endp != '.' && *endp != '\0'; endp++)
871*00b67f09SDavid van Moolenbroek 			;  /* nothing to be done */
872*00b67f09SDavid van Moolenbroek 		length = (endp - name) + 1;
873*00b67f09SDavid van Moolenbroek 		malloc_length = length + 15;  /* add 15 for margin */
874*00b67f09SDavid van Moolenbroek 
875*00b67f09SDavid van Moolenbroek 		new_label = (labellist_t)
876*00b67f09SDavid van Moolenbroek 			    malloc(sizeof(struct labellist));
877*00b67f09SDavid van Moolenbroek 		if (new_label == NULL) {
878*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
879*00b67f09SDavid van Moolenbroek 			goto ret;
880*00b67f09SDavid van Moolenbroek 		}
881*00b67f09SDavid van Moolenbroek 		if (head_label == NULL)
882*00b67f09SDavid van Moolenbroek 			head_label = new_label;
883*00b67f09SDavid van Moolenbroek 
884*00b67f09SDavid van Moolenbroek 		new_label->name = NULL;
885*00b67f09SDavid van Moolenbroek 		new_label->undo_name = NULL;
886*00b67f09SDavid van Moolenbroek 		new_label->name_length = malloc_length;
887*00b67f09SDavid van Moolenbroek 		new_label->next = NULL;
888*00b67f09SDavid van Moolenbroek 		new_label->previous = NULL;
889*00b67f09SDavid van Moolenbroek 		new_label->dot_followed = (*endp == '.');
890*00b67f09SDavid van Moolenbroek 
891*00b67f09SDavid van Moolenbroek 		new_label->name = (unsigned long *)
892*00b67f09SDavid van Moolenbroek 				  malloc(sizeof(long) * malloc_length);
893*00b67f09SDavid van Moolenbroek 		if (new_label->name == NULL) {
894*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
895*00b67f09SDavid van Moolenbroek 			goto ret;
896*00b67f09SDavid van Moolenbroek 		}
897*00b67f09SDavid van Moolenbroek 		memcpy(new_label->name, name, sizeof(long) * length);
898*00b67f09SDavid van Moolenbroek 		*(new_label->name + length - 1) = '\0';
899*00b67f09SDavid van Moolenbroek 
900*00b67f09SDavid van Moolenbroek 		new_label->undo_name = (unsigned long *)
901*00b67f09SDavid van Moolenbroek 				       malloc(sizeof(long) * malloc_length);
902*00b67f09SDavid van Moolenbroek 		if (new_label->undo_name == NULL) {
903*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
904*00b67f09SDavid van Moolenbroek 			goto ret;
905*00b67f09SDavid van Moolenbroek 		}
906*00b67f09SDavid van Moolenbroek 		memcpy(new_label->undo_name, name, sizeof(long) * length);
907*00b67f09SDavid van Moolenbroek 		*(new_label->undo_name + length - 1) = '\0';
908*00b67f09SDavid van Moolenbroek 
909*00b67f09SDavid van Moolenbroek 		if (tail_label != NULL) {
910*00b67f09SDavid van Moolenbroek 			tail_label->next = new_label;
911*00b67f09SDavid van Moolenbroek 			new_label->previous = tail_label;
912*00b67f09SDavid van Moolenbroek 		}
913*00b67f09SDavid van Moolenbroek 		tail_label = new_label;
914*00b67f09SDavid van Moolenbroek 
915*00b67f09SDavid van Moolenbroek 		if (*endp == '.')
916*00b67f09SDavid van Moolenbroek 			name = endp + 1;
917*00b67f09SDavid van Moolenbroek 		else
918*00b67f09SDavid van Moolenbroek 			name = endp;
919*00b67f09SDavid van Moolenbroek 	}
920*00b67f09SDavid van Moolenbroek 
921*00b67f09SDavid van Moolenbroek 	*labelp = head_label;
922*00b67f09SDavid van Moolenbroek 	r = idn_success;
923*00b67f09SDavid van Moolenbroek 
924*00b67f09SDavid van Moolenbroek ret:
925*00b67f09SDavid van Moolenbroek 	if (r != idn_success) {
926*00b67f09SDavid van Moolenbroek 		if (new_label != NULL) {
927*00b67f09SDavid van Moolenbroek 			free(new_label->name);
928*00b67f09SDavid van Moolenbroek 			free(new_label->undo_name);
929*00b67f09SDavid van Moolenbroek 			free(new_label);
930*00b67f09SDavid van Moolenbroek 		}
931*00b67f09SDavid van Moolenbroek 		if (head_label != NULL)
932*00b67f09SDavid van Moolenbroek 			labellist_destroy(head_label);
933*00b67f09SDavid van Moolenbroek 	}
934*00b67f09SDavid van Moolenbroek 	return (r);
935*00b67f09SDavid van Moolenbroek }
936*00b67f09SDavid van Moolenbroek 
937*00b67f09SDavid van Moolenbroek 
938*00b67f09SDavid van Moolenbroek static void
labellist_destroy(labellist_t label)939*00b67f09SDavid van Moolenbroek labellist_destroy(labellist_t label) {
940*00b67f09SDavid van Moolenbroek 	labellist_t l, l_next;
941*00b67f09SDavid van Moolenbroek 
942*00b67f09SDavid van Moolenbroek 	for (l = label; l != NULL; l = l_next) {
943*00b67f09SDavid van Moolenbroek 		l_next = l->next;
944*00b67f09SDavid van Moolenbroek 		free(l->name);
945*00b67f09SDavid van Moolenbroek 		free(l->undo_name);
946*00b67f09SDavid van Moolenbroek 		free(l);
947*00b67f09SDavid van Moolenbroek 	}
948*00b67f09SDavid van Moolenbroek }
949*00b67f09SDavid van Moolenbroek 
950*00b67f09SDavid van Moolenbroek static idn_result_t
labellist_setname(labellist_t label,const unsigned long * name)951*00b67f09SDavid van Moolenbroek labellist_setname(labellist_t label, const unsigned long *name) {
952*00b67f09SDavid van Moolenbroek 	unsigned long *new_name;
953*00b67f09SDavid van Moolenbroek 	size_t length, new_length;
954*00b67f09SDavid van Moolenbroek 
955*00b67f09SDavid van Moolenbroek 	length = idn_ucs4_strlen(name) + 1;
956*00b67f09SDavid van Moolenbroek 	new_length = length + 15;  /* add 15 for margin */
957*00b67f09SDavid van Moolenbroek 
958*00b67f09SDavid van Moolenbroek 	if (label->name_length < new_length) {
959*00b67f09SDavid van Moolenbroek 		new_name = (unsigned long *)
960*00b67f09SDavid van Moolenbroek 			   realloc(label->name, sizeof(long) * new_length);
961*00b67f09SDavid van Moolenbroek 		if (new_name == NULL)
962*00b67f09SDavid van Moolenbroek 			return (idn_nomemory);
963*00b67f09SDavid van Moolenbroek 		label->name = new_name;
964*00b67f09SDavid van Moolenbroek 		label->name_length = new_length;
965*00b67f09SDavid van Moolenbroek 	}
966*00b67f09SDavid van Moolenbroek 	memcpy(label->name, name, sizeof(long) * length);
967*00b67f09SDavid van Moolenbroek 
968*00b67f09SDavid van Moolenbroek 	return (idn_success);
969*00b67f09SDavid van Moolenbroek }
970*00b67f09SDavid van Moolenbroek 
971*00b67f09SDavid van Moolenbroek static const unsigned long *
labellist_getname(labellist_t label)972*00b67f09SDavid van Moolenbroek labellist_getname(labellist_t label) {
973*00b67f09SDavid van Moolenbroek 	return (label->name);
974*00b67f09SDavid van Moolenbroek }
975*00b67f09SDavid van Moolenbroek 
976*00b67f09SDavid van Moolenbroek static const unsigned long *
labellist_gettldname(labellist_t label)977*00b67f09SDavid van Moolenbroek labellist_gettldname(labellist_t label) {
978*00b67f09SDavid van Moolenbroek 	labellist_t l;
979*00b67f09SDavid van Moolenbroek 
980*00b67f09SDavid van Moolenbroek 	if (label->previous == NULL && label->next == NULL &&
981*00b67f09SDavid van Moolenbroek 	    !label->dot_followed)
982*00b67f09SDavid van Moolenbroek 		return (idn_mapselector_getnotld());
983*00b67f09SDavid van Moolenbroek 
984*00b67f09SDavid van Moolenbroek 	for (l = label; l->next != NULL; l = l->next)
985*00b67f09SDavid van Moolenbroek 		;  /* nothing to be done */
986*00b67f09SDavid van Moolenbroek 
987*00b67f09SDavid van Moolenbroek 	return (l->name);
988*00b67f09SDavid van Moolenbroek }
989*00b67f09SDavid van Moolenbroek 
990*00b67f09SDavid van Moolenbroek static idn_result_t
labellist_getnamelist(labellist_t label,unsigned long * name,size_t name_length)991*00b67f09SDavid van Moolenbroek labellist_getnamelist(labellist_t label, unsigned long *name,
992*00b67f09SDavid van Moolenbroek 			  size_t name_length) {
993*00b67f09SDavid van Moolenbroek 	static const unsigned long dot_string[] = {0x002e, 0x0000};  /* "." */
994*00b67f09SDavid van Moolenbroek 	size_t length;
995*00b67f09SDavid van Moolenbroek 	labellist_t l;
996*00b67f09SDavid van Moolenbroek 
997*00b67f09SDavid van Moolenbroek 	for (l = label, length = 0; l != NULL; l = l->next)
998*00b67f09SDavid van Moolenbroek 		length += idn_ucs4_strlen(l->name) + 1;  /* name + `.' */
999*00b67f09SDavid van Moolenbroek 	length++;  /* for NUL */
1000*00b67f09SDavid van Moolenbroek 
1001*00b67f09SDavid van Moolenbroek 	if (name_length < length)
1002*00b67f09SDavid van Moolenbroek 		return (idn_buffer_overflow);
1003*00b67f09SDavid van Moolenbroek 
1004*00b67f09SDavid van Moolenbroek 	*name = '\0';
1005*00b67f09SDavid van Moolenbroek 	for (l = label; l != NULL; l = l->next) {
1006*00b67f09SDavid van Moolenbroek 		idn_ucs4_strcat(name, l->name);
1007*00b67f09SDavid van Moolenbroek 		name += idn_ucs4_strlen(name);
1008*00b67f09SDavid van Moolenbroek 		if (l->dot_followed)
1009*00b67f09SDavid van Moolenbroek 			idn_ucs4_strcat(name, dot_string);
1010*00b67f09SDavid van Moolenbroek 	}
1011*00b67f09SDavid van Moolenbroek 	return (idn_success);
1012*00b67f09SDavid van Moolenbroek }
1013*00b67f09SDavid van Moolenbroek 
1014*00b67f09SDavid van Moolenbroek static void
labellist_undo(labellist_t label)1015*00b67f09SDavid van Moolenbroek labellist_undo(labellist_t label) {
1016*00b67f09SDavid van Moolenbroek 	size_t length;
1017*00b67f09SDavid van Moolenbroek 
1018*00b67f09SDavid van Moolenbroek 	length = idn_ucs4_strlen(label->undo_name) + 1;
1019*00b67f09SDavid van Moolenbroek 	memcpy(label->name, label->undo_name, sizeof(long) * length);
1020*00b67f09SDavid van Moolenbroek }
1021*00b67f09SDavid van Moolenbroek 
1022*00b67f09SDavid van Moolenbroek static labellist_t
labellist_tail(labellist_t label)1023*00b67f09SDavid van Moolenbroek labellist_tail(labellist_t label) {
1024*00b67f09SDavid van Moolenbroek 	labellist_t l;
1025*00b67f09SDavid van Moolenbroek 
1026*00b67f09SDavid van Moolenbroek 	if (label == NULL)
1027*00b67f09SDavid van Moolenbroek 		return (NULL);
1028*00b67f09SDavid van Moolenbroek 	for (l = label; l->next != NULL; l = l->next)
1029*00b67f09SDavid van Moolenbroek 		;  /* nothing to be done */
1030*00b67f09SDavid van Moolenbroek 	return (l);
1031*00b67f09SDavid van Moolenbroek }
1032*00b67f09SDavid van Moolenbroek 
1033*00b67f09SDavid van Moolenbroek static labellist_t
labellist_previous(labellist_t label)1034*00b67f09SDavid van Moolenbroek labellist_previous(labellist_t label) {
1035*00b67f09SDavid van Moolenbroek 	return (label->previous);
1036*00b67f09SDavid van Moolenbroek }
1037*00b67f09SDavid van Moolenbroek 
1038*00b67f09SDavid van Moolenbroek #ifndef WITHOUT_ICONV
1039*00b67f09SDavid van Moolenbroek 
1040*00b67f09SDavid van Moolenbroek static idn_result_t
label_localdecodecheck(idn_resconf_t ctx,labellist_t label)1041*00b67f09SDavid van Moolenbroek label_localdecodecheck(idn_resconf_t ctx, labellist_t label) {
1042*00b67f09SDavid van Moolenbroek 	idn_converter_t local_converter = NULL;
1043*00b67f09SDavid van Moolenbroek 	const unsigned long *from;
1044*00b67f09SDavid van Moolenbroek 	char *to = NULL;
1045*00b67f09SDavid van Moolenbroek 	size_t to_length;
1046*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1047*00b67f09SDavid van Moolenbroek 
1048*00b67f09SDavid van Moolenbroek 	from = labellist_getname(label);
1049*00b67f09SDavid van Moolenbroek 	to_length = idn_ucs4_strlen(from) + 1 + 15;  /* 15 for margin */
1050*00b67f09SDavid van Moolenbroek 	TRACE(("res ucs4tolocal_check(label=\"%s\")\n",
1051*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(from, 50)));
1052*00b67f09SDavid van Moolenbroek 
1053*00b67f09SDavid van Moolenbroek 	local_converter = idn_resconf_getlocalconverter(ctx);
1054*00b67f09SDavid van Moolenbroek 	if (local_converter == NULL) {
1055*00b67f09SDavid van Moolenbroek 		r = idn_success;
1056*00b67f09SDavid van Moolenbroek 		goto ret;
1057*00b67f09SDavid van Moolenbroek 	}
1058*00b67f09SDavid van Moolenbroek 
1059*00b67f09SDavid van Moolenbroek 	for (;;) {
1060*00b67f09SDavid van Moolenbroek 		char *new_buffer;
1061*00b67f09SDavid van Moolenbroek 
1062*00b67f09SDavid van Moolenbroek 		new_buffer = (char *)realloc(to, to_length);
1063*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1064*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1065*00b67f09SDavid van Moolenbroek 			goto ret;
1066*00b67f09SDavid van Moolenbroek 		}
1067*00b67f09SDavid van Moolenbroek 		to = new_buffer;
1068*00b67f09SDavid van Moolenbroek 		r = idn_converter_convfromucs4(local_converter, from, to,
1069*00b67f09SDavid van Moolenbroek 					       to_length);
1070*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1071*00b67f09SDavid van Moolenbroek 			break;
1072*00b67f09SDavid van Moolenbroek 		else if (r == idn_nomapping) {
1073*00b67f09SDavid van Moolenbroek 			r = label_idnencode_ace(ctx, label);
1074*00b67f09SDavid van Moolenbroek 			if (r != idn_success)
1075*00b67f09SDavid van Moolenbroek 				goto ret;
1076*00b67f09SDavid van Moolenbroek 			break;
1077*00b67f09SDavid van Moolenbroek 		} else if (r != idn_buffer_overflow) {
1078*00b67f09SDavid van Moolenbroek 			goto ret;
1079*00b67f09SDavid van Moolenbroek 		}
1080*00b67f09SDavid van Moolenbroek 		to_length *= 2;
1081*00b67f09SDavid van Moolenbroek 	}
1082*00b67f09SDavid van Moolenbroek 
1083*00b67f09SDavid van Moolenbroek 	r = idn_success;
1084*00b67f09SDavid van Moolenbroek ret:
1085*00b67f09SDavid van Moolenbroek 	TRACE(("res ucs4tolocal_check(): %s\n", idn_result_tostring(r)));
1086*00b67f09SDavid van Moolenbroek 	if (local_converter != NULL)
1087*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(local_converter);
1088*00b67f09SDavid van Moolenbroek 	free(to);
1089*00b67f09SDavid van Moolenbroek 	return (r);
1090*00b67f09SDavid van Moolenbroek }
1091*00b67f09SDavid van Moolenbroek 
1092*00b67f09SDavid van Moolenbroek #endif /* !WITHOUT_ICONV */
1093*00b67f09SDavid van Moolenbroek 
1094*00b67f09SDavid van Moolenbroek static idn_result_t
label_idndecode(idn_resconf_t ctx,labellist_t label)1095*00b67f09SDavid van Moolenbroek label_idndecode(idn_resconf_t ctx, labellist_t label) {
1096*00b67f09SDavid van Moolenbroek 	idn_converter_t idn_converter = NULL;
1097*00b67f09SDavid van Moolenbroek 	const unsigned long *from;
1098*00b67f09SDavid van Moolenbroek 	char *ascii_from = NULL;
1099*00b67f09SDavid van Moolenbroek 	unsigned long *to = NULL;
1100*00b67f09SDavid van Moolenbroek 	size_t from_length, to_length;
1101*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1102*00b67f09SDavid van Moolenbroek 
1103*00b67f09SDavid van Moolenbroek 	from = labellist_getname(label);
1104*00b67f09SDavid van Moolenbroek 	from_length = idn_ucs4_strlen(from) + 1;
1105*00b67f09SDavid van Moolenbroek 	TRACE(("res idntoucs4(label=\"%s\")\n",
1106*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(from, 50)));
1107*00b67f09SDavid van Moolenbroek 
1108*00b67f09SDavid van Moolenbroek 	idn_converter = idn_resconf_getidnconverter(ctx);
1109*00b67f09SDavid van Moolenbroek 	if (idn_converter == NULL) {
1110*00b67f09SDavid van Moolenbroek 		r = idn_success;
1111*00b67f09SDavid van Moolenbroek 		goto ret;
1112*00b67f09SDavid van Moolenbroek 	}
1113*00b67f09SDavid van Moolenbroek 
1114*00b67f09SDavid van Moolenbroek 	for (;;) {
1115*00b67f09SDavid van Moolenbroek 		char *new_buffer;
1116*00b67f09SDavid van Moolenbroek 
1117*00b67f09SDavid van Moolenbroek 		new_buffer = (char *) realloc(ascii_from, from_length);
1118*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1119*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1120*00b67f09SDavid van Moolenbroek 			goto ret;
1121*00b67f09SDavid van Moolenbroek 		}
1122*00b67f09SDavid van Moolenbroek 		ascii_from = new_buffer;
1123*00b67f09SDavid van Moolenbroek 		r = idn_ucs4_ucs4toutf8(from, ascii_from, from_length);
1124*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1125*00b67f09SDavid van Moolenbroek 			break;
1126*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
1127*00b67f09SDavid van Moolenbroek 			goto ret;
1128*00b67f09SDavid van Moolenbroek 		from_length *= 2;
1129*00b67f09SDavid van Moolenbroek 	}
1130*00b67f09SDavid van Moolenbroek 
1131*00b67f09SDavid van Moolenbroek 	to = NULL;
1132*00b67f09SDavid van Moolenbroek 	to_length = from_length;
1133*00b67f09SDavid van Moolenbroek 
1134*00b67f09SDavid van Moolenbroek 	for (;;) {
1135*00b67f09SDavid van Moolenbroek 		unsigned long *new_buffer;
1136*00b67f09SDavid van Moolenbroek 
1137*00b67f09SDavid van Moolenbroek 		new_buffer = (unsigned long *)
1138*00b67f09SDavid van Moolenbroek 			     realloc(to, sizeof(long) * to_length);
1139*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1140*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1141*00b67f09SDavid van Moolenbroek 			goto ret;
1142*00b67f09SDavid van Moolenbroek 		}
1143*00b67f09SDavid van Moolenbroek 		to = new_buffer;
1144*00b67f09SDavid van Moolenbroek 		r = idn_converter_convtoucs4(idn_converter, ascii_from, to,
1145*00b67f09SDavid van Moolenbroek 					     to_length);
1146*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1147*00b67f09SDavid van Moolenbroek 			break;
1148*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
1149*00b67f09SDavid van Moolenbroek 			goto ret;
1150*00b67f09SDavid van Moolenbroek 		to_length *= 2;
1151*00b67f09SDavid van Moolenbroek 	}
1152*00b67f09SDavid van Moolenbroek 
1153*00b67f09SDavid van Moolenbroek 	r = labellist_setname(label, to);
1154*00b67f09SDavid van Moolenbroek ret:
1155*00b67f09SDavid van Moolenbroek 	if (r == idn_success) {
1156*00b67f09SDavid van Moolenbroek 		TRACE(("res idntoucs4(): success (label=\"%s\")\n",
1157*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(labellist_getname(label),
1158*00b67f09SDavid van Moolenbroek 					      50)));
1159*00b67f09SDavid van Moolenbroek 	} else {
1160*00b67f09SDavid van Moolenbroek 		TRACE(("res idntoucs4(): %s\n", idn_result_tostring(r)));
1161*00b67f09SDavid van Moolenbroek 	}
1162*00b67f09SDavid van Moolenbroek 	if (idn_converter != NULL)
1163*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(idn_converter);
1164*00b67f09SDavid van Moolenbroek 	free(to);
1165*00b67f09SDavid van Moolenbroek 	free(ascii_from);
1166*00b67f09SDavid van Moolenbroek 	return (r);
1167*00b67f09SDavid van Moolenbroek }
1168*00b67f09SDavid van Moolenbroek 
1169*00b67f09SDavid van Moolenbroek static idn_result_t
label_idnencode_ace(idn_resconf_t ctx,labellist_t label)1170*00b67f09SDavid van Moolenbroek label_idnencode_ace(idn_resconf_t ctx, labellist_t label) {
1171*00b67f09SDavid van Moolenbroek 	idn_converter_t idn_converter = NULL;
1172*00b67f09SDavid van Moolenbroek 	const unsigned long *from;
1173*00b67f09SDavid van Moolenbroek 	char *ascii_to = NULL;
1174*00b67f09SDavid van Moolenbroek 	unsigned long *to = NULL;
1175*00b67f09SDavid van Moolenbroek 	size_t to_length;
1176*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1177*00b67f09SDavid van Moolenbroek 
1178*00b67f09SDavid van Moolenbroek 	from = labellist_getname(label);
1179*00b67f09SDavid van Moolenbroek 	TRACE(("res ucs4toidn(label=\"%s\")\n",
1180*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(from, 50)));
1181*00b67f09SDavid van Moolenbroek 
1182*00b67f09SDavid van Moolenbroek 	idn_converter = idn_resconf_getidnconverter(ctx);
1183*00b67f09SDavid van Moolenbroek 	if (idn_converter == NULL) {
1184*00b67f09SDavid van Moolenbroek 		r = idn_success;
1185*00b67f09SDavid van Moolenbroek 		goto ret;
1186*00b67f09SDavid van Moolenbroek 	}
1187*00b67f09SDavid van Moolenbroek 
1188*00b67f09SDavid van Moolenbroek 	ascii_to = NULL;
1189*00b67f09SDavid van Moolenbroek 	to_length = idn_ucs4_strlen(from) * 4 + 16;  /* add mergin */
1190*00b67f09SDavid van Moolenbroek 
1191*00b67f09SDavid van Moolenbroek 	for (;;) {
1192*00b67f09SDavid van Moolenbroek 		char *new_buffer;
1193*00b67f09SDavid van Moolenbroek 
1194*00b67f09SDavid van Moolenbroek 		new_buffer = (char *) realloc(ascii_to, to_length);
1195*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1196*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1197*00b67f09SDavid van Moolenbroek 			goto ret;
1198*00b67f09SDavid van Moolenbroek 		}
1199*00b67f09SDavid van Moolenbroek 		ascii_to = new_buffer;
1200*00b67f09SDavid van Moolenbroek 		r = idn_converter_convfromucs4(idn_converter, from, ascii_to,
1201*00b67f09SDavid van Moolenbroek 					       to_length);
1202*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1203*00b67f09SDavid van Moolenbroek 			break;
1204*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
1205*00b67f09SDavid van Moolenbroek 			goto ret;
1206*00b67f09SDavid van Moolenbroek 		to_length *= 2;
1207*00b67f09SDavid van Moolenbroek 	}
1208*00b67f09SDavid van Moolenbroek 
1209*00b67f09SDavid van Moolenbroek 	for (;;) {
1210*00b67f09SDavid van Moolenbroek 		unsigned long *new_buffer;
1211*00b67f09SDavid van Moolenbroek 
1212*00b67f09SDavid van Moolenbroek 		new_buffer = (unsigned long *)
1213*00b67f09SDavid van Moolenbroek 			     realloc(to, sizeof(long) * to_length);
1214*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1215*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1216*00b67f09SDavid van Moolenbroek 			goto ret;
1217*00b67f09SDavid van Moolenbroek 		}
1218*00b67f09SDavid van Moolenbroek 		to = new_buffer;
1219*00b67f09SDavid van Moolenbroek 		r = idn_ucs4_utf8toucs4(ascii_to, to, to_length);
1220*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1221*00b67f09SDavid van Moolenbroek 			break;
1222*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
1223*00b67f09SDavid van Moolenbroek 			goto ret;
1224*00b67f09SDavid van Moolenbroek 		to_length *= 2;
1225*00b67f09SDavid van Moolenbroek 	}
1226*00b67f09SDavid van Moolenbroek 
1227*00b67f09SDavid van Moolenbroek 	if (r != idn_success)
1228*00b67f09SDavid van Moolenbroek 		goto ret;
1229*00b67f09SDavid van Moolenbroek 
1230*00b67f09SDavid van Moolenbroek 	r = labellist_setname(label, to);
1231*00b67f09SDavid van Moolenbroek ret:
1232*00b67f09SDavid van Moolenbroek 	if (r == idn_success) {
1233*00b67f09SDavid van Moolenbroek 		TRACE(("res ucs4toidn(): success (label=\"%s\")\n",
1234*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(labellist_getname(label),
1235*00b67f09SDavid van Moolenbroek 					      50)));
1236*00b67f09SDavid van Moolenbroek 	} else {
1237*00b67f09SDavid van Moolenbroek 		TRACE(("res ucs4toidn(): %s\n", idn_result_tostring(r)));
1238*00b67f09SDavid van Moolenbroek 	}
1239*00b67f09SDavid van Moolenbroek 	if (idn_converter != NULL)
1240*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(idn_converter);
1241*00b67f09SDavid van Moolenbroek 	free(to);
1242*00b67f09SDavid van Moolenbroek 	free(ascii_to);
1243*00b67f09SDavid van Moolenbroek 	return (r);
1244*00b67f09SDavid van Moolenbroek }
1245*00b67f09SDavid van Moolenbroek 
1246*00b67f09SDavid van Moolenbroek static idn_result_t
label_localmap(idn_resconf_t ctx,labellist_t label)1247*00b67f09SDavid van Moolenbroek label_localmap(idn_resconf_t ctx, labellist_t label) {
1248*00b67f09SDavid van Moolenbroek 	const unsigned long *from;
1249*00b67f09SDavid van Moolenbroek 	const unsigned long *tld;
1250*00b67f09SDavid van Moolenbroek 	unsigned long *to = NULL;
1251*00b67f09SDavid van Moolenbroek 	size_t to_length;
1252*00b67f09SDavid van Moolenbroek 	idn_mapselector_t local_mapper;
1253*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1254*00b67f09SDavid van Moolenbroek 
1255*00b67f09SDavid van Moolenbroek 	from = labellist_getname(label);
1256*00b67f09SDavid van Moolenbroek 	tld = labellist_gettldname(label);
1257*00b67f09SDavid van Moolenbroek 	TRACE(("res localmap(label=\"%s\", tld=\"%s\")\n",
1258*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(from, 50),
1259*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(tld, 50)));
1260*00b67f09SDavid van Moolenbroek 
1261*00b67f09SDavid van Moolenbroek 	local_mapper = idn_resconf_getlocalmapselector(ctx);
1262*00b67f09SDavid van Moolenbroek 	if (local_mapper == NULL) {
1263*00b67f09SDavid van Moolenbroek 		r = idn_success;
1264*00b67f09SDavid van Moolenbroek 		goto ret;
1265*00b67f09SDavid van Moolenbroek 	}
1266*00b67f09SDavid van Moolenbroek 
1267*00b67f09SDavid van Moolenbroek 	if (tld == from)
1268*00b67f09SDavid van Moolenbroek 		tld = idn_mapselector_getdefaulttld();
1269*00b67f09SDavid van Moolenbroek 	to_length = idn_ucs4_strlen(from) + 1 + 15;  /* 15 for margin */
1270*00b67f09SDavid van Moolenbroek 
1271*00b67f09SDavid van Moolenbroek 	for (;;) {
1272*00b67f09SDavid van Moolenbroek 		unsigned long *new_buffer;
1273*00b67f09SDavid van Moolenbroek 
1274*00b67f09SDavid van Moolenbroek 		new_buffer = (unsigned long *)
1275*00b67f09SDavid van Moolenbroek 			     realloc(to, sizeof(long) * to_length);
1276*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1277*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1278*00b67f09SDavid van Moolenbroek 			goto ret;
1279*00b67f09SDavid van Moolenbroek 		}
1280*00b67f09SDavid van Moolenbroek 		to = new_buffer;
1281*00b67f09SDavid van Moolenbroek 		r = idn_mapselector_map2(local_mapper, from, tld, to,
1282*00b67f09SDavid van Moolenbroek 					 to_length);
1283*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1284*00b67f09SDavid van Moolenbroek 			break;
1285*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
1286*00b67f09SDavid van Moolenbroek 			goto ret;
1287*00b67f09SDavid van Moolenbroek 		to_length *= 2;
1288*00b67f09SDavid van Moolenbroek 	}
1289*00b67f09SDavid van Moolenbroek 
1290*00b67f09SDavid van Moolenbroek 	r = labellist_setname(label, to);
1291*00b67f09SDavid van Moolenbroek ret:
1292*00b67f09SDavid van Moolenbroek 	if (r == idn_success) {
1293*00b67f09SDavid van Moolenbroek 		TRACE(("res localmap(): success (label=\"%s\")\n",
1294*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(labellist_getname(label),
1295*00b67f09SDavid van Moolenbroek 					      50)));
1296*00b67f09SDavid van Moolenbroek 	} else {
1297*00b67f09SDavid van Moolenbroek 		TRACE(("res localmap(): %s\n", idn_result_tostring(r)));
1298*00b67f09SDavid van Moolenbroek 	}
1299*00b67f09SDavid van Moolenbroek 	if (local_mapper != NULL)
1300*00b67f09SDavid van Moolenbroek 		idn_mapselector_destroy(local_mapper);
1301*00b67f09SDavid van Moolenbroek 	free(to);
1302*00b67f09SDavid van Moolenbroek 	return (r);
1303*00b67f09SDavid van Moolenbroek }
1304*00b67f09SDavid van Moolenbroek 
1305*00b67f09SDavid van Moolenbroek static idn_result_t
label_map(idn_resconf_t ctx,labellist_t label)1306*00b67f09SDavid van Moolenbroek label_map(idn_resconf_t ctx, labellist_t label) {
1307*00b67f09SDavid van Moolenbroek 	const unsigned long *from;
1308*00b67f09SDavid van Moolenbroek 	unsigned long *to = NULL;
1309*00b67f09SDavid van Moolenbroek 	size_t to_length;
1310*00b67f09SDavid van Moolenbroek 	idn_mapper_t mapper;
1311*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1312*00b67f09SDavid van Moolenbroek 
1313*00b67f09SDavid van Moolenbroek 	from = labellist_getname(label);
1314*00b67f09SDavid van Moolenbroek 	TRACE(("res map(label=\"%s\")\n", idn__debug_ucs4xstring(from, 50)));
1315*00b67f09SDavid van Moolenbroek 
1316*00b67f09SDavid van Moolenbroek 	mapper = idn_resconf_getmapper(ctx);
1317*00b67f09SDavid van Moolenbroek 	if (mapper == NULL) {
1318*00b67f09SDavid van Moolenbroek 		r = idn_success;
1319*00b67f09SDavid van Moolenbroek 		goto ret;
1320*00b67f09SDavid van Moolenbroek 	}
1321*00b67f09SDavid van Moolenbroek 	to_length = idn_ucs4_strlen(from) + 1 + 15;  /* 15 for margin */
1322*00b67f09SDavid van Moolenbroek 
1323*00b67f09SDavid van Moolenbroek 	for (;;) {
1324*00b67f09SDavid van Moolenbroek 		unsigned long *new_buffer;
1325*00b67f09SDavid van Moolenbroek 
1326*00b67f09SDavid van Moolenbroek 		new_buffer = (unsigned long *)
1327*00b67f09SDavid van Moolenbroek 			     realloc(to, sizeof(long) * to_length);
1328*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1329*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1330*00b67f09SDavid van Moolenbroek 			goto ret;
1331*00b67f09SDavid van Moolenbroek 		}
1332*00b67f09SDavid van Moolenbroek 		to = new_buffer;
1333*00b67f09SDavid van Moolenbroek 		r = idn_mapper_map(mapper, from, to, to_length);
1334*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1335*00b67f09SDavid van Moolenbroek 			break;
1336*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
1337*00b67f09SDavid van Moolenbroek 			goto ret;
1338*00b67f09SDavid van Moolenbroek 		to_length *= 2;
1339*00b67f09SDavid van Moolenbroek 	}
1340*00b67f09SDavid van Moolenbroek 
1341*00b67f09SDavid van Moolenbroek 	r = labellist_setname(label, to);
1342*00b67f09SDavid van Moolenbroek ret:
1343*00b67f09SDavid van Moolenbroek 	if (r == idn_success) {
1344*00b67f09SDavid van Moolenbroek 		TRACE(("res map(): success (label=\"%s\")\n",
1345*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(labellist_getname(label),
1346*00b67f09SDavid van Moolenbroek 					      50)));
1347*00b67f09SDavid van Moolenbroek 	} else {
1348*00b67f09SDavid van Moolenbroek 		TRACE(("res map(): %s\n", idn_result_tostring(r)));
1349*00b67f09SDavid van Moolenbroek 	}
1350*00b67f09SDavid van Moolenbroek 	if (mapper != NULL)
1351*00b67f09SDavid van Moolenbroek 		idn_mapper_destroy(mapper);
1352*00b67f09SDavid van Moolenbroek 	free(to);
1353*00b67f09SDavid van Moolenbroek 	return (r);
1354*00b67f09SDavid van Moolenbroek }
1355*00b67f09SDavid van Moolenbroek 
1356*00b67f09SDavid van Moolenbroek static idn_result_t
label_normalize(idn_resconf_t ctx,labellist_t label)1357*00b67f09SDavid van Moolenbroek label_normalize(idn_resconf_t ctx, labellist_t label) {
1358*00b67f09SDavid van Moolenbroek 	const unsigned long *from;
1359*00b67f09SDavid van Moolenbroek 	unsigned long *to = NULL;
1360*00b67f09SDavid van Moolenbroek 	size_t to_length;
1361*00b67f09SDavid van Moolenbroek 	idn_normalizer_t normalizer;
1362*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1363*00b67f09SDavid van Moolenbroek 
1364*00b67f09SDavid van Moolenbroek 	from = labellist_getname(label);
1365*00b67f09SDavid van Moolenbroek 	TRACE(("res normalzie(label=\"%s\")\n",
1366*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(from, 50)));
1367*00b67f09SDavid van Moolenbroek 
1368*00b67f09SDavid van Moolenbroek 	normalizer = idn_resconf_getnormalizer(ctx);
1369*00b67f09SDavid van Moolenbroek 	if (normalizer == NULL) {
1370*00b67f09SDavid van Moolenbroek 		r = idn_success;
1371*00b67f09SDavid van Moolenbroek 		goto ret;
1372*00b67f09SDavid van Moolenbroek 	}
1373*00b67f09SDavid van Moolenbroek 	to_length = idn_ucs4_strlen(from) + 1 + 15;  /* 15 for margin */
1374*00b67f09SDavid van Moolenbroek 
1375*00b67f09SDavid van Moolenbroek 	for (;;) {
1376*00b67f09SDavid van Moolenbroek 		unsigned long *new_buffer;
1377*00b67f09SDavid van Moolenbroek 
1378*00b67f09SDavid van Moolenbroek 		new_buffer = (unsigned long *)
1379*00b67f09SDavid van Moolenbroek 			     realloc(to, sizeof(long) * to_length);
1380*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1381*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1382*00b67f09SDavid van Moolenbroek 			goto ret;
1383*00b67f09SDavid van Moolenbroek 		}
1384*00b67f09SDavid van Moolenbroek 		to = new_buffer;
1385*00b67f09SDavid van Moolenbroek 		r = idn_normalizer_normalize(normalizer, from, to, to_length);
1386*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1387*00b67f09SDavid van Moolenbroek 			break;
1388*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
1389*00b67f09SDavid van Moolenbroek 			goto ret;
1390*00b67f09SDavid van Moolenbroek 		to_length *= 2;
1391*00b67f09SDavid van Moolenbroek 	}
1392*00b67f09SDavid van Moolenbroek 
1393*00b67f09SDavid van Moolenbroek 	r = labellist_setname(label, to);
1394*00b67f09SDavid van Moolenbroek ret:
1395*00b67f09SDavid van Moolenbroek 	if (r == idn_success) {
1396*00b67f09SDavid van Moolenbroek 		TRACE(("res normalize(): success (label=\"%s\")\n",
1397*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(labellist_getname(label),
1398*00b67f09SDavid van Moolenbroek 					      50)));
1399*00b67f09SDavid van Moolenbroek 	} else {
1400*00b67f09SDavid van Moolenbroek 		TRACE(("res normalize(): %s\n", idn_result_tostring(r)));
1401*00b67f09SDavid van Moolenbroek 	}
1402*00b67f09SDavid van Moolenbroek 	if (normalizer != NULL)
1403*00b67f09SDavid van Moolenbroek 		idn_normalizer_destroy(normalizer);
1404*00b67f09SDavid van Moolenbroek 	free(to);
1405*00b67f09SDavid van Moolenbroek 	return (r);
1406*00b67f09SDavid van Moolenbroek }
1407*00b67f09SDavid van Moolenbroek 
1408*00b67f09SDavid van Moolenbroek static idn_result_t
label_prohcheck(idn_resconf_t ctx,labellist_t label)1409*00b67f09SDavid van Moolenbroek label_prohcheck(idn_resconf_t ctx, labellist_t label) {
1410*00b67f09SDavid van Moolenbroek 	const unsigned long *name, *found;
1411*00b67f09SDavid van Moolenbroek 	idn_checker_t prohibit_checker;
1412*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1413*00b67f09SDavid van Moolenbroek 
1414*00b67f09SDavid van Moolenbroek 	name = labellist_getname(label);
1415*00b67f09SDavid van Moolenbroek 	TRACE(("res prohcheck(label=\"%s\")\n",
1416*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(name, 50)));
1417*00b67f09SDavid van Moolenbroek 
1418*00b67f09SDavid van Moolenbroek 	prohibit_checker = idn_resconf_getprohibitchecker(ctx);
1419*00b67f09SDavid van Moolenbroek 	if (prohibit_checker == NULL) {
1420*00b67f09SDavid van Moolenbroek 		r = idn_success;
1421*00b67f09SDavid van Moolenbroek 		goto ret;
1422*00b67f09SDavid van Moolenbroek 	}
1423*00b67f09SDavid van Moolenbroek 
1424*00b67f09SDavid van Moolenbroek 	r = idn_checker_lookup(prohibit_checker, name, &found);
1425*00b67f09SDavid van Moolenbroek 	idn_checker_destroy(prohibit_checker);
1426*00b67f09SDavid van Moolenbroek 	if (r == idn_success && found != NULL)
1427*00b67f09SDavid van Moolenbroek 		r = idn_prohibited;
1428*00b67f09SDavid van Moolenbroek 
1429*00b67f09SDavid van Moolenbroek ret:
1430*00b67f09SDavid van Moolenbroek 	TRACE(("res prohcheck(): %s\n", idn_result_tostring(r)));
1431*00b67f09SDavid van Moolenbroek 	return (r);
1432*00b67f09SDavid van Moolenbroek }
1433*00b67f09SDavid van Moolenbroek 
1434*00b67f09SDavid van Moolenbroek static idn_result_t
label_unascheck(idn_resconf_t ctx,labellist_t label)1435*00b67f09SDavid van Moolenbroek label_unascheck(idn_resconf_t ctx, labellist_t label) {
1436*00b67f09SDavid van Moolenbroek 	const unsigned long *name, *found;
1437*00b67f09SDavid van Moolenbroek 	idn_checker_t unassigned_checker;
1438*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1439*00b67f09SDavid van Moolenbroek 
1440*00b67f09SDavid van Moolenbroek 	name = labellist_getname(label);
1441*00b67f09SDavid van Moolenbroek 	TRACE(("res unascheck(label=\"%s\")\n",
1442*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(name, 50)));
1443*00b67f09SDavid van Moolenbroek 
1444*00b67f09SDavid van Moolenbroek 	unassigned_checker = idn_resconf_getunassignedchecker(ctx);
1445*00b67f09SDavid van Moolenbroek 	if (unassigned_checker == NULL) {
1446*00b67f09SDavid van Moolenbroek 		r = idn_success;
1447*00b67f09SDavid van Moolenbroek 		goto ret;
1448*00b67f09SDavid van Moolenbroek 	}
1449*00b67f09SDavid van Moolenbroek 
1450*00b67f09SDavid van Moolenbroek 	r = idn_checker_lookup(unassigned_checker, name, &found);
1451*00b67f09SDavid van Moolenbroek 	idn_checker_destroy(unassigned_checker);
1452*00b67f09SDavid van Moolenbroek 	if (r == idn_success && found != NULL)
1453*00b67f09SDavid van Moolenbroek 		r = idn_prohibited;
1454*00b67f09SDavid van Moolenbroek 
1455*00b67f09SDavid van Moolenbroek ret:
1456*00b67f09SDavid van Moolenbroek 	TRACE(("res unascheck(): %s\n", idn_result_tostring(r)));
1457*00b67f09SDavid van Moolenbroek 	return (r);
1458*00b67f09SDavid van Moolenbroek }
1459*00b67f09SDavid van Moolenbroek 
1460*00b67f09SDavid van Moolenbroek static idn_result_t
label_bidicheck(idn_resconf_t ctx,labellist_t label)1461*00b67f09SDavid van Moolenbroek label_bidicheck(idn_resconf_t ctx, labellist_t label) {
1462*00b67f09SDavid van Moolenbroek 	const unsigned long *name, *found;
1463*00b67f09SDavid van Moolenbroek 	idn_checker_t bidi_checker;
1464*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1465*00b67f09SDavid van Moolenbroek 
1466*00b67f09SDavid van Moolenbroek 	name = labellist_getname(label);
1467*00b67f09SDavid van Moolenbroek 	TRACE(("res bidicheck(label=\"%s\")\n",
1468*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(name, 50)));
1469*00b67f09SDavid van Moolenbroek 
1470*00b67f09SDavid van Moolenbroek 	bidi_checker = idn_resconf_getbidichecker(ctx);
1471*00b67f09SDavid van Moolenbroek 	if (bidi_checker == NULL) {
1472*00b67f09SDavid van Moolenbroek 		r = idn_success;
1473*00b67f09SDavid van Moolenbroek 		goto ret;
1474*00b67f09SDavid van Moolenbroek 	}
1475*00b67f09SDavid van Moolenbroek 
1476*00b67f09SDavid van Moolenbroek 	r = idn_checker_lookup(bidi_checker, name, &found);
1477*00b67f09SDavid van Moolenbroek 	idn_checker_destroy(bidi_checker);
1478*00b67f09SDavid van Moolenbroek 	if (r == idn_success && found != NULL)
1479*00b67f09SDavid van Moolenbroek 		r = idn_prohibited;
1480*00b67f09SDavid van Moolenbroek 
1481*00b67f09SDavid van Moolenbroek ret:
1482*00b67f09SDavid van Moolenbroek 	TRACE(("res bidicheck(): %s\n", idn_result_tostring(r)));
1483*00b67f09SDavid van Moolenbroek 	return (r);
1484*00b67f09SDavid van Moolenbroek }
1485*00b67f09SDavid van Moolenbroek 
1486*00b67f09SDavid van Moolenbroek static idn_result_t
label_asccheck(idn_resconf_t ctx,labellist_t label)1487*00b67f09SDavid van Moolenbroek label_asccheck(idn_resconf_t ctx, labellist_t label) {
1488*00b67f09SDavid van Moolenbroek 	const unsigned long *name, *n;
1489*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1490*00b67f09SDavid van Moolenbroek 
1491*00b67f09SDavid van Moolenbroek 	name = labellist_getname(label);
1492*00b67f09SDavid van Moolenbroek 	TRACE(("res asccheck(label=\"%s\")\n",
1493*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(name, 50)));
1494*00b67f09SDavid van Moolenbroek 
1495*00b67f09SDavid van Moolenbroek 	if (*name == '-') {
1496*00b67f09SDavid van Moolenbroek 		r = idn_prohibited;
1497*00b67f09SDavid van Moolenbroek 		goto ret;
1498*00b67f09SDavid van Moolenbroek 	}
1499*00b67f09SDavid van Moolenbroek 
1500*00b67f09SDavid van Moolenbroek 	for (n = name; *n != '\0'; n++) {
1501*00b67f09SDavid van Moolenbroek 		if (*n <= '\177') {
1502*00b67f09SDavid van Moolenbroek 			if ((*n < '0' || *n > '9') &&
1503*00b67f09SDavid van Moolenbroek 			    (*n < 'A' || *n > 'Z') &&
1504*00b67f09SDavid van Moolenbroek 			    (*n < 'a' || *n > 'z') &&
1505*00b67f09SDavid van Moolenbroek 			    *n != '-') {
1506*00b67f09SDavid van Moolenbroek 				r  = idn_prohibited;
1507*00b67f09SDavid van Moolenbroek 				goto ret;
1508*00b67f09SDavid van Moolenbroek 			}
1509*00b67f09SDavid van Moolenbroek 		}
1510*00b67f09SDavid van Moolenbroek 	}
1511*00b67f09SDavid van Moolenbroek 
1512*00b67f09SDavid van Moolenbroek 	if (n > name && *(n - 1) == '-') {
1513*00b67f09SDavid van Moolenbroek 		r  = idn_prohibited;
1514*00b67f09SDavid van Moolenbroek 		goto ret;
1515*00b67f09SDavid van Moolenbroek 	}
1516*00b67f09SDavid van Moolenbroek 
1517*00b67f09SDavid van Moolenbroek 	r = idn_success;
1518*00b67f09SDavid van Moolenbroek ret:
1519*00b67f09SDavid van Moolenbroek 	TRACE(("res asccheck(): %s\n", idn_result_tostring(r)));
1520*00b67f09SDavid van Moolenbroek 	return (r);
1521*00b67f09SDavid van Moolenbroek }
1522*00b67f09SDavid van Moolenbroek 
1523*00b67f09SDavid van Moolenbroek static idn_result_t
label_lencheck_ace(idn_resconf_t ctx,labellist_t label)1524*00b67f09SDavid van Moolenbroek label_lencheck_ace(idn_resconf_t ctx, labellist_t label) {
1525*00b67f09SDavid van Moolenbroek 	const unsigned long *name;
1526*00b67f09SDavid van Moolenbroek 	size_t name_length;
1527*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1528*00b67f09SDavid van Moolenbroek 
1529*00b67f09SDavid van Moolenbroek 	name = labellist_getname(label);
1530*00b67f09SDavid van Moolenbroek 	name_length = idn_ucs4_strlen(name);
1531*00b67f09SDavid van Moolenbroek 	TRACE(("res lencheck(label=\"%s\")\n",
1532*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(name, 50)));
1533*00b67f09SDavid van Moolenbroek 
1534*00b67f09SDavid van Moolenbroek 	if (name_length == 0 || name_length > MAX_LABEL_LENGTH) {
1535*00b67f09SDavid van Moolenbroek 		r = idn_invalid_length;
1536*00b67f09SDavid van Moolenbroek 		goto ret;
1537*00b67f09SDavid van Moolenbroek 	}
1538*00b67f09SDavid van Moolenbroek 
1539*00b67f09SDavid van Moolenbroek 	r = idn_success;
1540*00b67f09SDavid van Moolenbroek ret:
1541*00b67f09SDavid van Moolenbroek 	TRACE(("res lencheck(): %s\n", idn_result_tostring(r)));
1542*00b67f09SDavid van Moolenbroek 	return (r);
1543*00b67f09SDavid van Moolenbroek }
1544*00b67f09SDavid van Moolenbroek 
1545*00b67f09SDavid van Moolenbroek static idn_result_t
label_lencheck_nonace(idn_resconf_t ctx,labellist_t label)1546*00b67f09SDavid van Moolenbroek label_lencheck_nonace(idn_resconf_t ctx, labellist_t label) {
1547*00b67f09SDavid van Moolenbroek 	idn_converter_t idn_converter;
1548*00b67f09SDavid van Moolenbroek 	const unsigned long *from;
1549*00b67f09SDavid van Moolenbroek 	size_t to_length;
1550*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1551*00b67f09SDavid van Moolenbroek 	char *buffer = NULL;
1552*00b67f09SDavid van Moolenbroek 	size_t buffer_length;
1553*00b67f09SDavid van Moolenbroek 
1554*00b67f09SDavid van Moolenbroek 	from = labellist_getname(label);
1555*00b67f09SDavid van Moolenbroek 	TRACE(("res lencheck(label=\"%s\")\n",
1556*00b67f09SDavid van Moolenbroek 	       idn__debug_ucs4xstring(from, 50)));
1557*00b67f09SDavid van Moolenbroek 
1558*00b67f09SDavid van Moolenbroek 	buffer_length = idn_ucs4_strlen(from) * 4 + 16; /* 16 for margin */
1559*00b67f09SDavid van Moolenbroek 	idn_converter = idn_resconf_getidnconverter(ctx);
1560*00b67f09SDavid van Moolenbroek 
1561*00b67f09SDavid van Moolenbroek 	for (;;) {
1562*00b67f09SDavid van Moolenbroek 		void *new_buffer;
1563*00b67f09SDavid van Moolenbroek 
1564*00b67f09SDavid van Moolenbroek 		new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
1565*00b67f09SDavid van Moolenbroek 		if (new_buffer == NULL) {
1566*00b67f09SDavid van Moolenbroek 			r = idn_nomemory;
1567*00b67f09SDavid van Moolenbroek 			goto ret;
1568*00b67f09SDavid van Moolenbroek 		}
1569*00b67f09SDavid van Moolenbroek 		buffer = (char *)new_buffer;
1570*00b67f09SDavid van Moolenbroek 
1571*00b67f09SDavid van Moolenbroek 		if (idn_converter != NULL) {
1572*00b67f09SDavid van Moolenbroek 			r = idn_converter_convfromucs4(idn_converter, from,
1573*00b67f09SDavid van Moolenbroek 						       buffer, buffer_length);
1574*00b67f09SDavid van Moolenbroek 		} else {
1575*00b67f09SDavid van Moolenbroek 			r = idn_ucs4_ucs4toutf8(from, buffer, buffer_length);
1576*00b67f09SDavid van Moolenbroek 		}
1577*00b67f09SDavid van Moolenbroek 		if (r == idn_success)
1578*00b67f09SDavid van Moolenbroek 			break;
1579*00b67f09SDavid van Moolenbroek 		else if (r != idn_buffer_overflow)
1580*00b67f09SDavid van Moolenbroek 			goto ret;
1581*00b67f09SDavid van Moolenbroek 
1582*00b67f09SDavid van Moolenbroek 		buffer_length *= 2;
1583*00b67f09SDavid van Moolenbroek 	}
1584*00b67f09SDavid van Moolenbroek 
1585*00b67f09SDavid van Moolenbroek 	to_length = strlen(buffer);
1586*00b67f09SDavid van Moolenbroek 	if (to_length == 0 || to_length > MAX_LABEL_LENGTH) {
1587*00b67f09SDavid van Moolenbroek 		r = idn_invalid_length;
1588*00b67f09SDavid van Moolenbroek 		goto ret;
1589*00b67f09SDavid van Moolenbroek 	}
1590*00b67f09SDavid van Moolenbroek 
1591*00b67f09SDavid van Moolenbroek 	r = idn_success;
1592*00b67f09SDavid van Moolenbroek ret:
1593*00b67f09SDavid van Moolenbroek 	TRACE(("res lencheck(): %s\n", idn_result_tostring(r)));
1594*00b67f09SDavid van Moolenbroek 	if (idn_converter != NULL)
1595*00b67f09SDavid van Moolenbroek 		idn_converter_destroy(idn_converter);
1596*00b67f09SDavid van Moolenbroek 	free(buffer);
1597*00b67f09SDavid van Moolenbroek 	return (r);
1598*00b67f09SDavid van Moolenbroek }
1599*00b67f09SDavid van Moolenbroek 
1600*00b67f09SDavid van Moolenbroek static idn_result_t
label_rtcheck(idn_resconf_t ctx,idn_action_t actions,labellist_t label,const unsigned long * original_name)1601*00b67f09SDavid van Moolenbroek label_rtcheck(idn_resconf_t ctx, idn_action_t actions, labellist_t label,
1602*00b67f09SDavid van Moolenbroek 	    const unsigned long *original_name) {
1603*00b67f09SDavid van Moolenbroek 	labellist_t rt_label = NULL;
1604*00b67f09SDavid van Moolenbroek 	const unsigned long *rt_name;
1605*00b67f09SDavid van Moolenbroek 	const unsigned long *cur_name;
1606*00b67f09SDavid van Moolenbroek 	idn_result_t r;
1607*00b67f09SDavid van Moolenbroek 
1608*00b67f09SDavid van Moolenbroek 	cur_name = labellist_getname(label);
1609*00b67f09SDavid van Moolenbroek 	TRACE(("res rtcheck(label=\"%s\", org_label=\"%s\")\n",
1610*00b67f09SDavid van Moolenbroek 		idn__debug_ucs4xstring(cur_name, 50),
1611*00b67f09SDavid van Moolenbroek 		idn__debug_ucs4xstring(original_name, 50)));
1612*00b67f09SDavid van Moolenbroek 
1613*00b67f09SDavid van Moolenbroek 	r = labellist_create(cur_name, &rt_label);
1614*00b67f09SDavid van Moolenbroek 	if (r != idn_success)
1615*00b67f09SDavid van Moolenbroek 		goto ret;
1616*00b67f09SDavid van Moolenbroek 	if (rt_label == NULL) {
1617*00b67f09SDavid van Moolenbroek 		if (*original_name == '\0')
1618*00b67f09SDavid van Moolenbroek 			r = idn_success;
1619*00b67f09SDavid van Moolenbroek 		else
1620*00b67f09SDavid van Moolenbroek 			r = idn_invalid_encoding;
1621*00b67f09SDavid van Moolenbroek 		goto ret;
1622*00b67f09SDavid van Moolenbroek 	}
1623*00b67f09SDavid van Moolenbroek 
1624*00b67f09SDavid van Moolenbroek 	if (!idn__util_ucs4isasciirange(labellist_getname(rt_label))) {
1625*00b67f09SDavid van Moolenbroek 		r = label_map(ctx, rt_label);
1626*00b67f09SDavid van Moolenbroek 		if (r != idn_success)
1627*00b67f09SDavid van Moolenbroek 			goto ret;
1628*00b67f09SDavid van Moolenbroek 		r = label_normalize(ctx, rt_label);
1629*00b67f09SDavid van Moolenbroek 		if (r != idn_success)
1630*00b67f09SDavid van Moolenbroek 			goto ret;
1631*00b67f09SDavid van Moolenbroek 		r = label_prohcheck(ctx, rt_label);
1632*00b67f09SDavid van Moolenbroek 		if (r != idn_success)
1633*00b67f09SDavid van Moolenbroek 			goto ret;
1634*00b67f09SDavid van Moolenbroek 		if (actions & IDN_UNASCHECK) {
1635*00b67f09SDavid van Moolenbroek 			r = label_unascheck(ctx, rt_label);
1636*00b67f09SDavid van Moolenbroek 			if (r != idn_success)
1637*00b67f09SDavid van Moolenbroek 				goto ret;
1638*00b67f09SDavid van Moolenbroek 		}
1639*00b67f09SDavid van Moolenbroek 		r = label_bidicheck(ctx, rt_label);
1640*00b67f09SDavid van Moolenbroek 		if (r != idn_success)
1641*00b67f09SDavid van Moolenbroek 			goto ret;
1642*00b67f09SDavid van Moolenbroek 	}
1643*00b67f09SDavid van Moolenbroek 
1644*00b67f09SDavid van Moolenbroek 	if (actions & IDN_ASCCHECK) {
1645*00b67f09SDavid van Moolenbroek 		r = label_asccheck(ctx, rt_label);
1646*00b67f09SDavid van Moolenbroek 		if (r != idn_success)
1647*00b67f09SDavid van Moolenbroek 			goto ret;
1648*00b67f09SDavid van Moolenbroek 	}
1649*00b67f09SDavid van Moolenbroek 	if (!idn__util_ucs4isasciirange(labellist_getname(rt_label))) {
1650*00b67f09SDavid van Moolenbroek 		r = label_idnencode_ace(ctx, rt_label);
1651*00b67f09SDavid van Moolenbroek 		if (r != idn_success)
1652*00b67f09SDavid van Moolenbroek 			goto ret;
1653*00b67f09SDavid van Moolenbroek 	}
1654*00b67f09SDavid van Moolenbroek 	r = label_lencheck_ace(ctx, rt_label);
1655*00b67f09SDavid van Moolenbroek 	if (r != idn_success)
1656*00b67f09SDavid van Moolenbroek 		goto ret;
1657*00b67f09SDavid van Moolenbroek 	rt_name = labellist_getname(rt_label);
1658*00b67f09SDavid van Moolenbroek 
1659*00b67f09SDavid van Moolenbroek 	if (idn_ucs4_strcasecmp(rt_name, original_name) != 0) {
1660*00b67f09SDavid van Moolenbroek 		TRACE(("res rtcheck(): round trip failed, org =\"%s\", rt=\"%s\"\n",
1661*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(original_name, 50),
1662*00b67f09SDavid van Moolenbroek 		       idn__debug_ucs4xstring(rt_name, 50)));
1663*00b67f09SDavid van Moolenbroek 		r = idn_invalid_encoding;
1664*00b67f09SDavid van Moolenbroek 		goto ret;
1665*00b67f09SDavid van Moolenbroek 	}
1666*00b67f09SDavid van Moolenbroek 
1667*00b67f09SDavid van Moolenbroek 	r  = idn_success;
1668*00b67f09SDavid van Moolenbroek ret:
1669*00b67f09SDavid van Moolenbroek 	if (r != idn_nomemory && r != idn_success)
1670*00b67f09SDavid van Moolenbroek 		r = idn_invalid_encoding;
1671*00b67f09SDavid van Moolenbroek 	TRACE(("res rtcheck(): %s\n", idn_result_tostring(r)));
1672*00b67f09SDavid van Moolenbroek 	if (rt_label != NULL)
1673*00b67f09SDavid van Moolenbroek 		labellist_destroy(rt_label);
1674*00b67f09SDavid van Moolenbroek 	return (r);
1675*00b67f09SDavid van Moolenbroek }
1676*00b67f09SDavid van Moolenbroek 
1677*00b67f09SDavid van Moolenbroek const char *
idn__res_actionstostring(idn_action_t actions)1678*00b67f09SDavid van Moolenbroek idn__res_actionstostring(idn_action_t actions) {
1679*00b67f09SDavid van Moolenbroek 	static char buf[100];
1680*00b67f09SDavid van Moolenbroek 
1681*00b67f09SDavid van Moolenbroek 	buf[0] = '\0';
1682*00b67f09SDavid van Moolenbroek 
1683*00b67f09SDavid van Moolenbroek 	if (actions == IDN_ENCODE_QUERY)
1684*00b67f09SDavid van Moolenbroek 		strcpy(buf, "encode-query");
1685*00b67f09SDavid van Moolenbroek 	else if (actions == IDN_DECODE_QUERY)
1686*00b67f09SDavid van Moolenbroek 		strcpy(buf, "decode-query");
1687*00b67f09SDavid van Moolenbroek 	else if (actions == IDN_ENCODE_APP)
1688*00b67f09SDavid van Moolenbroek 		strcpy(buf, "encode-app");
1689*00b67f09SDavid van Moolenbroek 	else if (actions == IDN_DECODE_APP)
1690*00b67f09SDavid van Moolenbroek 		strcpy(buf, "decode-app");
1691*00b67f09SDavid van Moolenbroek 	else if (actions == IDN_ENCODE_STORED)
1692*00b67f09SDavid van Moolenbroek 		strcpy(buf, "encode-stored");
1693*00b67f09SDavid van Moolenbroek 	else if (actions == IDN_DECODE_STORED)
1694*00b67f09SDavid van Moolenbroek 		strcpy(buf, "decode-stored");
1695*00b67f09SDavid van Moolenbroek 	else {
1696*00b67f09SDavid van Moolenbroek 		if (actions & IDN_LOCALCONV)
1697*00b67f09SDavid van Moolenbroek 			strcat(buf, "|localconv");
1698*00b67f09SDavid van Moolenbroek 		if (actions & IDN_DELIMMAP)
1699*00b67f09SDavid van Moolenbroek 			strcat(buf, "|delimmap");
1700*00b67f09SDavid van Moolenbroek 		if (actions & IDN_LOCALMAP)
1701*00b67f09SDavid van Moolenbroek 			strcat(buf, "|localmap");
1702*00b67f09SDavid van Moolenbroek 
1703*00b67f09SDavid van Moolenbroek 		if (actions & IDN_MAP)
1704*00b67f09SDavid van Moolenbroek 			strcat(buf, "|map");
1705*00b67f09SDavid van Moolenbroek 		if (actions & IDN_NORMALIZE)
1706*00b67f09SDavid van Moolenbroek 			strcat(buf, "|normalize");
1707*00b67f09SDavid van Moolenbroek 		if (actions & IDN_PROHCHECK)
1708*00b67f09SDavid van Moolenbroek 			strcat(buf, "|prohcheck");
1709*00b67f09SDavid van Moolenbroek 		if (actions & IDN_UNASCHECK)
1710*00b67f09SDavid van Moolenbroek 			strcat(buf, "|unascheck");
1711*00b67f09SDavid van Moolenbroek 		if (actions & IDN_BIDICHECK)
1712*00b67f09SDavid van Moolenbroek 			strcat(buf, "|bidicheck");
1713*00b67f09SDavid van Moolenbroek 
1714*00b67f09SDavid van Moolenbroek 		if (actions & IDN_IDNCONV)
1715*00b67f09SDavid van Moolenbroek 			strcat(buf, "|idnconv");
1716*00b67f09SDavid van Moolenbroek 		if (actions & IDN_ASCCHECK)
1717*00b67f09SDavid van Moolenbroek 			strcat(buf, "|asccheck");
1718*00b67f09SDavid van Moolenbroek 		if (actions & IDN_LENCHECK)
1719*00b67f09SDavid van Moolenbroek 			strcat(buf, "|lencheck");
1720*00b67f09SDavid van Moolenbroek 		if (actions & IDN_RTCHECK)
1721*00b67f09SDavid van Moolenbroek 			strcat(buf, "|rtcheck");
1722*00b67f09SDavid van Moolenbroek 	}
1723*00b67f09SDavid van Moolenbroek 
1724*00b67f09SDavid van Moolenbroek 	if (buf[0] == '|')
1725*00b67f09SDavid van Moolenbroek 		return (buf + 1);
1726*00b67f09SDavid van Moolenbroek 	else
1727*00b67f09SDavid van Moolenbroek 		return (buf);
1728*00b67f09SDavid van Moolenbroek }
1729