1*00b67f09SDavid van Moolenbroek /* $NetBSD: normalizer.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: normalizer.c,v 1.1 2003/06/04 00:26:05 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 #include <ctype.h>
56*00b67f09SDavid van Moolenbroek
57*00b67f09SDavid van Moolenbroek #include <idn/assert.h>
58*00b67f09SDavid van Moolenbroek #include <idn/logmacro.h>
59*00b67f09SDavid van Moolenbroek #include <idn/result.h>
60*00b67f09SDavid van Moolenbroek #include <idn/normalizer.h>
61*00b67f09SDavid van Moolenbroek #include <idn/strhash.h>
62*00b67f09SDavid van Moolenbroek #include <idn/unormalize.h>
63*00b67f09SDavid van Moolenbroek #include <idn/unicode.h>
64*00b67f09SDavid van Moolenbroek #include <idn/ucs4.h>
65*00b67f09SDavid van Moolenbroek #include <idn/debug.h>
66*00b67f09SDavid van Moolenbroek #include <idn/util.h>
67*00b67f09SDavid van Moolenbroek
68*00b67f09SDavid van Moolenbroek #define MAX_LOCAL_SCHEME 3
69*00b67f09SDavid van Moolenbroek
70*00b67f09SDavid van Moolenbroek #define INITIALIZED (scheme_hash != NULL)
71*00b67f09SDavid van Moolenbroek
72*00b67f09SDavid van Moolenbroek typedef struct {
73*00b67f09SDavid van Moolenbroek char *name;
74*00b67f09SDavid van Moolenbroek idn_normalizer_proc_t proc;
75*00b67f09SDavid van Moolenbroek } normalize_scheme_t;
76*00b67f09SDavid van Moolenbroek
77*00b67f09SDavid van Moolenbroek struct idn_normalizer {
78*00b67f09SDavid van Moolenbroek int nschemes;
79*00b67f09SDavid van Moolenbroek int scheme_size;
80*00b67f09SDavid van Moolenbroek normalize_scheme_t **schemes;
81*00b67f09SDavid van Moolenbroek normalize_scheme_t *local_buf[MAX_LOCAL_SCHEME];
82*00b67f09SDavid van Moolenbroek int reference_count;
83*00b67f09SDavid van Moolenbroek };
84*00b67f09SDavid van Moolenbroek
85*00b67f09SDavid van Moolenbroek static idn__strhash_t scheme_hash;
86*00b67f09SDavid van Moolenbroek
87*00b67f09SDavid van Moolenbroek static idn__unicode_version_t vcur = NULL;
88*00b67f09SDavid van Moolenbroek static idn__unicode_version_t v320 = NULL;
89*00b67f09SDavid van Moolenbroek #define INIT_VERSION(version, var) \
90*00b67f09SDavid van Moolenbroek if (var == NULL) { \
91*00b67f09SDavid van Moolenbroek idn_result_t r = idn__unicode_create(version, &var); \
92*00b67f09SDavid van Moolenbroek if (r != idn_success) \
93*00b67f09SDavid van Moolenbroek return (r); \
94*00b67f09SDavid van Moolenbroek }
95*00b67f09SDavid van Moolenbroek
96*00b67f09SDavid van Moolenbroek static idn_result_t expand_schemes(idn_normalizer_t ctx);
97*00b67f09SDavid van Moolenbroek static idn_result_t register_standard_normalizers(void);
98*00b67f09SDavid van Moolenbroek static idn_result_t normalizer_formkc(const unsigned long *from,
99*00b67f09SDavid van Moolenbroek unsigned long *to, size_t tolen);
100*00b67f09SDavid van Moolenbroek static idn_result_t normalizer_formkc_v320(const unsigned long *from,
101*00b67f09SDavid van Moolenbroek unsigned long *to,
102*00b67f09SDavid van Moolenbroek size_t tolen);
103*00b67f09SDavid van Moolenbroek
104*00b67f09SDavid van Moolenbroek static struct standard_normalizer {
105*00b67f09SDavid van Moolenbroek char *name;
106*00b67f09SDavid van Moolenbroek idn_normalizer_proc_t proc;
107*00b67f09SDavid van Moolenbroek } standard_normalizer[] = {
108*00b67f09SDavid van Moolenbroek { "unicode-form-kc", normalizer_formkc },
109*00b67f09SDavid van Moolenbroek { "unicode-form-kc/3.2.0", normalizer_formkc_v320 },
110*00b67f09SDavid van Moolenbroek { "RFC3491", normalizer_formkc_v320 },
111*00b67f09SDavid van Moolenbroek { NULL, NULL },
112*00b67f09SDavid van Moolenbroek };
113*00b67f09SDavid van Moolenbroek
114*00b67f09SDavid van Moolenbroek idn_result_t
idn_normalizer_initialize(void)115*00b67f09SDavid van Moolenbroek idn_normalizer_initialize(void) {
116*00b67f09SDavid van Moolenbroek idn__strhash_t hash;
117*00b67f09SDavid van Moolenbroek idn_result_t r;
118*00b67f09SDavid van Moolenbroek
119*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_initialize()\n"));
120*00b67f09SDavid van Moolenbroek
121*00b67f09SDavid van Moolenbroek if (scheme_hash != NULL) {
122*00b67f09SDavid van Moolenbroek r = idn_success; /* already initialized */
123*00b67f09SDavid van Moolenbroek goto ret;
124*00b67f09SDavid van Moolenbroek }
125*00b67f09SDavid van Moolenbroek
126*00b67f09SDavid van Moolenbroek if ((r = idn__strhash_create(&hash)) != idn_success)
127*00b67f09SDavid van Moolenbroek goto ret;
128*00b67f09SDavid van Moolenbroek scheme_hash = hash;
129*00b67f09SDavid van Moolenbroek
130*00b67f09SDavid van Moolenbroek /* Register standard normalizers */
131*00b67f09SDavid van Moolenbroek r = register_standard_normalizers();
132*00b67f09SDavid van Moolenbroek ret:
133*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_initialize(): %s\n", idn_result_tostring(r)));
134*00b67f09SDavid van Moolenbroek return (r);
135*00b67f09SDavid van Moolenbroek }
136*00b67f09SDavid van Moolenbroek
137*00b67f09SDavid van Moolenbroek idn_result_t
idn_normalizer_create(idn_normalizer_t * ctxp)138*00b67f09SDavid van Moolenbroek idn_normalizer_create(idn_normalizer_t *ctxp) {
139*00b67f09SDavid van Moolenbroek idn_normalizer_t ctx;
140*00b67f09SDavid van Moolenbroek idn_result_t r;
141*00b67f09SDavid van Moolenbroek
142*00b67f09SDavid van Moolenbroek assert(ctxp != NULL);
143*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_create()\n"));
144*00b67f09SDavid van Moolenbroek
145*00b67f09SDavid van Moolenbroek if ((ctx = malloc(sizeof(struct idn_normalizer))) == NULL) {
146*00b67f09SDavid van Moolenbroek r = idn_nomemory;
147*00b67f09SDavid van Moolenbroek goto ret;
148*00b67f09SDavid van Moolenbroek }
149*00b67f09SDavid van Moolenbroek
150*00b67f09SDavid van Moolenbroek ctx->nschemes = 0;
151*00b67f09SDavid van Moolenbroek ctx->scheme_size = MAX_LOCAL_SCHEME;
152*00b67f09SDavid van Moolenbroek ctx->schemes = ctx->local_buf;
153*00b67f09SDavid van Moolenbroek ctx->reference_count = 1;
154*00b67f09SDavid van Moolenbroek *ctxp = ctx;
155*00b67f09SDavid van Moolenbroek
156*00b67f09SDavid van Moolenbroek r = idn_success;
157*00b67f09SDavid van Moolenbroek ret:
158*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_create(): %s\n", idn_result_tostring(r)));
159*00b67f09SDavid van Moolenbroek return (r);
160*00b67f09SDavid van Moolenbroek }
161*00b67f09SDavid van Moolenbroek
162*00b67f09SDavid van Moolenbroek void
idn_normalizer_destroy(idn_normalizer_t ctx)163*00b67f09SDavid van Moolenbroek idn_normalizer_destroy(idn_normalizer_t ctx) {
164*00b67f09SDavid van Moolenbroek assert(ctx != NULL);
165*00b67f09SDavid van Moolenbroek
166*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_destroy()\n"));
167*00b67f09SDavid van Moolenbroek
168*00b67f09SDavid van Moolenbroek ctx->reference_count--;
169*00b67f09SDavid van Moolenbroek if (ctx->reference_count <= 0) {
170*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_destroy(): the object is destroyed\n"));
171*00b67f09SDavid van Moolenbroek if (ctx->schemes != ctx->local_buf)
172*00b67f09SDavid van Moolenbroek free(ctx->schemes);
173*00b67f09SDavid van Moolenbroek free(ctx);
174*00b67f09SDavid van Moolenbroek } else {
175*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_destroy(): "
176*00b67f09SDavid van Moolenbroek "update reference count (%d->%d)\n",
177*00b67f09SDavid van Moolenbroek ctx->reference_count + 1, ctx->reference_count));
178*00b67f09SDavid van Moolenbroek }
179*00b67f09SDavid van Moolenbroek }
180*00b67f09SDavid van Moolenbroek
181*00b67f09SDavid van Moolenbroek void
idn_normalizer_incrref(idn_normalizer_t ctx)182*00b67f09SDavid van Moolenbroek idn_normalizer_incrref(idn_normalizer_t ctx) {
183*00b67f09SDavid van Moolenbroek assert(ctx != NULL);
184*00b67f09SDavid van Moolenbroek
185*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_incrref()\n"));
186*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_incrref: update reference count (%d->%d)\n",
187*00b67f09SDavid van Moolenbroek ctx->reference_count, ctx->reference_count + 1));
188*00b67f09SDavid van Moolenbroek
189*00b67f09SDavid van Moolenbroek ctx->reference_count++;
190*00b67f09SDavid van Moolenbroek }
191*00b67f09SDavid van Moolenbroek
192*00b67f09SDavid van Moolenbroek idn_result_t
idn_normalizer_add(idn_normalizer_t ctx,const char * scheme_name)193*00b67f09SDavid van Moolenbroek idn_normalizer_add(idn_normalizer_t ctx, const char *scheme_name) {
194*00b67f09SDavid van Moolenbroek idn_result_t r;
195*00b67f09SDavid van Moolenbroek void *v;
196*00b67f09SDavid van Moolenbroek normalize_scheme_t *scheme;
197*00b67f09SDavid van Moolenbroek
198*00b67f09SDavid van Moolenbroek assert(ctx != NULL && scheme_name != NULL);
199*00b67f09SDavid van Moolenbroek
200*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_add(scheme_name=%s)\n", scheme_name));
201*00b67f09SDavid van Moolenbroek
202*00b67f09SDavid van Moolenbroek assert(INITIALIZED);
203*00b67f09SDavid van Moolenbroek
204*00b67f09SDavid van Moolenbroek if (idn__strhash_get(scheme_hash, scheme_name, &v) != idn_success) {
205*00b67f09SDavid van Moolenbroek ERROR(("idn_normalizer_add(): invalid scheme \"%-.30s\"\n",
206*00b67f09SDavid van Moolenbroek scheme_name));
207*00b67f09SDavid van Moolenbroek r = idn_invalid_name;
208*00b67f09SDavid van Moolenbroek goto ret;
209*00b67f09SDavid van Moolenbroek }
210*00b67f09SDavid van Moolenbroek
211*00b67f09SDavid van Moolenbroek scheme = v;
212*00b67f09SDavid van Moolenbroek
213*00b67f09SDavid van Moolenbroek assert(ctx->nschemes <= ctx->scheme_size);
214*00b67f09SDavid van Moolenbroek
215*00b67f09SDavid van Moolenbroek if (ctx->nschemes == ctx->scheme_size &&
216*00b67f09SDavid van Moolenbroek (r = expand_schemes(ctx)) != idn_success) {
217*00b67f09SDavid van Moolenbroek goto ret;
218*00b67f09SDavid van Moolenbroek }
219*00b67f09SDavid van Moolenbroek
220*00b67f09SDavid van Moolenbroek ctx->schemes[ctx->nschemes++] = scheme;
221*00b67f09SDavid van Moolenbroek r = idn_success;
222*00b67f09SDavid van Moolenbroek ret:
223*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_add(): %s\n", idn_result_tostring(r)));
224*00b67f09SDavid van Moolenbroek return (r);
225*00b67f09SDavid van Moolenbroek }
226*00b67f09SDavid van Moolenbroek
227*00b67f09SDavid van Moolenbroek idn_result_t
idn_normalizer_addall(idn_normalizer_t ctx,const char ** scheme_names,int nschemes)228*00b67f09SDavid van Moolenbroek idn_normalizer_addall(idn_normalizer_t ctx, const char **scheme_names,
229*00b67f09SDavid van Moolenbroek int nschemes) {
230*00b67f09SDavid van Moolenbroek idn_result_t r;
231*00b67f09SDavid van Moolenbroek int i;
232*00b67f09SDavid van Moolenbroek
233*00b67f09SDavid van Moolenbroek assert(ctx != NULL && scheme_names != NULL);
234*00b67f09SDavid van Moolenbroek
235*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_addall(nschemes=%d)\n", nschemes));
236*00b67f09SDavid van Moolenbroek
237*00b67f09SDavid van Moolenbroek for (i = 0; i < nschemes; i++) {
238*00b67f09SDavid van Moolenbroek r = idn_normalizer_add(ctx, (const char *)*scheme_names);
239*00b67f09SDavid van Moolenbroek if (r != idn_success)
240*00b67f09SDavid van Moolenbroek goto ret;
241*00b67f09SDavid van Moolenbroek scheme_names++;
242*00b67f09SDavid van Moolenbroek }
243*00b67f09SDavid van Moolenbroek
244*00b67f09SDavid van Moolenbroek r = idn_success;
245*00b67f09SDavid van Moolenbroek ret:
246*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_addall(): %s\n", idn_result_tostring(r)));
247*00b67f09SDavid van Moolenbroek return (r);
248*00b67f09SDavid van Moolenbroek }
249*00b67f09SDavid van Moolenbroek
250*00b67f09SDavid van Moolenbroek idn_result_t
idn_normalizer_normalize(idn_normalizer_t ctx,const unsigned long * from,unsigned long * to,size_t tolen)251*00b67f09SDavid van Moolenbroek idn_normalizer_normalize(idn_normalizer_t ctx, const unsigned long *from,
252*00b67f09SDavid van Moolenbroek unsigned long *to, size_t tolen) {
253*00b67f09SDavid van Moolenbroek idn_result_t r;
254*00b67f09SDavid van Moolenbroek unsigned long *src, *dst;
255*00b67f09SDavid van Moolenbroek unsigned long *buffers[2] = {NULL, NULL};
256*00b67f09SDavid van Moolenbroek size_t buflen[2] = {0, 0};
257*00b67f09SDavid van Moolenbroek size_t dstlen;
258*00b67f09SDavid van Moolenbroek int idx;
259*00b67f09SDavid van Moolenbroek int i;
260*00b67f09SDavid van Moolenbroek
261*00b67f09SDavid van Moolenbroek assert(scheme_hash != NULL);
262*00b67f09SDavid van Moolenbroek assert(ctx != NULL && from != NULL && to != NULL);
263*00b67f09SDavid van Moolenbroek
264*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_normalize(from=\"%s\", tolen=%d)\n",
265*00b67f09SDavid van Moolenbroek idn__debug_ucs4xstring(from, 50), (int)tolen));
266*00b67f09SDavid van Moolenbroek
267*00b67f09SDavid van Moolenbroek if (ctx->nschemes <= 0) {
268*00b67f09SDavid van Moolenbroek if (tolen < idn_ucs4_strlen(from) + 1) {
269*00b67f09SDavid van Moolenbroek r = idn_buffer_overflow;
270*00b67f09SDavid van Moolenbroek goto ret;
271*00b67f09SDavid van Moolenbroek }
272*00b67f09SDavid van Moolenbroek idn_ucs4_strcpy(to, from);
273*00b67f09SDavid van Moolenbroek r = idn_success;
274*00b67f09SDavid van Moolenbroek goto ret;
275*00b67f09SDavid van Moolenbroek }
276*00b67f09SDavid van Moolenbroek
277*00b67f09SDavid van Moolenbroek /*
278*00b67f09SDavid van Moolenbroek * Normalize.
279*00b67f09SDavid van Moolenbroek */
280*00b67f09SDavid van Moolenbroek src = (void *)from;
281*00b67f09SDavid van Moolenbroek dstlen = idn_ucs4_strlen(from) + 1;
282*00b67f09SDavid van Moolenbroek
283*00b67f09SDavid van Moolenbroek i = 0;
284*00b67f09SDavid van Moolenbroek while (i < ctx->nschemes) {
285*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_normalize(): normalize %s\n",
286*00b67f09SDavid van Moolenbroek ctx->schemes[i]->name));
287*00b67f09SDavid van Moolenbroek
288*00b67f09SDavid van Moolenbroek /*
289*00b67f09SDavid van Moolenbroek * Choose destination area to restore the result of a mapping.
290*00b67f09SDavid van Moolenbroek */
291*00b67f09SDavid van Moolenbroek if (i + 1 == ctx->nschemes) {
292*00b67f09SDavid van Moolenbroek dst = to;
293*00b67f09SDavid van Moolenbroek dstlen = tolen;
294*00b67f09SDavid van Moolenbroek } else {
295*00b67f09SDavid van Moolenbroek if (src == buffers[0])
296*00b67f09SDavid van Moolenbroek idx = 1;
297*00b67f09SDavid van Moolenbroek else
298*00b67f09SDavid van Moolenbroek idx = 0;
299*00b67f09SDavid van Moolenbroek
300*00b67f09SDavid van Moolenbroek if (buflen[idx] < dstlen) {
301*00b67f09SDavid van Moolenbroek void *newbuf;
302*00b67f09SDavid van Moolenbroek
303*00b67f09SDavid van Moolenbroek newbuf = realloc(buffers[idx],
304*00b67f09SDavid van Moolenbroek sizeof(long) * dstlen);
305*00b67f09SDavid van Moolenbroek if (newbuf == NULL) {
306*00b67f09SDavid van Moolenbroek r = idn_nomemory;
307*00b67f09SDavid van Moolenbroek goto ret;
308*00b67f09SDavid van Moolenbroek }
309*00b67f09SDavid van Moolenbroek buffers[idx] = (unsigned long *)newbuf;
310*00b67f09SDavid van Moolenbroek buflen[idx] = dstlen;
311*00b67f09SDavid van Moolenbroek }
312*00b67f09SDavid van Moolenbroek
313*00b67f09SDavid van Moolenbroek dst = buffers[idx];
314*00b67f09SDavid van Moolenbroek dstlen = buflen[idx];
315*00b67f09SDavid van Moolenbroek }
316*00b67f09SDavid van Moolenbroek
317*00b67f09SDavid van Moolenbroek /*
318*00b67f09SDavid van Moolenbroek * Perform i-th normalization scheme.
319*00b67f09SDavid van Moolenbroek * If buffer size is not enough, we double it and try again.
320*00b67f09SDavid van Moolenbroek */
321*00b67f09SDavid van Moolenbroek r = (ctx->schemes[i]->proc)(src, dst, dstlen);
322*00b67f09SDavid van Moolenbroek if (r == idn_buffer_overflow && dst != to) {
323*00b67f09SDavid van Moolenbroek dstlen *= 2;
324*00b67f09SDavid van Moolenbroek continue;
325*00b67f09SDavid van Moolenbroek }
326*00b67f09SDavid van Moolenbroek if (r != idn_success)
327*00b67f09SDavid van Moolenbroek goto ret;
328*00b67f09SDavid van Moolenbroek
329*00b67f09SDavid van Moolenbroek src = dst;
330*00b67f09SDavid van Moolenbroek i++;
331*00b67f09SDavid van Moolenbroek }
332*00b67f09SDavid van Moolenbroek
333*00b67f09SDavid van Moolenbroek r = idn_success;
334*00b67f09SDavid van Moolenbroek ret:
335*00b67f09SDavid van Moolenbroek free(buffers[0]);
336*00b67f09SDavid van Moolenbroek free(buffers[1]);
337*00b67f09SDavid van Moolenbroek if (r == idn_success) {
338*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_normalize(): success (to=\"%s\")\n",
339*00b67f09SDavid van Moolenbroek idn__debug_ucs4xstring(to, 50)));
340*00b67f09SDavid van Moolenbroek } else {
341*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_normalize(): %s\n",
342*00b67f09SDavid van Moolenbroek idn_result_tostring(r)));
343*00b67f09SDavid van Moolenbroek }
344*00b67f09SDavid van Moolenbroek return (r);
345*00b67f09SDavid van Moolenbroek }
346*00b67f09SDavid van Moolenbroek
347*00b67f09SDavid van Moolenbroek idn_result_t
idn_normalizer_register(const char * scheme_name,idn_normalizer_proc_t proc)348*00b67f09SDavid van Moolenbroek idn_normalizer_register(const char *scheme_name, idn_normalizer_proc_t proc) {
349*00b67f09SDavid van Moolenbroek idn_result_t r;
350*00b67f09SDavid van Moolenbroek normalize_scheme_t *scheme;
351*00b67f09SDavid van Moolenbroek
352*00b67f09SDavid van Moolenbroek assert(scheme_name != NULL && proc != NULL);
353*00b67f09SDavid van Moolenbroek
354*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_register(scheme_name=%s)\n", scheme_name));
355*00b67f09SDavid van Moolenbroek
356*00b67f09SDavid van Moolenbroek assert(INITIALIZED);
357*00b67f09SDavid van Moolenbroek
358*00b67f09SDavid van Moolenbroek scheme = malloc(sizeof(*scheme) + strlen(scheme_name) + 1);
359*00b67f09SDavid van Moolenbroek if (scheme == NULL) {
360*00b67f09SDavid van Moolenbroek r = idn_nomemory;
361*00b67f09SDavid van Moolenbroek goto ret;
362*00b67f09SDavid van Moolenbroek }
363*00b67f09SDavid van Moolenbroek scheme->name = (char *)(scheme + 1);
364*00b67f09SDavid van Moolenbroek (void)strcpy(scheme->name, scheme_name);
365*00b67f09SDavid van Moolenbroek scheme->proc = proc;
366*00b67f09SDavid van Moolenbroek
367*00b67f09SDavid van Moolenbroek r = idn__strhash_put(scheme_hash, scheme_name, scheme);
368*00b67f09SDavid van Moolenbroek if (r != idn_success)
369*00b67f09SDavid van Moolenbroek goto ret;
370*00b67f09SDavid van Moolenbroek
371*00b67f09SDavid van Moolenbroek r = idn_success;
372*00b67f09SDavid van Moolenbroek ret:
373*00b67f09SDavid van Moolenbroek TRACE(("idn_normalizer_register(): %s\n", idn_result_tostring(r)));
374*00b67f09SDavid van Moolenbroek return (r);
375*00b67f09SDavid van Moolenbroek }
376*00b67f09SDavid van Moolenbroek
377*00b67f09SDavid van Moolenbroek static idn_result_t
expand_schemes(idn_normalizer_t ctx)378*00b67f09SDavid van Moolenbroek expand_schemes(idn_normalizer_t ctx) {
379*00b67f09SDavid van Moolenbroek normalize_scheme_t **new_schemes;
380*00b67f09SDavid van Moolenbroek int new_size = ctx->scheme_size * 2;
381*00b67f09SDavid van Moolenbroek
382*00b67f09SDavid van Moolenbroek if (ctx->schemes == ctx->local_buf) {
383*00b67f09SDavid van Moolenbroek new_schemes = malloc(sizeof(normalize_scheme_t) * new_size);
384*00b67f09SDavid van Moolenbroek } else {
385*00b67f09SDavid van Moolenbroek new_schemes = realloc(ctx->schemes,
386*00b67f09SDavid van Moolenbroek sizeof(normalize_scheme_t) * new_size);
387*00b67f09SDavid van Moolenbroek }
388*00b67f09SDavid van Moolenbroek if (new_schemes == NULL)
389*00b67f09SDavid van Moolenbroek return (idn_nomemory);
390*00b67f09SDavid van Moolenbroek
391*00b67f09SDavid van Moolenbroek if (ctx->schemes == ctx->local_buf)
392*00b67f09SDavid van Moolenbroek memcpy(new_schemes, ctx->local_buf, sizeof(ctx->local_buf));
393*00b67f09SDavid van Moolenbroek
394*00b67f09SDavid van Moolenbroek ctx->schemes = new_schemes;
395*00b67f09SDavid van Moolenbroek ctx->scheme_size = new_size;
396*00b67f09SDavid van Moolenbroek
397*00b67f09SDavid van Moolenbroek return (idn_success);
398*00b67f09SDavid van Moolenbroek }
399*00b67f09SDavid van Moolenbroek
400*00b67f09SDavid van Moolenbroek static idn_result_t
register_standard_normalizers(void)401*00b67f09SDavid van Moolenbroek register_standard_normalizers(void) {
402*00b67f09SDavid van Moolenbroek int i;
403*00b67f09SDavid van Moolenbroek int failed = 0;
404*00b67f09SDavid van Moolenbroek
405*00b67f09SDavid van Moolenbroek for (i = 0; standard_normalizer[i].name != NULL; i++) {
406*00b67f09SDavid van Moolenbroek idn_result_t r;
407*00b67f09SDavid van Moolenbroek r = idn_normalizer_register(standard_normalizer[i].name,
408*00b67f09SDavid van Moolenbroek standard_normalizer[i].proc);
409*00b67f09SDavid van Moolenbroek if (r != idn_success) {
410*00b67f09SDavid van Moolenbroek WARNING(("idn_normalizer_initialize(): "
411*00b67f09SDavid van Moolenbroek "failed to register \"%-.100s\"\n",
412*00b67f09SDavid van Moolenbroek standard_normalizer[i].name));
413*00b67f09SDavid van Moolenbroek failed++;
414*00b67f09SDavid van Moolenbroek }
415*00b67f09SDavid van Moolenbroek }
416*00b67f09SDavid van Moolenbroek if (failed > 0)
417*00b67f09SDavid van Moolenbroek return (idn_failure);
418*00b67f09SDavid van Moolenbroek else
419*00b67f09SDavid van Moolenbroek return (idn_success);
420*00b67f09SDavid van Moolenbroek }
421*00b67f09SDavid van Moolenbroek
422*00b67f09SDavid van Moolenbroek /*
423*00b67f09SDavid van Moolenbroek * Unicode Normalization Forms -- latest version
424*00b67f09SDavid van Moolenbroek */
425*00b67f09SDavid van Moolenbroek
426*00b67f09SDavid van Moolenbroek static idn_result_t
normalizer_formkc(const unsigned long * from,unsigned long * to,size_t tolen)427*00b67f09SDavid van Moolenbroek normalizer_formkc(const unsigned long *from, unsigned long *to, size_t tolen) {
428*00b67f09SDavid van Moolenbroek INIT_VERSION(NULL, vcur);
429*00b67f09SDavid van Moolenbroek return (idn__unormalize_formkc(vcur, from, to, tolen));
430*00b67f09SDavid van Moolenbroek }
431*00b67f09SDavid van Moolenbroek
432*00b67f09SDavid van Moolenbroek /*
433*00b67f09SDavid van Moolenbroek * Unicode Normalization Forms -- version 3.2.0
434*00b67f09SDavid van Moolenbroek */
435*00b67f09SDavid van Moolenbroek
436*00b67f09SDavid van Moolenbroek static idn_result_t
normalizer_formkc_v320(const unsigned long * from,unsigned long * to,size_t tolen)437*00b67f09SDavid van Moolenbroek normalizer_formkc_v320(const unsigned long *from, unsigned long *to,
438*00b67f09SDavid van Moolenbroek size_t tolen) {
439*00b67f09SDavid van Moolenbroek INIT_VERSION("3.2.0", v320);
440*00b67f09SDavid van Moolenbroek return (idn__unormalize_formkc(v320, from, to, tolen));
441*00b67f09SDavid van Moolenbroek }
442