1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * The contents of this file are subject to the Netscape Public 8 * License Version 1.1 (the "License"); you may not use this file 9 * except in compliance with the License. You may obtain a copy of 10 * the License at http://www.mozilla.org/NPL/ 11 * 12 * Software distributed under the License is distributed on an "AS 13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 14 * implied. See the License for the specific language governing 15 * rights and limitations under the License. 16 * 17 * The Original Code is Mozilla Communicator client code, released 18 * March 31, 1998. 19 * 20 * The Initial Developer of the Original Code is Netscape 21 * Communications Corporation. Portions created by Netscape are 22 * Copyright (C) 1998-1999 Netscape Communications Corporation. All 23 * Rights Reserved. 24 * 25 * Contributor(s): 26 */ 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <locale.h> 32 #include <ctype.h> 33 34 #ifndef HAVE_LIBICU 35 36 #ifdef SOLARIS_LDAP_CMD 37 #include <errno.h> 38 #include <langinfo.h> 39 #include <iconv.h> 40 #endif 41 42 #ifdef __cplusplus 43 extern "C" { 44 #endif 45 46 extern char *ldaptool_charset; 47 char *ldaptool_convdir = NULL; 48 static int charsetset = 0; 49 char *ldaptool_local2UTF8( const char *src ); 50 51 #ifdef SOLARIS_LDAP_CMD 52 static char *ldaptool_convert( const char *src, const char *fcode, 53 const char *tcode); 54 char *ldaptool_UTF82local( const char *src ); 55 #endif /* SOLARIS_LDAP_CMD */ 56 57 #ifdef SOLARIS_LDAP_CMD 58 /* 59 * ICU version always returns string, unless strdup fails. 60 * As in ICU version, in case of error strdup(src) 61 * Usually strdup(src) will be ASCII and legal anyways. 62 */ 63 64 static char * 65 ldaptool_convert( const char *src, const char *fcode, 66 const char *tcode) { 67 char *dest, *tptr, *tmp; 68 const char *fptr; 69 iconv_t cd; 70 size_t ileft, oleft, ret, size; 71 72 if (src == NULL) 73 return (NULL); 74 75 if (fcode == NULL || tcode == NULL) 76 return (strdup(src)); 77 78 if (strcasecmp(fcode, tcode) == 0) 79 return (strdup(src)); 80 81 if ((cd = iconv_open(tcode, fcode)) == (iconv_t)-1) { 82 /* conversion table not available */ 83 return (strdup(src)); 84 } 85 86 ileft = strlen(src); 87 oleft = 2 * ileft; 88 size = oleft; 89 ret = -1; 90 if ((dest = (char *)malloc(size)) == NULL) { 91 (void) iconv_close(cd); 92 /* maybe sizeof strlen(src) memory still exists */ 93 return (strdup(src)); 94 } 95 tptr = dest; 96 fptr = src; 97 98 for (;;) { 99 ret = iconv(cd, &fptr, &ileft, &tptr, &oleft); 100 101 if (ret != (size_t)-1) { 102 /* 103 * Success. Place 'cd' into its initial shift 104 * state before returning. 105 */ 106 if (fptr == NULL) /* already in initial state */ 107 break; 108 fptr = NULL; 109 ileft = 0; 110 continue; 111 } if (errno == E2BIG) { 112 /* 113 * Lack of space in output buffer. 114 * Hence double the size and retry. 115 * But before calling iconv(), oleft 116 * and tptr have to re-adjusted, so that 117 * iconv() doesn't overwrite the data 118 * which has already been converted. 119 */ 120 oleft += size; 121 size *= 2; 122 if ((tmp = (char *) realloc(dest, size)) == NULL) 123 break; 124 tptr = tmp + (tptr - dest); 125 dest = tmp; 126 continue; 127 } else { 128 /* Other errors */ 129 break; 130 } 131 } 132 133 if (dest != NULL) { 134 if (ret == -1) { 135 /* Free malloc'ed memory on failure */ 136 free(dest); 137 dest = NULL; 138 } else if (oleft > 0) { 139 /* NULL terminate the return value */ 140 *(dest + (size - oleft)) = '\0'; 141 } else { 142 /* realloc one more byte and NULL terminate */ 143 if ((tmp = (char *) realloc(dest, size + 1)) == NULL) { 144 free(dest); 145 dest = NULL; 146 } else { 147 *(dest + size) = '\0'; 148 } 149 } 150 } 151 152 (void) iconv_close(cd); 153 if (dest == NULL) { 154 /* last chance in case some other failure along the way occurs */ 155 return (strdup(src)); 156 } 157 return (dest); 158 } 159 160 char * 161 ldaptool_UTF82local( const char *src ) 162 { 163 char *to_code; 164 if ((to_code = nl_langinfo(CODESET)) == NULL) 165 return (strdup(src)); 166 return (ldaptool_convert(src, "UTF-8", (const char *)to_code)); 167 } 168 #endif /* SOLARIS_LDAP_CMD */ 169 170 char * 171 ldaptool_local2UTF8( const char *src ) 172 { 173 #ifdef SOLARIS_LDAP_CMD 174 char *from_code; 175 if ((from_code = nl_langinfo(CODESET)) == NULL) 176 return (strdup(src)); 177 return (ldaptool_convert(src, (const char *)from_code, "UTF-8")); 178 #else 179 char *utf8; 180 charsetset = 0; 181 if (src == NULL) 182 { 183 return NULL; 184 } 185 utf8 = strdup(src); 186 return ( utf8 ); 187 #endif /* SOLARIS_LDAP_CMD */ 188 } 189 190 #else /* HAVE_LIBICU */ 191 192 #include "unicode/utypes.h" 193 #include "unicode/ucnv.h" 194 195 #define NSPR20 196 197 #ifdef XP_WIN32 198 #define VC_EXTRALEAN 199 #include <afxwin.h> 200 #include <winnls.h> 201 #endif 202 203 extern char *ldaptool_charset; 204 static int charsetset = 0; 205 206 extern "C" { 207 char *ldaptool_convdir = NULL; 208 char *ldaptool_local2UTF8( const char * ); 209 } 210 211 #ifndef XP_WIN32 212 char * GetNormalizedLocaleName(void); 213 214 215 char * 216 GetNormalizedLocaleName(void) 217 { 218 #ifdef _HPUX_SOURCE 219 220 int len; 221 char *locale; 222 223 locale = setlocale(LC_CTYPE, ""); 224 if (locale && *locale) { 225 len = strlen(locale); 226 } else { 227 locale = "C"; 228 len = 1; 229 } 230 231 if ((!strncmp(locale, "/\x03:", 3)) && 232 (!strcmp(&locale[len - 2], ";/"))) { 233 locale += 3; 234 len -= 5; 235 } 236 237 locale = strdup(locale); 238 if (locale) { 239 locale[len] = 0; 240 } 241 242 return locale; 243 244 #else 245 246 char *locale; 247 248 locale = setlocale(LC_CTYPE, ""); 249 if (locale && *locale) { 250 return strdup(locale); 251 } 252 253 return strdup("C"); 254 255 #endif 256 } 257 258 #if defined(IRIX) 259 const char *CHARCONVTABLE[] = 260 { 261 "! This table maps the host's locale names to IANA charsets", 262 "!", 263 "C: ISO_8859-1:1987", 264 "cs: ISO_8859-2:1987", 265 "da: ISO_8859-1:1987", 266 "de: ISO_8859-1:1987", 267 "de_AT: ISO_8859-1:1987", 268 "de_CH: ISO_8859-1:1987", 269 "en: ISO_8859-1:1987", 270 "en_AU: ISO_8859-1:1987", 271 "en_CA: ISO_8859-1:1987", 272 "en_TH: ISO_8859-1:1987", 273 "en_US: ISO_8859-1:1987", 274 "es: ISO_8859-1:1987", 275 "fi: ISO_8859-1:1987", 276 "fr: ISO_8859-1:1987", 277 "fr_BE: ISO_8859-1:1987", 278 "fr_CA: ISO_8859-1:1987", 279 "fr_CH: ISO_8859-1:1987", 280 "is: ISO_8859-1:1987", 281 "it: ISO_8859-1:1987", 282 "it_CH: ISO_8859-1:1987", 283 "ja_JP.EUC: Extended_UNIX_Code_Packed_Format_for_Japanese", 284 "ko_KR.euc: EUC-KR", 285 "nl: ISO_8859-1:1987", 286 "nl_BE: ISO_8859-1:1987", 287 "no: ISO_8859-1:1987", 288 "pl: ISO_8859-2:1987", 289 "pt: ISO_8859-1:1987", 290 "sh: ISO_8859-2:1987", 291 "sk: ISO_8859-2:1987", 292 "sv: ISO_8859-1:1987", 293 "zh_CN.ugb: GB2312", 294 "zh_TW.ucns: cns11643_1", 295 NULL 296 }; 297 #elif defined(SOLARIS) 298 const char *CHARCONVTABLE[] = 299 { 300 "! This table maps the host's locale names to IANA charsets", 301 "!", 302 "C: ISO_8859-1:1987", 303 "ja: Extended_UNIX_Code_Packed_Format_for_Japanese", 304 "ja_JP.EUC: Extended_UNIX_Code_Packed_Format_for_Japanese", 305 "ja_JP.PCK: Shift_JIS", 306 "en: ISO_8859-1:1987", 307 "en_AU: ISO_8859-1:1987", 308 "en_CA: ISO_8859-1:1987", 309 "en_UK: ISO_8859-1:1987", 310 "en_US: ISO_8859-1:1987", 311 "es: ISO_8859-1:1987", 312 "es_AR: ISO_8859-1:1987", 313 "es_BO: ISO_8859-1:1987", 314 "es_CL: ISO_8859-1:1987", 315 "es_CO: ISO_8859-1:1987", 316 "es_CR: ISO_8859-1:1987", 317 "es_EC: ISO_8859-1:1987", 318 "es_GT: ISO_8859-1:1987", 319 "es_MX: ISO_8859-1:1987", 320 "es_NI: ISO_8859-1:1987", 321 "es_PA: ISO_8859-1:1987", 322 "es_PE: ISO_8859-1:1987", 323 "es_PY: ISO_8859-1:1987", 324 "es_SV: ISO_8859-1:1987", 325 "es_UY: ISO_8859-1:1987", 326 "es_VE: ISO_8859-1:1987", 327 "fr: ISO_8859-1:1987", 328 "fr_BE: ISO_8859-1:1987", 329 "fr_CA: ISO_8859-1:1987", 330 "fr_CH: ISO_8859-1:1987", 331 "de: ISO_8859-1:1987", 332 "de_AT: ISO_8859-1:1987", 333 "de_CH: ISO_8859-1:1987", 334 "nl: ISO_8859-1:1987", 335 "nl_BE: ISO_8859-1:1987", 336 "it: ISO_8859-1:1987", 337 "sv: ISO_8859-1:1987", 338 "no: ISO_8859-1:1987", 339 "da: ISO_8859-1:1987", 340 "iso_8859_1: ISO_8859-1:1987", 341 "japanese: Extended_UNIX_Code_Packed_Format_for_Japanese", 342 "ko: EUC-KR", 343 "zh: GB2312", 344 "zh_TW: cns11643_1", 345 NULL 346 }; 347 #elif defined(OSF1) 348 const char *CHARCONVTABLE[] = 349 { 350 "! This table maps the host's locale names to IANA charsets", 351 "!", 352 "C: ISO_8859-1:1987", 353 "cs_CZ.ISO8859-2: ISO_8859-2:1987", 354 "cs_CZ: ISO_8859-2:1987", 355 "da_DK.ISO8859-1: ISO_8859-1:1987", 356 "de_CH.ISO8859-1: ISO_8859-1:1987", 357 "de_DE.ISO8859-1: ISO_8859-1:1987", 358 "en_GB.ISO8859-1: ISO_8859-1:1987", 359 "en_US.ISO8859-1: ISO_8859-1:1987", 360 "es_ES.ISO8859-1: ISO_8859-1:1987", 361 "fi_FI.ISO8859-1: ISO_8859-1:1987", 362 "fr_BE.ISO8859-1: ISO_8859-1:1987", 363 "fr_CA.ISO8859-1: ISO_8859-1:1987", 364 "fr_CH.ISO8859-1: ISO_8859-1:1987", 365 "fr_FR.ISO8859-1: ISO_8859-1:1987", 366 "hu_HU.ISO8859-2: ISO_8859-2:1987", 367 "hu_HU: ISO_8859-2:1987", 368 "is_IS.ISO8859-1: ISO_8859-1:1987", 369 "it_IT.ISO8859-1: ISO_8859-1:1987", 370 "ja_JP.SJIS: Shift_JIS", 371 "ja_JP.eucJP: Extended_UNIX_Code_Packed_Format_for_Japanese", 372 "ja_JP: Extended_UNIX_Code_Packed_Format_for_Japanese", 373 "ko_KR.eucKR: EUC-KR", 374 "ko_KR: EUC-KR", 375 "nl_BE.ISO8859-1: ISO_8859-1:1987", 376 "nl_NL.ISO8859-1: ISO_8859-1:1987", 377 "no_NO.ISO8859-1: ISO_8859-1:1987", 378 "pl_PL.ISO8859-2: ISO_8859-2:1987", 379 "pl_PL: ISO_8859-2:1987", 380 "pt_PT.ISO8859-1: ISO_8859-1:1987", 381 "sk_SK.ISO8859-2: ISO_8859-2:1987", 382 "sk_SK: ISO_8859-2:1987", 383 "sv_SE.ISO8859-1: ISO_8859-1:1987", 384 "zh_CN: GB2312", 385 "zh_HK.big5: Big5", 386 "zh_HK.eucTW: cns11643_1", 387 "zh_TW.big5: Big5", 388 "zh_TW.big5@chuyin: Big5", 389 "zh_TW.big5@radical: Big5", 390 "zh_TW.big5@stroke: Big5", 391 "zh_TW.eucTW: cns11643_1", 392 "zh_TW.eucTW@chuyin: cns11643_1", 393 "zh_TW.eucTW@radical: cns11643_1", 394 "zh_TW.eucTW@stroke: cns11643_1", 395 "zh_TW: cns11643_1", 396 NULL 397 }; 398 #elif defined(HPUX) 399 const char *CHARCONVTABLE[] = 400 { 401 "! This table maps the host's locale names to IANA charsets", 402 "!", 403 "C: ISO_8859-1:1987", 404 "ja_JP: Extended_UNIX_Code_Packed_Format_for_Japanese", 405 "ja_JP.SJIS: Shift_JIS", 406 "ja_JP.eucJP: Extended_UNIX_Code_Packed_Format_for_Japanese", 407 "es_ES: ISO_8859-1:1987", 408 "es_ES.iso88591: ISO_8859-1:1987", 409 "sv_SE: ISO_8859-1:1987", 410 "sv_SE.iso88591: ISO_8859-1:1987", 411 "da_DK: ISO_8859-1:1987", 412 "da_DK.iso88591: ISO_8859-1:1987", 413 "nl_NL: ISO_8859-1:1987", 414 "nl_NL.iso88591: ISO_8859-1:1987", 415 "en: ISO_8859-1:1987", 416 "en_GB: ISO_8859-1:1987", 417 "en_GB.iso88591: ISO_8859-1:1987", 418 "en_US: ISO_8859-1:1987", 419 "en_US.iso88591: ISO_8859-1:1987", 420 "fi_FI: ISO_8859-1:1987", 421 "fi_FI.iso88591: ISO_8859-1:1987", 422 "fr_CA: ISO_8859-1:1987", 423 "fr_CA.iso88591: ISO_8859-1:1987", 424 "fr_FR: ISO_8859-1:1987", 425 "fr_FR.iso88591: ISO_8859-1:1987", 426 "de_DE: ISO_8859-1:1987", 427 "de_DE.iso88591: ISO_8859-1:1987", 428 "is_IS: ISO_8859-1:1987", 429 "is_IS.iso88591: ISO_8859-1:1987", 430 "it_IT: ISO_8859-1:1987", 431 "it_IT.iso88591: ISO_8859-1:1987", 432 "no_NO: ISO_8859-1:1987", 433 "no_NO.iso88591: ISO_8859-1:1987", 434 "pt_PT: ISO_8859-1:1987", 435 "pt_PT.iso88591: ISO_8859-1:1987", 436 "hu_HU: ISO_8859-2:1987", 437 "hu_HU.iso88592: ISO_8859-2:1987", 438 "cs_CZ: ISO_8859-2:1987", 439 "cs_CZ.iso88592: ISO_8859-2:1987", 440 "pl_PL: ISO_8859-2:1987", 441 "pl_PL.iso88592: ISO_8859-2:1987", 442 "ro_RO: ISO_8859-2:1987", 443 "ro_RO.iso88592: ISO_8859-2:1987", 444 "hr_HR: ISO_8859-2:1987", 445 "hr_HR.iso88592: ISO_8859-2:1987", 446 "sk_SK: ISO_8859-2:1987", 447 "sk_SK.iso88592: ISO_8859-2:1987", 448 "sl_SI: ISO_8859-2:1987", 449 "sl_SI.iso88592: ISO_8859-2:1987", 450 "american.iso88591: ISO_8859-1:1987", 451 "bulgarian: ISO_8859-2:1987", 452 "c-french.iso88591: ISO_8859-1:1987", 453 "chinese-s: GB2312", 454 "chinese-t.big5: Big5", 455 "czech: ISO_8859-2:1987", 456 "danish.iso88591: ISO_8859-1:1987", 457 "dutch.iso88591: ISO_8859-1:1987", 458 "english.iso88591: ISO_8859-1:1987", 459 "finnish.iso88591: ISO_8859-1:1987", 460 "french.iso88591: ISO_8859-1:1987", 461 "german.iso88591: ISO_8859-1:1987", 462 "hungarian: ISO_8859-2:1987", 463 "icelandic.iso88591: ISO_8859-1:1987", 464 "italian.iso88591: ISO_8859-1:1987", 465 "japanese.euc: Extended_UNIX_Code_Packed_Format_for_Japanese", 466 "japanese: Shift_JIS", 467 "katakana: Shift_JIS", 468 "korean: EUC-KR", 469 "norwegian.iso88591: ISO_8859-1:1987", 470 "polish: ISO_8859-2:1987", 471 "portuguese.iso88591: ISO_8859-1:1987", 472 "rumanian: ISO_8859-2:1987", 473 "serbocroatian: ISO_8859-2:1987", 474 "slovene: ISO_8859-2:1987", 475 "spanish.iso88591: ISO_8859-1:1987", 476 "swedish.iso88591: ISO_8859-1:1987", 477 NULL 478 }; 479 #elif defined(AIX) 480 const char *CHARCONVTABLE[] = 481 { 482 "! This table maps the host's locale names to IANA charsets", 483 "!", 484 "C: ISO_8859-1:1987", 485 "En_JP.IBM-932: Shift_JIS", 486 "En_JP: Shift_JIS", 487 "Ja_JP.IBM-932: Shift_JIS", 488 "Ja_JP: Shift_JIS", 489 "da_DK.ISO8859-1: ISO_8859-1:1987", 490 "da_DK: ISO_8859-1:1987", 491 "de_CH.ISO8859-1: ISO_8859-1:1987", 492 "de_CH: ISO_8859-1:1987", 493 "de_DE.ISO8859-1: ISO_8859-1:1987", 494 "de_DE: ISO_8859-1:1987", 495 "en_GB.ISO8859-1: ISO_8859-1:1987", 496 "en_GB: ISO_8859-1:1987", 497 "en_JP.IBM-eucJP: Extended_UNIX_Code_Packed_Format_for_Japanese", 498 "en_JP: Extended_UNIX_Code_Packed_Format_for_Japanese", 499 "en_KR.IBM-eucKR: EUC-KR", 500 "en_KR: EUC-KR", 501 "en_TW.IBM-eucTW: cns11643_1", 502 "en_TW: cns11643_1", 503 "en_US.ISO8859-1: ISO_8859-1:1987", 504 "en_US: ISO_8859-1:1987", 505 "es_ES.ISO8859-1: ISO_8859-1:1987", 506 "es_ES: ISO_8859-1:1987", 507 "fi_FI.ISO8859-1: ISO_8859-1:1987", 508 "fi_FI: ISO_8859-1:1987", 509 "fr_BE.ISO8859-1: ISO_8859-1:1987", 510 "fr_BE: ISO_8859-1:1987", 511 "fr_CA.ISO8859-1: ISO_8859-1:1987", 512 "fr_CA: ISO_8859-1:1987", 513 "fr_CH.ISO8859-1: ISO_8859-1:1987", 514 "fr_CH: ISO_8859-1:1987", 515 "fr_FR.ISO8859-1: ISO_8859-1:1987", 516 "fr_FR: ISO_8859-1:1987", 517 "is_IS.ISO8859-1: ISO_8859-1:1987", 518 "is_IS: ISO_8859-1:1987", 519 "it_IT.ISO8859-1: ISO_8859-1:1987", 520 "it_IT: ISO_8859-1:1987", 521 "ja_JP.IBM-eucJP: Extended_UNIX_Code_Packed_Format_for_Japanese", 522 "ja_JP: Extended_UNIX_Code_Packed_Format_for_Japanese", 523 "ko_KR.IBM-eucKR: EUC-KR", 524 "ko_KR: EUC-KR", 525 "nl_BE.ISO8859-1: ISO_8859-1:1987", 526 "nl_BE: ISO_8859-1:1987", 527 "nl_NL.ISO8859-1: ISO_8859-1:1987", 528 "nl_NL: ISO_8859-1:1987", 529 "no_NO.ISO8859-1: ISO_8859-1:1987", 530 "no_NO: ISO_8859-1:1987", 531 "pt_PT.ISO8859-1: ISO_8859-1:1987", 532 "pt_PT: ISO_8859-1:1987", 533 "sv_SE.ISO8859-1: ISO_8859-1:1987", 534 "sv_SE: ISO_8859-1:1987", 535 "zh_TW.IBM-eucTW: cns11643_1", 536 "zh_TW: cns11643_1", 537 NULL 538 }; 539 #else // sunos by default 540 const char *CHARCONVTABLE[] = 541 { 542 "! This table maps the host's locale names to IANA charsets", 543 "!", 544 "C: ISO_8859-1:1987", 545 "de: ISO_8859-1:1987", 546 "en_US: ISO_8859-1:1987", 547 "es: ISO_8859-1:1987", 548 "fr: ISO_8859-1:1987", 549 "iso_8859_1: ISO_8859-1:1987", 550 "it: ISO_8859-1:1987", 551 "ja: Extended_UNIX_Code_Packed_Format_for_Japanese", 552 "ja_JP.EUC: Extended_UNIX_Code_Packed_Format_for_Japanese", 553 "japanese: Extended_UNIX_Code_Packed_Format_for_Japanese", 554 "ko: EUC-KR", 555 "sv: ISO_8859-1:1987", 556 "zh: GB2312", 557 "zh_TW: cns11643_1", 558 NULL 559 }; 560 #endif 561 562 #define BSZ 256 563 564 char * 565 GetCharsetFromLocale(char *locale) 566 { 567 char *tmpcharset = NULL; 568 char buf[BSZ]; 569 char *p; 570 const char *line; 571 int i=0; 572 573 line = CHARCONVTABLE[i]; 574 while (line != NULL) 575 { 576 if (*line == 0) 577 { 578 break; 579 } 580 581 strcpy(buf, line); 582 line = CHARCONVTABLE[++i]; 583 584 if (strlen(buf) == 0 || buf[0] == '!') 585 { 586 continue; 587 } 588 p = strchr(buf, ':'); 589 if (p == NULL) 590 { 591 tmpcharset = NULL; 592 break; 593 } 594 *p = 0; 595 if (strcmp(buf, locale) == 0) { 596 while (*++p == ' ' || *p == '\t') 597 ; 598 if (isalpha(*p)) { 599 tmpcharset = strdup(p); 600 } else 601 tmpcharset = NULL; 602 603 break; 604 } 605 } 606 return tmpcharset; 607 } 608 609 #endif /* Not defined XP_WIN32 */ 610 611 #ifdef XP_WIN32 612 char *_convertor(const char *instr, int bFromUTF8) 613 { 614 char *outstr = NULL; 615 int inlen, wclen, outlen; 616 LPWSTR wcstr; 617 618 if (instr == NULL) 619 return NULL; 620 621 if ((inlen = strlen(instr)) <= 0) 622 return NULL; 623 624 /* output never becomes longer than input, 625 * thus we don't have to ask for the length 626 */ 627 wcstr = (LPWSTR) malloc( sizeof( WCHAR ) * (inlen+1) ); 628 if (!wcstr) 629 return NULL; 630 631 wclen = MultiByteToWideChar(bFromUTF8 ? CP_UTF8 : CP_ACP, 0, instr, 632 inlen, wcstr, inlen); 633 outlen = WideCharToMultiByte(bFromUTF8 ? CP_ACP : CP_UTF8, 0, wcstr, 634 wclen, NULL, 0, NULL, NULL); 635 636 if (outlen > 0) { 637 outstr = (char *) malloc(outlen + 2); 638 outlen = WideCharToMultiByte(bFromUTF8 ? CP_ACP : CP_UTF8, 0, wcstr, 639 wclen, outstr, outlen, NULL, NULL); 640 if (outlen > 0) 641 *(outstr+outlen) = _T('\0'); 642 else 643 return NULL; 644 } 645 free( wcstr ); 646 return outstr; 647 } 648 #endif 649 650 char * 651 ldaptool_local2UTF8( const char *src ) 652 { 653 char *utf8; 654 #ifndef XP_WIN32 655 char *locale, *newcharset; 656 size_t outLen, resultLen; 657 UErrorCode err = U_ZERO_ERROR; 658 UConverter *cnv; 659 660 if (src == NULL) 661 { 662 return NULL; 663 } 664 else if (*src == 0 || (ldaptool_charset == NULL) 665 || (!strcmp( ldaptool_charset, "" ))) 666 { 667 /* no option specified, so assume it's already in utf-8 */ 668 utf8 = strdup(src); 669 return utf8; 670 } 671 672 if( !strcmp( ldaptool_charset, "0" ) 673 && (!charsetset) ) 674 { 675 /* zero option specified, so try to get default codepage 676 this sucker is strdup'd immediately so it's OK to cast */ 677 newcharset = (char *)ucnv_getDefaultName(); 678 if (newcharset != NULL) { 679 free( ldaptool_charset ); 680 /* the default codepage lives in ICU */ 681 ldaptool_charset = strdup(newcharset); 682 if (ldaptool_charset == NULL) { 683 return strdup(src); 684 } 685 } 686 charsetset = 1; 687 } 688 else 689 if( strcmp( ldaptool_charset, "" ) && (!charsetset) ) 690 { 691 /* -i option specified with charset name */ 692 charsetset = 1; 693 } 694 695 /* do the preflight - get the size needed for the target buffer */ 696 outLen = (size_t) ucnv_convert( "utf-8", ldaptool_charset, NULL, 0, src, 697 strlen( src ) * sizeof(char), &err); 698 699 if ((err != U_BUFFER_OVERFLOW_ERROR) || (outLen == 0)) { 700 /* default to just a copy of the string - this covers 701 the case of an illegal charset also */ 702 return strdup(src); 703 } 704 705 utf8 = (char *) malloc( outLen + 1); 706 if( utf8 == NULL ) { 707 /* if we're already out of memory, does strdup just return NULL? */ 708 return strdup(src); 709 } 710 711 /* do the actual conversion this time */ 712 err = U_ZERO_ERROR; 713 resultLen = ucnv_convert( "utf-8", ldaptool_charset, utf8, (outLen + 1), src, 714 strlen(src) * sizeof(char), &err ); 715 716 if (!U_SUCCESS(err)) { 717 free(utf8); 718 return strdup(src); 719 } 720 721 #else 722 utf8 = _convertor(src, FALSE); 723 if( utf8 == NULL ) 724 utf8 = strdup(src); 725 #endif 726 727 return utf8; 728 } 729 #endif /* HAVE_LIBICU */ 730 731 #ifndef HAVE_LIBICU 732 #ifdef __cplusplus 733 } 734 #endif 735 #endif 736