Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / contrib / idn / idnkit-1.0-src / lib / resconf.c
blob8df4f1ace82a9c51b9becc11771c7d49bc321236
1 /* $NetBSD: resconf.c,v 1.4 2014/12/10 04:37:55 christos Exp $ */
3 #ifndef lint
4 static char *rcsid = "Id: resconf.c,v 1.1 2003/06/04 00:26:12 marka Exp ";
5 #endif
7 /*
8 * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
9 *
10 * By using this file, you agree to the terms and conditions set forth bellow.
12 * LICENSE TERMS AND CONDITIONS
14 * The following License Terms and Conditions apply, unless a different
15 * license is obtained from Japan Network Information Center ("JPNIC"),
16 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
17 * Chiyoda-ku, Tokyo 101-0047, Japan.
19 * 1. Use, Modification and Redistribution (including distribution of any
20 * modified or derived work) in source and/or binary forms is permitted
21 * under this License Terms and Conditions.
23 * 2. Redistribution of source code must retain the copyright notices as they
24 * appear in each source code file, this License Terms and Conditions.
26 * 3. Redistribution in binary form must reproduce the Copyright Notice,
27 * this License Terms and Conditions, in the documentation and/or other
28 * materials provided with the distribution. For the purposes of binary
29 * distribution the "Copyright Notice" refers to the following language:
30 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
32 * 4. The name of JPNIC may not be used to endorse or promote products
33 * derived from this Software without specific prior written approval of
34 * JPNIC.
36 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
37 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
46 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
49 #include <config.h>
51 #include <stddef.h>
52 #include <stdarg.h>
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <ctype.h>
57 #include <errno.h>
58 #ifdef HAVE_UNISTD_H
59 #include <unistd.h>
60 #endif
61 #ifdef HAVE_PWD_H
62 #include <pwd.h>
63 #endif
65 #include <idn/result.h>
66 #include <idn/assert.h>
67 #include <idn/logmacro.h>
68 #include <idn/converter.h>
69 #include <idn/nameprep.h>
70 #include <idn/normalizer.h>
71 #include <idn/checker.h>
72 #include <idn/mapper.h>
73 #include <idn/mapselector.h>
74 #include <idn/delimitermap.h>
75 #include <idn/localencoding.h>
76 #include <idn/resconf.h>
77 #include <idn/debug.h>
78 #include <idn/util.h>
80 #ifdef WIN32
81 #define MAX_PATH_SIZE 500 /* a good longer than MAX_PATH */
82 #define IDNVAL_CONFFILE "ConfFile"
83 #else /* WIN32 */
85 #ifndef IDN_RESCONF_DIR
86 #define IDN_RESCONF_DIR "/etc"
87 #endif
88 #define IDN_RESCONF_FILE IDN_RESCONF_DIR "/idn.conf"
89 #define IDN_USER_RESCONF_FILE "/.idnrc"
91 #endif /* WIN32 */
93 #define MAX_CONF_LINE_LENGTH 255
94 #define MAX_CONF_LINE_ARGS 63
96 #define DEFAULT_CONF_NAMEPREP 0x0001
97 #define DEFAULT_CONF_IDN_ENCODING 0x0010
98 #define DEFAULT_CONF_ALL (DEFAULT_CONF_NAMEPREP | \
99 DEFAULT_CONF_IDN_ENCODING)
101 #define IDN_ENCODING_CURRENT "Punycode"
103 #ifdef ENABLE_MDNKIT_COMPAT
104 #define MDN_RESCONF_FILE IDN_RESCONF_DIR "/mdn.conf"
105 #endif
107 struct idn_resconf {
108 int local_converter_is_static;
109 idn_converter_t local_converter;
110 idn_converter_t idn_converter;
111 idn_converter_t aux_idn_converter;
112 idn_normalizer_t normalizer;
113 idn_checker_t prohibit_checker;
114 idn_checker_t unassigned_checker;
115 idn_checker_t bidi_checker;
116 idn_mapper_t mapper;
117 idn_mapselector_t local_mapper;
118 idn_delimitermap_t delimiter_mapper;
119 int reference_count;
122 static int initialized;
124 #ifndef WIN32
125 static const char * userhomedir(void);
126 #endif
127 static idn_result_t open_userdefaultfile(FILE **fpp);
128 static idn_result_t open_defaultfile(FILE **fpp);
129 static idn_result_t parse_conf(idn_resconf_t ctx, FILE *fp);
130 static idn_result_t parse_idn_encoding(idn_resconf_t ctx, char *args,
131 int lineno);
132 static idn_result_t parse_local_map(idn_resconf_t ctx, char *args,
133 int lineno);
134 static idn_result_t parse_nameprep(idn_resconf_t ctx, char *args,
135 int lineno);
136 static int split_args(char *s, char **av, int max_ac);
137 static void resetconf(idn_resconf_t ctx);
138 #ifndef WITHOUT_ICONV
139 static idn_result_t update_local_converter(idn_resconf_t ctx);
140 #endif
141 static idn_result_t setdefaults_body(idn_resconf_t ctx, int conf_mask);
143 idn_result_t
144 idn_resconf_initialize(void) {
145 idn_result_t r;
147 TRACE(("idn_resconf_initialize()\n"));
149 if (initialized) {
150 r = idn_success;
151 goto ret;
155 * Initialize sub modules.
157 if ((r = idn_converter_initialize()) != idn_success)
158 goto ret;
159 if ((r = idn_normalizer_initialize()) != idn_success)
160 goto ret;
161 if ((r = idn_checker_initialize()) != idn_success)
162 goto ret;
163 if ((r = idn_mapselector_initialize()) != idn_success)
164 goto ret;
165 if ((r = idn_mapper_initialize()) != idn_success)
166 goto ret;
168 r = idn_success;
169 initialized = 1;
170 ret:
171 TRACE(("idn_resconf_initialize(): %s\n", idn_result_tostring(r)));
172 return (r);
175 idn_result_t
176 idn_resconf_create(idn_resconf_t *ctxp) {
177 idn_resconf_t ctx = NULL;
178 idn_result_t r;
180 assert(ctxp != NULL);
182 TRACE(("idn_resconf_create()\n"));
184 if (!initialized) {
185 r = idn_failure;
186 goto ret;
188 if ((ctx = malloc(sizeof(*ctx))) == NULL) {
189 r = idn_nomemory;
190 goto ret;
193 ctx->local_converter_is_static = 0;
194 ctx->local_converter = NULL;
195 ctx->idn_converter = NULL;
196 ctx->aux_idn_converter = NULL;
197 ctx->normalizer = NULL;
198 ctx->prohibit_checker = NULL;
199 ctx->unassigned_checker = NULL;
200 ctx->bidi_checker = NULL;
201 ctx->mapper = NULL;
202 ctx->local_mapper = NULL;
203 ctx->reference_count = 1;
205 r = idn_delimitermap_create(&ctx->delimiter_mapper);
206 if (r != idn_success)
207 goto ret;
209 *ctxp = ctx;
210 r = idn_success;
211 ret:
212 TRACE(("idn_resconf_create(): %s\n", idn_result_tostring(r)));
213 return (r);
216 char *
217 idn_resconf_defaultfile() {
218 #ifdef WIN32
219 static char default_path[MAX_PATH_SIZE];
221 if (idn__util_getregistrystring(idn__util_hkey_localmachine,
222 IDNVAL_CONFFILE, default_path,
223 sizeof(default_path))) {
224 return (default_path);
225 } else {
226 return (NULL);
228 #else
229 return (IDN_RESCONF_FILE);
230 #endif
233 #ifndef WIN32
234 static const char *
235 userhomedir() {
236 uid_t uid;
237 struct passwd *pwd;
239 uid = getuid();
240 pwd = getpwuid(uid);
241 if (pwd == NULL) {
242 return (NULL);
245 return (pwd->pw_dir);
247 #endif
249 static idn_result_t
250 open_userdefaultfile(FILE **fpp) {
251 #ifdef WIN32
252 char user_path[MAX_PATH_SIZE];
254 TRACE(("open_userdefaultfile()\n"));
256 if (idn__util_getregistrystring(idn__util_hkey_currentuser,
257 IDNVAL_CONFFILE, user_path,
258 sizeof(user_path)) == 0) {
259 return (idn_nofile);
261 *fpp = fopen(user_path, "r");
262 if (*fpp == NULL) {
263 return (idn_nofile);
265 return (idn_success);
266 #else /* WIN32 */
267 const char *homedir;
268 char *file;
269 int len;
271 TRACE(("open_userdefaultfile()\n"));
273 homedir = userhomedir();
274 len = strlen(IDN_USER_RESCONF_FILE) + 1;
275 if (homedir != NULL) {
276 len += strlen(homedir);
277 } else {
278 return (idn_notfound);
281 file = (char *)malloc(sizeof(char) * len);
282 if (file == NULL) {
283 WARNING(("open_userdefaultfile(): malloc failed\n"));
284 return (idn_nomemory);
287 (void)strcpy(file, homedir);
288 strcat(file, IDN_USER_RESCONF_FILE);
290 *fpp = fopen(file, "r");
291 free(file);
292 if (*fpp == NULL) {
293 return (idn_nofile);
296 return (idn_success);
297 #endif /* WIN32 */
300 static idn_result_t
301 open_defaultfile(FILE **fpp) {
302 idn_result_t r;
303 const char *file;
305 r = open_userdefaultfile(fpp);
306 if (r == idn_nofile || r == idn_notfound) {
307 TRACE(("open_defaultfile: "
308 "cannot open user configuration file\n"));
309 file = idn_resconf_defaultfile();
310 *fpp = fopen(file, "r");
311 #ifdef ENABLE_MDNKIT_COMPAT
312 if (*fpp == NULL)
313 *fpp = fopen(MDN_RESCONF_FILE, "r");
314 #endif
315 if (*fpp == NULL) {
316 TRACE(("open_defaultfile: "
317 "cannot open system configuration file\n"));
318 return (idn_nofile);
320 } else if (r != idn_success) {
321 return (r);
324 return (idn_success);
327 idn_result_t
328 idn_resconf_loadfile(idn_resconf_t ctx, const char *file) {
329 FILE *fp = NULL;
330 idn_result_t r;
332 assert(ctx != NULL);
334 TRACE(("idn_resconf_loadfile(file=%s)\n",
335 file == NULL ? "<null>" : file));
337 resetconf(ctx);
338 r = idn_delimitermap_create(&ctx->delimiter_mapper);
339 if (r != idn_success) {
340 goto ret;
343 if (file == NULL) {
344 r = open_defaultfile(&fp);
345 if (r == idn_nofile || r == idn_notfound) {
346 r = setdefaults_body(ctx, 0);
347 goto ret;
348 } else if (r != idn_success) {
349 goto ret;
351 } else {
352 fp = fopen(file, "r");
353 if (fp == NULL) {
354 TRACE(("idn_resconf_loadfile: cannot open %-.40s\n",
355 file));
356 r = idn_nofile;
357 goto ret;
361 r = parse_conf(ctx, fp);
362 fclose(fp);
364 ret:
365 TRACE(("idn_resconf_loadfile(): %s\n", idn_result_tostring(r)));
366 return (r);
369 void
370 idn_resconf_destroy(idn_resconf_t ctx) {
371 assert(ctx != NULL);
373 TRACE(("idn_resconf_destroy()\n"));
375 ctx->reference_count--;
376 if (ctx->reference_count <= 0) {
377 resetconf(ctx);
378 free(ctx);
379 TRACE(("idn_resconf_destroy: the object is destroyed\n"));
380 } else {
381 TRACE(("idn_resconf_destroy(): "
382 "update reference count (%d->%d)\n",
383 ctx->reference_count + 1, ctx->reference_count));
387 void
388 idn_resconf_incrref(idn_resconf_t ctx) {
389 assert(ctx != NULL);
391 TRACE(("idn_resconf_incrref()\n"));
392 TRACE(("idn_resconf_incrref: update reference count (%d->%d)\n",
393 ctx->reference_count, ctx->reference_count + 1));
395 ctx->reference_count++;
398 idn_converter_t
399 idn_resconf_getalternateconverter(idn_resconf_t ctx) {
400 assert(ctx != NULL);
402 TRACE(("idn_resconf_getalternateconverter()\n"));
404 return (idn_resconf_getidnconverter(ctx));
407 idn_delimitermap_t
408 idn_resconf_getdelimitermap(idn_resconf_t ctx) {
409 assert(ctx != NULL);
411 TRACE(("idn_resconf_getdelimitermap()\n"));
413 if (ctx->delimiter_mapper != NULL)
414 idn_delimitermap_incrref(ctx->delimiter_mapper);
415 return (ctx->delimiter_mapper);
418 idn_converter_t
419 idn_resconf_getidnconverter(idn_resconf_t ctx) {
420 assert(ctx != NULL);
422 TRACE(("idn_resconf_getidnconverter()\n"));
424 if (ctx->idn_converter != NULL)
425 idn_converter_incrref(ctx->idn_converter);
426 return (ctx->idn_converter);
429 idn_converter_t
430 idn_resconf_getauxidnconverter(idn_resconf_t ctx) {
431 assert(ctx != NULL);
433 TRACE(("idn_resconf_getauxidnconverter()\n"));
435 if (ctx->aux_idn_converter != NULL)
436 idn_converter_incrref(ctx->aux_idn_converter);
437 return (ctx->aux_idn_converter);
440 idn_converter_t
441 idn_resconf_getlocalconverter(idn_resconf_t ctx) {
442 assert(ctx != NULL);
444 TRACE(("idn_resconf_getlocalconverter()\n"));
446 #ifdef WITHOUT_ICONV
447 return NULL;
449 #else /* WITHOUT_ICONV */
450 if (update_local_converter(ctx) != idn_success)
451 return (NULL);
453 idn_converter_incrref(ctx->local_converter);
454 return (ctx->local_converter);
456 #endif /* WITHOUT_ICONV */
459 idn_mapselector_t
460 idn_resconf_getlocalmapselector(idn_resconf_t ctx) {
461 assert(ctx != NULL);
463 TRACE(("idn_resconf_getlocalmapselector()\n"));
465 if (ctx->local_mapper != NULL)
466 idn_mapselector_incrref(ctx->local_mapper);
467 return (ctx->local_mapper);
470 idn_mapper_t
471 idn_resconf_getmapper(idn_resconf_t ctx) {
472 assert(ctx != NULL);
474 TRACE(("idn_resconf_getmapper()\n"));
476 if (ctx->mapper != NULL)
477 idn_mapper_incrref(ctx->mapper);
478 return (ctx->mapper);
481 idn_normalizer_t
482 idn_resconf_getnormalizer(idn_resconf_t ctx) {
483 assert(ctx != NULL);
485 TRACE(("idn_resconf_getnormalizer()\n"));
487 if (ctx->normalizer != NULL)
488 idn_normalizer_incrref(ctx->normalizer);
489 return (ctx->normalizer);
492 idn_checker_t
493 idn_resconf_getprohibitchecker(idn_resconf_t ctx) {
494 assert(ctx != NULL);
496 TRACE(("idn_resconf_getprohibitchecker()\n"));
498 if (ctx->prohibit_checker != NULL)
499 idn_checker_incrref(ctx->prohibit_checker);
500 return (ctx->prohibit_checker);
503 idn_checker_t
504 idn_resconf_getunassignedchecker(idn_resconf_t ctx) {
505 assert(ctx != NULL);
507 TRACE(("idn_resconf_getunassignedchecker()\n"));
509 if (ctx->unassigned_checker != NULL)
510 idn_checker_incrref(ctx->unassigned_checker);
511 return (ctx->unassigned_checker);
514 idn_checker_t
515 idn_resconf_getbidichecker(idn_resconf_t ctx) {
516 assert(ctx != NULL);
518 TRACE(("idn_resconf_getbidichecker()\n"));
520 if (ctx->bidi_checker != NULL)
521 idn_checker_incrref(ctx->bidi_checker);
522 return (ctx->bidi_checker);
525 void
526 idn_resconf_setalternateconverter(idn_resconf_t ctx,
527 idn_converter_t alternate_converter) {
528 assert(ctx != NULL);
530 TRACE(("idn_resconf_setalternateconverter()\n"));
533 void
534 idn_resconf_setdelimitermap(idn_resconf_t ctx,
535 idn_delimitermap_t delimiter_mapper) {
536 assert(ctx != NULL);
538 TRACE(("idn_resconf_setdelimitermap()\n"));
540 if (ctx->delimiter_mapper != NULL)
541 idn_delimitermap_destroy(ctx->delimiter_mapper);
542 ctx->delimiter_mapper = delimiter_mapper;
543 if (delimiter_mapper != NULL)
544 idn_delimitermap_incrref(ctx->delimiter_mapper);
547 void
548 idn_resconf_setidnconverter(idn_resconf_t ctx,
549 idn_converter_t idn_converter) {
550 assert(ctx != NULL);
552 TRACE(("idn_resconf_setidnconverter()\n"));
554 if (ctx->idn_converter != NULL)
555 idn_converter_destroy(ctx->idn_converter);
556 ctx->idn_converter = idn_converter;
557 if (idn_converter != NULL)
558 idn_converter_incrref(ctx->idn_converter);
561 void
562 idn_resconf_setauxidnconverter(idn_resconf_t ctx,
563 idn_converter_t aux_idn_converter) {
564 assert(ctx != NULL);
566 TRACE(("idn_resconf_setauxidnconverter()\n"));
568 if (ctx->aux_idn_converter != NULL)
569 idn_converter_destroy(ctx->aux_idn_converter);
570 ctx->aux_idn_converter = aux_idn_converter;
571 if (aux_idn_converter != NULL)
572 idn_converter_incrref(ctx->aux_idn_converter);
575 void
576 idn_resconf_setlocalconverter(idn_resconf_t ctx,
577 idn_converter_t local_converter) {
578 #ifndef WITHOUT_ICONV
579 assert(ctx != NULL);
581 TRACE(("idn_resconf_setlocalconverter()\n"));
583 if (ctx->local_converter != NULL) {
584 idn_converter_destroy(ctx->local_converter);
585 ctx->local_converter = NULL;
588 if (local_converter == NULL)
589 ctx->local_converter_is_static = 0;
590 else {
591 ctx->local_converter = local_converter;
592 idn_converter_incrref(local_converter);
593 ctx->local_converter_is_static = 1;
595 #endif /* WITHOUT_ICONV */
598 void
599 idn_resconf_setlocalmapselector(idn_resconf_t ctx,
600 idn_mapselector_t local_mapper) {
601 assert(ctx != NULL);
603 TRACE(("idn_resconf_setlocalmapselector()\n"));
605 if (ctx->local_mapper != NULL)
606 idn_mapselector_destroy(ctx->local_mapper);
607 ctx->local_mapper = local_mapper;
608 if (local_mapper != NULL)
609 idn_mapselector_incrref(ctx->local_mapper);
612 void
613 idn_resconf_setmapper(idn_resconf_t ctx, idn_mapper_t mapper) {
614 assert(ctx != NULL);
616 TRACE(("idn_resconf_setmapper()\n"));
618 if (ctx->mapper != NULL)
619 idn_mapper_destroy(ctx->mapper);
620 ctx->mapper = mapper;
621 if (mapper != NULL)
622 idn_mapper_incrref(ctx->mapper);
625 void
626 idn_resconf_setnormalizer(idn_resconf_t ctx, idn_normalizer_t normalizer) {
627 assert(ctx != NULL);
629 TRACE(("idn_resconf_setnormalizer()\n"));
631 if (ctx->normalizer != NULL)
632 idn_normalizer_destroy(ctx->normalizer);
633 ctx->normalizer = normalizer;
634 if (normalizer != NULL)
635 idn_normalizer_incrref(ctx->normalizer);
638 void
639 idn_resconf_setprohibitchecker(idn_resconf_t ctx,
640 idn_checker_t prohibit_checker) {
641 assert(ctx != NULL);
643 TRACE(("idn_resconf_setprohibitchecker()\n"));
645 if (ctx->prohibit_checker != NULL)
646 idn_checker_destroy(ctx->prohibit_checker);
647 ctx->prohibit_checker = prohibit_checker;
648 if (prohibit_checker != NULL)
649 idn_checker_incrref(ctx->prohibit_checker);
652 void
653 idn_resconf_setunassignedchecker(idn_resconf_t ctx,
654 idn_checker_t unassigned_checker) {
655 assert(ctx != NULL);
657 TRACE(("idn_resconf_setunassignedchecker()\n"));
659 if (ctx->unassigned_checker != NULL)
660 idn_checker_destroy(ctx->unassigned_checker);
661 ctx->unassigned_checker = unassigned_checker;
662 if (unassigned_checker != NULL)
663 idn_checker_incrref(ctx->unassigned_checker);
666 void
667 idn_resconf_setbidichecker(idn_resconf_t ctx,
668 idn_checker_t bidi_checker) {
669 assert(ctx != NULL);
671 TRACE(("idn_resconf_setbidichecker()\n"));
673 if (ctx->bidi_checker != NULL)
674 idn_checker_destroy(ctx->bidi_checker);
675 ctx->bidi_checker = bidi_checker;
676 if (bidi_checker != NULL)
677 idn_checker_incrref(ctx->bidi_checker);
680 idn_result_t
681 idn_resconf_setnameprepversion(idn_resconf_t ctx, const char *version)
683 char prohibit_scheme_name[MAX_CONF_LINE_LENGTH + 1];
684 char unassigned_scheme_name[MAX_CONF_LINE_LENGTH + 1];
685 char bidi_scheme_name[MAX_CONF_LINE_LENGTH + 1];
686 idn_mapper_t mapper = NULL;
687 idn_normalizer_t normalizer = NULL;
688 idn_checker_t prohibit_checker = NULL;
689 idn_checker_t unassigned_checker = NULL;
690 idn_checker_t bidi_checker = NULL;
691 idn_result_t r;
693 assert(ctx != NULL && version != NULL);
695 TRACE(("idn_resconf_setnameprepversion()\n"));
698 * Set canonical scheme names.
700 if (strlen(version) + strlen(IDN_CHECKER_PROHIBIT_PREFIX)
701 > MAX_CONF_LINE_LENGTH) {
702 r = idn_invalid_name;
703 goto failure;
705 sprintf(prohibit_scheme_name, "%s%s",
706 IDN_CHECKER_PROHIBIT_PREFIX, version);
708 if (strlen(version) + strlen(IDN_CHECKER_UNASSIGNED_PREFIX)
709 > MAX_CONF_LINE_LENGTH) {
710 r = idn_invalid_name;
711 goto failure;
713 sprintf(unassigned_scheme_name, "%s%s",
714 IDN_CHECKER_UNASSIGNED_PREFIX, version);
716 if (strlen(version) + strlen(IDN_CHECKER_BIDI_PREFIX)
717 > MAX_CONF_LINE_LENGTH) {
718 r = idn_invalid_name;
719 goto failure;
721 sprintf(bidi_scheme_name, "%s%s",
722 IDN_CHECKER_BIDI_PREFIX, version);
725 * Create objects.
727 r = idn_mapper_create(&mapper);
728 if (r != idn_success)
729 goto failure;
730 r = idn_normalizer_create(&normalizer);
731 if (r != idn_success)
732 goto failure;
733 r = idn_checker_create(&prohibit_checker);
734 if (r != idn_success)
735 goto failure;
736 r = idn_checker_create(&unassigned_checker);
737 if (r != idn_success)
738 goto failure;
739 r = idn_checker_create(&bidi_checker);
740 if (r != idn_success)
741 goto failure;
743 r = idn_mapper_add(mapper, version);
744 if (r != idn_success)
745 goto failure;
746 r = idn_normalizer_add(normalizer, version);
747 if (r != idn_success)
748 goto failure;
749 r = idn_checker_add(prohibit_checker, prohibit_scheme_name);
750 if (r != idn_success)
751 goto failure;
752 r = idn_checker_add(unassigned_checker, unassigned_scheme_name);
753 if (r != idn_success)
754 goto failure;
755 r = idn_checker_add(bidi_checker, bidi_scheme_name);
756 if (r != idn_success)
757 goto failure;
760 * Set the objects.
762 idn_resconf_setmapper(ctx, mapper);
763 idn_resconf_setnormalizer(ctx, normalizer);
764 idn_resconf_setprohibitchecker(ctx, prohibit_checker);
765 idn_resconf_setunassignedchecker(ctx, unassigned_checker);
766 idn_resconf_setbidichecker(ctx, bidi_checker);
769 * Destroy the objects.
771 idn_mapper_destroy(mapper);
772 idn_normalizer_destroy(normalizer);
773 idn_checker_destroy(prohibit_checker);
774 idn_checker_destroy(unassigned_checker);
775 idn_checker_destroy(bidi_checker);
777 return (idn_success);
779 failure:
780 if (mapper != NULL)
781 idn_mapper_destroy(mapper);
782 if (normalizer != NULL)
783 idn_normalizer_destroy(normalizer);
784 if (prohibit_checker != NULL)
785 idn_checker_destroy(prohibit_checker);
786 if (unassigned_checker != NULL)
787 idn_checker_destroy(unassigned_checker);
788 if (bidi_checker != NULL)
789 idn_checker_destroy(bidi_checker);
791 return (r);
794 idn_result_t
795 idn_resconf_setalternateconvertername(idn_resconf_t ctx, const char *name,
796 int flags) {
797 assert(ctx != NULL && name != NULL);
799 TRACE(("idn_resconf_setalternateconvertername(name=%s, flags=%d)\n",
800 name, flags));
802 return (idn_success);
805 idn_result_t
806 idn_resconf_setidnconvertername(idn_resconf_t ctx, const char *name,
807 int flags) {
808 idn_converter_t idn_converter;
809 idn_result_t r;
811 assert(ctx != NULL && name != NULL);
813 TRACE(("idn_resconf_setidnconvertername(name=%s, flags=%d)\n",
814 name, flags));
816 r = idn_converter_create(name, &idn_converter, flags);
817 if (r != idn_success)
818 return (r);
820 if (ctx->idn_converter != NULL)
821 idn_converter_destroy(ctx->idn_converter);
822 ctx->idn_converter = idn_converter;
824 return (idn_success);
827 idn_result_t
828 idn_resconf_setauxidnconvertername(idn_resconf_t ctx, const char *name,
829 int flags) {
830 idn_converter_t aux_idn_converter;
831 const char *old_name;
832 idn_result_t r;
834 assert(ctx != NULL && name != NULL);
836 TRACE(("idn_resconf_setauxidnconvertername(name=%s, flags=%d)\n",
837 name, flags));
839 if (ctx->aux_idn_converter != NULL) {
840 old_name = idn_converter_localencoding(ctx->aux_idn_converter);
841 if (old_name != NULL && strcmp(old_name, name) == 0)
842 return (idn_success);
845 r = idn_converter_create(name, &aux_idn_converter, flags);
846 if (r != idn_success)
847 return (r);
849 if (ctx->aux_idn_converter != NULL)
850 idn_converter_destroy(ctx->aux_idn_converter);
851 ctx->aux_idn_converter = aux_idn_converter;
853 return (idn_success);
856 idn_result_t
857 idn_resconf_setlocalconvertername(idn_resconf_t ctx, const char *name,
858 int flags) {
859 #ifdef WITHOUT_ICONV
860 return idn_failure;
862 #else /* WITHOUT_ICONV */
863 idn_converter_t local_converter;
864 idn_result_t r;
866 assert(ctx != NULL);
868 TRACE(("idn_resconf_setlocalconvertername(name=%s, flags=%d)\n",
869 name == NULL ? "<null>" : name, flags));
871 if (ctx->local_converter != NULL) {
872 idn_converter_destroy(ctx->local_converter);
873 ctx->local_converter = NULL;
875 ctx->local_converter_is_static = 0;
877 if (name != NULL) {
878 r = idn_converter_create(name, &local_converter, flags);
879 if (r != idn_success)
880 return (r);
881 ctx->local_converter = local_converter;
882 ctx->local_converter_is_static = 1;
885 return (idn_success);
887 #endif /* WITHOUT_ICONV */
890 idn_result_t
891 idn_resconf_addalldelimitermapucs(idn_resconf_t ctx, unsigned long *v,
892 int nv) {
893 idn_result_t r;
895 TRACE(("idn_resconf_addalldelimitermapucs(nv=%d)\n", nv));
897 if (ctx->delimiter_mapper == NULL) {
898 r = idn_delimitermap_create(&(ctx->delimiter_mapper));
899 if (r != idn_success)
900 return (r);
903 r = idn_delimitermap_addall(ctx->delimiter_mapper, v, nv);
904 return (r);
907 idn_result_t
908 idn_resconf_addalllocalmapselectornames(idn_resconf_t ctx, const char *tld,
909 const char **names, int nnames) {
910 idn_result_t r;
912 assert(ctx != NULL && names != NULL && tld != NULL);
914 TRACE(("idn_resconf_addalllocalmapselectorname(tld=%s, nnames=%d)\n",
915 tld, nnames));
917 if (ctx->local_mapper == NULL) {
918 r = idn_mapselector_create(&(ctx->local_mapper));
919 if (r != idn_success)
920 return (r);
923 r = idn_mapselector_addall(ctx->local_mapper, tld, names, nnames);
924 return (r);
927 idn_result_t
928 idn_resconf_addallmappernames(idn_resconf_t ctx, const char **names,
929 int nnames) {
930 idn_result_t r;
932 assert(ctx != NULL && names != NULL);
934 TRACE(("idn_resconf_addallmappername()\n"));
936 if (ctx->mapper == NULL) {
937 r = idn_mapper_create(&(ctx->mapper));
938 if (r != idn_success)
939 return (r);
942 r = idn_mapper_addall(ctx->mapper, names, nnames);
943 return (r);
946 idn_result_t
947 idn_resconf_addallnormalizernames(idn_resconf_t ctx, const char **names,
948 int nnames) {
949 idn_result_t r;
951 assert(ctx != NULL && names != NULL);
953 TRACE(("idn_resconf_addallnormalizername(nnames=%d)\n", nnames));
955 if (ctx->normalizer == NULL) {
956 r = idn_normalizer_create(&(ctx->normalizer));
957 if (r != idn_success)
958 return (r);
961 r = idn_normalizer_addall(ctx->normalizer, names, nnames);
962 return (r);
965 idn_result_t
966 idn_resconf_addallprohibitcheckernames(idn_resconf_t ctx, const char **names,
967 int nnames) {
968 char long_name[MAX_CONF_LINE_LENGTH + 1];
969 idn_result_t r;
970 int i;
972 assert(ctx != NULL && names != NULL);
974 TRACE(("idn_resconf_addallprohibitcheckername(nnames=%d)\n", nnames));
976 if (ctx->prohibit_checker == NULL) {
977 r = idn_checker_create(&(ctx->prohibit_checker));
978 if (r != idn_success)
979 return (r);
982 for (i = 0; i < nnames; i++, names++) {
983 if (strlen(*names) + strlen(IDN_CHECKER_PROHIBIT_PREFIX)
984 > MAX_CONF_LINE_LENGTH) {
985 return (idn_invalid_name);
987 strcpy(long_name, IDN_CHECKER_PROHIBIT_PREFIX);
988 strcat(long_name, *names);
990 r = idn_checker_add(ctx->prohibit_checker, long_name);
991 if (r != idn_success)
992 return (r);
995 return (idn_success);
998 idn_result_t
999 idn_resconf_addallunassignedcheckernames(idn_resconf_t ctx, const char **names,
1000 int nnames) {
1001 char long_name[MAX_CONF_LINE_LENGTH + 1];
1002 idn_result_t r;
1003 int i;
1005 assert(ctx != NULL && names != NULL);
1007 TRACE(("idn_resconf_addallunassignedcheckername(nnames=%d)\n",
1008 nnames));
1010 if (ctx->unassigned_checker == NULL) {
1011 r = idn_checker_create(&(ctx->unassigned_checker));
1012 if (r != idn_success)
1013 return (r);
1016 for (i = 0; i < nnames; i++, names++) {
1017 if (strlen(*names) + strlen(IDN_CHECKER_UNASSIGNED_PREFIX)
1018 > MAX_CONF_LINE_LENGTH) {
1019 return (idn_invalid_name);
1021 strcpy(long_name, IDN_CHECKER_UNASSIGNED_PREFIX);
1022 strcat(long_name, *names);
1024 r = idn_checker_add(ctx->unassigned_checker, long_name);
1025 if (r != idn_success)
1026 return (r);
1029 return (idn_success);
1032 idn_result_t
1033 idn_resconf_addallbidicheckernames(idn_resconf_t ctx, const char **names,
1034 int nnames) {
1035 char long_name[MAX_CONF_LINE_LENGTH + 1];
1036 idn_result_t r;
1037 int i;
1039 assert(ctx != NULL && names != NULL);
1041 TRACE(("idn_resconf_addallbidicheckername(nnames=%d)\n", nnames));
1043 if (ctx->bidi_checker == NULL) {
1044 r = idn_checker_create(&(ctx->bidi_checker));
1045 if (r != idn_success)
1046 return (r);
1049 for (i = 0; i < nnames; i++, names++) {
1050 if (strlen(*names) + strlen(IDN_CHECKER_BIDI_PREFIX)
1051 > MAX_CONF_LINE_LENGTH) {
1052 return (idn_invalid_name);
1054 strcpy(long_name, IDN_CHECKER_BIDI_PREFIX);
1055 strcat(long_name, *names);
1057 r = idn_checker_add(ctx->bidi_checker, long_name);
1058 if (r != idn_success)
1059 return (r);
1062 return (idn_success);
1065 static idn_result_t
1066 parse_conf(idn_resconf_t ctx, FILE *fp) {
1067 char line[MAX_CONF_LINE_LENGTH + 1];
1068 int lineno = 0;
1069 char *argv[3];
1070 int argc;
1071 idn_result_t r;
1072 int conf_mask = 0;
1074 TRACE(("parse_conf()\n"));
1077 * Parse config file. parsing of 'idn-encoding' line is
1078 * postponed because 'alias-file' line must be processed
1079 * before them.
1081 while (fgets(line, sizeof(line), fp) != NULL) {
1082 char *newline;
1084 lineno++;
1085 newline = strpbrk(line, "\r\n");
1086 if (newline != NULL)
1087 *newline = '\0';
1088 else if (fgetc(fp) != EOF) {
1089 ERROR(("libidnkit: too long line \"%-.30s\", "
1090 "line %d\n", line, lineno));
1091 return (idn_invalid_syntax);
1094 argc = split_args(line, argv, 2);
1095 if (argc == -1) {
1096 ERROR(("libidnkit: syntax error, line %d\n", lineno));
1097 return (idn_invalid_syntax);
1098 } else if (argc == 0 || argv[0][0] == '#') {
1099 continue;
1100 } else if (argc == 1) {
1101 ERROR(("libidnkit: syntax error, line %d\n", lineno));
1102 return (idn_invalid_syntax);
1105 if (strcmp(argv[0], "idn-encoding") == 0) {
1106 if (conf_mask & DEFAULT_CONF_IDN_ENCODING) {
1107 ERROR(("libidnkit: \"%s\" redefined, "
1108 "line %d\n", argv[0], lineno));
1109 r = idn_invalid_syntax;
1110 } else {
1111 conf_mask |= DEFAULT_CONF_IDN_ENCODING;
1112 r = parse_idn_encoding(ctx, argv[1], lineno);
1114 } else if (strcmp(argv[0], "local-map") == 0) {
1115 r = parse_local_map(ctx, argv[1], lineno);
1117 } else if (strcmp(argv[0], "nameprep") == 0) {
1118 if (conf_mask & DEFAULT_CONF_NAMEPREP) {
1119 ERROR(("libidnkit: \"%s\" redefined, "
1120 "line %d\n", argv[0], lineno));
1121 r = idn_invalid_syntax;
1122 } else {
1123 conf_mask |= DEFAULT_CONF_NAMEPREP;
1124 r = parse_nameprep(ctx, argv[1], lineno);
1126 } else if (strcmp(argv[0], "nameprep-map") == 0 ||
1127 strcmp(argv[0], "nameprep-normalize") == 0 ||
1128 strcmp(argv[0], "nameprep-prohibit") == 0 ||
1129 strcmp(argv[0], "nameprep-unassigned") == 0 ||
1130 strcmp(argv[0], "alias-file") == 0 ||
1131 strcmp(argv[0], "encoding-alias-file") == 0 ||
1132 strcmp(argv[0], "normalize") == 0 ||
1133 strcmp(argv[0], "server-encoding") == 0 ||
1134 strcmp(argv[0], "alternate-encoding") == 0 ||
1135 strcmp(argv[0], "delimiter-map") == 0) {
1136 WARNING(("libidnkit: obsolete command \"%s\", line %d "
1137 "(ignored)\n", argv[0], lineno));
1138 r = idn_success;
1139 } else {
1140 ERROR(("libidnkit: unknown command \"%-.30s\", "
1141 "line %d\n", argv[0], lineno));
1142 r = idn_invalid_syntax;
1144 if (r != idn_success)
1145 return (r);
1148 lineno++;
1150 if (conf_mask != DEFAULT_CONF_ALL) {
1151 return setdefaults_body(ctx, conf_mask);
1154 return (idn_success);
1157 static idn_result_t
1158 parse_idn_encoding(idn_resconf_t ctx, char *args, int lineno) {
1159 idn_result_t r;
1160 char *argv[MAX_CONF_LINE_ARGS + 1];
1161 int argc;
1163 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1165 if (argc != 1) {
1166 ERROR(("libidnkit: wrong # of args for idn-encoding, "
1167 "line %d\n", lineno));
1168 return (idn_invalid_syntax);
1171 r = idn_converter_create(argv[0], &ctx->idn_converter,
1172 IDN_CONVERTER_DELAYEDOPEN |
1173 IDN_CONVERTER_RTCHECK);
1174 if (r != idn_success) {
1175 ERROR(("libidnkit: cannot create idn converter, %s, "
1176 "line %d\n", idn_result_tostring(r), lineno));
1179 return (r);
1182 static idn_result_t
1183 parse_local_map(idn_resconf_t ctx, char *args, int lineno) {
1184 idn_result_t r;
1185 char *argv[MAX_CONF_LINE_ARGS + 1];
1186 int argc;
1187 int i;
1189 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1191 if (argc < 2 || argc > MAX_CONF_LINE_ARGS) {
1192 ERROR(("libidnkit: wrong # of args for local-map, line %d\n",
1193 lineno));
1194 return (idn_invalid_syntax);
1197 if (ctx->local_mapper == NULL) {
1198 r = idn_mapselector_create(&ctx->local_mapper);
1199 if (r != idn_success) {
1200 ERROR(("libidnkit: cannot create local mapper, %s, "
1201 "line %d\n", idn_result_tostring(r), lineno));
1202 return (r);
1206 for (i = 1; i < argc; i++) {
1207 r = idn_mapselector_add(ctx->local_mapper, argv[0], argv[i]);
1208 if (r == idn_invalid_name) {
1209 ERROR(("libidnkit: map scheme unavailable \"%-.30s\""
1210 " or invalid TLD \"%-.30s\", line %d\n",
1211 argv[i], argv[0], lineno));
1212 return (r);
1213 } else if (r != idn_success) {
1214 return (r);
1218 return (idn_success);
1221 static idn_result_t
1222 parse_nameprep(idn_resconf_t ctx, char *args, int lineno) {
1223 idn_result_t r;
1224 char *argv[MAX_CONF_LINE_ARGS + 1];
1225 char scheme_name[MAX_CONF_LINE_LENGTH + 1];
1226 int argc;
1228 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1230 if (argc != 1) {
1231 ERROR(("libidnkit: wrong # of args for nameprep, line %d\n",
1232 lineno));
1233 return (idn_invalid_syntax);
1237 * Set mapper.
1239 r = idn_mapper_create(&ctx->mapper);
1240 if (r != idn_success) {
1241 ERROR(("libidnkit: cannot create mapper, %s, line %d\n",
1242 idn_result_tostring(r), lineno));
1243 return (r);
1246 r = idn_mapper_add(ctx->mapper, argv[0]);
1247 if (r == idn_invalid_name) {
1248 ERROR(("libidnkit: map scheme unavailable \"%-.30s\", "
1249 "line %d\n", argv[0], lineno));
1250 return (r);
1251 } else if (r != idn_success) {
1252 return (r);
1256 * Set normalizer.
1258 r = idn_normalizer_create(&ctx->normalizer);
1259 if (r != idn_success) {
1260 ERROR(("libidnkit: cannot create normalizer, %s, line %d\n",
1261 idn_result_tostring(r), lineno));
1262 return (r);
1265 r = idn_normalizer_add(ctx->normalizer, argv[0]);
1266 if (r == idn_invalid_name) {
1267 ERROR(("libidnkit: unknown normalization scheme \"%-.30s\", "
1268 "line %d\n", argv[0], lineno));
1269 return (r);
1270 } else if (r != idn_success) {
1271 return (r);
1275 * Set prohibit checker.
1277 r = idn_checker_create(&ctx->prohibit_checker);
1278 if (r != idn_success) {
1279 ERROR(("libidnkit: cannot create prohibit checker, %s, "
1280 "line %d\n", idn_result_tostring(r), lineno));
1281 return (r);
1284 sprintf(scheme_name, "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, argv[0]);
1285 r = idn_checker_add(ctx->prohibit_checker, scheme_name);
1286 if (r == idn_invalid_name) {
1287 ERROR(("libidnkit: unknown prohibit scheme \"%-.30s\", "
1288 "line %d\n", argv[0], lineno));
1289 return (r);
1290 } else if (r != idn_success) {
1291 return (r);
1295 * Set unassigned checker.
1297 r = idn_checker_create(&ctx->unassigned_checker);
1298 if (r != idn_success) {
1299 ERROR(("libidnkit: cannot create unassigned checker, %s, "
1300 "line %d\n", idn_result_tostring(r), lineno));
1301 return (r);
1304 sprintf(scheme_name, "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, argv[0]);
1305 r = idn_checker_add(ctx->unassigned_checker, scheme_name);
1306 if (r == idn_invalid_name) {
1307 ERROR(("libidnkit: unknown unassigned scheme \"%-.30s\", "
1308 "line %d\n", argv[0], lineno));
1309 return (r);
1310 } else if (r != idn_success) {
1311 return (r);
1315 * Set bidi checker.
1317 r = idn_checker_create(&ctx->bidi_checker);
1318 if (r != idn_success) {
1319 ERROR(("libidnkit: cannot create bidi checker, %s, line %d\n",
1320 idn_result_tostring(r), lineno));
1321 return (r);
1324 sprintf(scheme_name, "%s%s", IDN_CHECKER_BIDI_PREFIX, argv[0]);
1325 r = idn_checker_add(ctx->bidi_checker, scheme_name);
1326 if (r == idn_invalid_name) {
1327 ERROR(("libidnkit: unknown bidi scheme \"%-.30s\", "
1328 "line %d\n", argv[0], lineno));
1329 return (r);
1330 } else if (r != idn_success) {
1331 return (r);
1334 return (idn_success);
1337 static int
1338 split_args(char *s, char **av, int max_ac) {
1339 int ac;
1340 int i;
1342 for (ac = 0; *s != '\0' && ac < max_ac; ac++) {
1343 if (ac > 0)
1344 *s++ = '\0';
1345 while (isspace((unsigned char)*s))
1346 s++;
1347 if (*s == '\0')
1348 break;
1349 if (*s == '"' || *s == '\'') {
1350 int qc = *s++;
1351 av[ac] = s;
1352 while (*s != qc) {
1353 if (*s == '\0')
1354 return (-1);
1355 s++;
1357 } else {
1358 av[ac] = s;
1359 while (*s != '\0' && !isspace((unsigned char)*s))
1360 s++;
1364 for (i = ac; i < max_ac; i++)
1365 av[i] = NULL;
1367 return (ac);
1370 static void
1371 resetconf(idn_resconf_t ctx) {
1372 #ifndef WITHOUT_ICONV
1373 idn_resconf_setlocalconverter(ctx, NULL);
1374 #endif
1375 idn_resconf_setidnconverter(ctx, NULL);
1376 idn_resconf_setauxidnconverter(ctx, NULL);
1377 idn_resconf_setdelimitermap(ctx, NULL);
1378 idn_resconf_setlocalmapselector(ctx, NULL);
1379 idn_resconf_setmapper(ctx, NULL);
1380 idn_resconf_setnormalizer(ctx, NULL);
1381 idn_resconf_setprohibitchecker(ctx, NULL);
1382 idn_resconf_setunassignedchecker(ctx, NULL);
1383 idn_resconf_setbidichecker(ctx, NULL);
1386 #ifndef WITHOUT_ICONV
1387 static idn_result_t
1388 update_local_converter(idn_resconf_t ctx) {
1389 idn_result_t r;
1390 const char *old_encoding;
1391 const char *new_encoding;
1394 * We don't update local converter, if the converter is set
1395 * by idn_resconf_setlocalconverter() or
1396 * idn_resconf_setlocalconvertername().
1398 if (ctx->local_converter_is_static)
1399 return (idn_success);
1402 * Update the local converter if the local encoding is changed.
1404 old_encoding = (ctx->local_converter != NULL) ?
1405 idn_converter_localencoding(ctx->local_converter) :
1406 NULL;
1407 new_encoding = idn_localencoding_name();
1408 if (new_encoding == NULL) {
1409 ERROR(("cannot determine local codeset name\n"));
1410 return (idn_notfound);
1413 if (old_encoding != NULL &&
1414 new_encoding != NULL &&
1415 strcmp(old_encoding, new_encoding) == 0) {
1416 return (idn_success);
1419 if (ctx->local_converter != NULL) {
1420 idn_converter_destroy(ctx->local_converter);
1421 ctx->local_converter = NULL;
1424 r = idn_converter_create(new_encoding,
1425 &ctx->local_converter,
1426 IDN_CONVERTER_RTCHECK);
1427 return (r);
1429 #endif
1431 idn_result_t
1432 idn_resconf_setdefaults(idn_resconf_t ctx)
1434 idn_result_t r;
1436 assert(ctx != NULL);
1438 TRACE(("idn_resconf_setdefaults()\n"));
1440 resetconf(ctx);
1441 r = idn_delimitermap_create(&ctx->delimiter_mapper);
1442 if (r != idn_success) {
1443 ERROR(("libidnkit: cannot create delimiter mapper, %s\n",
1444 idn_result_tostring(r)));
1445 return (r);
1448 return setdefaults_body(ctx, 0);
1451 static idn_result_t
1452 setdefaults_body(idn_resconf_t ctx, int conf_mask) {
1453 idn_result_t r;
1455 TRACE(("setdefaults_body()\n"));
1456 assert(ctx != NULL);
1458 if (!(conf_mask & DEFAULT_CONF_NAMEPREP)) {
1459 TRACE(("set default nameprep\n"));
1460 r = idn_resconf_setnameprepversion(ctx, IDN_NAMEPREP_CURRENT);
1461 if (r != idn_success) {
1462 return (r);
1465 if (!(conf_mask & DEFAULT_CONF_IDN_ENCODING)) {
1466 TRACE(("set default idn encoding\n"));
1467 r = idn_converter_create(IDN_ENCODING_CURRENT,
1468 &ctx->idn_converter,
1469 IDN_CONVERTER_DELAYEDOPEN |
1470 IDN_CONVERTER_RTCHECK);
1471 if (r != idn_success) {
1472 ERROR(("libidnkit: cannot create idn converter, %s\n",
1473 idn_result_tostring(r)));
1474 return (r);
1478 return (idn_success);