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