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