00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026
00027
00028 char lp_failed_convert_char(void)
00029 {
00030 return '_';
00031 }
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
00050 static BOOL conv_silent;
00051
00052
00053
00054
00055 static const char *charset_name(charset_t ch)
00056 {
00057 const char *ret = NULL;
00058
00059 if (ch == CH_UTF16LE) ret = "UTF-16LE";
00060 else if (ch == CH_UTF16BE) ret = "UTF-16BE";
00061 else if (ch == CH_UNIX) ret = lp_unix_charset();
00062 else if (ch == CH_DOS) ret = lp_dos_charset();
00063 else if (ch == CH_DISPLAY) ret = lp_display_charset();
00064 else if (ch == CH_UTF8) ret = "UTF8";
00065
00066 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
00067 if (ret && !strcmp(ret, "LOCALE")) {
00068 const char *ln = NULL;
00069
00070 #ifdef HAVE_SETLOCALE
00071 setlocale(LC_ALL, "");
00072 #endif
00073 ln = nl_langinfo(CODESET);
00074 if (ln) {
00075
00076
00077 smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE");
00078 if (handle == (smb_iconv_t) -1) {
00079 DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln));
00080 ln = NULL;
00081 } else {
00082 DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln));
00083 smb_iconv_close(handle);
00084 }
00085 }
00086 ret = ln;
00087 }
00088 #endif
00089
00090 if (!ret || !*ret) ret = "ASCII";
00091 return ret;
00092 }
00093
00094 void lazy_initialize_conv(void)
00095 {
00096 static int initialized = False;
00097
00098 if (!initialized) {
00099 initialized = True;
00100 load_case_tables();
00101 init_iconv();
00102 }
00103 }
00104
00105
00106
00107
00108 void gfree_charcnv(void)
00109 {
00110 int c1, c2;
00111
00112 for (c1=0;c1<NUM_CHARSETS;c1++) {
00113 for (c2=0;c2<NUM_CHARSETS;c2++) {
00114 if ( conv_handles[c1][c2] ) {
00115 smb_iconv_close( conv_handles[c1][c2] );
00116 conv_handles[c1][c2] = 0;
00117 }
00118 }
00119 }
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129 void init_iconv(void)
00130 {
00131 int c1, c2;
00132 BOOL did_reload = False;
00133
00134
00135
00136 if (!conv_handles[CH_UNIX][CH_UTF16LE])
00137 conv_handles[CH_UNIX][CH_UTF16LE] = smb_iconv_open(charset_name(CH_UTF16LE), "ASCII");
00138
00139 if (!conv_handles[CH_UTF16LE][CH_UNIX])
00140 conv_handles[CH_UTF16LE][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UTF16LE));
00141
00142 for (c1=0;c1<NUM_CHARSETS;c1++) {
00143 for (c2=0;c2<NUM_CHARSETS;c2++) {
00144 const char *n1 = charset_name((charset_t)c1);
00145 const char *n2 = charset_name((charset_t)c2);
00146 if (conv_handles[c1][c2] &&
00147 strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
00148 strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
00149 continue;
00150
00151 did_reload = True;
00152
00153 if (conv_handles[c1][c2])
00154 smb_iconv_close(conv_handles[c1][c2]);
00155
00156 conv_handles[c1][c2] = smb_iconv_open(n2,n1);
00157 if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
00158 DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
00159 charset_name((charset_t)c1), charset_name((charset_t)c2)));
00160 if (c1 != CH_UTF16LE && c1 != CH_UTF16BE) {
00161 n1 = "ASCII";
00162 }
00163 if (c2 != CH_UTF16LE && c2 != CH_UTF16BE) {
00164 n2 = "ASCII";
00165 }
00166 DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
00167 n1, n2 ));
00168 conv_handles[c1][c2] = smb_iconv_open(n2,n1);
00169 if (!conv_handles[c1][c2]) {
00170 DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1, n2));
00171 smb_panic("init_iconv: conv_handle initialization failed.");
00172 }
00173 }
00174 }
00175 }
00176
00177 if (did_reload) {
00178
00179
00180
00181 conv_silent = True;
00182 init_doschar_table();
00183 init_valid_table();
00184 conv_silent = False;
00185 }
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 static size_t convert_string_internal(charset_t from, charset_t to,
00204 void const *src, size_t srclen,
00205 void *dest, size_t destlen, BOOL allow_bad_conv)
00206 {
00207 size_t i_len, o_len;
00208 size_t retval;
00209 const char* inbuf = (const char*)src;
00210 char* outbuf = (char*)dest;
00211 smb_iconv_t descriptor;
00212
00213 lazy_initialize_conv();
00214
00215 descriptor = conv_handles[from][to];
00216
00217 if (srclen == (size_t)-1) {
00218 if (from == CH_UTF16LE || from == CH_UTF16BE) {
00219 srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
00220 } else {
00221 srclen = strlen((const char *)src)+1;
00222 }
00223 }
00224
00225
00226 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
00227 if (!conv_silent)
00228 DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
00229 return (size_t)-1;
00230 }
00231
00232 i_len=srclen;
00233 o_len=destlen;
00234
00235 again:
00236
00237 retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
00238 if(retval==(size_t)-1) {
00239 const char *reason="unknown error";
00240 switch(errno) {
00241 case EINVAL:
00242 reason="Incomplete multibyte sequence";
00243 if (!conv_silent)
00244 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
00245 if (allow_bad_conv)
00246 goto use_as_is;
00247 break;
00248 case E2BIG:
00249 reason="No more room";
00250 if (!conv_silent) {
00251 if (from == CH_UNIX) {
00252 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
00253 charset_name(from), charset_name(to),
00254 (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
00255 } else {
00256 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
00257 charset_name(from), charset_name(to),
00258 (unsigned int)srclen, (unsigned int)destlen));
00259 }
00260 }
00261 break;
00262 case EILSEQ:
00263 reason="Illegal multibyte sequence";
00264 if (!conv_silent)
00265 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
00266 if (allow_bad_conv)
00267 goto use_as_is;
00268 break;
00269 default:
00270 if (!conv_silent)
00271 DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
00272 break;
00273 }
00274
00275 }
00276 return destlen-o_len;
00277
00278 use_as_is:
00279
00280
00281
00282
00283
00284
00285
00286 {
00287 if (o_len == 0 || i_len == 0)
00288 return destlen - o_len;
00289
00290 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
00291 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
00292
00293
00294
00295 if (i_len < 2)
00296 return destlen - o_len;
00297 if (i_len >= 2) {
00298 *outbuf = lp_failed_convert_char();
00299
00300 outbuf++;
00301 o_len--;
00302
00303 inbuf += 2;
00304 i_len -= 2;
00305 }
00306
00307 if (o_len == 0 || i_len == 0)
00308 return destlen - o_len;
00309
00310
00311 goto again;
00312
00313 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
00314
00315
00316
00317 if (o_len < 2)
00318 return destlen - o_len;
00319
00320 outbuf[0] = lp_failed_convert_char();
00321 outbuf[1] = '\0';
00322
00323 inbuf++;
00324 i_len--;
00325
00326 outbuf += 2;
00327 o_len -= 2;
00328
00329 if (o_len == 0 || i_len == 0)
00330 return destlen - o_len;
00331
00332
00333 goto again;
00334
00335 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
00336 to != CH_UTF16LE && to != CH_UTF16BE) {
00337
00338
00339 outbuf[0] = lp_failed_convert_char();
00340
00341 inbuf++;
00342 i_len--;
00343
00344 outbuf++;
00345 o_len--;
00346
00347 if (o_len == 0 || i_len == 0)
00348 return destlen - o_len;
00349
00350
00351 goto again;
00352
00353 } else {
00354
00355 return destlen - o_len;
00356 }
00357 }
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 size_t convert_string(charset_t from, charset_t to,
00378 void const *src, size_t srclen,
00379 void *dest, size_t destlen, BOOL allow_bad_conv)
00380 {
00381
00382
00383
00384
00385
00386
00387 #ifdef DEVELOPER
00388 SMB_ASSERT(destlen != (size_t)-1);
00389 #endif
00390
00391 if (srclen == 0)
00392 return 0;
00393
00394 if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
00395 const unsigned char *p = (const unsigned char *)src;
00396 unsigned char *q = (unsigned char *)dest;
00397 size_t slen = srclen;
00398 size_t dlen = destlen;
00399 unsigned char lastp = '\0';
00400 size_t retval = 0;
00401
00402
00403 while (slen && dlen) {
00404 if ((lastp = *p) <= 0x7f) {
00405 *q++ = *p++;
00406 if (slen != (size_t)-1) {
00407 slen--;
00408 }
00409 dlen--;
00410 retval++;
00411 if (!lastp)
00412 break;
00413 } else {
00414 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
00415 goto general_case;
00416 #else
00417 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
00418 #endif
00419 }
00420 }
00421 if (!dlen) {
00422
00423 if (((slen != (size_t)-1) && slen) ||
00424 ((slen == (size_t)-1) && lastp)) {
00425 errno = E2BIG;
00426 }
00427 }
00428 return retval;
00429 } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
00430 const unsigned char *p = (const unsigned char *)src;
00431 unsigned char *q = (unsigned char *)dest;
00432 size_t retval = 0;
00433 size_t slen = srclen;
00434 size_t dlen = destlen;
00435 unsigned char lastp = '\0';
00436
00437
00438 while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
00439 if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
00440 *q++ = *p;
00441 if (slen != (size_t)-1) {
00442 slen -= 2;
00443 }
00444 p += 2;
00445 dlen--;
00446 retval++;
00447 if (!lastp)
00448 break;
00449 } else {
00450 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
00451 goto general_case;
00452 #else
00453 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
00454 #endif
00455 }
00456 }
00457 if (!dlen) {
00458
00459 if (((slen != (size_t)-1) && slen) ||
00460 ((slen == (size_t)-1) && lastp)) {
00461 errno = E2BIG;
00462 }
00463 }
00464 return retval;
00465 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
00466 const unsigned char *p = (const unsigned char *)src;
00467 unsigned char *q = (unsigned char *)dest;
00468 size_t retval = 0;
00469 size_t slen = srclen;
00470 size_t dlen = destlen;
00471 unsigned char lastp = '\0';
00472
00473
00474 while (slen && (dlen >= 2)) {
00475 if ((lastp = *p) <= 0x7F) {
00476 *q++ = *p++;
00477 *q++ = '\0';
00478 if (slen != (size_t)-1) {
00479 slen--;
00480 }
00481 dlen -= 2;
00482 retval += 2;
00483 if (!lastp)
00484 break;
00485 } else {
00486 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
00487 goto general_case;
00488 #else
00489 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
00490 #endif
00491 }
00492 }
00493 if (!dlen) {
00494
00495 if (((slen != (size_t)-1) && slen) ||
00496 ((slen == (size_t)-1) && lastp)) {
00497 errno = E2BIG;
00498 }
00499 }
00500 return retval;
00501 }
00502
00503 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
00504 general_case:
00505 #endif
00506 return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
00526 void const *src, size_t srclen, void *dst, BOOL allow_bad_conv)
00527 {
00528 size_t i_len, o_len, destlen = (srclen * 3) / 2;
00529 size_t retval;
00530 const char *inbuf = (const char *)src;
00531 char *outbuf = NULL, *ob = NULL;
00532 smb_iconv_t descriptor;
00533 void **dest = (void **)dst;
00534
00535 *dest = NULL;
00536
00537 if (src == NULL || srclen == (size_t)-1)
00538 return (size_t)-1;
00539 if (srclen == 0)
00540 return 0;
00541
00542 lazy_initialize_conv();
00543
00544 descriptor = conv_handles[from][to];
00545
00546 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
00547 if (!conv_silent)
00548 DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
00549 return (size_t)-1;
00550 }
00551
00552 convert:
00553
00554
00555 if ((destlen*2)+2 < destlen) {
00556
00557 if (!conv_silent)
00558 DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
00559 if (!ctx)
00560 SAFE_FREE(outbuf);
00561 return (size_t)-1;
00562 } else {
00563 destlen = destlen * 2;
00564 }
00565
00566
00567 if (ctx) {
00568 ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2);
00569 } else {
00570 ob = (char *)SMB_REALLOC(ob, destlen + 2);
00571 }
00572
00573 if (!ob) {
00574 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
00575 return (size_t)-1;
00576 }
00577 outbuf = ob;
00578 i_len = srclen;
00579 o_len = destlen;
00580
00581 again:
00582
00583 retval = smb_iconv(descriptor,
00584 &inbuf, &i_len,
00585 &outbuf, &o_len);
00586 if(retval == (size_t)-1) {
00587 const char *reason="unknown error";
00588 switch(errno) {
00589 case EINVAL:
00590 reason="Incomplete multibyte sequence";
00591 if (!conv_silent)
00592 DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
00593 if (allow_bad_conv)
00594 goto use_as_is;
00595 break;
00596 case E2BIG:
00597 goto convert;
00598 case EILSEQ:
00599 reason="Illegal multibyte sequence";
00600 if (!conv_silent)
00601 DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
00602 if (allow_bad_conv)
00603 goto use_as_is;
00604 break;
00605 }
00606 if (!conv_silent)
00607 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
00608
00609 return (size_t)-1;
00610 }
00611
00612 out:
00613
00614 destlen = destlen - o_len;
00615 if (ctx) {
00616
00617 ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2);
00618 } else {
00619 ob = (char *)SMB_REALLOC(ob,destlen + 2);
00620 }
00621
00622 if (destlen && !ob) {
00623 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
00624 return (size_t)-1;
00625 }
00626
00627 *dest = ob;
00628
00629
00630 ob[destlen] = '\0';
00631 ob[destlen+1] = '\0';
00632
00633 return destlen;
00634
00635 use_as_is:
00636
00637
00638
00639
00640
00641
00642
00643 {
00644 if (o_len == 0 || i_len == 0)
00645 goto out;
00646
00647 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
00648 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
00649
00650
00651
00652
00653 if (i_len < 2)
00654 goto out;
00655
00656 if (i_len >= 2) {
00657 *outbuf = lp_failed_convert_char();
00658
00659 outbuf++;
00660 o_len--;
00661
00662 inbuf += 2;
00663 i_len -= 2;
00664 }
00665
00666 if (o_len == 0 || i_len == 0)
00667 goto out;
00668
00669
00670 goto again;
00671
00672 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
00673
00674
00675
00676 if (o_len < 2)
00677 goto out;
00678
00679 outbuf[0] = lp_failed_convert_char();
00680 outbuf[1] = '\0';
00681
00682 inbuf++;
00683 i_len--;
00684
00685 outbuf += 2;
00686 o_len -= 2;
00687
00688 if (o_len == 0 || i_len == 0)
00689 goto out;
00690
00691
00692 goto again;
00693
00694 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
00695 to != CH_UTF16LE && to != CH_UTF16BE) {
00696
00697
00698 outbuf[0] = lp_failed_convert_char();
00699
00700 inbuf++;
00701 i_len--;
00702
00703 outbuf++;
00704 o_len--;
00705
00706 if (o_len == 0 || i_len == 0)
00707 goto out;
00708
00709
00710 goto again;
00711
00712 } else {
00713
00714 goto out;
00715 }
00716 }
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
00729 void const *src, size_t srclen, void *dst,
00730 BOOL allow_bad_conv)
00731 {
00732 void **dest = (void **)dst;
00733 size_t dest_len;
00734
00735 *dest = NULL;
00736 dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, allow_bad_conv);
00737 if (dest_len == (size_t)-1)
00738 return (size_t)-1;
00739 if (*dest == NULL)
00740 return (size_t)-1;
00741 return dest_len;
00742 }
00743
00744 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
00745 {
00746 size_t size;
00747 smb_ucs2_t *buffer;
00748
00749 size = push_ucs2_allocate(&buffer, src);
00750 if (size == (size_t)-1) {
00751 smb_panic("failed to create UCS2 buffer");
00752 }
00753 if (!strupper_w(buffer) && (dest == src)) {
00754 free(buffer);
00755 return srclen;
00756 }
00757
00758 size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
00759 free(buffer);
00760 return size;
00761 }
00762
00763
00764
00765
00766
00767
00768 char *strdup_upper(const char *s)
00769 {
00770 pstring out_buffer;
00771 const unsigned char *p = (const unsigned char *)s;
00772 unsigned char *q = (unsigned char *)out_buffer;
00773
00774
00775
00776
00777
00778
00779 while (1) {
00780 if (*p & 0x80)
00781 break;
00782 *q++ = toupper_ascii(*p);
00783 if (!*p)
00784 break;
00785 p++;
00786 if (p - ( const unsigned char *)s >= sizeof(pstring))
00787 break;
00788 }
00789
00790 if (*p) {
00791
00792 size_t size;
00793 wpstring buffer;
00794 size = convert_string(CH_UNIX, CH_UTF16LE, s, -1, buffer, sizeof(buffer), True);
00795 if (size == (size_t)-1) {
00796 return NULL;
00797 }
00798
00799 strupper_w(buffer);
00800
00801 size = convert_string(CH_UTF16LE, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True);
00802 if (size == (size_t)-1) {
00803 return NULL;
00804 }
00805 }
00806
00807 return SMB_STRDUP(out_buffer);
00808 }
00809
00810 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
00811 {
00812 size_t size;
00813 smb_ucs2_t *buffer = NULL;
00814
00815 size = convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, srclen,
00816 (void **)(void *)&buffer, True);
00817 if (size == (size_t)-1 || !buffer) {
00818 smb_panic("failed to create UCS2 buffer");
00819 }
00820 if (!strlower_w(buffer) && (dest == src)) {
00821 SAFE_FREE(buffer);
00822 return srclen;
00823 }
00824 size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
00825 SAFE_FREE(buffer);
00826 return size;
00827 }
00828
00829
00830
00831
00832
00833 char *strdup_lower(const char *s)
00834 {
00835 size_t size;
00836 smb_ucs2_t *buffer = NULL;
00837 char *out_buffer;
00838
00839 size = push_ucs2_allocate(&buffer, s);
00840 if (size == -1 || !buffer) {
00841 return NULL;
00842 }
00843
00844 strlower_w(buffer);
00845
00846 size = pull_ucs2_allocate(&out_buffer, buffer);
00847 SAFE_FREE(buffer);
00848
00849 if (size == (size_t)-1) {
00850 return NULL;
00851 }
00852
00853 return out_buffer;
00854 }
00855
00856 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
00857 {
00858 if (flags & (STR_NOALIGN|STR_ASCII))
00859 return 0;
00860 return PTR_DIFF(p, base_ptr) & 1;
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
00879 {
00880 size_t src_len = strlen(src);
00881 pstring tmpbuf;
00882 size_t ret;
00883
00884
00885 if (dest_len == (size_t)-1)
00886 smb_panic("push_ascii - dest_len == -1");
00887
00888 if (flags & STR_UPPER) {
00889 pstrcpy(tmpbuf, src);
00890 strupper_m(tmpbuf);
00891 src = tmpbuf;
00892 }
00893
00894 if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
00895 src_len++;
00896
00897 ret =convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);
00898 if (ret == (size_t)-1 &&
00899 (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
00900 && dest_len > 0) {
00901 ((char *)dest)[0] = '\0';
00902 }
00903 return ret;
00904 }
00905
00906 size_t push_ascii_fstring(void *dest, const char *src)
00907 {
00908 return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
00909 }
00910
00911 size_t push_ascii_pstring(void *dest, const char *src)
00912 {
00913 return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
00914 }
00915
00916
00917
00918
00919
00920
00921 size_t push_ascii_nstring(void *dest, const char *src)
00922 {
00923 size_t i, buffer_len, dest_len;
00924 smb_ucs2_t *buffer;
00925
00926 conv_silent = True;
00927 buffer_len = push_ucs2_allocate(&buffer, src);
00928 if (buffer_len == (size_t)-1) {
00929 smb_panic("failed to create UCS2 buffer");
00930 }
00931
00932
00933 buffer_len /= sizeof(smb_ucs2_t);
00934
00935 dest_len = 0;
00936 for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
00937 unsigned char mb[10];
00938
00939 size_t mb_len = convert_string(CH_UTF16LE, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
00940 if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
00941 memcpy((char *)dest + dest_len, mb, mb_len);
00942 dest_len += mb_len;
00943 } else {
00944 errno = E2BIG;
00945 break;
00946 }
00947 }
00948 ((char *)dest)[dest_len] = '\0';
00949
00950 SAFE_FREE(buffer);
00951 conv_silent = False;
00952 return dest_len;
00953 }
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
00971 {
00972 size_t ret;
00973
00974 if (dest_len == (size_t)-1)
00975 dest_len = sizeof(pstring);
00976
00977 if (flags & STR_TERMINATE) {
00978 if (src_len == (size_t)-1) {
00979 src_len = strlen((const char *)src) + 1;
00980 } else {
00981 size_t len = strnlen((const char *)src, src_len);
00982 if (len < src_len)
00983 len++;
00984 src_len = len;
00985 }
00986 }
00987
00988 ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
00989 if (ret == (size_t)-1) {
00990 ret = 0;
00991 dest_len = 0;
00992 }
00993
00994 if (dest_len && ret) {
00995
00996 if (dest[MIN(ret-1, dest_len-1)] != 0) {
00997 dest[MIN(ret, dest_len-1)] = 0;
00998 }
00999 } else {
01000 dest[0] = 0;
01001 }
01002
01003 return src_len;
01004 }
01005
01006 size_t pull_ascii_pstring(char *dest, const void *src)
01007 {
01008 return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
01009 }
01010
01011 size_t pull_ascii_fstring(char *dest, const void *src)
01012 {
01013 return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
01014 }
01015
01016
01017
01018 size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
01019 {
01020 return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
01041 {
01042 size_t len=0;
01043 size_t src_len;
01044 size_t ret;
01045
01046
01047 if (dest_len == (size_t)-1)
01048 dest_len = sizeof(pstring);
01049
01050 if (flags & STR_TERMINATE)
01051 src_len = (size_t)-1;
01052 else
01053 src_len = strlen(src);
01054
01055 if (ucs2_align(base_ptr, dest, flags)) {
01056 *(char *)dest = 0;
01057 dest = (void *)((char *)dest + 1);
01058 if (dest_len)
01059 dest_len--;
01060 len++;
01061 }
01062
01063
01064 dest_len &= ~1;
01065
01066 ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True);
01067 if (ret == (size_t)-1) {
01068 return 0;
01069 }
01070
01071 len += ret;
01072
01073 if (flags & STR_UPPER) {
01074 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
01075 size_t i;
01076
01077
01078
01079
01080 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
01081 smb_ucs2_t v = toupper_w(dest_ucs2[i]);
01082 if (v != dest_ucs2[i]) {
01083 dest_ucs2[i] = v;
01084 }
01085 }
01086 }
01087
01088 return len;
01089 }
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
01102 {
01103 size_t src_len = strlen(src)+1;
01104
01105 *dest = NULL;
01106 return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
01107 }
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
01120 {
01121 size_t src_len = strlen(src)+1;
01122
01123 *dest = NULL;
01124 return convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
01125 }
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
01138 {
01139 size_t src_len = strlen(src);
01140 pstring tmpbuf;
01141
01142
01143 if (dest_len == (size_t)-1)
01144 dest_len = sizeof(pstring);
01145
01146 if (flags & STR_UPPER) {
01147 pstrcpy(tmpbuf, src);
01148 strupper_m(tmpbuf);
01149 src = tmpbuf;
01150 }
01151
01152 if (flags & STR_TERMINATE)
01153 src_len++;
01154
01155 return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
01156 }
01157
01158 size_t push_utf8_fstring(void *dest, const char *src)
01159 {
01160 return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
01161 }
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
01172 {
01173 size_t src_len = strlen(src)+1;
01174
01175 *dest = NULL;
01176 return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest, True);
01177 }
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187 size_t push_utf8_allocate(char **dest, const char *src)
01188 {
01189 size_t src_len = strlen(src)+1;
01190
01191 *dest = NULL;
01192 return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, True);
01193 }
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
01207 {
01208 size_t ret;
01209
01210 if (dest_len == (size_t)-1)
01211 dest_len = sizeof(pstring);
01212
01213 if (ucs2_align(base_ptr, src, flags)) {
01214 src = (const void *)((const char *)src + 1);
01215 if (src_len != (size_t)-1)
01216 src_len--;
01217 }
01218
01219 if (flags & STR_TERMINATE) {
01220
01221 if (src_len != (size_t)-1) {
01222 size_t len = strnlen_w((const smb_ucs2_t *)src,
01223 src_len/2);
01224 if (len < src_len/2)
01225 len++;
01226 src_len = len*2;
01227 }
01228 }
01229
01230
01231 if (src_len != (size_t)-1)
01232 src_len &= ~1;
01233
01234 ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
01235 if (ret == (size_t)-1) {
01236 return 0;
01237 }
01238
01239 if (src_len == (size_t)-1)
01240 src_len = ret*2;
01241
01242 if (dest_len && ret) {
01243
01244 if (dest[MIN(ret-1, dest_len-1)] != 0) {
01245 dest[MIN(ret, dest_len-1)] = 0;
01246 }
01247 } else {
01248 dest[0] = 0;
01249 }
01250
01251 return src_len;
01252 }
01253
01254 size_t pull_ucs2_pstring(char *dest, const void *src)
01255 {
01256 return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
01257 }
01258
01259 size_t pull_ucs2_fstring(char *dest, const void *src)
01260 {
01261 return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
01262 }
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
01273 {
01274 size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
01275 *dest = NULL;
01276 return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
01288 {
01289 size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
01290 *dest = NULL;
01291 return convert_string_allocate(NULL, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
01292 }
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
01303 {
01304 size_t src_len = strlen(src)+1;
01305 *dest = NULL;
01306 return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
01307 }
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 size_t pull_utf8_allocate(char **dest, const char *src)
01318 {
01319 size_t src_len = strlen(src)+1;
01320 *dest = NULL;
01321 return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
01322 }
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 size_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
01333 {
01334 size_t src_len = strlen(src)+1;
01335 *dest = NULL;
01336 return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, True);
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353 size_t push_string_fn(const char *function, unsigned int line, const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
01354 {
01355 #ifdef DEVELOPER
01356
01357
01358
01359
01360
01361
01362 #if 0
01363 if (dest_len != (size_t)-1)
01364 clobber_region(function, line, dest, dest_len);
01365 #else
01366 if (dest_len != (size_t)-1)
01367 memset(dest, '\0', dest_len);
01368 #endif
01369 #endif
01370
01371 if (!(flags & STR_ASCII) && \
01372 ((flags & STR_UNICODE || \
01373 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
01374 return push_ucs2(base_ptr, dest, src, dest_len, flags);
01375 }
01376 return push_ascii(dest, src, dest_len, flags);
01377 }
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394 size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
01395 {
01396 #ifdef DEVELOPER
01397 if (dest_len != (size_t)-1)
01398 clobber_region(function, line, dest, dest_len);
01399 #endif
01400
01401 if (!(flags & STR_ASCII) && \
01402 ((flags & STR_UNICODE || \
01403 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
01404 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
01405 }
01406 return pull_ascii(dest, src, dest_len, src_len, flags);
01407 }
01408
01409 size_t align_string(const void *base_ptr, const char *p, int flags)
01410 {
01411 if (!(flags & STR_ASCII) && \
01412 ((flags & STR_UNICODE || \
01413 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
01414 return ucs2_align(base_ptr, p, flags);
01415 }
01416 return 0;
01417 }
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429 codepoint_t next_codepoint(const char *str, size_t *size)
01430 {
01431
01432 uint8_t buf[4];
01433 smb_iconv_t descriptor;
01434 size_t ilen_orig;
01435 size_t ilen;
01436 size_t olen;
01437 char *outbuf;
01438
01439 if ((str[0] & 0x80) == 0) {
01440 *size = 1;
01441 return (codepoint_t)str[0];
01442 }
01443
01444
01445
01446
01447
01448 ilen_orig = strnlen(str, 5);
01449 ilen = ilen_orig;
01450
01451 lazy_initialize_conv();
01452
01453 descriptor = conv_handles[CH_UNIX][CH_UTF16LE];
01454 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
01455 *size = 1;
01456 return INVALID_CODEPOINT;
01457 }
01458
01459
01460
01461 olen = 2;
01462 outbuf = (char *)buf;
01463 smb_iconv(descriptor, &str, &ilen, &outbuf, &olen);
01464 if (olen == 2) {
01465
01466
01467
01468 olen = 4;
01469 outbuf = (char *)buf;
01470 smb_iconv(descriptor, &str, &ilen, &outbuf, &olen);
01471 if (olen == 4) {
01472
01473 *size = 1;
01474 return INVALID_CODEPOINT;
01475 }
01476 olen = 4 - olen;
01477 } else {
01478 olen = 2 - olen;
01479 }
01480
01481 *size = ilen_orig - ilen;
01482
01483 if (olen == 2) {
01484
01485 return (codepoint_t)SVAL(buf, 0);
01486 }
01487 if (olen == 4) {
01488
01489
01490
01491 codepoint_t w1 = SVAL(buf,0) & ~0xD800;
01492 codepoint_t w2 = SVAL(buf,2) & ~0xDC00;
01493
01494 return (codepoint_t)0x10000 +
01495 (w1 << 10) + w2;
01496 }
01497
01498
01499 return INVALID_CODEPOINT;
01500 }