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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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