Ignore:
Timestamp:
Mar 12, 2008, 9:08:18 AM (17 years ago)
Author:
Paul Smedley
Message:

Update source to 3.0.28a

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/samba-3.0/source/lib/charcnv.c

    r120 r124  
    2828char lp_failed_convert_char(void)
    2929{
    30     return '_';
     30        return '_';
    3131}
    3232
     
    5555static const char *charset_name(charset_t ch)
    5656{
    57     const char *ret = NULL;
    58 
    59     if (ch == CH_UTF16LE) ret = "UTF-16LE";
    60     else if (ch == CH_UTF16BE) ret = "UTF-16BE";
    61     else if (ch == CH_UNIX) ret = lp_unix_charset();
    62     else if (ch == CH_DOS) ret = lp_dos_charset();
    63     else if (ch == CH_DISPLAY) ret = lp_display_charset();
    64     else if (ch == CH_UTF8) ret = "UTF8";
     57        const char *ret = NULL;
     58
     59        if (ch == CH_UTF16LE) ret = "UTF-16LE";
     60        else if (ch == CH_UTF16BE) ret = "UTF-16BE";
     61        else if (ch == CH_UNIX) ret = lp_unix_charset();
     62        else if (ch == CH_DOS) ret = lp_dos_charset();
     63        else if (ch == CH_DISPLAY) ret = lp_display_charset();
     64        else if (ch == CH_UTF8) ret = "UTF8";
    6565
    6666#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
    67     if (ret && !strcmp(ret, "LOCALE")) {
    68         const char *ln = NULL;
     67        if (ret && !strcmp(ret, "LOCALE")) {
     68                const char *ln = NULL;
    6969
    7070#ifdef HAVE_SETLOCALE
    71         setlocale(LC_ALL, "");
     71                setlocale(LC_ALL, "");
    7272#endif
    73         ln = nl_langinfo(CODESET);
    74         if (ln) {
    75             /* Check whether the charset name is supported
    76                by iconv */
    77             smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE");
    78             if (handle == (smb_iconv_t) -1) {
    79                 DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln));
    80                 ln = NULL;
    81             } else {
    82                 DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln));
    83                 smb_iconv_close(handle);
    84             }
    85         }
    86         ret = ln;
    87     }
     73                ln = nl_langinfo(CODESET);
     74                if (ln) {
     75                        /* Check whether the charset name is supported
     76                           by iconv */
     77                        smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE");
     78                        if (handle == (smb_iconv_t) -1) {
     79                                DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln));
     80                                ln = NULL;
     81                        } else {
     82                                DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln));
     83                                smb_iconv_close(handle);
     84                        }
     85                }
     86                ret = ln;
     87        }
    8888#endif
    8989
    90     if (!ret || !*ret) ret = "ASCII";
    91     return ret;
     90        if (!ret || !*ret) ret = "ASCII";
     91        return ret;
    9292}
    9393
    9494void lazy_initialize_conv(void)
    9595{
    96     static int initialized = False;
    97 
    98     if (!initialized) {
    99         initialized = True;
    100         load_case_tables();
    101         init_iconv();
    102     }
     96        static int initialized = False;
     97
     98        if (!initialized) {
     99                initialized = True;
     100                load_case_tables();
     101                init_iconv();
     102        }
    103103}
    104104
     
    108108void gfree_charcnv(void)
    109109{
    110     int c1, c2;
    111 
    112     for (c1=0;c1<NUM_CHARSETS;c1++) {
    113         for (c2=0;c2<NUM_CHARSETS;c2++) {
    114             if ( conv_handles[c1][c2] ) {
    115                 smb_iconv_close( conv_handles[c1][c2] );
    116                 conv_handles[c1][c2] = 0;
    117             }
    118         }
    119     }
     110        int c1, c2;
     111
     112        for (c1=0;c1<NUM_CHARSETS;c1++) {
     113                for (c2=0;c2<NUM_CHARSETS;c2++) {
     114                        if ( conv_handles[c1][c2] ) {
     115                                smb_iconv_close( conv_handles[c1][c2] );
     116                                conv_handles[c1][c2] = 0;
     117                        }
     118                }
     119        }
    120120}
    121121
     
    129129void init_iconv(void)
    130130{
    131     int c1, c2;
    132     BOOL did_reload = False;
    133 
    134     /* so that charset_name() works we need to get the UNIX<->UCS2 going
    135        first */
    136     if (!conv_handles[CH_UNIX][CH_UTF16LE])
    137         conv_handles[CH_UNIX][CH_UTF16LE] = smb_iconv_open(charset_name(CH_UTF16LE), "ASCII");
    138 
    139     if (!conv_handles[CH_UTF16LE][CH_UNIX])
    140         conv_handles[CH_UTF16LE][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UTF16LE));
    141 
    142     for (c1=0;c1<NUM_CHARSETS;c1++) {
    143         for (c2=0;c2<NUM_CHARSETS;c2++) {
    144             const char *n1 = charset_name((charset_t)c1);
    145             const char *n2 = charset_name((charset_t)c2);
    146             if (conv_handles[c1][c2] &&
    147                 strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
    148                 strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
    149                 continue;
    150 
    151             did_reload = True;
    152 
    153             if (conv_handles[c1][c2])
    154                 smb_iconv_close(conv_handles[c1][c2]);
    155 
    156             conv_handles[c1][c2] = smb_iconv_open(n2,n1);
    157             if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
    158                 DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
    159                     charset_name((charset_t)c1), charset_name((charset_t)c2)));
    160                 if (c1 != CH_UTF16LE && c1 != CH_UTF16BE) {
    161                     n1 = "ASCII";
    162                 }
    163                 if (c2 != CH_UTF16LE && c2 != CH_UTF16BE) {
    164                     n2 = "ASCII";
    165                 }
    166                 DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
    167                     n1, n2 ));
    168                 conv_handles[c1][c2] = smb_iconv_open(n2,n1);
    169                 if (!conv_handles[c1][c2]) {
    170                     DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1, n2));
    171                     smb_panic("init_iconv: conv_handle initialization failed.");
    172                 }
    173             }
    174         }
    175     }
    176 
    177     if (did_reload) {
    178         /* XXX: Does this really get called every time the dos
    179         * codepage changes? */
    180         /* XXX: Is the did_reload test too strict? */
    181         conv_silent = True;
    182         init_doschar_table();
    183         init_valid_table();
    184         conv_silent = False;
    185     }
     131        int c1, c2;
     132        BOOL did_reload = False;
     133
     134        /* so that charset_name() works we need to get the UNIX<->UCS2 going
     135           first */
     136        if (!conv_handles[CH_UNIX][CH_UTF16LE])
     137                conv_handles[CH_UNIX][CH_UTF16LE] = smb_iconv_open(charset_name(CH_UTF16LE), "ASCII");
     138
     139        if (!conv_handles[CH_UTF16LE][CH_UNIX])
     140                conv_handles[CH_UTF16LE][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UTF16LE));
     141
     142        for (c1=0;c1<NUM_CHARSETS;c1++) {
     143                for (c2=0;c2<NUM_CHARSETS;c2++) {
     144                        const char *n1 = charset_name((charset_t)c1);
     145                        const char *n2 = charset_name((charset_t)c2);
     146                        if (conv_handles[c1][c2] &&
     147                                strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
     148                                strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
     149                                continue;
     150
     151                        did_reload = True;
     152
     153                        if (conv_handles[c1][c2])
     154                                smb_iconv_close(conv_handles[c1][c2]);
     155
     156                        conv_handles[c1][c2] = smb_iconv_open(n2,n1);
     157                        if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
     158                                DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
     159                                        charset_name((charset_t)c1), charset_name((charset_t)c2)));
     160                                if (c1 != CH_UTF16LE && c1 != CH_UTF16BE) {
     161                                        n1 = "ASCII";
     162                                }
     163                                if (c2 != CH_UTF16LE && c2 != CH_UTF16BE) {
     164                                        n2 = "ASCII";
     165                                }
     166                                DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
     167                                        n1, n2 ));
     168                                conv_handles[c1][c2] = smb_iconv_open(n2,n1);
     169                                if (!conv_handles[c1][c2]) {
     170                                        DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1, n2));
     171                                        smb_panic("init_iconv: conv_handle initialization failed.");
     172                                }
     173                        }
     174                }
     175        }
     176
     177        if (did_reload) {
     178                /* XXX: Does this really get called every time the dos
     179                * codepage changes? */
     180                /* XXX: Is the did_reload test too strict? */
     181                conv_silent = True;
     182                init_doschar_table();
     183                init_valid_table();
     184                conv_silent = False;
     185        }
    186186}
    187187
     
    202202
    203203static size_t convert_string_internal(charset_t from, charset_t to,
    204               void const *src, size_t srclen,
    205               void *dest, size_t destlen, BOOL allow_bad_conv)
    206 {
    207     size_t i_len, o_len;
    208     size_t retval;
    209     const char* inbuf = (const char*)src;
    210     char* outbuf = (char*)dest;
    211     smb_iconv_t descriptor;
    212 
    213     lazy_initialize_conv();
    214 
    215     descriptor = conv_handles[from][to];
    216 
    217     if (srclen == (size_t)-1) {
    218         if (from == CH_UTF16LE || from == CH_UTF16BE) {
    219             srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
    220         } else {
    221             srclen = strlen((const char *)src)+1;
    222         }
    223     }
    224 
    225 
    226     if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
    227         if (!conv_silent)
    228             DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
    229         return (size_t)-1;
    230     }
    231 
    232     i_len=srclen;
    233     o_len=destlen;
     204                          void const *src, size_t srclen,
     205                          void *dest, size_t destlen, BOOL allow_bad_conv)
     206{
     207        size_t i_len, o_len;
     208        size_t retval;
     209        const char* inbuf = (const char*)src;
     210        char* outbuf = (char*)dest;
     211        smb_iconv_t descriptor;
     212
     213        lazy_initialize_conv();
     214
     215        descriptor = conv_handles[from][to];
     216
     217        if (srclen == (size_t)-1) {
     218                if (from == CH_UTF16LE || from == CH_UTF16BE) {
     219                        srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
     220                } else {
     221                        srclen = strlen((const char *)src)+1;
     222                }
     223        }
     224
     225
     226        if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
     227                if (!conv_silent)
     228                        DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
     229                return (size_t)-1;
     230        }
     231
     232        i_len=srclen;
     233        o_len=destlen;
    234234
    235235 again:
    236236
    237     retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
    238     if(retval==(size_t)-1) {
    239             const char *reason="unknown error";
    240         switch(errno) {
    241             case EINVAL:
    242                 reason="Incomplete multibyte sequence";
    243                 if (!conv_silent)
    244                     DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
    245                 if (allow_bad_conv)
    246                     goto use_as_is;
    247                 break;
    248             case E2BIG:
    249                 reason="No more room";
    250                 if (!conv_silent) {
    251                     if (from == CH_UNIX) {
    252                         DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
    253                             charset_name(from), charset_name(to),
    254                             (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
    255                     } else {
    256                         DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
    257                             charset_name(from), charset_name(to),
    258                             (unsigned int)srclen, (unsigned int)destlen));
    259                     }
    260                 }
    261                 break;
    262             case EILSEQ:
    263                 reason="Illegal multibyte sequence";
    264                 if (!conv_silent)
    265                     DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
    266                 if (allow_bad_conv)
    267                     goto use_as_is;
    268                 break;
    269             default:
    270                 if (!conv_silent)
    271                     DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
    272                 break;
    273         }
    274         /* smb_panic(reason); */
    275     }
    276     return destlen-o_len;
     237        retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
     238        if(retval==(size_t)-1) {
     239                        const char *reason="unknown error";
     240                switch(errno) {
     241                        case EINVAL:
     242                                reason="Incomplete multibyte sequence";
     243                                if (!conv_silent)
     244                                        DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
     245                                if (allow_bad_conv)
     246                                        goto use_as_is;
     247                                break;
     248                        case E2BIG:
     249                                reason="No more room";
     250                                if (!conv_silent) {
     251                                        if (from == CH_UNIX) {
     252                                                DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
     253                                                        charset_name(from), charset_name(to),
     254                                                        (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
     255                                        } else {
     256                                                DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
     257                                                        charset_name(from), charset_name(to),
     258                                                        (unsigned int)srclen, (unsigned int)destlen));
     259                                        }
     260                                }
     261                                break;
     262                        case EILSEQ:
     263                                reason="Illegal multibyte sequence";
     264                                if (!conv_silent)
     265                                        DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
     266                                if (allow_bad_conv)
     267                                        goto use_as_is;
     268                                break;
     269                        default:
     270                                if (!conv_silent)
     271                                        DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
     272                                break;
     273                }
     274                /* smb_panic(reason); */
     275        }
     276        return destlen-o_len;
    277277
    278278 use_as_is:
    279279
    280     /*
    281     * Conversion not supported. This is actually an error, but there are so
    282     * many misconfigured iconv systems and smb.conf's out there we can't just
    283     * fail. Do a very bad conversion instead.... JRA.
    284     */
    285 
    286     {
    287         if (o_len == 0 || i_len == 0)
    288             return destlen - o_len;
    289 
    290         if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
    291                 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
    292             /* Can't convert from utf16 any endian to multibyte.
    293                Replace with the default fail char.
    294             */
    295             if (i_len < 2)
    296                 return destlen - o_len;
    297             if (i_len >= 2) {
    298                 *outbuf = lp_failed_convert_char();
    299 
    300                 outbuf++;
    301                 o_len--;
    302 
    303                 inbuf += 2;
    304                 i_len -= 2;
    305             }
    306 
    307             if (o_len == 0 || i_len == 0)
    308                 return destlen - o_len;
    309 
    310             /* Keep trying with the next char... */
    311             goto again;
    312 
    313         } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
    314             /* Can't convert to UTF16LE - just widen by adding the
    315                default fail char then zero.
    316             */
    317             if (o_len < 2)
    318                 return destlen - o_len;
    319 
    320             outbuf[0] = lp_failed_convert_char();
    321             outbuf[1] = '\0';
    322 
    323             inbuf++;
    324             i_len--;
    325 
    326             outbuf += 2;
    327             o_len -= 2;
    328 
    329             if (o_len == 0 || i_len == 0)
    330                 return destlen - o_len;
    331 
    332             /* Keep trying with the next char... */
    333             goto again;
    334 
    335         } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
    336                 to != CH_UTF16LE && to != CH_UTF16BE) {
    337             /* Failed multibyte to multibyte. Just copy the default fail char and
    338                 try again. */
    339             outbuf[0] = lp_failed_convert_char();
    340 
    341             inbuf++;
    342             i_len--;
    343 
    344             outbuf++;
    345             o_len--;
    346 
    347             if (o_len == 0 || i_len == 0)
    348                 return destlen - o_len;
    349 
    350             /* Keep trying with the next char... */
    351             goto again;
    352 
    353         } else {
    354             /* Keep compiler happy.... */
    355             return destlen - o_len;
    356         }
    357     }
     280        /*
     281        * Conversion not supported. This is actually an error, but there are so
     282        * many misconfigured iconv systems and smb.conf's out there we can't just
     283        * fail. Do a very bad conversion instead.... JRA.
     284        */
     285
     286        {
     287                if (o_len == 0 || i_len == 0)
     288                        return destlen - o_len;
     289
     290                if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
     291                                ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
     292                        /* Can't convert from utf16 any endian to multibyte.
     293                           Replace with the default fail char.
     294                        */
     295                        if (i_len < 2)
     296                                return destlen - o_len;
     297                        if (i_len >= 2) {
     298                                *outbuf = lp_failed_convert_char();
     299
     300                                outbuf++;
     301                                o_len--;
     302
     303                                inbuf += 2;
     304                                i_len -= 2;
     305                        }
     306
     307                        if (o_len == 0 || i_len == 0)
     308                                return destlen - o_len;
     309
     310                        /* Keep trying with the next char... */
     311                        goto again;
     312
     313                } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
     314                        /* Can't convert to UTF16LE - just widen by adding the
     315                           default fail char then zero.
     316                        */
     317                        if (o_len < 2)
     318                                return destlen - o_len;
     319
     320                        outbuf[0] = lp_failed_convert_char();
     321                        outbuf[1] = '\0';
     322
     323                        inbuf++;
     324                        i_len--;
     325
     326                        outbuf += 2;
     327                        o_len -= 2;
     328
     329                        if (o_len == 0 || i_len == 0)
     330                                return destlen - o_len;
     331
     332                        /* Keep trying with the next char... */
     333                        goto again;
     334
     335                } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
     336                                to != CH_UTF16LE && to != CH_UTF16BE) {
     337                        /* Failed multibyte to multibyte. Just copy the default fail char and
     338                                try again. */
     339                        outbuf[0] = lp_failed_convert_char();
     340
     341                        inbuf++;
     342                        i_len--;
     343
     344                        outbuf++;
     345                        o_len--;
     346
     347                        if (o_len == 0 || i_len == 0)
     348                                return destlen - o_len;
     349
     350                        /* Keep trying with the next char... */
     351                        goto again;
     352
     353                } else {
     354                        /* Keep compiler happy.... */
     355                        return destlen - o_len;
     356                }
     357        }
    358358}
    359359
     
    376376
    377377size_t convert_string(charset_t from, charset_t to,
    378               void const *src, size_t srclen,
    379               void *dest, size_t destlen, BOOL allow_bad_conv)
    380 {
    381     /*
    382     * NB. We deliberately don't do a strlen here if srclen == -1.
    383     * This is very expensive over millions of calls and is taken
    384     * care of in the slow path in convert_string_internal. JRA.
    385     */
     378                          void const *src, size_t srclen,
     379                          void *dest, size_t destlen, BOOL allow_bad_conv)
     380{
     381        /*
     382        * NB. We deliberately don't do a strlen here if srclen == -1.
     383        * This is very expensive over millions of calls and is taken
     384        * care of in the slow path in convert_string_internal. JRA.
     385        */
    386386
    387387#ifdef DEVELOPER
    388     SMB_ASSERT(destlen != (size_t)-1);
     388        SMB_ASSERT(destlen != (size_t)-1);
    389389#endif
    390390
    391     if (srclen == 0)
    392         return 0;
    393 
    394     if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
    395         const unsigned char *p = (const unsigned char *)src;
    396         unsigned char *q = (unsigned char *)dest;
    397         size_t slen = srclen;
    398         size_t dlen = destlen;
    399         unsigned char lastp = '\0';
    400         size_t retval = 0;
    401 
    402         /* If all characters are ascii, fast path here. */
    403         while (slen && dlen) {
    404             if ((lastp = *p) <= 0x7f) {
    405                 *q++ = *p++;
    406                 if (slen != (size_t)-1) {
    407                     slen--;
    408                 }
    409                 dlen--;
    410                 retval++;
    411                 if (!lastp)
    412                     break;
    413             } else {
     391        if (srclen == 0)
     392                return 0;
     393
     394        if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
     395                const unsigned char *p = (const unsigned char *)src;
     396                unsigned char *q = (unsigned char *)dest;
     397                size_t slen = srclen;
     398                size_t dlen = destlen;
     399                unsigned char lastp = '\0';
     400                size_t retval = 0;
     401
     402                /* If all characters are ascii, fast path here. */
     403                while (slen && dlen) {
     404                        if ((lastp = *p) <= 0x7f) {
     405                                *q++ = *p++;
     406                                if (slen != (size_t)-1) {
     407                                        slen--;
     408                                }
     409                                dlen--;
     410                                retval++;
     411                                if (!lastp)
     412                                        break;
     413                        } else {
    414414#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
    415                 goto general_case;
     415                                goto general_case;
    416416#else
    417                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
     417                                return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
    418418#endif
    419             }
    420         }
    421         if (!dlen) {
    422             /* Even if we fast path we should note if we ran out of room. */
    423             if (((slen != (size_t)-1) && slen) ||
    424                     ((slen == (size_t)-1) && lastp)) {
    425                 errno = E2BIG;
    426             }
    427         }
    428         return retval;
    429     } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
    430         const unsigned char *p = (const unsigned char *)src;
    431         unsigned char *q = (unsigned char *)dest;
    432         size_t retval = 0;
    433         size_t slen = srclen;
    434         size_t dlen = destlen;
    435         unsigned char lastp = '\0';
    436 
    437         /* If all characters are ascii, fast path here. */
    438         while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
    439             if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
    440                 *q++ = *p;
    441                 if (slen != (size_t)-1) {
    442                     slen -= 2;
    443                 }
    444                 p += 2;
    445                 dlen--;
    446                 retval++;
    447                 if (!lastp)
    448                     break;
    449             } else {
     419                        }
     420                }
     421                if (!dlen) {
     422                        /* Even if we fast path we should note if we ran out of room. */
     423                        if (((slen != (size_t)-1) && slen) ||
     424                                        ((slen == (size_t)-1) && lastp)) {
     425                                errno = E2BIG;
     426                        }
     427                }
     428                return retval;
     429        } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
     430                const unsigned char *p = (const unsigned char *)src;
     431                unsigned char *q = (unsigned char *)dest;
     432                size_t retval = 0;
     433                size_t slen = srclen;
     434                size_t dlen = destlen;
     435                unsigned char lastp = '\0';
     436
     437                /* If all characters are ascii, fast path here. */
     438                while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
     439                        if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
     440                                *q++ = *p;
     441                                if (slen != (size_t)-1) {
     442                                        slen -= 2;
     443                                }
     444                                p += 2;
     445                                dlen--;
     446                                retval++;
     447                                if (!lastp)
     448                                        break;
     449                        } else {
    450450#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
    451                 goto general_case;
     451                                goto general_case;
    452452#else
    453                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
     453                                return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
    454454#endif
    455             }
    456         }
    457         if (!dlen) {
    458             /* Even if we fast path we should note if we ran out of room. */
    459             if (((slen != (size_t)-1) && slen) ||
    460                     ((slen == (size_t)-1) && lastp)) {
    461                 errno = E2BIG;
    462             }
    463         }
    464         return retval;
    465     } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
    466         const unsigned char *p = (const unsigned char *)src;
    467         unsigned char *q = (unsigned char *)dest;
    468         size_t retval = 0;
    469         size_t slen = srclen;
    470         size_t dlen = destlen;
    471         unsigned char lastp = '\0';
    472 
    473         /* If all characters are ascii, fast path here. */
    474         while (slen && (dlen >= 2)) {
    475             if ((lastp = *p) <= 0x7F) {
    476                 *q++ = *p++;
    477                 *q++ = '\0';
    478                 if (slen != (size_t)-1) {
    479                     slen--;
    480                 }
    481                 dlen -= 2;
    482                 retval += 2;
    483                 if (!lastp)
    484                     break;
    485             } else {
     455                        }
     456                }
     457                if (!dlen) {
     458                        /* Even if we fast path we should note if we ran out of room. */
     459                        if (((slen != (size_t)-1) && slen) ||
     460                                        ((slen == (size_t)-1) && lastp)) {
     461                                errno = E2BIG;
     462                        }
     463                }
     464                return retval;
     465        } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
     466                const unsigned char *p = (const unsigned char *)src;
     467                unsigned char *q = (unsigned char *)dest;
     468                size_t retval = 0;
     469                size_t slen = srclen;
     470                size_t dlen = destlen;
     471                unsigned char lastp = '\0';
     472
     473                /* If all characters are ascii, fast path here. */
     474                while (slen && (dlen >= 2)) {
     475                        if ((lastp = *p) <= 0x7F) {
     476                                *q++ = *p++;
     477                                *q++ = '\0';
     478                                if (slen != (size_t)-1) {
     479                                        slen--;
     480                                }
     481                                dlen -= 2;
     482                                retval += 2;
     483                                if (!lastp)
     484                                        break;
     485                        } else {
    486486#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
    487                 goto general_case;
     487                                goto general_case;
    488488#else
    489                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
     489                                return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
    490490#endif
    491             }
    492         }
    493         if (!dlen) {
    494             /* Even if we fast path we should note if we ran out of room. */
    495             if (((slen != (size_t)-1) && slen) ||
    496                     ((slen == (size_t)-1) && lastp)) {
    497                 errno = E2BIG;
    498             }
    499         }
    500         return retval;
    501     }
     491                        }
     492                }
     493                if (!dlen) {
     494                        /* Even if we fast path we should note if we ran out of room. */
     495                        if (((slen != (size_t)-1) && slen) ||
     496                                        ((slen == (size_t)-1) && lastp)) {
     497                                errno = E2BIG;
     498                        }
     499                }
     500                return retval;
     501        }
    502502
    503503#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
    504504  general_case:
    505505#endif
    506     return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);
     506        return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);
    507507}
    508508
     
    524524
    525525size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
    526                    void const *src, size_t srclen, void *dst, BOOL allow_bad_conv)
    527 {
    528     size_t i_len, o_len, destlen = MAX(srclen, 512);
    529     size_t retval;
    530     const char *inbuf = (const char *)src;
    531     char *outbuf = NULL, *ob = NULL;
    532     smb_iconv_t descriptor;
    533     void **dest = (void **)dst;
    534 
    535     *dest = NULL;
    536 
    537     if (src == NULL || srclen == (size_t)-1)
    538         return (size_t)-1;
    539     if (srclen == 0)
    540         return 0;
    541 
    542     lazy_initialize_conv();
    543 
    544     descriptor = conv_handles[from][to];
    545 
    546     if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
    547         if (!conv_silent)
    548             DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
    549         return (size_t)-1;
    550     }
     526                                   void const *src, size_t srclen, void *dst, BOOL allow_bad_conv)
     527{
     528        size_t i_len, o_len, destlen = (srclen * 3) / 2;
     529        size_t retval;
     530        const char *inbuf = (const char *)src;
     531        char *outbuf = NULL, *ob = NULL;
     532        smb_iconv_t descriptor;
     533        void **dest = (void **)dst;
     534
     535        *dest = NULL;
     536
     537        if (src == NULL || srclen == (size_t)-1)
     538                return (size_t)-1;
     539        if (srclen == 0)
     540                return 0;
     541
     542        lazy_initialize_conv();
     543
     544        descriptor = conv_handles[from][to];
     545
     546        if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
     547                if (!conv_silent)
     548                        DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
     549                return (size_t)-1;
     550        }
    551551
    552552  convert:
    553553
    554     if ((destlen*2) < destlen) {
    555         /* wrapped ! abort. */
    556         if (!conv_silent)
    557             DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
    558         if (!ctx)
    559             SAFE_FREE(outbuf);
    560         return (size_t)-1;
    561     } else {
    562         destlen = destlen * 2;
    563     }
    564 
    565     if (ctx) {
    566         ob = (char *)TALLOC_REALLOC(ctx, ob, destlen);
    567     } else {
    568         ob = (char *)SMB_REALLOC(ob, destlen);
    569     }
    570 
    571     if (!ob) {
    572         DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
    573         return (size_t)-1;
    574     }
    575     outbuf = ob;
    576     i_len = srclen;
    577     o_len = destlen;
     554        /* +2 is for ucs2 null termination. */
     555        if ((destlen*2)+2 < destlen) {
     556                /* wrapped ! abort. */
     557                if (!conv_silent)
     558                        DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
     559                if (!ctx)
     560                        SAFE_FREE(outbuf);
     561                return (size_t)-1;
     562        } else {
     563                destlen = destlen * 2;
     564        }
     565
     566        /* +2 is for ucs2 null termination. */
     567        if (ctx) {
     568                ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2);
     569        } else {
     570                ob = (char *)SMB_REALLOC(ob, destlen + 2);
     571        }
     572
     573        if (!ob) {
     574                DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
     575                return (size_t)-1;
     576        }
     577        outbuf = ob;
     578        i_len = srclen;
     579        o_len = destlen;
    578580
    579581 again:
    580582
    581     retval = smb_iconv(descriptor,
    582                &inbuf, &i_len,
    583                &outbuf, &o_len);
    584     if(retval == (size_t)-1)        {
    585             const char *reason="unknown error";
    586         switch(errno) {
    587             case EINVAL:
    588                 reason="Incomplete multibyte sequence";
    589                 if (!conv_silent)
    590                     DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
    591                 if (allow_bad_conv)
    592                     goto use_as_is;
    593                 break;
    594             case E2BIG:
    595                 goto convert;
    596             case EILSEQ:
    597                 reason="Illegal multibyte sequence";
    598                 if (!conv_silent)
    599                     DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
    600                 if (allow_bad_conv)
    601                     goto use_as_is;
    602                 break;
    603         }
    604         if (!conv_silent)
    605             DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
    606         /* smb_panic(reason); */
    607         return (size_t)-1;
    608     }
     583        retval = smb_iconv(descriptor,
     584                           &inbuf, &i_len,
     585                           &outbuf, &o_len);
     586        if(retval == (size_t)-1)                {
     587                        const char *reason="unknown error";
     588                switch(errno) {
     589                        case EINVAL:
     590                                reason="Incomplete multibyte sequence";
     591                                if (!conv_silent)
     592                                        DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
     593                                if (allow_bad_conv)
     594                                        goto use_as_is;
     595                                break;
     596                        case E2BIG:
     597                                goto convert;
     598                        case EILSEQ:
     599                                reason="Illegal multibyte sequence";
     600                                if (!conv_silent)
     601                                        DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
     602                                if (allow_bad_conv)
     603                                        goto use_as_is;
     604                                break;
     605                }
     606                if (!conv_silent)
     607                        DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
     608                /* smb_panic(reason); */
     609                return (size_t)-1;
     610        }
    609611
    610612  out:
    611613
    612     destlen = destlen - o_len;
    613     if (ctx) {
    614         ob = (char *)TALLOC_REALLOC(ctx,ob,destlen);
    615     } else {
    616         ob = (char *)SMB_REALLOC(ob,destlen);
    617     }
    618 
    619     if (destlen && !ob) {
    620         DEBUG(0, ("convert_string_allocate: out of memory!\n"));
    621         return (size_t)-1;
    622     }
    623 
    624     *dest = ob;
    625     return destlen;
     614        destlen = destlen - o_len;
     615        if (ctx) {
     616                /* We're shrinking here so we know the +2 is safe from wrap. */
     617                ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2);
     618        } else {
     619                ob = (char *)SMB_REALLOC(ob,destlen + 2);
     620        }
     621
     622        if (destlen && !ob) {
     623                DEBUG(0, ("convert_string_allocate: out of memory!\n"));
     624                return (size_t)-1;
     625        }
     626
     627        *dest = ob;
     628
     629        /* Must ucs2 null terminate in the extra space we allocated. */
     630        ob[destlen] = '\0';
     631        ob[destlen+1] = '\0';
     632        return destlen;
    626633
    627634 use_as_is:
    628635
    629     /*
    630     * Conversion not supported. This is actually an error, but there are so
    631     * many misconfigured iconv systems and smb.conf's out there we can't just
    632     * fail. Do a very bad conversion instead.... JRA.
    633     */
    634 
    635     {
    636         if (o_len == 0 || i_len == 0)
    637             goto out;
    638 
    639         if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
    640                 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
    641             /* Can't convert from utf16 any endian to multibyte.
    642                Replace with the default fail char.
    643             */
    644 
    645             if (i_len < 2)
    646                 goto out;
    647 
    648             if (i_len >= 2) {
    649                 *outbuf = lp_failed_convert_char();
    650 
    651                 outbuf++;
    652                 o_len--;
    653 
    654                 inbuf += 2;
    655                 i_len -= 2;
    656             }
    657 
    658             if (o_len == 0 || i_len == 0)
    659                 goto out;
    660 
    661             /* Keep trying with the next char... */
    662             goto again;
    663 
    664         } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
    665             /* Can't convert to UTF16LE - just widen by adding the
    666                default fail char then zero.
    667             */
    668             if (o_len < 2)
    669                 goto out;
    670 
    671             outbuf[0] = lp_failed_convert_char();
    672             outbuf[1] = '\0';
    673 
    674             inbuf++;
    675             i_len--;
    676 
    677             outbuf += 2;
    678             o_len -= 2;
    679 
    680             if (o_len == 0 || i_len == 0)
    681                 goto out;
    682 
    683             /* Keep trying with the next char... */
    684             goto again;
    685 
    686         } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
    687                 to != CH_UTF16LE && to != CH_UTF16BE) {
    688             /* Failed multibyte to multibyte. Just copy the default fail char and
    689                try again. */
    690             outbuf[0] = lp_failed_convert_char();
    691 
    692             inbuf++;
    693             i_len--;
    694 
    695             outbuf++;
    696             o_len--;
    697 
    698             if (o_len == 0 || i_len == 0)
    699                 goto out;
    700 
    701             /* Keep trying with the next char... */
    702             goto again;
    703 
    704         } else {
    705             /* Keep compiler happy.... */
    706             goto out;
    707         }
    708     }
     636        /*
     637        * Conversion not supported. This is actually an error, but there are so
     638        * many misconfigured iconv systems and smb.conf's out there we can't just
     639        * fail. Do a very bad conversion instead.... JRA.
     640        */
     641
     642        {
     643                if (o_len == 0 || i_len == 0)
     644                        goto out;
     645
     646                if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
     647                                ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
     648                        /* Can't convert from utf16 any endian to multibyte.
     649                           Replace with the default fail char.
     650                        */
     651
     652                        if (i_len < 2)
     653                                goto out;
     654
     655                        if (i_len >= 2) {
     656                                *outbuf = lp_failed_convert_char();
     657
     658                                outbuf++;
     659                                o_len--;
     660
     661                                inbuf += 2;
     662                                i_len -= 2;
     663                        }
     664
     665                        if (o_len == 0 || i_len == 0)
     666                                goto out;
     667
     668                        /* Keep trying with the next char... */
     669                        goto again;
     670
     671                } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
     672                        /* Can't convert to UTF16LE - just widen by adding the
     673                           default fail char then zero.
     674                        */
     675                        if (o_len < 2)
     676                                goto out;
     677
     678                        outbuf[0] = lp_failed_convert_char();
     679                        outbuf[1] = '\0';
     680
     681                        inbuf++;
     682                        i_len--;
     683
     684                        outbuf += 2;
     685                        o_len -= 2;
     686
     687                        if (o_len == 0 || i_len == 0)
     688                                goto out;
     689
     690                        /* Keep trying with the next char... */
     691                        goto again;
     692
     693                } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
     694                                to != CH_UTF16LE && to != CH_UTF16BE) {
     695                        /* Failed multibyte to multibyte. Just copy the default fail char and
     696                           try again. */
     697                        outbuf[0] = lp_failed_convert_char();
     698
     699                        inbuf++;
     700                        i_len--;
     701
     702                        outbuf++;
     703                        o_len--;
     704
     705                        if (o_len == 0 || i_len == 0)
     706                                goto out;
     707
     708                        /* Keep trying with the next char... */
     709                        goto again;
     710
     711                } else {
     712                        /* Keep compiler happy.... */
     713                        goto out;
     714                }
     715        }
    709716}
    710717
     
    719726 **/
    720727size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
    721                 void const *src, size_t srclen, void *dst,
    722                 BOOL allow_bad_conv)
    723 {
    724     void **dest = (void **)dst;
    725     size_t dest_len;
    726 
    727     *dest = NULL;
    728     dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, allow_bad_conv);
    729     if (dest_len == (size_t)-1)
    730         return (size_t)-1;
    731     if (*dest == NULL)
    732         return (size_t)-1;
    733     return dest_len;
     728                                void const *src, size_t srclen, void *dst,
     729                                BOOL allow_bad_conv)
     730{
     731        void **dest = (void **)dst;
     732        size_t dest_len;
     733
     734        *dest = NULL;
     735        dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, allow_bad_conv);
     736        if (dest_len == (size_t)-1)
     737                return (size_t)-1;
     738        if (*dest == NULL)
     739                return (size_t)-1;
     740        return dest_len;
    734741}
    735742
    736743size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
    737744{
    738     size_t size;
    739     smb_ucs2_t *buffer;
    740 
    741     size = push_ucs2_allocate(&buffer, src);
    742     if (size == (size_t)-1) {
    743         smb_panic("failed to create UCS2 buffer");
    744     }
    745     if (!strupper_w(buffer) && (dest == src)) {
    746         free(buffer);
    747         return srclen;
    748     }
    749 
    750     size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
    751     free(buffer);
    752     return size;
     745        size_t size;
     746        smb_ucs2_t *buffer;
     747
     748        size = push_ucs2_allocate(&buffer, src);
     749        if (size == (size_t)-1) {
     750                smb_panic("failed to create UCS2 buffer");
     751        }
     752        if (!strupper_w(buffer) && (dest == src)) {
     753                free(buffer);
     754                return srclen;
     755        }
     756
     757        size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
     758        free(buffer);
     759        return size;
    753760}
    754761
     
    760767char *strdup_upper(const char *s)
    761768{
    762     pstring out_buffer;
    763     const unsigned char *p = (const unsigned char *)s;
    764     unsigned char *q = (unsigned char *)out_buffer;
    765 
    766     /* this is quite a common operation, so we want it to be
    767        fast. We optimise for the ascii case, knowing that all our
    768        supported multi-byte character sets are ascii-compatible
    769        (ie. they match for the first 128 chars) */
    770 
    771     while (1) {
    772         if (*p & 0x80)
    773             break;
    774         *q++ = toupper_ascii(*p);
    775         if (!*p)
    776             break;
    777         p++;
    778         if (p - ( const unsigned char *)s >= sizeof(pstring))
    779             break;
    780     }
    781 
    782     if (*p) {
    783         /* MB case. */
    784         size_t size;
    785         wpstring buffer;
    786         size = convert_string(CH_UNIX, CH_UTF16LE, s, -1, buffer, sizeof(buffer), True);
    787         if (size == (size_t)-1) {
    788             return NULL;
    789         }
    790 
    791         strupper_w(buffer);
    792 
    793         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True);
    794         if (size == (size_t)-1) {
    795             return NULL;
    796         }
    797     }
    798 
    799     return SMB_STRDUP(out_buffer);
     769        pstring out_buffer;
     770        const unsigned char *p = (const unsigned char *)s;
     771        unsigned char *q = (unsigned char *)out_buffer;
     772
     773        /* this is quite a common operation, so we want it to be
     774           fast. We optimise for the ascii case, knowing that all our
     775           supported multi-byte character sets are ascii-compatible
     776           (ie. they match for the first 128 chars) */
     777
     778        while (1) {
     779                if (*p & 0x80)
     780                        break;
     781                *q++ = toupper_ascii(*p);
     782                if (!*p)
     783                        break;
     784                p++;
     785                if (p - ( const unsigned char *)s >= sizeof(pstring))
     786                        break;
     787        }
     788
     789        if (*p) {
     790                /* MB case. */
     791                size_t size;
     792                wpstring buffer;
     793                size = convert_string(CH_UNIX, CH_UTF16LE, s, -1, buffer, sizeof(buffer), True);
     794                if (size == (size_t)-1) {
     795                        return NULL;
     796                }
     797
     798                strupper_w(buffer);
     799
     800                size = convert_string(CH_UTF16LE, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True);
     801                if (size == (size_t)-1) {
     802                        return NULL;
     803                }
     804        }
     805
     806        return SMB_STRDUP(out_buffer);
    800807}
    801808
    802809size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
    803810{
    804     size_t size;
    805     smb_ucs2_t *buffer = NULL;
    806 
    807     size = convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, srclen,
    808                        (void **)(void *)&buffer, True);
    809     if (size == (size_t)-1 || !buffer) {
    810         smb_panic("failed to create UCS2 buffer");
    811     }
    812     if (!strlower_w(buffer) && (dest == src)) {
    813         SAFE_FREE(buffer);
    814         return srclen;
    815     }
    816     size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
    817     SAFE_FREE(buffer);
    818     return size;
     811        size_t size;
     812        smb_ucs2_t *buffer = NULL;
     813
     814        size = convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, srclen,
     815                                           (void **)(void *)&buffer, True);
     816        if (size == (size_t)-1 || !buffer) {
     817                smb_panic("failed to create UCS2 buffer");
     818        }
     819        if (!strlower_w(buffer) && (dest == src)) {
     820                SAFE_FREE(buffer);
     821                return srclen;
     822        }
     823        size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
     824        SAFE_FREE(buffer);
     825        return size;
    819826}
    820827
     
    825832char *strdup_lower(const char *s)
    826833{
    827     size_t size;
    828     smb_ucs2_t *buffer = NULL;
    829     char *out_buffer;
    830 
    831     size = push_ucs2_allocate(&buffer, s);
    832     if (size == -1 || !buffer) {
    833         return NULL;
    834     }
    835 
    836     strlower_w(buffer);
    837 
    838     size = pull_ucs2_allocate(&out_buffer, buffer);
    839     SAFE_FREE(buffer);
    840 
    841     if (size == (size_t)-1) {
    842         return NULL;
    843     }
    844 
    845     return out_buffer;
     834        size_t size;
     835        smb_ucs2_t *buffer = NULL;
     836        char *out_buffer;
     837
     838        size = push_ucs2_allocate(&buffer, s);
     839        if (size == -1 || !buffer) {
     840                return NULL;
     841        }
     842
     843        strlower_w(buffer);
     844
     845        size = pull_ucs2_allocate(&out_buffer, buffer);
     846        SAFE_FREE(buffer);
     847
     848        if (size == (size_t)-1) {
     849                return NULL;
     850        }
     851
     852        return out_buffer;
    846853}
    847854
    848855static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
    849856{
    850     if (flags & (STR_NOALIGN|STR_ASCII))
    851         return 0;
    852     return PTR_DIFF(p, base_ptr) & 1;
     857        if (flags & (STR_NOALIGN|STR_ASCII))
     858                return 0;
     859        return PTR_DIFF(p, base_ptr) & 1;
    853860}
    854861
     
    875882
    876883        /* No longer allow a length of -1 */
    877             if (dest_len == (size_t)-1)
     884                if (dest_len == (size_t)-1)
    878885                smb_panic("push_ascii - dest_len == -1");
    879886
    880     if (flags & STR_UPPER) {
    881         pstrcpy(tmpbuf, src);
    882         strupper_m(tmpbuf);
    883         src = tmpbuf;
    884     }
    885 
    886     if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
    887         src_len++;
     887        if (flags & STR_UPPER) {
     888                pstrcpy(tmpbuf, src);
     889                strupper_m(tmpbuf);
     890                src = tmpbuf;
     891        }
     892
     893        if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
     894                src_len++;
    888895
    889896        ret =convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);
     
    899906size_t push_ascii_fstring(void *dest, const char *src)
    900907{
    901     return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
     908        return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
    902909}
    903910
    904911size_t push_ascii_pstring(void *dest, const char *src)
    905912{
    906     return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
     913        return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
    907914}
    908915
     
    914921size_t push_ascii_nstring(void *dest, const char *src)
    915922{
    916     size_t i, buffer_len, dest_len;
    917     smb_ucs2_t *buffer;
    918 
    919     conv_silent = True;
    920     buffer_len = push_ucs2_allocate(&buffer, src);
    921     if (buffer_len == (size_t)-1) {
    922         smb_panic("failed to create UCS2 buffer");
    923     }
    924 
    925     /* We're using buffer_len below to count ucs2 characters, not bytes. */
    926     buffer_len /= sizeof(smb_ucs2_t);
    927 
    928     dest_len = 0;
    929     for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
    930         unsigned char mb[10];
    931         /* Convert one smb_ucs2_t character at a time. */
    932         size_t mb_len = convert_string(CH_UTF16LE, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
    933         if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
    934             memcpy((char *)dest + dest_len, mb, mb_len);
    935             dest_len += mb_len;
    936         } else {
    937             errno = E2BIG;
    938             break;
    939         }
    940     }
    941     ((char *)dest)[dest_len] = '\0';
    942 
    943     SAFE_FREE(buffer);
    944     conv_silent = False;
    945     return dest_len;
     923        size_t i, buffer_len, dest_len;
     924        smb_ucs2_t *buffer;
     925
     926        conv_silent = True;
     927        buffer_len = push_ucs2_allocate(&buffer, src);
     928        if (buffer_len == (size_t)-1) {
     929                smb_panic("failed to create UCS2 buffer");
     930        }
     931
     932        /* We're using buffer_len below to count ucs2 characters, not bytes. */
     933        buffer_len /= sizeof(smb_ucs2_t);
     934
     935        dest_len = 0;
     936        for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
     937                unsigned char mb[10];
     938                /* Convert one smb_ucs2_t character at a time. */
     939                size_t mb_len = convert_string(CH_UTF16LE, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
     940                if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
     941                        memcpy((char *)dest + dest_len, mb, mb_len);
     942                        dest_len += mb_len;
     943                } else {
     944                        errno = E2BIG;
     945                        break;
     946                }
     947        }
     948        ((char *)dest)[dest_len] = '\0';
     949
     950        SAFE_FREE(buffer);
     951        conv_silent = False;
     952        return dest_len;
    946953}
    947954
     
    963970size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
    964971{
    965     size_t ret;
    966 
    967     if (dest_len == (size_t)-1)
    968         dest_len = sizeof(pstring);
    969 
    970     if (flags & STR_TERMINATE) {
    971         if (src_len == (size_t)-1) {
    972             src_len = strlen((const char *)src) + 1;
    973         } else {
    974             size_t len = strnlen((const char *)src, src_len);
    975             if (len < src_len)
    976                 len++;
    977             src_len = len;
    978         }
    979     }
    980 
    981     ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
    982     if (ret == (size_t)-1) {
    983         ret = 0;
    984         dest_len = 0;
    985     }
    986 
    987     if (dest_len && ret) {
    988         /* Did we already process the terminating zero ? */
    989         if (dest[MIN(ret-1, dest_len-1)] != 0) {
    990             dest[MIN(ret, dest_len-1)] = 0;
    991         }
    992     } else  {
    993         dest[0] = 0;
    994     }
    995 
    996     return src_len;
     972        size_t ret;
     973
     974        if (dest_len == (size_t)-1)
     975                dest_len = sizeof(pstring);
     976
     977        if (flags & STR_TERMINATE) {
     978                if (src_len == (size_t)-1) {
     979                        src_len = strlen((const char *)src) + 1;
     980                } else {
     981                        size_t len = strnlen((const char *)src, src_len);
     982                        if (len < src_len)
     983                                len++;
     984                        src_len = len;
     985                }
     986        }
     987
     988        ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
     989        if (ret == (size_t)-1) {
     990                ret = 0;
     991                dest_len = 0;
     992        }
     993
     994        if (dest_len && ret) {
     995                /* Did we already process the terminating zero ? */
     996                if (dest[MIN(ret-1, dest_len-1)] != 0) {
     997                        dest[MIN(ret, dest_len-1)] = 0;
     998                }
     999        } else  {
     1000                dest[0] = 0;
     1001        }
     1002
     1003        return src_len;
    9971004}
    9981005
    9991006size_t pull_ascii_pstring(char *dest, const void *src)
    10001007{
    1001     return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
     1008        return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
    10021009}
    10031010
    10041011size_t pull_ascii_fstring(char *dest, const void *src)
    10051012{
    1006     return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
     1013        return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
    10071014}
    10081015
     
    10111018size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
    10121019{
    1013     return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
     1020        return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
    10141021}
    10151022
     
    10231030 * <dl>
    10241031 * <dt>STR_TERMINATE <dd>means include the null termination.
    1025  * <dt>STR_UPPER    <dd>means uppercase in the destination.
     1032 * <dt>STR_UPPER        <dd>means uppercase in the destination.
    10261033 * <dt>STR_NOALIGN   <dd>means don't do alignment.
    10271034 * </dl>
     
    10331040size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
    10341041{
    1035     size_t len=0;
    1036     size_t src_len;
    1037     size_t ret;
    1038 
    1039     /* treat a pstring as "unlimited" length */
    1040     if (dest_len == (size_t)-1)
    1041         dest_len = sizeof(pstring);
    1042 
    1043     if (flags & STR_TERMINATE)
    1044         src_len = (size_t)-1;
    1045     else
    1046         src_len = strlen(src);
    1047 
    1048     if (ucs2_align(base_ptr, dest, flags)) {
    1049         *(char *)dest = 0;
    1050         dest = (void *)((char *)dest + 1);
    1051         if (dest_len)
    1052             dest_len--;
    1053         len++;
    1054     }
    1055 
    1056     /* ucs2 is always a multiple of 2 bytes */
    1057     dest_len &= ~1;
    1058 
    1059     ret =  convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True);
    1060     if (ret == (size_t)-1) {
    1061         return 0;
    1062     }
    1063 
    1064     len += ret;
    1065 
    1066     if (flags & STR_UPPER) {
    1067         smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
    1068         size_t i;
    1069 
    1070         /* We check for i < (ret / 2) below as the dest string isn't null
    1071            terminated if STR_TERMINATE isn't set. */
    1072 
    1073         for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
    1074             smb_ucs2_t v = toupper_w(dest_ucs2[i]);
    1075             if (v != dest_ucs2[i]) {
    1076                 dest_ucs2[i] = v;
    1077             }
    1078         }
    1079     }
    1080 
    1081     return len;
     1042        size_t len=0;
     1043        size_t src_len;
     1044        size_t ret;
     1045
     1046        /* treat a pstring as "unlimited" length */
     1047        if (dest_len == (size_t)-1)
     1048                dest_len = sizeof(pstring);
     1049
     1050        if (flags & STR_TERMINATE)
     1051                src_len = (size_t)-1;
     1052        else
     1053                src_len = strlen(src);
     1054
     1055        if (ucs2_align(base_ptr, dest, flags)) {
     1056                *(char *)dest = 0;
     1057                dest = (void *)((char *)dest + 1);
     1058                if (dest_len)
     1059                        dest_len--;
     1060                len++;
     1061        }
     1062
     1063        /* ucs2 is always a multiple of 2 bytes */
     1064        dest_len &= ~1;
     1065
     1066        ret =  convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True);
     1067        if (ret == (size_t)-1) {
     1068                return 0;
     1069        }
     1070
     1071        len += ret;
     1072
     1073        if (flags & STR_UPPER) {
     1074                smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
     1075                size_t i;
     1076
     1077                /* We check for i < (ret / 2) below as the dest string isn't null
     1078                   terminated if STR_TERMINATE isn't set. */
     1079
     1080                for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
     1081                        smb_ucs2_t v = toupper_w(dest_ucs2[i]);
     1082                        if (v != dest_ucs2[i]) {
     1083                                dest_ucs2[i] = v;
     1084                        }
     1085                }
     1086        }
     1087
     1088        return len;
    10821089}
    10831090
     
    10901097 *
    10911098 * @returns The number of bytes occupied by the string in the destination
    1092  *        or -1 in case of error.
     1099 *              or -1 in case of error.
    10931100 **/
    10941101size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
    10951102{
    1096     size_t src_len = strlen(src)+1;
    1097 
    1098     *dest = NULL;
    1099     return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
     1103        size_t src_len = strlen(src)+1;
     1104
     1105        *dest = NULL;
     1106        return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
    11001107}
    11011108
     
    11071114 *
    11081115 * @returns The number of bytes occupied by the string in the destination
    1109  *        or -1 in case of error.
     1116 *              or -1 in case of error.
    11101117 **/
    11111118
    11121119size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
    11131120{
    1114     size_t src_len = strlen(src)+1;
    1115 
    1116     *dest = NULL;
    1117     return convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
     1121        size_t src_len = strlen(src)+1;
     1122
     1123        *dest = NULL;
     1124        return convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
    11181125}
    11191126
     
    11231130 Flags can have:
    11241131  STR_TERMINATE means include the null termination
    1125   STR_UPPER    means uppercase in the destination
     1132  STR_UPPER      means uppercase in the destination
    11261133 dest_len is the maximum length allowed in the destination. If dest_len
    11271134 is -1 then no maxiumum is used.
     
    11301137static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
    11311138{
    1132     size_t src_len = strlen(src);
    1133     pstring tmpbuf;
    1134 
    1135     /* treat a pstring as "unlimited" length */
    1136     if (dest_len == (size_t)-1)
    1137         dest_len = sizeof(pstring);
    1138 
    1139     if (flags & STR_UPPER) {
    1140         pstrcpy(tmpbuf, src);
    1141         strupper_m(tmpbuf);
    1142         src = tmpbuf;
    1143     }
    1144 
    1145     if (flags & STR_TERMINATE)
    1146         src_len++;
    1147 
    1148     return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
     1139        size_t src_len = strlen(src);
     1140        pstring tmpbuf;
     1141
     1142        /* treat a pstring as "unlimited" length */
     1143        if (dest_len == (size_t)-1)
     1144                dest_len = sizeof(pstring);
     1145
     1146        if (flags & STR_UPPER) {
     1147                pstrcpy(tmpbuf, src);
     1148                strupper_m(tmpbuf);
     1149                src = tmpbuf;
     1150        }
     1151
     1152        if (flags & STR_TERMINATE)
     1153                src_len++;
     1154
     1155        return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
    11491156}
    11501157
    11511158size_t push_utf8_fstring(void *dest, const char *src)
    11521159{
    1153     return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
     1160        return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
    11541161}
    11551162
     
    11641171size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
    11651172{
    1166     size_t src_len = strlen(src)+1;
    1167 
    1168     *dest = NULL;
    1169     return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest, True);
     1173        size_t src_len = strlen(src)+1;
     1174
     1175        *dest = NULL;
     1176        return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest, True);
    11701177}
    11711178
     
    11801187size_t push_utf8_allocate(char **dest, const char *src)
    11811188{
    1182     size_t src_len = strlen(src)+1;
    1183 
    1184     *dest = NULL;
    1185     return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, True);
     1189        size_t src_len = strlen(src)+1;
     1190
     1191        *dest = NULL;
     1192        return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, True);
    11861193}
    11871194
     
    11991206size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
    12001207{
    1201     size_t ret;
    1202 
    1203     if (dest_len == (size_t)-1)
    1204         dest_len = sizeof(pstring);
    1205 
    1206     if (ucs2_align(base_ptr, src, flags)) {
    1207         src = (const void *)((const char *)src + 1);
    1208         if (src_len != (size_t)-1)
    1209             src_len--;
    1210     }
    1211 
    1212     if (flags & STR_TERMINATE) {
    1213         /* src_len -1 is the default for null terminated strings. */
    1214         if (src_len != (size_t)-1) {
    1215             size_t len = strnlen_w((const smb_ucs2_t *)src,
    1216                         src_len/2);
    1217             if (len < src_len/2)
    1218                 len++;
    1219             src_len = len*2;
    1220         }
    1221     }
    1222 
    1223     /* ucs2 is always a multiple of 2 bytes */
    1224     if (src_len != (size_t)-1)
    1225         src_len &= ~1;
    1226 
    1227     ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
    1228     if (ret == (size_t)-1) {
    1229         return 0;
    1230     }
    1231 
    1232     if (src_len == (size_t)-1)
    1233         src_len = ret*2;
    1234 
    1235     if (dest_len && ret) {
    1236         /* Did we already process the terminating zero ? */
    1237         if (dest[MIN(ret-1, dest_len-1)] != 0) {
    1238             dest[MIN(ret, dest_len-1)] = 0;
    1239         }
    1240     } else {
    1241         dest[0] = 0;
    1242     }
    1243 
    1244     return src_len;
     1208        size_t ret;
     1209
     1210        if (dest_len == (size_t)-1)
     1211                dest_len = sizeof(pstring);
     1212
     1213        if (ucs2_align(base_ptr, src, flags)) {
     1214                src = (const void *)((const char *)src + 1);
     1215                if (src_len != (size_t)-1)
     1216                        src_len--;
     1217        }
     1218
     1219        if (flags & STR_TERMINATE) {
     1220                /* src_len -1 is the default for null terminated strings. */
     1221                if (src_len != (size_t)-1) {
     1222                        size_t len = strnlen_w((const smb_ucs2_t *)src,
     1223                                                src_len/2);
     1224                        if (len < src_len/2)
     1225                                len++;
     1226                        src_len = len*2;
     1227                }
     1228        }
     1229
     1230        /* ucs2 is always a multiple of 2 bytes */
     1231        if (src_len != (size_t)-1)
     1232                src_len &= ~1;
     1233
     1234        ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
     1235        if (ret == (size_t)-1) {
     1236                return 0;
     1237        }
     1238
     1239        if (src_len == (size_t)-1)
     1240                src_len = ret*2;
     1241
     1242        if (dest_len && ret) {
     1243                /* Did we already process the terminating zero ? */
     1244                if (dest[MIN(ret-1, dest_len-1)] != 0) {
     1245                        dest[MIN(ret, dest_len-1)] = 0;
     1246                }
     1247        } else {
     1248                dest[0] = 0;
     1249        }
     1250
     1251        return src_len;
    12451252}
    12461253
    12471254size_t pull_ucs2_pstring(char *dest, const void *src)
    12481255{
    1249     return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
     1256        return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
    12501257}
    12511258
    12521259size_t pull_ucs2_fstring(char *dest, const void *src)
    12531260{
    1254     return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
     1261        return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
    12551262}
    12561263
     
    12651272size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
    12661273{
    1267     size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
    1268     *dest = NULL;
    1269     return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
     1274        size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
     1275        *dest = NULL;
     1276        return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
    12701277}
    12711278
     
    12801287size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
    12811288{
    1282     size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
    1283     *dest = NULL;
    1284     return convert_string_allocate(NULL, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
     1289        size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
     1290        *dest = NULL;
     1291        return convert_string_allocate(NULL, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
    12851292}
    12861293
     
    12951302size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
    12961303{
    1297     size_t src_len = strlen(src)+1;
    1298     *dest = NULL;
    1299     return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
     1304        size_t src_len = strlen(src)+1;
     1305        *dest = NULL;
     1306        return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
    13001307}
    13011308
     
    13101317size_t pull_utf8_allocate(char **dest, const char *src)
    13111318{
    1312     size_t src_len = strlen(src)+1;
    1313     *dest = NULL;
    1314     return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
     1319        size_t src_len = strlen(src)+1;
     1320        *dest = NULL;
     1321        return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
    13151322}
    13161323
     
    13251332size_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
    13261333{
    1327     size_t src_len = strlen(src)+1;
    1328     *dest = NULL;
    1329     return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, True);
     1334        size_t src_len = strlen(src)+1;
     1335        *dest = NULL;
     1336        return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, True);
    13301337}
    13311338
     
    13371344 flags can have:
    13381345  STR_TERMINATE means include the null termination.
    1339   STR_UPPER    means uppercase in the destination.
    1340   STR_ASCII    use ascii even with unicode packet.
     1346  STR_UPPER      means uppercase in the destination.
     1347  STR_ASCII      use ascii even with unicode packet.
    13411348  STR_NOALIGN   means don't do alignment.
    13421349 dest_len is the maximum length allowed in the destination. If dest_len
     
    13471354{
    13481355#ifdef DEVELOPER
    1349     /* We really need to zero fill here, not clobber
    1350     * region, as we want to ensure that valgrind thinks
    1351     * all of the outgoing buffer has been written to
    1352     * so a send() or write() won't trap an error.
    1353     * JRA.
    1354     */
     1356        /* We really need to zero fill here, not clobber
     1357        * region, as we want to ensure that valgrind thinks
     1358        * all of the outgoing buffer has been written to
     1359        * so a send() or write() won't trap an error.
     1360        * JRA.
     1361        */
    13551362#if 0
    1356     if (dest_len != (size_t)-1)
    1357         clobber_region(function, line, dest, dest_len);
     1363        if (dest_len != (size_t)-1)
     1364                clobber_region(function, line, dest, dest_len);
    13581365#else
    1359     if (dest_len != (size_t)-1)
    1360         memset(dest, '\0', dest_len);
     1366        if (dest_len != (size_t)-1)
     1367                memset(dest, '\0', dest_len);
    13611368#endif
    13621369#endif
    13631370
    1364     if (!(flags & STR_ASCII) && \
    1365         ((flags & STR_UNICODE || \
    1366           (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
    1367         return push_ucs2(base_ptr, dest, src, dest_len, flags);
    1368     }
    1369     return push_ascii(dest, src, dest_len, flags);
     1371        if (!(flags & STR_ASCII) && \
     1372                ((flags & STR_UNICODE || \
     1373                  (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
     1374                return push_ucs2(base_ptr, dest, src, dest_len, flags);
     1375        }
     1376        return push_ascii(dest, src, dest_len, flags);
    13701377}
    13711378
     
    13771384  STR_TERMINATE means the string in src is null terminated.
    13781385  STR_UNICODE   means to force as unicode.
    1379   STR_ASCII    use ascii even with unicode packet.
     1386  STR_ASCII      use ascii even with unicode packet.
    13801387  STR_NOALIGN   means don't do alignment.
    13811388 if STR_TERMINATE is set then src_len is ignored is it is -1
     
    13881395{
    13891396#ifdef DEVELOPER
    1390     if (dest_len != (size_t)-1)
    1391         clobber_region(function, line, dest, dest_len);
     1397        if (dest_len != (size_t)-1)
     1398                clobber_region(function, line, dest, dest_len);
    13921399#endif
    13931400
    1394     if (!(flags & STR_ASCII) && \
    1395         ((flags & STR_UNICODE || \
    1396           (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
    1397         return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
    1398     }
    1399     return pull_ascii(dest, src, dest_len, src_len, flags);
     1401        if (!(flags & STR_ASCII) && \
     1402                ((flags & STR_UNICODE || \
     1403                  (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
     1404                return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
     1405        }
     1406        return pull_ascii(dest, src, dest_len, src_len, flags);
    14001407}
    14011408
    14021409size_t align_string(const void *base_ptr, const char *p, int flags)
    14031410{
    1404     if (!(flags & STR_ASCII) && \
    1405         ((flags & STR_UNICODE || \
    1406           (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
    1407         return ucs2_align(base_ptr, p, flags);
    1408     }
    1409     return 0;
     1411        if (!(flags & STR_ASCII) && \
     1412                ((flags & STR_UNICODE || \
     1413                  (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
     1414                return ucs2_align(base_ptr, p, flags);
     1415        }
     1416        return 0;
    14101417}
    14111418
     
    14221429codepoint_t next_codepoint(const char *str, size_t *size)
    14231430{
    1424     /* It cannot occupy more than 4 bytes in UTF16 format */
    1425     uint8_t buf[4];
    1426     smb_iconv_t descriptor;
     1431        /* It cannot occupy more than 4 bytes in UTF16 format */
     1432        uint8_t buf[4];
     1433        smb_iconv_t descriptor;
    14271434#ifdef __OS2__
    1428     size_t ilen_max;
     1435        size_t ilen_max;
    14291436#endif
    1430     size_t ilen_orig;
    1431     size_t ilen;
    1432     size_t olen_orig;
    1433     size_t olen;
    1434     const char *inbuf;
    1435     char *outbuf;
     1437        size_t ilen_orig;
     1438        size_t ilen;
     1439        size_t olen_orig;
     1440        size_t olen;
     1441        const char *inbuf;
     1442        char *outbuf;
    14361443
    14371444#ifdef __OS2__
    1438     *size = 1;
     1445        *size = 1;
    14391446#endif
    14401447
    1441     if ((str[0] & 0x80) == 0) {
     1448        if ((str[0] & 0x80) == 0) {
    14421449#ifndef __OS2__
    1443         *size = 1;
     1450                *size = 1;
    14441451#endif
    1445         return (codepoint_t)str[0];
    1446     }
    1447 
    1448     lazy_initialize_conv();
    1449 
    1450     descriptor = conv_handles[CH_UNIX][CH_UTF16LE];
    1451     if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
     1452                return (codepoint_t)str[0];
     1453        }
     1454
     1455        lazy_initialize_conv();
     1456
     1457        descriptor = conv_handles[CH_UNIX][CH_UTF16LE];
     1458        if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
    14521459#ifndef __OS2__
    1453         *size = 1;
     1460                *size = 1;
    14541461#endif
    1455         return INVALID_CODEPOINT;
    1456     }
     1462                return INVALID_CODEPOINT;
     1463        }
    14571464#ifdef __OS2__
    1458     /* We assume that no multi-byte character can take
    1459        more than 5 bytes. This is OK as we only
    1460        support codepoints up to 1M */
    1461 
    1462     ilen_max = strnlen( str, 5 );
     1465        /* We assume that no multi-byte character can take
     1466           more than 5 bytes. This is OK as we only
     1467           support codepoints up to 1M */
     1468
     1469        ilen_max = strnlen( str, 5 );
    14631470#else
    1464     *size = 1;
     1471        *size = 1;
    14651472#endif
    1466     ilen_orig = 1;
    1467     olen_orig = 2;
    1468     while( 1 )
    1469     {
    1470         ilen = ilen_orig;
    1471         olen = olen_orig;
    1472         inbuf = str;
    1473         outbuf = ( char * )buf;
    1474         if( smb_iconv( descriptor, &inbuf, &ilen, &outbuf, &olen ) != ( size_t )-1 )
    1475             break;
    1476 
    1477         switch( errno )
    1478         {
    1479             case E2BIG :
    1480                 if( olen_orig == 2 )
    1481                     olen_orig = 4;
    1482                 else
    1483                     return INVALID_CODEPOINT;
    1484                 break;
    1485 
    1486             case EINVAL :
     1473        ilen_orig = 1;
     1474        olen_orig = 2;
     1475        while( 1 )
     1476        {
     1477                ilen = ilen_orig;
     1478                olen = olen_orig;
     1479                inbuf = str;
     1480                outbuf = ( char * )buf;
     1481                if( smb_iconv( descriptor, &inbuf, &ilen, &outbuf, &olen ) != ( size_t )-1 )
     1482                        break;
     1483
     1484                switch( errno )
     1485                {
     1486                        case E2BIG :
     1487                                if( olen_orig == 2 )
     1488                                        olen_orig = 4;
     1489                                else
     1490                                        return INVALID_CODEPOINT;
     1491                                break;
     1492
     1493                        case EINVAL :
    14871494#ifndef __OS2__
    1488                 /* We assume that no multi-byte character can take
    1489                    more than 5 bytes. This is OK as we only
    1490                    support codepoints up to 1M */
    1491                 if( ilen_orig < 5 )
     1495                                /* We assume that no multi-byte character can take
     1496                                   more than 5 bytes. This is OK as we only
     1497                                   support codepoints up to 1M */
     1498                                if( ilen_orig < 5 )
    14921499#else
    1493                 if( ilen_orig < ilen_max )
     1500                                if( ilen_orig < ilen_max )
    14941501#endif
    1495                     ilen_orig++;
    1496                 else
    1497                     return INVALID_CODEPOINT;
    1498                 break;
    1499 
    1500             case EILSEQ :
    1501             default :
    1502                 return INVALID_CODEPOINT;
    1503         }
    1504     }
    1505 
    1506     olen = olen_orig - olen;
    1507 
    1508     *size = ilen_orig - ilen;
    1509 
    1510     if (olen == 2) {
    1511         /* 2 byte, UTF16-LE encoded value. */
    1512         return (codepoint_t)SVAL(buf, 0);
    1513     }
    1514     if (olen == 4) {
    1515         /* Decode a 4 byte UTF16-LE character manually.
    1516            See RFC2871 for the encoding machanism.
    1517         */
    1518         codepoint_t w1 = SVAL(buf,0) & ~0xD800;
    1519         codepoint_t w2 = SVAL(buf,2) & ~0xDC00;
    1520 
    1521         return (codepoint_t)0x10000 +
    1522                 (w1 << 10) + w2;
    1523     }
    1524 
    1525     /* no other length is valid */
    1526     return INVALID_CODEPOINT;
    1527 }
     1502                                        ilen_orig++;
     1503                                else
     1504                                        return INVALID_CODEPOINT;
     1505                                break;
     1506
     1507                        case EILSEQ :
     1508                        default :
     1509                                return INVALID_CODEPOINT;
     1510                }
     1511        }
     1512
     1513        olen = olen_orig - olen;
     1514
     1515        *size = ilen_orig - ilen;
     1516
     1517        if (olen == 2) {
     1518                /* 2 byte, UTF16-LE encoded value. */
     1519                return (codepoint_t)SVAL(buf, 0);
     1520        }
     1521        if (olen == 4) {
     1522                /* Decode a 4 byte UTF16-LE character manually.
     1523                   See RFC2871 for the encoding machanism.
     1524                */
     1525                codepoint_t w1 = SVAL(buf,0) & ~0xD800;
     1526                codepoint_t w2 = SVAL(buf,2) & ~0xDC00;
     1527
     1528                return (codepoint_t)0x10000 +
     1529                                (w1 << 10) + w2;
     1530        }
     1531
     1532        /* no other length is valid */
     1533        return INVALID_CODEPOINT;
     1534}
Note: See TracChangeset for help on using the changeset viewer.