1 #ifndef lint
2 static char *rcsid = "$Id: resconf.c,v 1.70 2003/01/20 13:39:58 m-kasahr Exp $";
3 #endif
4
5 /*
6 * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set forth bellow.
9 *
10 * LICENSE TERMS AND CONDITIONS
11 *
12 * The following License Terms and Conditions apply, unless a different
13 * license is obtained from Japan Network Information Center ("JPNIC"),
14 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
15 * Chiyoda-ku, Tokyo 101-0047, Japan.
16 *
17 * 1. Use, Modification and Redistribution (including distribution of any
18 * modified or derived work) in source and/or binary forms is permitted
19 * under this License Terms and Conditions.
20 *
21 * 2. Redistribution of source code must retain the copyright notices as they
22 * appear in each source code file, this License Terms and Conditions.
23 *
24 * 3. Redistribution in binary form must reproduce the Copyright Notice,
25 * this License Terms and Conditions, in the documentation and/or other
26 * materials provided with the distribution. For the purposes of binary
27 * distribution the "Copyright Notice" refers to the following language:
28 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
29 *
30 * 4. The name of JPNIC may not be used to endorse or promote products
31 * derived from this Software without specific prior written approval of
32 * JPNIC.
33 *
34 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
35 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
43 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
44 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
45 */
46
47 #include <config.h>
48
49 #include <stddef.h>
50 #include <stdarg.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <ctype.h>
55 #include <errno.h>
56 #ifdef HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59 #ifdef HAVE_PWD_H
60 #include <pwd.h>
61 #endif
62
63 #include <idn/result.h>
64 #include <idn/assert.h>
65 #include <idn/logmacro.h>
66 #include <idn/converter.h>
67 #include <idn/nameprep.h>
68 #include <idn/normalizer.h>
69 #include <idn/checker.h>
70 #include <idn/mapper.h>
71 #include <idn/mapselector.h>
72 #include <idn/delimitermap.h>
73 #include <idn/localencoding.h>
74 #include <idn/resconf.h>
75 #include <idn/debug.h>
76 #include <idn/util.h>
77
78 #ifdef WIN32
79 #define MAX_PATH_SIZE 500 /* a good longer than MAX_PATH */
80 #define IDNVAL_CONFFILE "ConfFile"
81 #else /* WIN32 */
82
83 #ifndef IDN_RESCONF_DIR
84 #define IDN_RESCONF_DIR "/etc"
85 #endif
86 #define IDN_RESCONF_FILE IDN_RESCONF_DIR "/idn.conf"
87 #define IDN_USER_RESCONF_FILE "/.idnrc"
88
89 #endif /* WIN32 */
90
91 #define MAX_CONF_LINE_LENGTH 255
92 #define MAX_CONF_LINE_ARGS 63
93
94 #define DEFAULT_CONF_NAMEPREP 0x0001
95 #define DEFAULT_CONF_IDN_ENCODING 0x0010
96 #define DEFAULT_CONF_ALL (DEFAULT_CONF_NAMEPREP | \
97 DEFAULT_CONF_IDN_ENCODING)
98
99 #define IDN_ENCODING_CURRENT "Punycode"
100
101 #ifdef ENABLE_MDNKIT_COMPAT
102 #define MDN_RESCONF_FILE IDN_RESCONF_DIR "/mdn.conf"
103 #endif
104
105 struct idn_resconf {
106 int local_converter_is_static;
107 idn_converter_t local_converter;
108 idn_converter_t idn_converter;
109 idn_converter_t aux_idn_converter;
110 idn_normalizer_t normalizer;
111 idn_checker_t prohibit_checker;
112 idn_checker_t unassigned_checker;
113 idn_checker_t bidi_checker;
114 idn_mapper_t mapper;
115 idn_mapselector_t local_mapper;
116 idn_delimitermap_t delimiter_mapper;
117 int reference_count;
118 };
119
120 static int initialized;
121
122 #ifndef WIN32
123 static const char * userhomedir(void);
124 #endif
125 static idn_result_t open_userdefaultfile(FILE **fpp);
126 static idn_result_t open_defaultfile(FILE **fpp);
127 static idn_result_t parse_conf(idn_resconf_t ctx, FILE *fp);
128 static idn_result_t parse_idn_encoding(idn_resconf_t ctx, char *args,
129 int lineno);
130 static idn_result_t parse_local_map(idn_resconf_t ctx, char *args,
131 int lineno);
132 static idn_result_t parse_nameprep(idn_resconf_t ctx, char *args,
133 int lineno);
134 static int split_args(char *s, char **av, int max_ac);
135 static void resetconf(idn_resconf_t ctx);
136 #ifndef WITHOUT_ICONV
137 static idn_result_t update_local_converter(idn_resconf_t ctx);
138 #endif
139 static idn_result_t setdefaults_body(idn_resconf_t ctx, int conf_mask);
140
141 idn_result_t
idn_resconf_initialize(void)142 idn_resconf_initialize(void) {
143 idn_result_t r;
144
145 TRACE(("idn_resconf_initialize()\n"));
146
147 if (initialized) {
148 r = idn_success;
149 goto ret;
150 }
151
152 /*
153 * Initialize sub modules.
154 */
155 if ((r = idn_converter_initialize()) != idn_success)
156 goto ret;
157 if ((r = idn_normalizer_initialize()) != idn_success)
158 goto ret;
159 if ((r = idn_checker_initialize()) != idn_success)
160 goto ret;
161 if ((r = idn_mapselector_initialize()) != idn_success)
162 goto ret;
163 if ((r = idn_mapper_initialize()) != idn_success)
164 goto ret;
165
166 r = idn_success;
167 initialized = 1;
168 ret:
169 TRACE(("idn_resconf_initialize(): %s\n", idn_result_tostring(r)));
170 return (r);
171 }
172
173 idn_result_t
idn_resconf_create(idn_resconf_t * ctxp)174 idn_resconf_create(idn_resconf_t *ctxp) {
175 idn_resconf_t ctx = NULL;
176 idn_result_t r;
177
178 assert(ctxp != NULL);
179
180 TRACE(("idn_resconf_create()\n"));
181
182 if (!initialized) {
183 r = idn_failure;
184 goto ret;
185 }
186 if ((ctx = malloc(sizeof(*ctx))) == NULL) {
187 r = idn_nomemory;
188 goto ret;
189 }
190
191 ctx->local_converter_is_static = 0;
192 ctx->local_converter = NULL;
193 ctx->idn_converter = NULL;
194 ctx->aux_idn_converter = NULL;
195 ctx->normalizer = NULL;
196 ctx->prohibit_checker = NULL;
197 ctx->unassigned_checker = NULL;
198 ctx->bidi_checker = NULL;
199 ctx->mapper = NULL;
200 ctx->local_mapper = NULL;
201 ctx->reference_count = 1;
202
203 r = idn_delimitermap_create(&ctx->delimiter_mapper);
204 if (r != idn_success)
205 goto ret;
206
207 *ctxp = ctx;
208 r = idn_success;
209 ret:
210 TRACE(("idn_resconf_create(): %s\n", idn_result_tostring(r)));
211 return (r);
212 }
213
214 char *
idn_resconf_defaultfile()215 idn_resconf_defaultfile() {
216 #ifdef WIN32
217 static char default_path[MAX_PATH_SIZE];
218
219 if (idn__util_getregistrystring(idn__util_hkey_localmachine,
220 IDNVAL_CONFFILE, default_path,
221 sizeof(default_path))) {
222 return (default_path);
223 } else {
224 return (NULL);
225 }
226 #else
227 return (IDN_RESCONF_FILE);
228 #endif
229 }
230
231 #ifndef WIN32
232 static const char *
userhomedir()233 userhomedir() {
234 uid_t uid;
235 struct passwd *pwd;
236
237 uid = getuid();
238 pwd = getpwuid(uid);
239 if (pwd == NULL) {
240 return (NULL);
241 }
242
243 return (pwd->pw_dir);
244 }
245 #endif
246
247 static idn_result_t
open_userdefaultfile(FILE ** fpp)248 open_userdefaultfile(FILE **fpp) {
249 #ifdef WIN32
250 char user_path[MAX_PATH_SIZE];
251
252 TRACE(("open_userdefaultfile()\n"));
253
254 if (idn__util_getregistrystring(idn__util_hkey_currentuser,
255 IDNVAL_CONFFILE, user_path,
256 sizeof(user_path)) == 0) {
257 return (idn_nofile);
258 }
259 *fpp = fopen(user_path, "r");
260 if (*fpp == NULL) {
261 return (idn_nofile);
262 }
263 return (idn_success);
264 #else /* WIN32 */
265 const char *homedir;
266 char *file;
267 int len;
268
269 TRACE(("open_userdefaultfile()\n"));
270
271 homedir = userhomedir();
272 len = strlen(IDN_USER_RESCONF_FILE) + 1;
273 if (homedir != NULL) {
274 len += strlen(homedir);
275 } else {
276 return (idn_notfound);
277 }
278
279 file = (char *)malloc(sizeof(char) * len);
280 if (file == NULL) {
281 WARNING(("open_userdefaultfile(): malloc failed\n"));
282 return (idn_nomemory);
283 }
284
285 (void)strcpy(file, homedir);
286 strcat(file, IDN_USER_RESCONF_FILE);
287
288 *fpp = fopen(file, "r");
289 free(file);
290 if (*fpp == NULL) {
291 return (idn_nofile);
292 }
293
294 return (idn_success);
295 #endif /* WIN32 */
296 }
297
298 static idn_result_t
open_defaultfile(FILE ** fpp)299 open_defaultfile(FILE **fpp) {
300 idn_result_t r;
301 const char *file;
302
303 r = open_userdefaultfile(fpp);
304 if (r == idn_nofile || r == idn_notfound) {
305 TRACE(("open_defaultfile: "
306 "cannot open user configuration file\n"));
307 file = idn_resconf_defaultfile();
308 *fpp = fopen(file, "r");
309 #ifdef ENABLE_MDNKIT_COMPAT
310 if (*fpp == NULL)
311 *fpp = fopen(MDN_RESCONF_FILE, "r");
312 #endif
313 if (*fpp == NULL) {
314 TRACE(("open_defaultfile: "
315 "cannot open system configuration file\n"));
316 return (idn_nofile);
317 }
318 } else if (r != idn_success) {
319 return (r);
320 }
321
322 return (idn_success);
323 }
324
325 idn_result_t
idn_resconf_loadfile(idn_resconf_t ctx,const char * file)326 idn_resconf_loadfile(idn_resconf_t ctx, const char *file) {
327 FILE *fp = NULL;
328 idn_result_t r;
329
330 assert(ctx != NULL);
331
332 TRACE(("idn_resconf_loadfile(file=%s)\n",
333 file == NULL ? "<null>" : file));
334
335 resetconf(ctx);
336 r = idn_delimitermap_create(&ctx->delimiter_mapper);
337 if (r != idn_success) {
338 goto ret;
339 }
340
341 if (file == NULL) {
342 r = open_defaultfile(&fp);
343 if (r == idn_nofile || r == idn_notfound) {
344 r = setdefaults_body(ctx, 0);
345 goto ret;
346 } else if (r != idn_success) {
347 goto ret;
348 }
349 } else {
350 fp = fopen(file, "r");
351 if (fp == NULL) {
352 TRACE(("idn_resconf_loadfile: cannot open %-.40s\n",
353 file));
354 r = idn_nofile;
355 goto ret;
356 }
357 }
358
359 r = parse_conf(ctx, fp);
360 fclose(fp);
361
362 ret:
363 TRACE(("idn_resconf_loadfile(): %s\n", idn_result_tostring(r)));
364 return (r);
365 }
366
367 void
idn_resconf_destroy(idn_resconf_t ctx)368 idn_resconf_destroy(idn_resconf_t ctx) {
369 assert(ctx != NULL);
370
371 TRACE(("idn_resconf_destroy()\n"));
372
373 ctx->reference_count--;
374 if (ctx->reference_count <= 0) {
375 resetconf(ctx);
376 free(ctx);
377 TRACE(("idn_resconf_destroy: the object is destroyed\n"));
378 } else {
379 TRACE(("idn_resconf_destroy(): "
380 "update reference count (%d->%d)\n",
381 ctx->reference_count + 1, ctx->reference_count));
382 }
383 }
384
385 void
idn_resconf_incrref(idn_resconf_t ctx)386 idn_resconf_incrref(idn_resconf_t ctx) {
387 assert(ctx != NULL);
388
389 TRACE(("idn_resconf_incrref()\n"));
390 TRACE(("idn_resconf_incrref: update reference count (%d->%d)\n",
391 ctx->reference_count, ctx->reference_count + 1));
392
393 ctx->reference_count++;
394 }
395
396 idn_converter_t
idn_resconf_getalternateconverter(idn_resconf_t ctx)397 idn_resconf_getalternateconverter(idn_resconf_t ctx) {
398 assert(ctx != NULL);
399
400 TRACE(("idn_resconf_getalternateconverter()\n"));
401
402 return (idn_resconf_getidnconverter(ctx));
403 }
404
405 idn_delimitermap_t
idn_resconf_getdelimitermap(idn_resconf_t ctx)406 idn_resconf_getdelimitermap(idn_resconf_t ctx) {
407 assert(ctx != NULL);
408
409 TRACE(("idn_resconf_getdelimitermap()\n"));
410
411 if (ctx->delimiter_mapper != NULL)
412 idn_delimitermap_incrref(ctx->delimiter_mapper);
413 return (ctx->delimiter_mapper);
414 }
415
416 idn_converter_t
idn_resconf_getidnconverter(idn_resconf_t ctx)417 idn_resconf_getidnconverter(idn_resconf_t ctx) {
418 assert(ctx != NULL);
419
420 TRACE(("idn_resconf_getidnconverter()\n"));
421
422 if (ctx->idn_converter != NULL)
423 idn_converter_incrref(ctx->idn_converter);
424 return (ctx->idn_converter);
425 }
426
427 idn_converter_t
idn_resconf_getauxidnconverter(idn_resconf_t ctx)428 idn_resconf_getauxidnconverter(idn_resconf_t ctx) {
429 assert(ctx != NULL);
430
431 TRACE(("idn_resconf_getauxidnconverter()\n"));
432
433 if (ctx->aux_idn_converter != NULL)
434 idn_converter_incrref(ctx->aux_idn_converter);
435 return (ctx->aux_idn_converter);
436 }
437
438 idn_converter_t
idn_resconf_getlocalconverter(idn_resconf_t ctx)439 idn_resconf_getlocalconverter(idn_resconf_t ctx) {
440 assert(ctx != NULL);
441
442 TRACE(("idn_resconf_getlocalconverter()\n"));
443
444 #ifdef WITHOUT_ICONV
445 return NULL;
446
447 #else /* WITHOUT_ICONV */
448 if (update_local_converter(ctx) != idn_success)
449 return (NULL);
450
451 idn_converter_incrref(ctx->local_converter);
452 return (ctx->local_converter);
453
454 #endif /* WITHOUT_ICONV */
455 }
456
457 idn_mapselector_t
idn_resconf_getlocalmapselector(idn_resconf_t ctx)458 idn_resconf_getlocalmapselector(idn_resconf_t ctx) {
459 assert(ctx != NULL);
460
461 TRACE(("idn_resconf_getlocalmapselector()\n"));
462
463 if (ctx->local_mapper != NULL)
464 idn_mapselector_incrref(ctx->local_mapper);
465 return (ctx->local_mapper);
466 }
467
468 idn_mapper_t
idn_resconf_getmapper(idn_resconf_t ctx)469 idn_resconf_getmapper(idn_resconf_t ctx) {
470 assert(ctx != NULL);
471
472 TRACE(("idn_resconf_getmapper()\n"));
473
474 if (ctx->mapper != NULL)
475 idn_mapper_incrref(ctx->mapper);
476 return (ctx->mapper);
477 }
478
479 idn_normalizer_t
idn_resconf_getnormalizer(idn_resconf_t ctx)480 idn_resconf_getnormalizer(idn_resconf_t ctx) {
481 assert(ctx != NULL);
482
483 TRACE(("idn_resconf_getnormalizer()\n"));
484
485 if (ctx->normalizer != NULL)
486 idn_normalizer_incrref(ctx->normalizer);
487 return (ctx->normalizer);
488 }
489
490 idn_checker_t
idn_resconf_getprohibitchecker(idn_resconf_t ctx)491 idn_resconf_getprohibitchecker(idn_resconf_t ctx) {
492 assert(ctx != NULL);
493
494 TRACE(("idn_resconf_getprohibitchecker()\n"));
495
496 if (ctx->prohibit_checker != NULL)
497 idn_checker_incrref(ctx->prohibit_checker);
498 return (ctx->prohibit_checker);
499 }
500
501 idn_checker_t
idn_resconf_getunassignedchecker(idn_resconf_t ctx)502 idn_resconf_getunassignedchecker(idn_resconf_t ctx) {
503 assert(ctx != NULL);
504
505 TRACE(("idn_resconf_getunassignedchecker()\n"));
506
507 if (ctx->unassigned_checker != NULL)
508 idn_checker_incrref(ctx->unassigned_checker);
509 return (ctx->unassigned_checker);
510 }
511
512 idn_checker_t
idn_resconf_getbidichecker(idn_resconf_t ctx)513 idn_resconf_getbidichecker(idn_resconf_t ctx) {
514 assert(ctx != NULL);
515
516 TRACE(("idn_resconf_getbidichecker()\n"));
517
518 if (ctx->bidi_checker != NULL)
519 idn_checker_incrref(ctx->bidi_checker);
520 return (ctx->bidi_checker);
521 }
522
523 void
idn_resconf_setalternateconverter(idn_resconf_t ctx,idn_converter_t alternate_converter)524 idn_resconf_setalternateconverter(idn_resconf_t ctx,
525 idn_converter_t alternate_converter) {
526 assert(ctx != NULL);
527
528 TRACE(("idn_resconf_setalternateconverter()\n"));
529 }
530
531 void
idn_resconf_setdelimitermap(idn_resconf_t ctx,idn_delimitermap_t delimiter_mapper)532 idn_resconf_setdelimitermap(idn_resconf_t ctx,
533 idn_delimitermap_t delimiter_mapper) {
534 assert(ctx != NULL);
535
536 TRACE(("idn_resconf_setdelimitermap()\n"));
537
538 if (ctx->delimiter_mapper != NULL)
539 idn_delimitermap_destroy(ctx->delimiter_mapper);
540 ctx->delimiter_mapper = delimiter_mapper;
541 if (delimiter_mapper != NULL)
542 idn_delimitermap_incrref(ctx->delimiter_mapper);
543 }
544
545 void
idn_resconf_setidnconverter(idn_resconf_t ctx,idn_converter_t idn_converter)546 idn_resconf_setidnconverter(idn_resconf_t ctx,
547 idn_converter_t idn_converter) {
548 assert(ctx != NULL);
549
550 TRACE(("idn_resconf_setidnconverter()\n"));
551
552 if (ctx->idn_converter != NULL)
553 idn_converter_destroy(ctx->idn_converter);
554 ctx->idn_converter = idn_converter;
555 if (idn_converter != NULL)
556 idn_converter_incrref(ctx->idn_converter);
557 }
558
559 void
idn_resconf_setauxidnconverter(idn_resconf_t ctx,idn_converter_t aux_idn_converter)560 idn_resconf_setauxidnconverter(idn_resconf_t ctx,
561 idn_converter_t aux_idn_converter) {
562 assert(ctx != NULL);
563
564 TRACE(("idn_resconf_setauxidnconverter()\n"));
565
566 if (ctx->aux_idn_converter != NULL)
567 idn_converter_destroy(ctx->aux_idn_converter);
568 ctx->aux_idn_converter = aux_idn_converter;
569 if (aux_idn_converter != NULL)
570 idn_converter_incrref(ctx->aux_idn_converter);
571 }
572
573 void
idn_resconf_setlocalconverter(idn_resconf_t ctx,idn_converter_t local_converter)574 idn_resconf_setlocalconverter(idn_resconf_t ctx,
575 idn_converter_t local_converter) {
576 #ifndef WITHOUT_ICONV
577 assert(ctx != NULL);
578
579 TRACE(("idn_resconf_setlocalconverter()\n"));
580
581 if (ctx->local_converter != NULL) {
582 idn_converter_destroy(ctx->local_converter);
583 ctx->local_converter = NULL;
584 }
585
586 if (local_converter == NULL)
587 ctx->local_converter_is_static = 0;
588 else {
589 ctx->local_converter = local_converter;
590 idn_converter_incrref(local_converter);
591 ctx->local_converter_is_static = 1;
592 }
593 #endif /* WITHOUT_ICONV */
594 }
595
596 void
idn_resconf_setlocalmapselector(idn_resconf_t ctx,idn_mapselector_t local_mapper)597 idn_resconf_setlocalmapselector(idn_resconf_t ctx,
598 idn_mapselector_t local_mapper) {
599 assert(ctx != NULL);
600
601 TRACE(("idn_resconf_setlocalmapselector()\n"));
602
603 if (ctx->local_mapper != NULL)
604 idn_mapselector_destroy(ctx->local_mapper);
605 ctx->local_mapper = local_mapper;
606 if (local_mapper != NULL)
607 idn_mapselector_incrref(ctx->local_mapper);
608 }
609
610 void
idn_resconf_setmapper(idn_resconf_t ctx,idn_mapper_t mapper)611 idn_resconf_setmapper(idn_resconf_t ctx, idn_mapper_t mapper) {
612 assert(ctx != NULL);
613
614 TRACE(("idn_resconf_setmapper()\n"));
615
616 if (ctx->mapper != NULL)
617 idn_mapper_destroy(ctx->mapper);
618 ctx->mapper = mapper;
619 if (mapper != NULL)
620 idn_mapper_incrref(ctx->mapper);
621 }
622
623 void
idn_resconf_setnormalizer(idn_resconf_t ctx,idn_normalizer_t normalizer)624 idn_resconf_setnormalizer(idn_resconf_t ctx, idn_normalizer_t normalizer) {
625 assert(ctx != NULL);
626
627 TRACE(("idn_resconf_setnormalizer()\n"));
628
629 if (ctx->normalizer != NULL)
630 idn_normalizer_destroy(ctx->normalizer);
631 ctx->normalizer = normalizer;
632 if (normalizer != NULL)
633 idn_normalizer_incrref(ctx->normalizer);
634 }
635
636 void
idn_resconf_setprohibitchecker(idn_resconf_t ctx,idn_checker_t prohibit_checker)637 idn_resconf_setprohibitchecker(idn_resconf_t ctx,
638 idn_checker_t prohibit_checker) {
639 assert(ctx != NULL);
640
641 TRACE(("idn_resconf_setprohibitchecker()\n"));
642
643 if (ctx->prohibit_checker != NULL)
644 idn_checker_destroy(ctx->prohibit_checker);
645 ctx->prohibit_checker = prohibit_checker;
646 if (prohibit_checker != NULL)
647 idn_checker_incrref(ctx->prohibit_checker);
648 }
649
650 void
idn_resconf_setunassignedchecker(idn_resconf_t ctx,idn_checker_t unassigned_checker)651 idn_resconf_setunassignedchecker(idn_resconf_t ctx,
652 idn_checker_t unassigned_checker) {
653 assert(ctx != NULL);
654
655 TRACE(("idn_resconf_setunassignedchecker()\n"));
656
657 if (ctx->unassigned_checker != NULL)
658 idn_checker_destroy(ctx->unassigned_checker);
659 ctx->unassigned_checker = unassigned_checker;
660 if (unassigned_checker != NULL)
661 idn_checker_incrref(ctx->unassigned_checker);
662 }
663
664 void
idn_resconf_setbidichecker(idn_resconf_t ctx,idn_checker_t bidi_checker)665 idn_resconf_setbidichecker(idn_resconf_t ctx,
666 idn_checker_t bidi_checker) {
667 assert(ctx != NULL);
668
669 TRACE(("idn_resconf_setbidichecker()\n"));
670
671 if (ctx->bidi_checker != NULL)
672 idn_checker_destroy(ctx->bidi_checker);
673 ctx->bidi_checker = bidi_checker;
674 if (bidi_checker != NULL)
675 idn_checker_incrref(ctx->bidi_checker);
676 }
677
678 idn_result_t
idn_resconf_setnameprepversion(idn_resconf_t ctx,const char * version)679 idn_resconf_setnameprepversion(idn_resconf_t ctx, const char *version)
680 {
681 char prohibit_scheme_name[MAX_CONF_LINE_LENGTH + 1];
682 char unassigned_scheme_name[MAX_CONF_LINE_LENGTH + 1];
683 char bidi_scheme_name[MAX_CONF_LINE_LENGTH + 1];
684 idn_mapper_t mapper = NULL;
685 idn_normalizer_t normalizer = NULL;
686 idn_checker_t prohibit_checker = NULL;
687 idn_checker_t unassigned_checker = NULL;
688 idn_checker_t bidi_checker = NULL;
689 idn_result_t r;
690
691 assert(ctx != NULL && version != NULL);
692
693 TRACE(("idn_resconf_setnameprepversion()\n"));
694
695 /*
696 * Set canonical scheme names.
697 */
698 if (strlen(version) + strlen(IDN_CHECKER_PROHIBIT_PREFIX)
699 > MAX_CONF_LINE_LENGTH) {
700 r = idn_invalid_name;
701 goto failure;
702 }
703 sprintf(prohibit_scheme_name, "%s%s",
704 IDN_CHECKER_PROHIBIT_PREFIX, version);
705
706 if (strlen(version) + strlen(IDN_CHECKER_UNASSIGNED_PREFIX)
707 > MAX_CONF_LINE_LENGTH) {
708 r = idn_invalid_name;
709 goto failure;
710 }
711 sprintf(unassigned_scheme_name, "%s%s",
712 IDN_CHECKER_UNASSIGNED_PREFIX, version);
713
714 if (strlen(version) + strlen(IDN_CHECKER_BIDI_PREFIX)
715 > MAX_CONF_LINE_LENGTH) {
716 r = idn_invalid_name;
717 goto failure;
718 }
719 sprintf(bidi_scheme_name, "%s%s",
720 IDN_CHECKER_BIDI_PREFIX, version);
721
722 /*
723 * Create objects.
724 */
725 r = idn_mapper_create(&mapper);
726 if (r != idn_success)
727 goto failure;
728 r = idn_normalizer_create(&normalizer);
729 if (r != idn_success)
730 goto failure;
731 r = idn_checker_create(&prohibit_checker);
732 if (r != idn_success)
733 goto failure;
734 r = idn_checker_create(&unassigned_checker);
735 if (r != idn_success)
736 goto failure;
737 r = idn_checker_create(&bidi_checker);
738 if (r != idn_success)
739 goto failure;
740
741 r = idn_mapper_add(mapper, version);
742 if (r != idn_success)
743 goto failure;
744 r = idn_normalizer_add(normalizer, version);
745 if (r != idn_success)
746 goto failure;
747 r = idn_checker_add(prohibit_checker, prohibit_scheme_name);
748 if (r != idn_success)
749 goto failure;
750 r = idn_checker_add(unassigned_checker, unassigned_scheme_name);
751 if (r != idn_success)
752 goto failure;
753 r = idn_checker_add(bidi_checker, bidi_scheme_name);
754 if (r != idn_success)
755 goto failure;
756
757 /*
758 * Set the objects.
759 */
760 idn_resconf_setmapper(ctx, mapper);
761 idn_resconf_setnormalizer(ctx, normalizer);
762 idn_resconf_setprohibitchecker(ctx, prohibit_checker);
763 idn_resconf_setunassignedchecker(ctx, unassigned_checker);
764 idn_resconf_setbidichecker(ctx, bidi_checker);
765
766 /*
767 * Destroy the objects.
768 */
769 idn_mapper_destroy(mapper);
770 idn_normalizer_destroy(normalizer);
771 idn_checker_destroy(prohibit_checker);
772 idn_checker_destroy(unassigned_checker);
773 idn_checker_destroy(bidi_checker);
774
775 return (idn_success);
776
777 failure:
778 if (mapper != NULL)
779 idn_mapper_destroy(mapper);
780 if (normalizer != NULL)
781 idn_normalizer_destroy(normalizer);
782 if (prohibit_checker != NULL)
783 idn_checker_destroy(prohibit_checker);
784 if (unassigned_checker != NULL)
785 idn_checker_destroy(unassigned_checker);
786 if (bidi_checker != NULL)
787 idn_checker_destroy(bidi_checker);
788
789 return (r);
790 }
791
792 idn_result_t
idn_resconf_setalternateconvertername(idn_resconf_t ctx,const char * name,int flags)793 idn_resconf_setalternateconvertername(idn_resconf_t ctx, const char *name,
794 int flags) {
795 assert(ctx != NULL && name != NULL);
796
797 TRACE(("idn_resconf_setalternateconvertername(name=%s, flags=%d)\n",
798 name, flags));
799
800 return (idn_success);
801 }
802
803 idn_result_t
idn_resconf_setidnconvertername(idn_resconf_t ctx,const char * name,int flags)804 idn_resconf_setidnconvertername(idn_resconf_t ctx, const char *name,
805 int flags) {
806 idn_converter_t idn_converter;
807 idn_result_t r;
808
809 assert(ctx != NULL && name != NULL);
810
811 TRACE(("idn_resconf_setidnconvertername(name=%s, flags=%d)\n",
812 name, flags));
813
814 r = idn_converter_create(name, &idn_converter, flags);
815 if (r != idn_success)
816 return (r);
817
818 if (ctx->idn_converter != NULL)
819 idn_converter_destroy(ctx->idn_converter);
820 ctx->idn_converter = idn_converter;
821
822 return (idn_success);
823 }
824
825 idn_result_t
idn_resconf_setauxidnconvertername(idn_resconf_t ctx,const char * name,int flags)826 idn_resconf_setauxidnconvertername(idn_resconf_t ctx, const char *name,
827 int flags) {
828 idn_converter_t aux_idn_converter;
829 const char *old_name;
830 idn_result_t r;
831
832 assert(ctx != NULL && name != NULL);
833
834 TRACE(("idn_resconf_setauxidnconvertername(name=%s, flags=%d)\n",
835 name, flags));
836
837 if (ctx->aux_idn_converter != NULL) {
838 old_name = idn_converter_localencoding(ctx->aux_idn_converter);
839 if (old_name != NULL && strcmp(old_name, name) == 0)
840 return (idn_success);
841 }
842
843 r = idn_converter_create(name, &aux_idn_converter, flags);
844 if (r != idn_success)
845 return (r);
846
847 if (ctx->aux_idn_converter != NULL)
848 idn_converter_destroy(ctx->aux_idn_converter);
849 ctx->aux_idn_converter = aux_idn_converter;
850
851 return (idn_success);
852 }
853
854 idn_result_t
idn_resconf_setlocalconvertername(idn_resconf_t ctx,const char * name,int flags)855 idn_resconf_setlocalconvertername(idn_resconf_t ctx, const char *name,
856 int flags) {
857 #ifdef WITHOUT_ICONV
858 return idn_failure;
859
860 #else /* WITHOUT_ICONV */
861 idn_converter_t local_converter;
862 idn_result_t r;
863
864 assert(ctx != NULL);
865
866 TRACE(("idn_resconf_setlocalconvertername(name=%s, flags=%d)\n",
867 name == NULL ? "<null>" : name, flags));
868
869 if (ctx->local_converter != NULL) {
870 idn_converter_destroy(ctx->local_converter);
871 ctx->local_converter = NULL;
872 }
873 ctx->local_converter_is_static = 0;
874
875 if (name != NULL) {
876 r = idn_converter_create(name, &local_converter, flags);
877 if (r != idn_success)
878 return (r);
879 ctx->local_converter = local_converter;
880 ctx->local_converter_is_static = 1;
881 }
882
883 return (idn_success);
884
885 #endif /* WITHOUT_ICONV */
886 }
887
888 idn_result_t
idn_resconf_addalldelimitermapucs(idn_resconf_t ctx,unsigned long * v,int nv)889 idn_resconf_addalldelimitermapucs(idn_resconf_t ctx, unsigned long *v,
890 int nv) {
891 idn_result_t r;
892
893 TRACE(("idn_resconf_addalldelimitermapucs(nv=%d)\n", nv));
894
895 if (ctx->delimiter_mapper == NULL) {
896 r = idn_delimitermap_create(&(ctx->delimiter_mapper));
897 if (r != idn_success)
898 return (r);
899 }
900
901 r = idn_delimitermap_addall(ctx->delimiter_mapper, v, nv);
902 return (r);
903 }
904
905 idn_result_t
idn_resconf_addalllocalmapselectornames(idn_resconf_t ctx,const char * tld,const char ** names,int nnames)906 idn_resconf_addalllocalmapselectornames(idn_resconf_t ctx, const char *tld,
907 const char **names, int nnames) {
908 idn_result_t r;
909
910 assert(ctx != NULL && names != NULL && tld != NULL);
911
912 TRACE(("idn_resconf_addalllocalmapselectorname(tld=%s, nnames=%d)\n",
913 tld, nnames));
914
915 if (ctx->local_mapper == NULL) {
916 r = idn_mapselector_create(&(ctx->local_mapper));
917 if (r != idn_success)
918 return (r);
919 }
920
921 r = idn_mapselector_addall(ctx->local_mapper, tld, names, nnames);
922 return (r);
923 }
924
925 idn_result_t
idn_resconf_addallmappernames(idn_resconf_t ctx,const char ** names,int nnames)926 idn_resconf_addallmappernames(idn_resconf_t ctx, const char **names,
927 int nnames) {
928 idn_result_t r;
929
930 assert(ctx != NULL && names != NULL);
931
932 TRACE(("idn_resconf_addallmappername()\n"));
933
934 if (ctx->mapper == NULL) {
935 r = idn_mapper_create(&(ctx->mapper));
936 if (r != idn_success)
937 return (r);
938 }
939
940 r = idn_mapper_addall(ctx->mapper, names, nnames);
941 return (r);
942 }
943
944 idn_result_t
idn_resconf_addallnormalizernames(idn_resconf_t ctx,const char ** names,int nnames)945 idn_resconf_addallnormalizernames(idn_resconf_t ctx, const char **names,
946 int nnames) {
947 idn_result_t r;
948
949 assert(ctx != NULL && names != NULL);
950
951 TRACE(("idn_resconf_addallnormalizername(nnames=%d)\n", nnames));
952
953 if (ctx->normalizer == NULL) {
954 r = idn_normalizer_create(&(ctx->normalizer));
955 if (r != idn_success)
956 return (r);
957 }
958
959 r = idn_normalizer_addall(ctx->normalizer, names, nnames);
960 return (r);
961 }
962
963 idn_result_t
idn_resconf_addallprohibitcheckernames(idn_resconf_t ctx,const char ** names,int nnames)964 idn_resconf_addallprohibitcheckernames(idn_resconf_t ctx, const char **names,
965 int nnames) {
966 char long_name[MAX_CONF_LINE_LENGTH + 1];
967 idn_result_t r;
968 int i;
969
970 assert(ctx != NULL && names != NULL);
971
972 TRACE(("idn_resconf_addallprohibitcheckername(nnames=%d)\n", nnames));
973
974 if (ctx->prohibit_checker == NULL) {
975 r = idn_checker_create(&(ctx->prohibit_checker));
976 if (r != idn_success)
977 return (r);
978 }
979
980 for (i = 0; i < nnames; i++, names++) {
981 if (strlen(*names) + strlen(IDN_CHECKER_PROHIBIT_PREFIX)
982 > MAX_CONF_LINE_LENGTH) {
983 return (idn_invalid_name);
984 }
985 strcpy(long_name, IDN_CHECKER_PROHIBIT_PREFIX);
986 strcat(long_name, *names);
987
988 r = idn_checker_add(ctx->prohibit_checker, long_name);
989 if (r != idn_success)
990 return (r);
991 }
992
993 return (idn_success);
994 }
995
996 idn_result_t
idn_resconf_addallunassignedcheckernames(idn_resconf_t ctx,const char ** names,int nnames)997 idn_resconf_addallunassignedcheckernames(idn_resconf_t ctx, const char **names,
998 int nnames) {
999 char long_name[MAX_CONF_LINE_LENGTH + 1];
1000 idn_result_t r;
1001 int i;
1002
1003 assert(ctx != NULL && names != NULL);
1004
1005 TRACE(("idn_resconf_addallunassignedcheckername(nnames=%d)\n",
1006 nnames));
1007
1008 if (ctx->unassigned_checker == NULL) {
1009 r = idn_checker_create(&(ctx->unassigned_checker));
1010 if (r != idn_success)
1011 return (r);
1012 }
1013
1014 for (i = 0; i < nnames; i++, names++) {
1015 if (strlen(*names) + strlen(IDN_CHECKER_UNASSIGNED_PREFIX)
1016 > MAX_CONF_LINE_LENGTH) {
1017 return (idn_invalid_name);
1018 }
1019 strcpy(long_name, IDN_CHECKER_UNASSIGNED_PREFIX);
1020 strcat(long_name, *names);
1021
1022 r = idn_checker_add(ctx->unassigned_checker, long_name);
1023 if (r != idn_success)
1024 return (r);
1025 }
1026
1027 return (idn_success);
1028 }
1029
1030 idn_result_t
idn_resconf_addallbidicheckernames(idn_resconf_t ctx,const char ** names,int nnames)1031 idn_resconf_addallbidicheckernames(idn_resconf_t ctx, const char **names,
1032 int nnames) {
1033 char long_name[MAX_CONF_LINE_LENGTH + 1];
1034 idn_result_t r;
1035 int i;
1036
1037 assert(ctx != NULL && names != NULL);
1038
1039 TRACE(("idn_resconf_addallbidicheckername(nnames=%d)\n", nnames));
1040
1041 if (ctx->bidi_checker == NULL) {
1042 r = idn_checker_create(&(ctx->bidi_checker));
1043 if (r != idn_success)
1044 return (r);
1045 }
1046
1047 for (i = 0; i < nnames; i++, names++) {
1048 if (strlen(*names) + strlen(IDN_CHECKER_BIDI_PREFIX)
1049 > MAX_CONF_LINE_LENGTH) {
1050 return (idn_invalid_name);
1051 }
1052 strcpy(long_name, IDN_CHECKER_BIDI_PREFIX);
1053 strcat(long_name, *names);
1054
1055 r = idn_checker_add(ctx->bidi_checker, long_name);
1056 if (r != idn_success)
1057 return (r);
1058 }
1059
1060 return (idn_success);
1061 }
1062
1063 static idn_result_t
parse_conf(idn_resconf_t ctx,FILE * fp)1064 parse_conf(idn_resconf_t ctx, FILE *fp) {
1065 char line[MAX_CONF_LINE_LENGTH + 1];
1066 int lineno = 0;
1067 char *argv[3];
1068 int argc;
1069 idn_result_t r;
1070 int conf_mask = 0;
1071
1072 TRACE(("parse_conf()\n"));
1073
1074 /*
1075 * Parse config file. parsing of 'idn-encoding' line is
1076 * postponed because 'alias-file' line must be processed
1077 * before them.
1078 */
1079 while (fgets(line, sizeof(line), fp) != NULL) {
1080 char *newline;
1081
1082 lineno++;
1083 newline = strpbrk(line, "\r\n");
1084 if (newline != NULL)
1085 *newline = '\0';
1086 else if (fgetc(fp) != EOF) {
1087 ERROR(("libidnkit: too long line \"%-.30s\", "
1088 "line %d\n", line, lineno));
1089 return (idn_invalid_syntax);
1090 }
1091
1092 argc = split_args(line, argv, 2);
1093 if (argc == -1) {
1094 ERROR(("libidnkit: syntax error, line %d\n", lineno));
1095 return (idn_invalid_syntax);
1096 } else if (argc == 0 || argv[0][0] == '#') {
1097 continue;
1098 } else if (argc == 1) {
1099 ERROR(("libidnkit: syntax error, line %d\n", lineno));
1100 return (idn_invalid_syntax);
1101 }
1102
1103 if (strcmp(argv[0], "idn-encoding") == 0) {
1104 if (conf_mask & DEFAULT_CONF_IDN_ENCODING) {
1105 ERROR(("libidnkit: \"%s\" redefined, "
1106 "line %d\n", argv[0], lineno));
1107 r = idn_invalid_syntax;
1108 } else {
1109 conf_mask |= DEFAULT_CONF_IDN_ENCODING;
1110 r = parse_idn_encoding(ctx, argv[1], lineno);
1111 }
1112 } else if (strcmp(argv[0], "local-map") == 0) {
1113 r = parse_local_map(ctx, argv[1], lineno);
1114
1115 } else if (strcmp(argv[0], "nameprep") == 0) {
1116 if (conf_mask & DEFAULT_CONF_NAMEPREP) {
1117 ERROR(("libidnkit: \"%s\" redefined, "
1118 "line %d\n", argv[0], lineno));
1119 r = idn_invalid_syntax;
1120 } else {
1121 conf_mask |= DEFAULT_CONF_NAMEPREP;
1122 r = parse_nameprep(ctx, argv[1], lineno);
1123 }
1124 } else if (strcmp(argv[0], "nameprep-map") == 0 ||
1125 strcmp(argv[0], "nameprep-normalize") == 0 ||
1126 strcmp(argv[0], "nameprep-prohibit") == 0 ||
1127 strcmp(argv[0], "nameprep-unassigned") == 0 ||
1128 strcmp(argv[0], "alias-file") == 0 ||
1129 strcmp(argv[0], "encoding-alias-file") == 0 ||
1130 strcmp(argv[0], "normalize") == 0 ||
1131 strcmp(argv[0], "server-encoding") == 0 ||
1132 strcmp(argv[0], "alternate-encoding") == 0 ||
1133 strcmp(argv[0], "delimiter-map") == 0) {
1134 WARNING(("libidnkit: obsolete command \"%s\", line %d "
1135 "(ignored)\n", argv[0], lineno));
1136 r = idn_success;
1137 } else {
1138 ERROR(("libidnkit: unknown command \"%-.30s\", "
1139 "line %d\n", argv[0], lineno));
1140 r = idn_invalid_syntax;
1141 }
1142 if (r != idn_success)
1143 return (r);
1144 }
1145
1146 lineno++;
1147
1148 if (conf_mask != DEFAULT_CONF_ALL) {
1149 return setdefaults_body(ctx, conf_mask);
1150 }
1151
1152 return (idn_success);
1153 }
1154
1155 static idn_result_t
parse_idn_encoding(idn_resconf_t ctx,char * args,int lineno)1156 parse_idn_encoding(idn_resconf_t ctx, char *args, int lineno) {
1157 idn_result_t r;
1158 char *argv[MAX_CONF_LINE_ARGS + 1];
1159 int argc;
1160
1161 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1162
1163 if (argc != 1) {
1164 ERROR(("libidnkit: wrong # of args for idn-encoding, "
1165 "line %d\n", lineno));
1166 return (idn_invalid_syntax);
1167 }
1168
1169 r = idn_converter_create(argv[0], &ctx->idn_converter,
1170 IDN_CONVERTER_DELAYEDOPEN |
1171 IDN_CONVERTER_RTCHECK);
1172 if (r != idn_success) {
1173 ERROR(("libidnkit: cannot create idn converter, %s, "
1174 "line %d\n", idn_result_tostring(r), lineno));
1175 }
1176
1177 return (r);
1178 }
1179
1180 static idn_result_t
parse_local_map(idn_resconf_t ctx,char * args,int lineno)1181 parse_local_map(idn_resconf_t ctx, char *args, int lineno) {
1182 idn_result_t r;
1183 char *argv[MAX_CONF_LINE_ARGS + 1];
1184 int argc;
1185 int i;
1186
1187 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1188
1189 if (argc < 2 || argc > MAX_CONF_LINE_ARGS) {
1190 ERROR(("libidnkit: wrong # of args for local-map, line %d\n",
1191 lineno));
1192 return (idn_invalid_syntax);
1193 }
1194
1195 if (ctx->local_mapper == NULL) {
1196 r = idn_mapselector_create(&ctx->local_mapper);
1197 if (r != idn_success) {
1198 ERROR(("libidnkit: cannot create local mapper, %s, "
1199 "line %d\n", idn_result_tostring(r), lineno));
1200 return (r);
1201 }
1202 }
1203
1204 for (i = 1; i < argc; i++) {
1205 r = idn_mapselector_add(ctx->local_mapper, argv[0], argv[i]);
1206 if (r == idn_invalid_name) {
1207 ERROR(("libidnkit: map scheme unavailable \"%-.30s\""
1208 " or invalid TLD \"%-.30s\", line %d\n",
1209 argv[i], argv[0], lineno));
1210 return (r);
1211 } else if (r != idn_success) {
1212 return (r);
1213 }
1214 }
1215
1216 return (idn_success);
1217 }
1218
1219 static idn_result_t
parse_nameprep(idn_resconf_t ctx,char * args,int lineno)1220 parse_nameprep(idn_resconf_t ctx, char *args, int lineno) {
1221 idn_result_t r;
1222 char *argv[MAX_CONF_LINE_ARGS + 1];
1223 char scheme_name[MAX_CONF_LINE_LENGTH + 1];
1224 int argc;
1225
1226 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1227
1228 if (argc != 1) {
1229 ERROR(("libidnkit: wrong # of args for nameprep, line %d\n",
1230 lineno));
1231 return (idn_invalid_syntax);
1232 }
1233
1234 /*
1235 * Set mapper.
1236 */
1237 r = idn_mapper_create(&ctx->mapper);
1238 if (r != idn_success) {
1239 ERROR(("libidnkit: cannot create mapper, %s, line %d\n",
1240 idn_result_tostring(r), lineno));
1241 return (r);
1242 }
1243
1244 r = idn_mapper_add(ctx->mapper, argv[0]);
1245 if (r == idn_invalid_name) {
1246 ERROR(("libidnkit: map scheme unavailable \"%-.30s\", "
1247 "line %d\n", argv[0], lineno));
1248 return (r);
1249 } else if (r != idn_success) {
1250 return (r);
1251 }
1252
1253 /*
1254 * Set normalizer.
1255 */
1256 r = idn_normalizer_create(&ctx->normalizer);
1257 if (r != idn_success) {
1258 ERROR(("libidnkit: cannot create normalizer, %s, line %d\n",
1259 idn_result_tostring(r), lineno));
1260 return (r);
1261 }
1262
1263 r = idn_normalizer_add(ctx->normalizer, argv[0]);
1264 if (r == idn_invalid_name) {
1265 ERROR(("libidnkit: unknown normalization scheme \"%-.30s\", "
1266 "line %d\n", argv[0], lineno));
1267 return (r);
1268 } else if (r != idn_success) {
1269 return (r);
1270 }
1271
1272 /*
1273 * Set prohibit checker.
1274 */
1275 r = idn_checker_create(&ctx->prohibit_checker);
1276 if (r != idn_success) {
1277 ERROR(("libidnkit: cannot create prohibit checker, %s, "
1278 "line %d\n", idn_result_tostring(r), lineno));
1279 return (r);
1280 }
1281
1282 sprintf(scheme_name, "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, argv[0]);
1283 r = idn_checker_add(ctx->prohibit_checker, scheme_name);
1284 if (r == idn_invalid_name) {
1285 ERROR(("libidnkit: unknown prohibit scheme \"%-.30s\", "
1286 "line %d\n", argv[0], lineno));
1287 return (r);
1288 } else if (r != idn_success) {
1289 return (r);
1290 }
1291
1292 /*
1293 * Set unassigned checker.
1294 */
1295 r = idn_checker_create(&ctx->unassigned_checker);
1296 if (r != idn_success) {
1297 ERROR(("libidnkit: cannot create unassigned checker, %s, "
1298 "line %d\n", idn_result_tostring(r), lineno));
1299 return (r);
1300 }
1301
1302 sprintf(scheme_name, "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, argv[0]);
1303 r = idn_checker_add(ctx->unassigned_checker, scheme_name);
1304 if (r == idn_invalid_name) {
1305 ERROR(("libidnkit: unknown unassigned scheme \"%-.30s\", "
1306 "line %d\n", argv[0], lineno));
1307 return (r);
1308 } else if (r != idn_success) {
1309 return (r);
1310 }
1311
1312 /*
1313 * Set bidi checker.
1314 */
1315 r = idn_checker_create(&ctx->bidi_checker);
1316 if (r != idn_success) {
1317 ERROR(("libidnkit: cannot create bidi checker, %s, line %d\n",
1318 idn_result_tostring(r), lineno));
1319 return (r);
1320 }
1321
1322 sprintf(scheme_name, "%s%s", IDN_CHECKER_BIDI_PREFIX, argv[0]);
1323 r = idn_checker_add(ctx->bidi_checker, scheme_name);
1324 if (r == idn_invalid_name) {
1325 ERROR(("libidnkit: unknown bidi scheme \"%-.30s\", "
1326 "line %d\n", argv[0], lineno));
1327 return (r);
1328 } else if (r != idn_success) {
1329 return (r);
1330 }
1331
1332 return (idn_success);
1333 }
1334
1335 static int
split_args(char * s,char ** av,int max_ac)1336 split_args(char *s, char **av, int max_ac) {
1337 int ac;
1338 int i;
1339
1340 for (ac = 0; *s != '\0' && ac < max_ac; ac++) {
1341 if (ac > 0)
1342 *s++ = '\0';
1343 while (isspace((unsigned char)*s))
1344 s++;
1345 if (*s == '\0')
1346 break;
1347 if (*s == '"' || *s == '\'') {
1348 int qc = *s++;
1349 av[ac] = s;
1350 while (*s != qc) {
1351 if (*s == '\0')
1352 return (-1);
1353 s++;
1354 }
1355 } else {
1356 av[ac] = s;
1357 while (*s != '\0' && !isspace((unsigned char)*s))
1358 s++;
1359 }
1360 }
1361
1362 for (i = ac; i < max_ac; i++)
1363 av[i] = NULL;
1364
1365 return (ac);
1366 }
1367
1368 static void
resetconf(idn_resconf_t ctx)1369 resetconf(idn_resconf_t ctx) {
1370 #ifndef WITHOUT_ICONV
1371 idn_resconf_setlocalconverter(ctx, NULL);
1372 #endif
1373 idn_resconf_setidnconverter(ctx, NULL);
1374 idn_resconf_setauxidnconverter(ctx, NULL);
1375 idn_resconf_setdelimitermap(ctx, NULL);
1376 idn_resconf_setlocalmapselector(ctx, NULL);
1377 idn_resconf_setmapper(ctx, NULL);
1378 idn_resconf_setnormalizer(ctx, NULL);
1379 idn_resconf_setprohibitchecker(ctx, NULL);
1380 idn_resconf_setunassignedchecker(ctx, NULL);
1381 idn_resconf_setbidichecker(ctx, NULL);
1382 }
1383
1384 #ifndef WITHOUT_ICONV
1385 static idn_result_t
update_local_converter(idn_resconf_t ctx)1386 update_local_converter(idn_resconf_t ctx) {
1387 idn_result_t r;
1388 const char *old_encoding;
1389 const char *new_encoding;
1390
1391 /*
1392 * We don't update local converter, if the converter is set
1393 * by idn_resconf_setlocalconverter() or
1394 * idn_resconf_setlocalconvertername().
1395 */
1396 if (ctx->local_converter_is_static)
1397 return (idn_success);
1398
1399 /*
1400 * Update the local converter if the local encoding is changed.
1401 */
1402 old_encoding = (ctx->local_converter != NULL) ?
1403 idn_converter_localencoding(ctx->local_converter) :
1404 NULL;
1405 new_encoding = idn_localencoding_name();
1406 if (new_encoding == NULL) {
1407 ERROR(("cannot determine local codeset name\n"));
1408 return (idn_notfound);
1409 }
1410
1411 if (old_encoding != NULL &&
1412 new_encoding != NULL &&
1413 strcmp(old_encoding, new_encoding) == 0) {
1414 return (idn_success);
1415 }
1416
1417 if (ctx->local_converter != NULL) {
1418 idn_converter_destroy(ctx->local_converter);
1419 ctx->local_converter = NULL;
1420 }
1421
1422 r = idn_converter_create(new_encoding,
1423 &ctx->local_converter,
1424 IDN_CONVERTER_RTCHECK);
1425 return (r);
1426 }
1427 #endif
1428
1429 idn_result_t
idn_resconf_setdefaults(idn_resconf_t ctx)1430 idn_resconf_setdefaults(idn_resconf_t ctx)
1431 {
1432 idn_result_t r;
1433
1434 assert(ctx != NULL);
1435
1436 TRACE(("idn_resconf_setdefaults()\n"));
1437
1438 resetconf(ctx);
1439 r = idn_delimitermap_create(&ctx->delimiter_mapper);
1440 if (r != idn_success) {
1441 ERROR(("libidnkit: cannot create delimiter mapper, %s\n",
1442 idn_result_tostring(r)));
1443 return (r);
1444 }
1445
1446 return setdefaults_body(ctx, 0);
1447 }
1448
1449 static idn_result_t
setdefaults_body(idn_resconf_t ctx,int conf_mask)1450 setdefaults_body(idn_resconf_t ctx, int conf_mask) {
1451 idn_result_t r;
1452
1453 TRACE(("setdefaults_body()\n"));
1454 assert(ctx != NULL);
1455
1456 if (!(conf_mask & DEFAULT_CONF_NAMEPREP)) {
1457 TRACE(("set default nameprep\n"));
1458 r = idn_resconf_setnameprepversion(ctx, IDN_NAMEPREP_CURRENT);
1459 if (r != idn_success) {
1460 return (r);
1461 }
1462 }
1463 if (!(conf_mask & DEFAULT_CONF_IDN_ENCODING)) {
1464 TRACE(("set default idn encoding\n"));
1465 r = idn_converter_create(IDN_ENCODING_CURRENT,
1466 &ctx->idn_converter,
1467 IDN_CONVERTER_DELAYEDOPEN |
1468 IDN_CONVERTER_RTCHECK);
1469 if (r != idn_success) {
1470 ERROR(("libidnkit: cannot create idn converter, %s\n",
1471 idn_result_tostring(r)));
1472 return (r);
1473 }
1474 }
1475
1476 return (idn_success);
1477 }
1478