1 /* $NetBSD: resconf.c,v 1.4 2014/12/10 04:37:55 christos Exp $ */
2
3 #ifndef lint
4 static char *rcsid = "Id: resconf.c,v 1.1 2003/06/04 00:26:12 marka Exp ";
5 #endif
6
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.
11 *
12 * LICENSE TERMS AND CONDITIONS
13 *
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.
18 *
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.
22 *
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.
25 *
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."
31 *
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.
35 *
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.
47 */
48
49 #include <config.h>
50
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
64
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>
79
80 #ifdef WIN32
81 #define MAX_PATH_SIZE 500 /* a good longer than MAX_PATH */
82 #define IDNVAL_CONFFILE "ConfFile"
83 #else /* WIN32 */
84
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"
90
91 #endif /* WIN32 */
92
93 #define MAX_CONF_LINE_LENGTH 255
94 #define MAX_CONF_LINE_ARGS 63
95
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)
100
101 #define IDN_ENCODING_CURRENT "Punycode"
102
103 #ifdef ENABLE_MDNKIT_COMPAT
104 #define MDN_RESCONF_FILE IDN_RESCONF_DIR "/mdn.conf"
105 #endif
106
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;
120 };
121
122 static int initialized;
123
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);
142
143 idn_result_t
idn_resconf_initialize(void)144 idn_resconf_initialize(void) {
145 idn_result_t r;
146
147 TRACE(("idn_resconf_initialize()\n"));
148
149 if (initialized) {
150 r = idn_success;
151 goto ret;
152 }
153
154 /*
155 * Initialize sub modules.
156 */
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;
167
168 r = idn_success;
169 initialized = 1;
170 ret:
171 TRACE(("idn_resconf_initialize(): %s\n", idn_result_tostring(r)));
172 return (r);
173 }
174
175 idn_result_t
idn_resconf_create(idn_resconf_t * ctxp)176 idn_resconf_create(idn_resconf_t *ctxp) {
177 idn_resconf_t ctx = NULL;
178 idn_result_t r;
179
180 assert(ctxp != NULL);
181
182 TRACE(("idn_resconf_create()\n"));
183
184 if (!initialized) {
185 r = idn_failure;
186 goto ret;
187 }
188 if ((ctx = malloc(sizeof(*ctx))) == NULL) {
189 r = idn_nomemory;
190 goto ret;
191 }
192
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;
204
205 r = idn_delimitermap_create(&ctx->delimiter_mapper);
206 if (r != idn_success)
207 goto ret;
208
209 *ctxp = ctx;
210 r = idn_success;
211 ret:
212 TRACE(("idn_resconf_create(): %s\n", idn_result_tostring(r)));
213 return (r);
214 }
215
216 char *
idn_resconf_defaultfile()217 idn_resconf_defaultfile() {
218 #ifdef WIN32
219 static char default_path[MAX_PATH_SIZE];
220
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);
227 }
228 #else
229 return (IDN_RESCONF_FILE);
230 #endif
231 }
232
233 #ifndef WIN32
234 static const char *
userhomedir()235 userhomedir() {
236 uid_t uid;
237 struct passwd *pwd;
238
239 uid = getuid();
240 pwd = getpwuid(uid);
241 if (pwd == NULL) {
242 return (NULL);
243 }
244
245 return (pwd->pw_dir);
246 }
247 #endif
248
249 static idn_result_t
open_userdefaultfile(FILE ** fpp)250 open_userdefaultfile(FILE **fpp) {
251 #ifdef WIN32
252 char user_path[MAX_PATH_SIZE];
253
254 TRACE(("open_userdefaultfile()\n"));
255
256 if (idn__util_getregistrystring(idn__util_hkey_currentuser,
257 IDNVAL_CONFFILE, user_path,
258 sizeof(user_path)) == 0) {
259 return (idn_nofile);
260 }
261 *fpp = fopen(user_path, "r");
262 if (*fpp == NULL) {
263 return (idn_nofile);
264 }
265 return (idn_success);
266 #else /* WIN32 */
267 const char *homedir;
268 char *file;
269 int len;
270
271 TRACE(("open_userdefaultfile()\n"));
272
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);
279 }
280
281 file = (char *)malloc(sizeof(char) * len);
282 if (file == NULL) {
283 WARNING(("open_userdefaultfile(): malloc failed\n"));
284 return (idn_nomemory);
285 }
286
287 (void)strcpy(file, homedir);
288 strcat(file, IDN_USER_RESCONF_FILE);
289
290 *fpp = fopen(file, "r");
291 free(file);
292 if (*fpp == NULL) {
293 return (idn_nofile);
294 }
295
296 return (idn_success);
297 #endif /* WIN32 */
298 }
299
300 static idn_result_t
open_defaultfile(FILE ** fpp)301 open_defaultfile(FILE **fpp) {
302 idn_result_t r;
303 const char *file;
304
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);
319 }
320 } else if (r != idn_success) {
321 return (r);
322 }
323
324 return (idn_success);
325 }
326
327 idn_result_t
idn_resconf_loadfile(idn_resconf_t ctx,const char * file)328 idn_resconf_loadfile(idn_resconf_t ctx, const char *file) {
329 FILE *fp = NULL;
330 idn_result_t r;
331
332 assert(ctx != NULL);
333
334 TRACE(("idn_resconf_loadfile(file=%s)\n",
335 file == NULL ? "<null>" : file));
336
337 resetconf(ctx);
338 r = idn_delimitermap_create(&ctx->delimiter_mapper);
339 if (r != idn_success) {
340 goto ret;
341 }
342
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;
350 }
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;
358 }
359 }
360
361 r = parse_conf(ctx, fp);
362 fclose(fp);
363
364 ret:
365 TRACE(("idn_resconf_loadfile(): %s\n", idn_result_tostring(r)));
366 return (r);
367 }
368
369 void
idn_resconf_destroy(idn_resconf_t ctx)370 idn_resconf_destroy(idn_resconf_t ctx) {
371 assert(ctx != NULL);
372
373 TRACE(("idn_resconf_destroy()\n"));
374
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));
384 }
385 }
386
387 void
idn_resconf_incrref(idn_resconf_t ctx)388 idn_resconf_incrref(idn_resconf_t ctx) {
389 assert(ctx != NULL);
390
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));
394
395 ctx->reference_count++;
396 }
397
398 idn_converter_t
idn_resconf_getalternateconverter(idn_resconf_t ctx)399 idn_resconf_getalternateconverter(idn_resconf_t ctx) {
400 assert(ctx != NULL);
401
402 TRACE(("idn_resconf_getalternateconverter()\n"));
403
404 return (idn_resconf_getidnconverter(ctx));
405 }
406
407 idn_delimitermap_t
idn_resconf_getdelimitermap(idn_resconf_t ctx)408 idn_resconf_getdelimitermap(idn_resconf_t ctx) {
409 assert(ctx != NULL);
410
411 TRACE(("idn_resconf_getdelimitermap()\n"));
412
413 if (ctx->delimiter_mapper != NULL)
414 idn_delimitermap_incrref(ctx->delimiter_mapper);
415 return (ctx->delimiter_mapper);
416 }
417
418 idn_converter_t
idn_resconf_getidnconverter(idn_resconf_t ctx)419 idn_resconf_getidnconverter(idn_resconf_t ctx) {
420 assert(ctx != NULL);
421
422 TRACE(("idn_resconf_getidnconverter()\n"));
423
424 if (ctx->idn_converter != NULL)
425 idn_converter_incrref(ctx->idn_converter);
426 return (ctx->idn_converter);
427 }
428
429 idn_converter_t
idn_resconf_getauxidnconverter(idn_resconf_t ctx)430 idn_resconf_getauxidnconverter(idn_resconf_t ctx) {
431 assert(ctx != NULL);
432
433 TRACE(("idn_resconf_getauxidnconverter()\n"));
434
435 if (ctx->aux_idn_converter != NULL)
436 idn_converter_incrref(ctx->aux_idn_converter);
437 return (ctx->aux_idn_converter);
438 }
439
440 idn_converter_t
idn_resconf_getlocalconverter(idn_resconf_t ctx)441 idn_resconf_getlocalconverter(idn_resconf_t ctx) {
442 assert(ctx != NULL);
443
444 TRACE(("idn_resconf_getlocalconverter()\n"));
445
446 #ifdef WITHOUT_ICONV
447 return NULL;
448
449 #else /* WITHOUT_ICONV */
450 if (update_local_converter(ctx) != idn_success)
451 return (NULL);
452
453 idn_converter_incrref(ctx->local_converter);
454 return (ctx->local_converter);
455
456 #endif /* WITHOUT_ICONV */
457 }
458
459 idn_mapselector_t
idn_resconf_getlocalmapselector(idn_resconf_t ctx)460 idn_resconf_getlocalmapselector(idn_resconf_t ctx) {
461 assert(ctx != NULL);
462
463 TRACE(("idn_resconf_getlocalmapselector()\n"));
464
465 if (ctx->local_mapper != NULL)
466 idn_mapselector_incrref(ctx->local_mapper);
467 return (ctx->local_mapper);
468 }
469
470 idn_mapper_t
idn_resconf_getmapper(idn_resconf_t ctx)471 idn_resconf_getmapper(idn_resconf_t ctx) {
472 assert(ctx != NULL);
473
474 TRACE(("idn_resconf_getmapper()\n"));
475
476 if (ctx->mapper != NULL)
477 idn_mapper_incrref(ctx->mapper);
478 return (ctx->mapper);
479 }
480
481 idn_normalizer_t
idn_resconf_getnormalizer(idn_resconf_t ctx)482 idn_resconf_getnormalizer(idn_resconf_t ctx) {
483 assert(ctx != NULL);
484
485 TRACE(("idn_resconf_getnormalizer()\n"));
486
487 if (ctx->normalizer != NULL)
488 idn_normalizer_incrref(ctx->normalizer);
489 return (ctx->normalizer);
490 }
491
492 idn_checker_t
idn_resconf_getprohibitchecker(idn_resconf_t ctx)493 idn_resconf_getprohibitchecker(idn_resconf_t ctx) {
494 assert(ctx != NULL);
495
496 TRACE(("idn_resconf_getprohibitchecker()\n"));
497
498 if (ctx->prohibit_checker != NULL)
499 idn_checker_incrref(ctx->prohibit_checker);
500 return (ctx->prohibit_checker);
501 }
502
503 idn_checker_t
idn_resconf_getunassignedchecker(idn_resconf_t ctx)504 idn_resconf_getunassignedchecker(idn_resconf_t ctx) {
505 assert(ctx != NULL);
506
507 TRACE(("idn_resconf_getunassignedchecker()\n"));
508
509 if (ctx->unassigned_checker != NULL)
510 idn_checker_incrref(ctx->unassigned_checker);
511 return (ctx->unassigned_checker);
512 }
513
514 idn_checker_t
idn_resconf_getbidichecker(idn_resconf_t ctx)515 idn_resconf_getbidichecker(idn_resconf_t ctx) {
516 assert(ctx != NULL);
517
518 TRACE(("idn_resconf_getbidichecker()\n"));
519
520 if (ctx->bidi_checker != NULL)
521 idn_checker_incrref(ctx->bidi_checker);
522 return (ctx->bidi_checker);
523 }
524
525 void
idn_resconf_setalternateconverter(idn_resconf_t ctx,idn_converter_t alternate_converter)526 idn_resconf_setalternateconverter(idn_resconf_t ctx,
527 idn_converter_t alternate_converter) {
528 assert(ctx != NULL);
529
530 TRACE(("idn_resconf_setalternateconverter()\n"));
531 }
532
533 void
idn_resconf_setdelimitermap(idn_resconf_t ctx,idn_delimitermap_t delimiter_mapper)534 idn_resconf_setdelimitermap(idn_resconf_t ctx,
535 idn_delimitermap_t delimiter_mapper) {
536 assert(ctx != NULL);
537
538 TRACE(("idn_resconf_setdelimitermap()\n"));
539
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);
545 }
546
547 void
idn_resconf_setidnconverter(idn_resconf_t ctx,idn_converter_t idn_converter)548 idn_resconf_setidnconverter(idn_resconf_t ctx,
549 idn_converter_t idn_converter) {
550 assert(ctx != NULL);
551
552 TRACE(("idn_resconf_setidnconverter()\n"));
553
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);
559 }
560
561 void
idn_resconf_setauxidnconverter(idn_resconf_t ctx,idn_converter_t aux_idn_converter)562 idn_resconf_setauxidnconverter(idn_resconf_t ctx,
563 idn_converter_t aux_idn_converter) {
564 assert(ctx != NULL);
565
566 TRACE(("idn_resconf_setauxidnconverter()\n"));
567
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);
573 }
574
575 void
idn_resconf_setlocalconverter(idn_resconf_t ctx,idn_converter_t local_converter)576 idn_resconf_setlocalconverter(idn_resconf_t ctx,
577 idn_converter_t local_converter) {
578 #ifndef WITHOUT_ICONV
579 assert(ctx != NULL);
580
581 TRACE(("idn_resconf_setlocalconverter()\n"));
582
583 if (ctx->local_converter != NULL) {
584 idn_converter_destroy(ctx->local_converter);
585 ctx->local_converter = NULL;
586 }
587
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;
594 }
595 #endif /* WITHOUT_ICONV */
596 }
597
598 void
idn_resconf_setlocalmapselector(idn_resconf_t ctx,idn_mapselector_t local_mapper)599 idn_resconf_setlocalmapselector(idn_resconf_t ctx,
600 idn_mapselector_t local_mapper) {
601 assert(ctx != NULL);
602
603 TRACE(("idn_resconf_setlocalmapselector()\n"));
604
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);
610 }
611
612 void
idn_resconf_setmapper(idn_resconf_t ctx,idn_mapper_t mapper)613 idn_resconf_setmapper(idn_resconf_t ctx, idn_mapper_t mapper) {
614 assert(ctx != NULL);
615
616 TRACE(("idn_resconf_setmapper()\n"));
617
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);
623 }
624
625 void
idn_resconf_setnormalizer(idn_resconf_t ctx,idn_normalizer_t normalizer)626 idn_resconf_setnormalizer(idn_resconf_t ctx, idn_normalizer_t normalizer) {
627 assert(ctx != NULL);
628
629 TRACE(("idn_resconf_setnormalizer()\n"));
630
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);
636 }
637
638 void
idn_resconf_setprohibitchecker(idn_resconf_t ctx,idn_checker_t prohibit_checker)639 idn_resconf_setprohibitchecker(idn_resconf_t ctx,
640 idn_checker_t prohibit_checker) {
641 assert(ctx != NULL);
642
643 TRACE(("idn_resconf_setprohibitchecker()\n"));
644
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);
650 }
651
652 void
idn_resconf_setunassignedchecker(idn_resconf_t ctx,idn_checker_t unassigned_checker)653 idn_resconf_setunassignedchecker(idn_resconf_t ctx,
654 idn_checker_t unassigned_checker) {
655 assert(ctx != NULL);
656
657 TRACE(("idn_resconf_setunassignedchecker()\n"));
658
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);
664 }
665
666 void
idn_resconf_setbidichecker(idn_resconf_t ctx,idn_checker_t bidi_checker)667 idn_resconf_setbidichecker(idn_resconf_t ctx,
668 idn_checker_t bidi_checker) {
669 assert(ctx != NULL);
670
671 TRACE(("idn_resconf_setbidichecker()\n"));
672
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);
678 }
679
680 idn_result_t
idn_resconf_setnameprepversion(idn_resconf_t ctx,const char * version)681 idn_resconf_setnameprepversion(idn_resconf_t ctx, const char *version)
682 {
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;
692
693 assert(ctx != NULL && version != NULL);
694
695 TRACE(("idn_resconf_setnameprepversion()\n"));
696
697 /*
698 * Set canonical scheme names.
699 */
700 if (strlen(version) + strlen(IDN_CHECKER_PROHIBIT_PREFIX)
701 > MAX_CONF_LINE_LENGTH) {
702 r = idn_invalid_name;
703 goto failure;
704 }
705 sprintf(prohibit_scheme_name, "%s%s",
706 IDN_CHECKER_PROHIBIT_PREFIX, version);
707
708 if (strlen(version) + strlen(IDN_CHECKER_UNASSIGNED_PREFIX)
709 > MAX_CONF_LINE_LENGTH) {
710 r = idn_invalid_name;
711 goto failure;
712 }
713 sprintf(unassigned_scheme_name, "%s%s",
714 IDN_CHECKER_UNASSIGNED_PREFIX, version);
715
716 if (strlen(version) + strlen(IDN_CHECKER_BIDI_PREFIX)
717 > MAX_CONF_LINE_LENGTH) {
718 r = idn_invalid_name;
719 goto failure;
720 }
721 sprintf(bidi_scheme_name, "%s%s",
722 IDN_CHECKER_BIDI_PREFIX, version);
723
724 /*
725 * Create objects.
726 */
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;
742
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;
758
759 /*
760 * Set the objects.
761 */
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);
767
768 /*
769 * Destroy the objects.
770 */
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);
776
777 return (idn_success);
778
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);
790
791 return (r);
792 }
793
794 idn_result_t
idn_resconf_setalternateconvertername(idn_resconf_t ctx,const char * name,int flags)795 idn_resconf_setalternateconvertername(idn_resconf_t ctx, const char *name,
796 int flags) {
797 assert(ctx != NULL && name != NULL);
798
799 TRACE(("idn_resconf_setalternateconvertername(name=%s, flags=%d)\n",
800 name, flags));
801
802 return (idn_success);
803 }
804
805 idn_result_t
idn_resconf_setidnconvertername(idn_resconf_t ctx,const char * name,int flags)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;
810
811 assert(ctx != NULL && name != NULL);
812
813 TRACE(("idn_resconf_setidnconvertername(name=%s, flags=%d)\n",
814 name, flags));
815
816 r = idn_converter_create(name, &idn_converter, flags);
817 if (r != idn_success)
818 return (r);
819
820 if (ctx->idn_converter != NULL)
821 idn_converter_destroy(ctx->idn_converter);
822 ctx->idn_converter = idn_converter;
823
824 return (idn_success);
825 }
826
827 idn_result_t
idn_resconf_setauxidnconvertername(idn_resconf_t ctx,const char * name,int flags)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;
833
834 assert(ctx != NULL && name != NULL);
835
836 TRACE(("idn_resconf_setauxidnconvertername(name=%s, flags=%d)\n",
837 name, flags));
838
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);
843 }
844
845 r = idn_converter_create(name, &aux_idn_converter, flags);
846 if (r != idn_success)
847 return (r);
848
849 if (ctx->aux_idn_converter != NULL)
850 idn_converter_destroy(ctx->aux_idn_converter);
851 ctx->aux_idn_converter = aux_idn_converter;
852
853 return (idn_success);
854 }
855
856 idn_result_t
idn_resconf_setlocalconvertername(idn_resconf_t ctx,const char * name,int flags)857 idn_resconf_setlocalconvertername(idn_resconf_t ctx, const char *name,
858 int flags) {
859 #ifdef WITHOUT_ICONV
860 return idn_failure;
861
862 #else /* WITHOUT_ICONV */
863 idn_converter_t local_converter;
864 idn_result_t r;
865
866 assert(ctx != NULL);
867
868 TRACE(("idn_resconf_setlocalconvertername(name=%s, flags=%d)\n",
869 name == NULL ? "<null>" : name, flags));
870
871 if (ctx->local_converter != NULL) {
872 idn_converter_destroy(ctx->local_converter);
873 ctx->local_converter = NULL;
874 }
875 ctx->local_converter_is_static = 0;
876
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;
883 }
884
885 return (idn_success);
886
887 #endif /* WITHOUT_ICONV */
888 }
889
890 idn_result_t
idn_resconf_addalldelimitermapucs(idn_resconf_t ctx,unsigned long * v,int nv)891 idn_resconf_addalldelimitermapucs(idn_resconf_t ctx, unsigned long *v,
892 int nv) {
893 idn_result_t r;
894
895 TRACE(("idn_resconf_addalldelimitermapucs(nv=%d)\n", nv));
896
897 if (ctx->delimiter_mapper == NULL) {
898 r = idn_delimitermap_create(&(ctx->delimiter_mapper));
899 if (r != idn_success)
900 return (r);
901 }
902
903 r = idn_delimitermap_addall(ctx->delimiter_mapper, v, nv);
904 return (r);
905 }
906
907 idn_result_t
idn_resconf_addalllocalmapselectornames(idn_resconf_t ctx,const char * tld,const char ** names,int nnames)908 idn_resconf_addalllocalmapselectornames(idn_resconf_t ctx, const char *tld,
909 const char **names, int nnames) {
910 idn_result_t r;
911
912 assert(ctx != NULL && names != NULL && tld != NULL);
913
914 TRACE(("idn_resconf_addalllocalmapselectorname(tld=%s, nnames=%d)\n",
915 tld, nnames));
916
917 if (ctx->local_mapper == NULL) {
918 r = idn_mapselector_create(&(ctx->local_mapper));
919 if (r != idn_success)
920 return (r);
921 }
922
923 r = idn_mapselector_addall(ctx->local_mapper, tld, names, nnames);
924 return (r);
925 }
926
927 idn_result_t
idn_resconf_addallmappernames(idn_resconf_t ctx,const char ** names,int nnames)928 idn_resconf_addallmappernames(idn_resconf_t ctx, const char **names,
929 int nnames) {
930 idn_result_t r;
931
932 assert(ctx != NULL && names != NULL);
933
934 TRACE(("idn_resconf_addallmappername()\n"));
935
936 if (ctx->mapper == NULL) {
937 r = idn_mapper_create(&(ctx->mapper));
938 if (r != idn_success)
939 return (r);
940 }
941
942 r = idn_mapper_addall(ctx->mapper, names, nnames);
943 return (r);
944 }
945
946 idn_result_t
idn_resconf_addallnormalizernames(idn_resconf_t ctx,const char ** names,int nnames)947 idn_resconf_addallnormalizernames(idn_resconf_t ctx, const char **names,
948 int nnames) {
949 idn_result_t r;
950
951 assert(ctx != NULL && names != NULL);
952
953 TRACE(("idn_resconf_addallnormalizername(nnames=%d)\n", nnames));
954
955 if (ctx->normalizer == NULL) {
956 r = idn_normalizer_create(&(ctx->normalizer));
957 if (r != idn_success)
958 return (r);
959 }
960
961 r = idn_normalizer_addall(ctx->normalizer, names, nnames);
962 return (r);
963 }
964
965 idn_result_t
idn_resconf_addallprohibitcheckernames(idn_resconf_t ctx,const char ** names,int nnames)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;
971
972 assert(ctx != NULL && names != NULL);
973
974 TRACE(("idn_resconf_addallprohibitcheckername(nnames=%d)\n", nnames));
975
976 if (ctx->prohibit_checker == NULL) {
977 r = idn_checker_create(&(ctx->prohibit_checker));
978 if (r != idn_success)
979 return (r);
980 }
981
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);
986 }
987 strcpy(long_name, IDN_CHECKER_PROHIBIT_PREFIX);
988 strcat(long_name, *names);
989
990 r = idn_checker_add(ctx->prohibit_checker, long_name);
991 if (r != idn_success)
992 return (r);
993 }
994
995 return (idn_success);
996 }
997
998 idn_result_t
idn_resconf_addallunassignedcheckernames(idn_resconf_t ctx,const char ** names,int nnames)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;
1004
1005 assert(ctx != NULL && names != NULL);
1006
1007 TRACE(("idn_resconf_addallunassignedcheckername(nnames=%d)\n",
1008 nnames));
1009
1010 if (ctx->unassigned_checker == NULL) {
1011 r = idn_checker_create(&(ctx->unassigned_checker));
1012 if (r != idn_success)
1013 return (r);
1014 }
1015
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);
1020 }
1021 strcpy(long_name, IDN_CHECKER_UNASSIGNED_PREFIX);
1022 strcat(long_name, *names);
1023
1024 r = idn_checker_add(ctx->unassigned_checker, long_name);
1025 if (r != idn_success)
1026 return (r);
1027 }
1028
1029 return (idn_success);
1030 }
1031
1032 idn_result_t
idn_resconf_addallbidicheckernames(idn_resconf_t ctx,const char ** names,int nnames)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;
1038
1039 assert(ctx != NULL && names != NULL);
1040
1041 TRACE(("idn_resconf_addallbidicheckername(nnames=%d)\n", nnames));
1042
1043 if (ctx->bidi_checker == NULL) {
1044 r = idn_checker_create(&(ctx->bidi_checker));
1045 if (r != idn_success)
1046 return (r);
1047 }
1048
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);
1053 }
1054 strcpy(long_name, IDN_CHECKER_BIDI_PREFIX);
1055 strcat(long_name, *names);
1056
1057 r = idn_checker_add(ctx->bidi_checker, long_name);
1058 if (r != idn_success)
1059 return (r);
1060 }
1061
1062 return (idn_success);
1063 }
1064
1065 static idn_result_t
parse_conf(idn_resconf_t ctx,FILE * fp)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;
1073
1074 TRACE(("parse_conf()\n"));
1075
1076 /*
1077 * Parse config file. parsing of 'idn-encoding' line is
1078 * postponed because 'alias-file' line must be processed
1079 * before them.
1080 */
1081 while (fgets(line, sizeof(line), fp) != NULL) {
1082 char *newline;
1083
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);
1092 }
1093
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);
1103 }
1104
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);
1113 }
1114 } else if (strcmp(argv[0], "local-map") == 0) {
1115 r = parse_local_map(ctx, argv[1], lineno);
1116
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);
1125 }
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;
1143 }
1144 if (r != idn_success)
1145 return (r);
1146 }
1147
1148 lineno++;
1149
1150 if (conf_mask != DEFAULT_CONF_ALL) {
1151 return setdefaults_body(ctx, conf_mask);
1152 }
1153
1154 return (idn_success);
1155 }
1156
1157 static idn_result_t
parse_idn_encoding(idn_resconf_t ctx,char * args,int lineno)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;
1162
1163 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1164
1165 if (argc != 1) {
1166 ERROR(("libidnkit: wrong # of args for idn-encoding, "
1167 "line %d\n", lineno));
1168 return (idn_invalid_syntax);
1169 }
1170
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));
1177 }
1178
1179 return (r);
1180 }
1181
1182 static idn_result_t
parse_local_map(idn_resconf_t ctx,char * args,int lineno)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;
1188
1189 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1190
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);
1195 }
1196
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);
1203 }
1204 }
1205
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);
1215 }
1216 }
1217
1218 return (idn_success);
1219 }
1220
1221 static idn_result_t
parse_nameprep(idn_resconf_t ctx,char * args,int lineno)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;
1227
1228 argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
1229
1230 if (argc != 1) {
1231 ERROR(("libidnkit: wrong # of args for nameprep, line %d\n",
1232 lineno));
1233 return (idn_invalid_syntax);
1234 }
1235
1236 /*
1237 * Set mapper.
1238 */
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);
1244 }
1245
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);
1253 }
1254
1255 /*
1256 * Set normalizer.
1257 */
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);
1263 }
1264
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);
1272 }
1273
1274 /*
1275 * Set prohibit checker.
1276 */
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);
1282 }
1283
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);
1292 }
1293
1294 /*
1295 * Set unassigned checker.
1296 */
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);
1302 }
1303
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);
1312 }
1313
1314 /*
1315 * Set bidi checker.
1316 */
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);
1322 }
1323
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);
1332 }
1333
1334 return (idn_success);
1335 }
1336
1337 static int
split_args(char * s,char ** av,int max_ac)1338 split_args(char *s, char **av, int max_ac) {
1339 int ac;
1340 int i;
1341
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++;
1356 }
1357 } else {
1358 av[ac] = s;
1359 while (*s != '\0' && !isspace((unsigned char)*s))
1360 s++;
1361 }
1362 }
1363
1364 for (i = ac; i < max_ac; i++)
1365 av[i] = NULL;
1366
1367 return (ac);
1368 }
1369
1370 static void
resetconf(idn_resconf_t ctx)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);
1384 }
1385
1386 #ifndef WITHOUT_ICONV
1387 static idn_result_t
update_local_converter(idn_resconf_t ctx)1388 update_local_converter(idn_resconf_t ctx) {
1389 idn_result_t r;
1390 const char *old_encoding;
1391 const char *new_encoding;
1392
1393 /*
1394 * We don't update local converter, if the converter is set
1395 * by idn_resconf_setlocalconverter() or
1396 * idn_resconf_setlocalconvertername().
1397 */
1398 if (ctx->local_converter_is_static)
1399 return (idn_success);
1400
1401 /*
1402 * Update the local converter if the local encoding is changed.
1403 */
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);
1411 }
1412
1413 if (old_encoding != NULL &&
1414 new_encoding != NULL &&
1415 strcmp(old_encoding, new_encoding) == 0) {
1416 return (idn_success);
1417 }
1418
1419 if (ctx->local_converter != NULL) {
1420 idn_converter_destroy(ctx->local_converter);
1421 ctx->local_converter = NULL;
1422 }
1423
1424 r = idn_converter_create(new_encoding,
1425 &ctx->local_converter,
1426 IDN_CONVERTER_RTCHECK);
1427 return (r);
1428 }
1429 #endif
1430
1431 idn_result_t
idn_resconf_setdefaults(idn_resconf_t ctx)1432 idn_resconf_setdefaults(idn_resconf_t ctx)
1433 {
1434 idn_result_t r;
1435
1436 assert(ctx != NULL);
1437
1438 TRACE(("idn_resconf_setdefaults()\n"));
1439
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);
1446 }
1447
1448 return setdefaults_body(ctx, 0);
1449 }
1450
1451 static idn_result_t
setdefaults_body(idn_resconf_t ctx,int conf_mask)1452 setdefaults_body(idn_resconf_t ctx, int conf_mask) {
1453 idn_result_t r;
1454
1455 TRACE(("setdefaults_body()\n"));
1456 assert(ctx != NULL);
1457
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);
1463 }
1464 }
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);
1475 }
1476 }
1477
1478 return (idn_success);
1479 }
1480