lib/util_str.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Samba utility functions
00004    
00005    Copyright (C) Andrew Tridgell 1992-2001
00006    Copyright (C) Simo Sorce      2001-2002
00007    Copyright (C) Martin Pool     2003
00008    Copyright (C) James Peach     2006
00009    
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023 */
00024 
00025 #include "includes.h"
00026 
00027 /**
00028  * @file
00029  * @brief String utilities.
00030  **/
00031 
00032 /**
00033  * Internal function to get the next token from a string, return False if none
00034  * found.  Handles double-quotes.  This is the work horse function called by
00035  * next_token() and next_token_no_ltrim().
00036  *
00037  * Based on a routine by GJC@VILLAGE.COM. 
00038  * Extensively modified by Andrew.Tridgell@anu.edu.au
00039  */
00040 static BOOL next_token_internal(const char **ptr,
00041                                 char *buff,
00042                                 const char *sep,
00043                                 size_t bufsize,
00044                                 BOOL ltrim)
00045 {
00046         char *s;
00047         char *pbuf;
00048         BOOL quoted;
00049         size_t len=1;
00050 
00051         if (!ptr)
00052                 return(False);
00053 
00054         s = (char *)*ptr;
00055 
00056         /* default to simple separators */
00057         if (!sep)
00058                 sep = " \t\n\r";
00059 
00060         /* find the first non sep char, if left-trimming is requested */
00061         if (ltrim) {
00062                 while (*s && strchr_m(sep,*s))
00063                         s++;
00064         }
00065         
00066         /* nothing left? */
00067         if (! *s)
00068                 return(False);
00069         
00070         /* copy over the token */
00071         pbuf = buff;
00072         for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
00073                 if ( *s == '\"' ) {
00074                         quoted = !quoted;
00075                 } else {
00076                         len++;
00077                         *pbuf++ = *s;
00078                 }
00079         }
00080         
00081         *ptr = (*s) ? s+1 : s;  
00082         *pbuf = 0;
00083         
00084         return(True);
00085 }
00086 
00087 /*
00088  * Get the next token from a string, return False if none found.  Handles
00089  * double-quotes.  This version trims leading separator characters before
00090  * looking for a token.
00091  */
00092 BOOL next_token(const char **ptr, char *buff, const char *sep, size_t bufsize)
00093 {
00094     return next_token_internal(ptr, buff, sep, bufsize, True);
00095 }
00096 
00097 /*
00098  * Get the next token from a string, return False if none found.  Handles
00099  * double-quotes.  This version does not trim leading separator characters
00100  * before looking for a token.
00101  */
00102 BOOL next_token_no_ltrim(const char **ptr,
00103                          char *buff,
00104                          const char *sep,
00105                          size_t bufsize)
00106 {
00107     return next_token_internal(ptr, buff, sep, bufsize, False);
00108 }
00109 
00110 /**
00111 This is like next_token but is not re-entrant and "remembers" the first 
00112 parameter so you can pass NULL. This is useful for user interface code
00113 but beware the fact that it is not re-entrant!
00114 **/
00115 
00116 static const char *last_ptr=NULL;
00117 
00118 BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
00119 {
00120         BOOL ret;
00121         if (!ptr)
00122                 ptr = &last_ptr;
00123 
00124         ret = next_token(ptr, buff, sep, bufsize);
00125         last_ptr = *ptr;
00126         return ret;     
00127 }
00128 
00129 static uint16 tmpbuf[sizeof(pstring)];
00130 
00131 void set_first_token(char *ptr)
00132 {
00133         last_ptr = ptr;
00134 }
00135 
00136 /**
00137  Convert list of tokens to array; dependent on above routine.
00138  Uses last_ptr from above - bit of a hack.
00139 **/
00140 
00141 char **toktocliplist(int *ctok, const char *sep)
00142 {
00143         char *s=(char *)last_ptr;
00144         int ictok=0;
00145         char **ret, **iret;
00146 
00147         if (!sep)
00148                 sep = " \t\n\r";
00149 
00150         while(*s && strchr_m(sep,*s))
00151                 s++;
00152 
00153         /* nothing left? */
00154         if (!*s)
00155                 return(NULL);
00156 
00157         do {
00158                 ictok++;
00159                 while(*s && (!strchr_m(sep,*s)))
00160                         s++;
00161                 while(*s && strchr_m(sep,*s))
00162                         *s++=0;
00163         } while(*s);
00164         
00165         *ctok=ictok;
00166         s=(char *)last_ptr;
00167         
00168         if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1)))
00169                 return NULL;
00170         
00171         while(ictok--) {    
00172                 *iret++=s;
00173                 if (ictok > 0) {
00174                         while(*s++)
00175                                 ;
00176                         while(!*s)
00177                                 s++;
00178                 }
00179         }
00180 
00181         ret[*ctok] = NULL;
00182         return ret;
00183 }
00184 
00185 /**
00186  * Case insensitive string compararison.
00187  *
00188  * iconv does not directly give us a way to compare strings in
00189  * arbitrary unix character sets -- all we can is convert and then
00190  * compare.  This is expensive.
00191  *
00192  * As an optimization, we do a first pass that considers only the
00193  * prefix of the strings that is entirely 7-bit.  Within this, we
00194  * check whether they have the same value.
00195  *
00196  * Hopefully this will often give the answer without needing to copy.
00197  * In particular it should speed comparisons to literal ascii strings
00198  * or comparisons of strings that are "obviously" different.
00199  *
00200  * If we find a non-ascii character we fall back to converting via
00201  * iconv.
00202  *
00203  * This should never be slower than convering the whole thing, and
00204  * often faster.
00205  *
00206  * A different optimization would be to compare for bitwise equality
00207  * in the binary encoding.  (It would be possible thought hairy to do
00208  * both simultaneously.)  But in that case if they turn out to be
00209  * different, we'd need to restart the whole thing.
00210  *
00211  * Even better is to implement strcasecmp for each encoding and use a
00212  * function pointer. 
00213  **/
00214 int StrCaseCmp(const char *s, const char *t)
00215 {
00216 
00217         const char *ps, *pt;
00218         size_t size;
00219         smb_ucs2_t *buffer_s, *buffer_t;
00220         int ret;
00221 
00222         for (ps = s, pt = t; ; ps++, pt++) {
00223                 char us, ut;
00224 
00225                 if (!*ps && !*pt)
00226                         return 0; /* both ended */
00227                 else if (!*ps)
00228                         return -1; /* s is a prefix */
00229                 else if (!*pt)
00230                         return +1; /* t is a prefix */
00231                 else if ((*ps & 0x80) || (*pt & 0x80))
00232                         /* not ascii anymore, do it the hard way from here on in */
00233                         break;
00234 
00235                 us = toupper_ascii(*ps);
00236                 ut = toupper_ascii(*pt);
00237                 if (us == ut)
00238                         continue;
00239                 else if (us < ut)
00240                         return -1;
00241                 else if (us > ut)
00242                         return +1;
00243         }
00244 
00245         size = push_ucs2_allocate(&buffer_s, ps);
00246         if (size == (size_t)-1) {
00247                 return strcmp(ps, pt); 
00248                 /* Not quite the right answer, but finding the right one
00249                    under this failure case is expensive, and it's pretty close */
00250         }
00251         
00252         size = push_ucs2_allocate(&buffer_t, pt);
00253         if (size == (size_t)-1) {
00254                 SAFE_FREE(buffer_s);
00255                 return strcmp(ps, pt); 
00256                 /* Not quite the right answer, but finding the right one
00257                    under this failure case is expensive, and it's pretty close */
00258         }
00259         
00260         ret = strcasecmp_w(buffer_s, buffer_t);
00261         SAFE_FREE(buffer_s);
00262         SAFE_FREE(buffer_t);
00263         return ret;
00264 }
00265 
00266 
00267 /**
00268  Case insensitive string compararison, length limited.
00269 **/
00270 int StrnCaseCmp(const char *s, const char *t, size_t n)
00271 {
00272         pstring buf1, buf2;
00273         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
00274         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
00275         return strncmp(buf1,buf2,n);
00276 }
00277 
00278 /**
00279  * Compare 2 strings.
00280  *
00281  * @note The comparison is case-insensitive.
00282  **/
00283 BOOL strequal(const char *s1, const char *s2)
00284 {
00285         if (s1 == s2)
00286                 return(True);
00287         if (!s1 || !s2)
00288                 return(False);
00289   
00290         return(StrCaseCmp(s1,s2)==0);
00291 }
00292 
00293 /**
00294  * Compare 2 strings up to and including the nth char.
00295  *
00296  * @note The comparison is case-insensitive.
00297  **/
00298 BOOL strnequal(const char *s1,const char *s2,size_t n)
00299 {
00300         if (s1 == s2)
00301                 return(True);
00302         if (!s1 || !s2 || !n)
00303                 return(False);
00304   
00305         return(StrnCaseCmp(s1,s2,n)==0);
00306 }
00307 
00308 /**
00309  Compare 2 strings (case sensitive).
00310 **/
00311 
00312 BOOL strcsequal(const char *s1,const char *s2)
00313 {
00314         if (s1 == s2)
00315                 return(True);
00316         if (!s1 || !s2)
00317                 return(False);
00318   
00319         return(strcmp(s1,s2)==0);
00320 }
00321 
00322 /**
00323 Do a case-insensitive, whitespace-ignoring string compare.
00324 **/
00325 
00326 int strwicmp(const char *psz1, const char *psz2)
00327 {
00328         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
00329         /* appropriate value. */
00330         if (psz1 == psz2)
00331                 return (0);
00332         else if (psz1 == NULL)
00333                 return (-1);
00334         else if (psz2 == NULL)
00335                 return (1);
00336 
00337         /* sync the strings on first non-whitespace */
00338         while (1) {
00339                 while (isspace((int)*psz1))
00340                         psz1++;
00341                 while (isspace((int)*psz2))
00342                         psz2++;
00343                 if (toupper_ascii(*psz1) != toupper_ascii(*psz2) || *psz1 == '\0'
00344                     || *psz2 == '\0')
00345                         break;
00346                 psz1++;
00347                 psz2++;
00348         }
00349         return (*psz1 - *psz2);
00350 }
00351 
00352 
00353 /**
00354  Convert a string to upper case, but don't modify it.
00355 **/
00356 
00357 char *strupper_static(const char *s)
00358 {
00359         static pstring str;
00360 
00361         pstrcpy(str, s);
00362         strupper_m(str);
00363 
00364         return str;
00365 }
00366 
00367 /**
00368  Convert a string to "normal" form.
00369 **/
00370 
00371 void strnorm(char *s, int case_default)
00372 {
00373         if (case_default == CASE_UPPER)
00374                 strupper_m(s);
00375         else
00376                 strlower_m(s);
00377 }
00378 
00379 /**
00380  Check if a string is in "normal" case.
00381 **/
00382 
00383 BOOL strisnormal(const char *s, int case_default)
00384 {
00385         if (case_default == CASE_UPPER)
00386                 return(!strhaslower(s));
00387         
00388         return(!strhasupper(s));
00389 }
00390 
00391 
00392 /**
00393  String replace.
00394  NOTE: oldc and newc must be 7 bit characters
00395 **/
00396 
00397 /**
00398  String replace.
00399  NOTE: oldc and newc must be 7 bit characters
00400 **/
00401 void string_replace( char *s, char oldc, char newc )
00402 {
00403         char *p;
00404 
00405         /* this is quite a common operation, so we want it to be
00406            fast. We optimise for the ascii case, knowing that all our
00407            supported multi-byte character sets are ascii-compatible
00408            (ie. they match for the first 128 chars) */
00409 
00410         for (p = s; *p; p++) {
00411                 if (*p & 0x80) /* mb string - slow path. */
00412                         break;
00413                 if (*p == oldc) {
00414                         *p = newc;
00415                 }
00416         }
00417 
00418         if (!*p)
00419                 return;
00420 
00421         /* Slow (mb) path. */
00422 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
00423         /* With compose characters we must restart from the beginning. JRA. */
00424         p = s;
00425 #endif
00426 
00427         while (*p) {
00428                 size_t c_size;
00429                 next_codepoint(p, &c_size);
00430 
00431                 if (c_size == 1) {
00432                         if (*p == oldc) {
00433                                 *p = newc;
00434                         }
00435                 }
00436                 p += c_size;
00437         }
00438 }
00439 
00440 /**
00441  *  Skip past some strings in a buffer - old version - no checks.
00442  *  **/
00443 
00444 char *push_skip_string(char *buf)
00445 {
00446         buf += strlen(buf) + 1;
00447         return(buf);
00448 }
00449 
00450 /**
00451  Skip past a string in a buffer. Buffer may not be
00452  null terminated. end_ptr points to the first byte after
00453  then end of the buffer.
00454 **/
00455 
00456 char *skip_string(const char *base, size_t len, char *buf)
00457 {
00458         const char *end_ptr = base + len;
00459 
00460         if (end_ptr < base || !base || !buf || buf >= end_ptr) {
00461                 return NULL;
00462         }
00463 
00464         /* Skip the string */
00465         while (*buf) {
00466                 buf++;
00467                 if (buf >= end_ptr) {
00468                         return NULL;
00469                 }
00470         }
00471         /* Skip the '\0' */
00472         buf++;
00473         return buf;
00474 }
00475 
00476 /**
00477  Count the number of characters in a string. Normally this will
00478  be the same as the number of bytes in a string for single byte strings,
00479  but will be different for multibyte.
00480 **/
00481 
00482 size_t str_charnum(const char *s)
00483 {
00484         uint16 tmpbuf2[sizeof(pstring)];
00485         push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
00486         return strlen_w(tmpbuf2);
00487 }
00488 
00489 /**
00490  Count the number of characters in a string. Normally this will
00491  be the same as the number of bytes in a string for single byte strings,
00492  but will be different for multibyte.
00493 **/
00494 
00495 size_t str_ascii_charnum(const char *s)
00496 {
00497         pstring tmpbuf2;
00498         push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
00499         return strlen(tmpbuf2);
00500 }
00501 
00502 BOOL trim_char(char *s,char cfront,char cback)
00503 {
00504         BOOL ret = False;
00505         char *ep;
00506         char *fp = s;
00507 
00508         /* Ignore null or empty strings. */
00509         if (!s || (s[0] == '\0'))
00510                 return False;
00511 
00512         if (cfront) {
00513                 while (*fp && *fp == cfront)
00514                         fp++;
00515                 if (!*fp) {
00516                         /* We ate the string. */
00517                         s[0] = '\0';
00518                         return True;
00519                 }
00520                 if (fp != s)
00521                         ret = True;
00522         }
00523 
00524         ep = fp + strlen(fp) - 1;
00525         if (cback) {
00526                 /* Attempt ascii only. Bail for mb strings. */
00527                 while ((ep >= fp) && (*ep == cback)) {
00528                         ret = True;
00529                         if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
00530                                 /* Could be mb... bail back to tim_string. */
00531                                 char fs[2], bs[2];
00532                                 if (cfront) {
00533                                         fs[0] = cfront;
00534                                         fs[1] = '\0';
00535                                 }
00536                                 bs[0] = cback;
00537                                 bs[1] = '\0';
00538                                 return trim_string(s, cfront ? fs : NULL, bs);
00539                         } else {
00540                                 ep--;
00541                         }
00542                 }
00543                 if (ep < fp) {
00544                         /* We ate the string. */
00545                         s[0] = '\0';
00546                         return True;
00547                 }
00548         }
00549 
00550         ep[1] = '\0';
00551         memmove(s, fp, ep-fp+2);
00552         return ret;
00553 }
00554 
00555 /**
00556  Trim the specified elements off the front and back of a string.
00557 **/
00558 
00559 BOOL trim_string(char *s,const char *front,const char *back)
00560 {
00561         BOOL ret = False;
00562         size_t front_len;
00563         size_t back_len;
00564         size_t len;
00565 
00566         /* Ignore null or empty strings. */
00567         if (!s || (s[0] == '\0'))
00568                 return False;
00569 
00570         front_len       = front? strlen(front) : 0;
00571         back_len        = back? strlen(back) : 0;
00572 
00573         len = strlen(s);
00574 
00575         if (front_len) {
00576                 while (len && strncmp(s, front, front_len)==0) {
00577                         /* Must use memmove here as src & dest can
00578                          * easily overlap. Found by valgrind. JRA. */
00579                         memmove(s, s+front_len, (len-front_len)+1);
00580                         len -= front_len;
00581                         ret=True;
00582                 }
00583         }
00584         
00585         if (back_len) {
00586                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
00587                         s[len-back_len]='\0';
00588                         len -= back_len;
00589                         ret=True;
00590                 }
00591         }
00592         return ret;
00593 }
00594 
00595 /**
00596  Does a string have any uppercase chars in it?
00597 **/
00598 
00599 BOOL strhasupper(const char *s)
00600 {
00601         smb_ucs2_t *ptr;
00602         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
00603         for(ptr=tmpbuf;*ptr;ptr++)
00604                 if(isupper_w(*ptr))
00605                         return True;
00606         return(False);
00607 }
00608 
00609 /**
00610  Does a string have any lowercase chars in it?
00611 **/
00612 
00613 BOOL strhaslower(const char *s)
00614 {
00615         smb_ucs2_t *ptr;
00616         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
00617         for(ptr=tmpbuf;*ptr;ptr++)
00618                 if(islower_w(*ptr))
00619                         return True;
00620         return(False);
00621 }
00622 
00623 /**
00624  Find the number of 'c' chars in a string
00625 **/
00626 
00627 size_t count_chars(const char *s,char c)
00628 {
00629         smb_ucs2_t *ptr;
00630         int count;
00631         smb_ucs2_t *alloc_tmpbuf = NULL;
00632 
00633         if (push_ucs2_allocate(&alloc_tmpbuf, s) == (size_t)-1) {
00634                 return 0;
00635         }
00636 
00637         for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++)
00638                 if(*ptr==UCS2_CHAR(c))
00639                         count++;
00640 
00641         SAFE_FREE(alloc_tmpbuf);
00642         return(count);
00643 }
00644 
00645 /**
00646  Safe string copy into a known length string. maxlength does not
00647  include the terminating zero.
00648 **/
00649 
00650 char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_t maxlength)
00651 {
00652         size_t len;
00653 
00654         if (!dest) {
00655                 DEBUG(0,("ERROR: NULL dest in safe_strcpy, called from [%s][%d]\n", fn, line));
00656                 return NULL;
00657         }
00658 
00659 #ifdef DEVELOPER
00660         clobber_region(fn,line,dest, maxlength+1);
00661 #endif
00662 
00663         if (!src) {
00664                 *dest = 0;
00665                 return dest;
00666         }  
00667 
00668         len = strnlen(src, maxlength+1);
00669 
00670         if (len > maxlength) {
00671                 DEBUG(0,("ERROR: string overflow by %lu (%lu - %lu) in safe_strcpy [%.50s]\n",
00672                          (unsigned long)(len-maxlength), (unsigned long)len, 
00673                          (unsigned long)maxlength, src));
00674                 len = maxlength;
00675         }
00676       
00677         memmove(dest, src, len);
00678         dest[len] = 0;
00679         return dest;
00680 }  
00681 
00682 /**
00683  Safe string cat into a string. maxlength does not
00684  include the terminating zero.
00685 **/
00686 char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
00687 {
00688         size_t src_len, dest_len;
00689 
00690         if (!dest) {
00691                 DEBUG(0,("ERROR: NULL dest in safe_strcat, called from [%s][%d]\n", fn, line));
00692                 return NULL;
00693         }
00694 
00695         if (!src)
00696                 return dest;
00697         
00698         src_len = strnlen(src, maxlength + 1);
00699         dest_len = strnlen(dest, maxlength + 1);
00700 
00701 #ifdef DEVELOPER
00702         clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
00703 #endif
00704 
00705         if (src_len + dest_len > maxlength) {
00706                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
00707                          (int)(src_len + dest_len - maxlength), src));
00708                 if (maxlength > dest_len) {
00709                         memcpy(&dest[dest_len], src, maxlength - dest_len);
00710                 }
00711                 dest[maxlength] = 0;
00712                 return NULL;
00713         }
00714 
00715         memcpy(&dest[dest_len], src, src_len);
00716         dest[dest_len + src_len] = 0;
00717         return dest;
00718 }
00719 
00720 /**
00721  Paranoid strcpy into a buffer of given length (includes terminating
00722  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
00723  and replaces with '_'. Deliberately does *NOT* check for multibyte
00724  characters. Don't change it !
00725 **/
00726 char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
00727 {
00728         size_t len, i;
00729 
00730 #ifdef DEVELOPER
00731         clobber_region(fn, line, dest, maxlength);
00732 #endif
00733 
00734         if (!dest) {
00735                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy, called from [%s][%d]\n", fn, line));
00736                 return NULL;
00737         }
00738 
00739         if (!src) {
00740                 *dest = 0;
00741                 return dest;
00742         }  
00743 
00744         len = strlen(src);
00745         if (len >= maxlength)
00746                 len = maxlength - 1;
00747 
00748         if (!other_safe_chars)
00749                 other_safe_chars = "";
00750 
00751         for(i = 0; i < len; i++) {
00752                 int val = (src[i] & 0xff);
00753                 if (isupper_ascii(val) || islower_ascii(val) || isdigit(val) || strchr_m(other_safe_chars, val))
00754                         dest[i] = src[i];
00755                 else
00756                         dest[i] = '_';
00757         }
00758 
00759         dest[i] = '\0';
00760 
00761         return dest;
00762 }
00763 
00764 /**
00765  Like strncpy but always null terminates. Make sure there is room!
00766  The variable n should always be one less than the available size.
00767 **/
00768 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
00769 {
00770         char *d = dest;
00771 
00772 #ifdef DEVELOPER
00773         clobber_region(fn, line, dest, n+1);
00774 #endif
00775 
00776         if (!dest) {
00777                 DEBUG(0,("ERROR: NULL dest in StrnCpy, called from [%s][%d]\n", fn, line));
00778                 return(NULL);
00779         }
00780 
00781         if (!src) {
00782                 *dest = 0;
00783                 return(dest);
00784         }
00785         
00786         while (n-- && (*d = *src)) {
00787                 d++;
00788                 src++;
00789         }
00790 
00791         *d = 0;
00792         return(dest);
00793 }
00794 
00795 #if 0
00796 /**
00797  Like strncpy but copies up to the character marker.  always null terminates.
00798  returns a pointer to the character marker in the source string (src).
00799 **/
00800 
00801 static char *strncpyn(char *dest, const char *src, size_t n, char c)
00802 {
00803         char *p;
00804         size_t str_len;
00805 
00806 #ifdef DEVELOPER
00807         clobber_region(dest, n+1);
00808 #endif
00809         p = strchr_m(src, c);
00810         if (p == NULL) {
00811                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
00812                 return NULL;
00813         }
00814 
00815         str_len = PTR_DIFF(p, src);
00816         strncpy(dest, src, MIN(n, str_len));
00817         dest[str_len] = '\0';
00818 
00819         return p;
00820 }
00821 #endif
00822 
00823 /**
00824  Routine to get hex characters and turn them into a 16 byte array.
00825  the array can be variable length, and any non-hex-numeric
00826  characters are skipped.  "0xnn" or "0Xnn" is specially catered
00827  for.
00828 
00829  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
00830 
00831 **/
00832 
00833 size_t strhex_to_str(char *p, size_t len, const char *strhex)
00834 {
00835         size_t i;
00836         size_t num_chars = 0;
00837         unsigned char   lonybble, hinybble;
00838         const char     *hexchars = "0123456789ABCDEF";
00839         char           *p1 = NULL, *p2 = NULL;
00840 
00841         for (i = 0; i < len && strhex[i] != 0; i++) {
00842                 if (strnequal(hexchars, "0x", 2)) {
00843                         i++; /* skip two chars */
00844                         continue;
00845                 }
00846 
00847                 if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
00848                         break;
00849 
00850                 i++; /* next hex digit */
00851 
00852                 if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
00853                         break;
00854 
00855                 /* get the two nybbles */
00856                 hinybble = PTR_DIFF(p1, hexchars);
00857                 lonybble = PTR_DIFF(p2, hexchars);
00858 
00859                 p[num_chars] = (hinybble << 4) | lonybble;
00860                 num_chars++;
00861 
00862                 p1 = NULL;
00863                 p2 = NULL;
00864         }
00865         return num_chars;
00866 }
00867 
00868 DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex) 
00869 {
00870         DATA_BLOB ret_blob;
00871 
00872         if (mem_ctx != NULL)
00873                 ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
00874         else
00875                 ret_blob = data_blob(NULL, strlen(strhex)/2+1);
00876 
00877         ret_blob.length = strhex_to_str((char*)ret_blob.data,   
00878                                         strlen(strhex), 
00879                                         strhex);
00880 
00881         return ret_blob;
00882 }
00883 
00884 /**
00885  * Routine to print a buffer as HEX digits, into an allocated string.
00886  */
00887 
00888 char *hex_encode(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
00889 {
00890         int i;
00891         char *hex_buffer;
00892 
00893         hex_buffer = TALLOC_ARRAY(mem_ctx, char, (len*2)+1);
00894 
00895         for (i = 0; i < len; i++)
00896                 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
00897 
00898         return hex_buffer;
00899 }
00900 
00901 /**
00902  Check if a string is part of a list.
00903 **/
00904 
00905 BOOL in_list(const char *s, const char *list, BOOL casesensitive)
00906 {
00907         pstring tok;
00908         const char *p=list;
00909 
00910         if (!list)
00911                 return(False);
00912 
00913         while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
00914                 if (casesensitive) {
00915                         if (strcmp(tok,s) == 0)
00916                                 return(True);
00917                 } else {
00918                         if (StrCaseCmp(tok,s) == 0)
00919                                 return(True);
00920                 }
00921         }
00922         return(False);
00923 }
00924 
00925 /* this is used to prevent lots of mallocs of size 1 */
00926 static const char *null_string = "";
00927 
00928 /**
00929  Set a string value, allocing the space for the string
00930 **/
00931 
00932 static BOOL string_init(char **dest,const char *src)
00933 {
00934         size_t l;
00935 
00936         if (!src)     
00937                 src = "";
00938 
00939         l = strlen(src);
00940 
00941         if (l == 0) {
00942                 *dest = CONST_DISCARD(char*, null_string);
00943         } else {
00944                 (*dest) = SMB_STRDUP(src);
00945                 if ((*dest) == NULL) {
00946                         DEBUG(0,("Out of memory in string_init\n"));
00947                         return False;
00948                 }
00949         }
00950         return(True);
00951 }
00952 
00953 /**
00954  Free a string value.
00955 **/
00956 
00957 void string_free(char **s)
00958 {
00959         if (!s || !(*s))
00960                 return;
00961         if (*s == null_string)
00962                 *s = NULL;
00963         SAFE_FREE(*s);
00964 }
00965 
00966 /**
00967  Set a string value, deallocating any existing space, and allocing the space
00968  for the string
00969 **/
00970 
00971 BOOL string_set(char **dest,const char *src)
00972 {
00973         string_free(dest);
00974         return(string_init(dest,src));
00975 }
00976 
00977 /**
00978  Substitute a string for a pattern in another string. Make sure there is 
00979  enough room!
00980 
00981  This routine looks for pattern in s and replaces it with 
00982  insert. It may do multiple replacements or just one.
00983 
00984  Any of " ; ' $ or ` in the insert string are replaced with _
00985  if len==0 then the string cannot be extended. This is different from the old
00986  use of len==0 which was for no length checks to be done.
00987 **/
00988 
00989 void string_sub2(char *s,const char *pattern, const char *insert, size_t len, 
00990                  BOOL remove_unsafe_characters, BOOL replace_once, BOOL allow_trailing_dollar)
00991 {
00992         char *p;
00993         ssize_t ls,lp,li, i;
00994 
00995         if (!insert || !pattern || !*pattern || !s)
00996                 return;
00997 
00998         ls = (ssize_t)strlen(s);
00999         lp = (ssize_t)strlen(pattern);
01000         li = (ssize_t)strlen(insert);
01001 
01002         if (len == 0)
01003                 len = ls + 1; /* len is number of *bytes* */
01004 
01005         while (lp <= ls && (p = strstr_m(s,pattern))) {
01006                 if (ls + (li-lp) >= len) {
01007                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
01008                                  (int)(ls + (li-lp) - len),
01009                                  pattern, (int)len));
01010                         break;
01011                 }
01012                 if (li != lp) {
01013                         memmove(p+li,p+lp,strlen(p+lp)+1);
01014                 }
01015                 for (i=0;i<li;i++) {
01016                         switch (insert[i]) {
01017                         case '`':
01018                         case '"':
01019                         case '\'':
01020                         case ';':
01021                         case '$':
01022                                 /* allow a trailing $ (as in machine accounts) */
01023                                 if (allow_trailing_dollar && (i == li - 1 )) {
01024                                         p[i] = insert[i];
01025                                         break;
01026                                 }
01027                         case '%':
01028                         case '\r':
01029                         case '\n':
01030                                 if ( remove_unsafe_characters ) {
01031                                         p[i] = '_';
01032                                         /* yes this break should be here since we want to 
01033                                            fall throw if not replacing unsafe chars */
01034                                         break;
01035                                 }
01036                         default:
01037                                 p[i] = insert[i];
01038                         }
01039                 }
01040                 s = p + li;
01041                 ls += (li-lp);
01042 
01043                 if (replace_once)
01044                         break;
01045         }
01046 }
01047 
01048 void string_sub_once(char *s, const char *pattern, const char *insert, size_t len)
01049 {
01050         string_sub2( s, pattern, insert, len, True, True, False );
01051 }
01052 
01053 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
01054 {
01055         string_sub2( s, pattern, insert, len, True, False, False );
01056 }
01057 
01058 void fstring_sub(char *s,const char *pattern,const char *insert)
01059 {
01060         string_sub(s, pattern, insert, sizeof(fstring));
01061 }
01062 
01063 void pstring_sub(char *s,const char *pattern,const char *insert)
01064 {
01065         string_sub(s, pattern, insert, sizeof(pstring));
01066 }
01067 
01068 /**
01069  Similar to string_sub, but it will accept only allocated strings
01070  and may realloc them so pay attention at what you pass on no
01071  pointers inside strings, no pstrings or const may be passed
01072  as string.
01073 **/
01074 
01075 char *realloc_string_sub(char *string, const char *pattern,
01076                          const char *insert)
01077 {
01078         char *p, *in;
01079         char *s;
01080         ssize_t ls,lp,li,ld, i;
01081 
01082         if (!insert || !pattern || !*pattern || !string || !*string)
01083                 return NULL;
01084 
01085         s = string;
01086 
01087         in = SMB_STRDUP(insert);
01088         if (!in) {
01089                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
01090                 return NULL;
01091         }
01092         ls = (ssize_t)strlen(s);
01093         lp = (ssize_t)strlen(pattern);
01094         li = (ssize_t)strlen(insert);
01095         ld = li - lp;
01096         for (i=0;i<li;i++) {
01097                 switch (in[i]) {
01098                         case '`':
01099                         case '"':
01100                         case '\'':
01101                         case ';':
01102                         case '$':
01103                         case '%':
01104                         case '\r':
01105                         case '\n':
01106                                 in[i] = '_';
01107                         default:
01108                                 /* ok */
01109                                 break;
01110                 }
01111         }
01112         
01113         while ((p = strstr_m(s,pattern))) {
01114                 if (ld > 0) {
01115                         int offset = PTR_DIFF(s,string);
01116                         string = (char *)SMB_REALLOC(string, ls + ld + 1);
01117                         if (!string) {
01118                                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
01119                                 SAFE_FREE(in);
01120                                 return NULL;
01121                         }
01122                         p = string + offset + (p - s);
01123                 }
01124                 if (li != lp) {
01125                         memmove(p+li,p+lp,strlen(p+lp)+1);
01126                 }
01127                 memcpy(p, in, li);
01128                 s = p + li;
01129                 ls += ld;
01130         }
01131         SAFE_FREE(in);
01132         return string;
01133 }
01134 
01135 /* Same as string_sub, but returns a talloc'ed string */
01136 
01137 char *talloc_string_sub(TALLOC_CTX *mem_ctx, const char *src,
01138                         const char *pattern, const char *insert)
01139 {
01140         char *p, *in;
01141         char *s;
01142         char *string;
01143         ssize_t ls,lp,li,ld, i;
01144 
01145         if (!insert || !pattern || !*pattern || !src || !*src)
01146                 return NULL;
01147 
01148         string = talloc_strdup(mem_ctx, src);
01149         if (string == NULL) {
01150                 DEBUG(0, ("talloc_strdup failed\n"));
01151                 return NULL;
01152         }
01153 
01154         s = string;
01155 
01156         in = SMB_STRDUP(insert);
01157         if (!in) {
01158                 DEBUG(0, ("talloc_string_sub: out of memory!\n"));
01159                 return NULL;
01160         }
01161         ls = (ssize_t)strlen(s);
01162         lp = (ssize_t)strlen(pattern);
01163         li = (ssize_t)strlen(insert);
01164         ld = li - lp;
01165         for (i=0;i<li;i++) {
01166                 switch (in[i]) {
01167                         case '`':
01168                         case '"':
01169                         case '\'':
01170                         case ';':
01171                         case '$':
01172                         case '%':
01173                         case '\r':
01174                         case '\n':
01175                                 in[i] = '_';
01176                         default:
01177                                 /* ok */
01178                                 break;
01179                 }
01180         }
01181         
01182         while ((p = strstr_m(s,pattern))) {
01183                 if (ld > 0) {
01184                         int offset = PTR_DIFF(s,string);
01185                         string = (char *)TALLOC_REALLOC(mem_ctx, string,
01186                                                         ls + ld + 1);
01187                         if (!string) {
01188                                 DEBUG(0, ("talloc_string_sub: out of "
01189                                           "memory!\n"));
01190                                 SAFE_FREE(in);
01191                                 return NULL;
01192                         }
01193                         p = string + offset + (p - s);
01194                 }
01195                 if (li != lp) {
01196                         memmove(p+li,p+lp,strlen(p+lp)+1);
01197                 }
01198                 memcpy(p, in, li);
01199                 s = p + li;
01200                 ls += ld;
01201         }
01202         SAFE_FREE(in);
01203         return string;
01204 }
01205 
01206 /**
01207  Similar to string_sub() but allows for any character to be substituted. 
01208  Use with caution!
01209  if len==0 then the string cannot be extended. This is different from the old
01210  use of len==0 which was for no length checks to be done.
01211 **/
01212 
01213 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
01214 {
01215         char *p;
01216         ssize_t ls,lp,li;
01217 
01218         if (!insert || !pattern || !s)
01219                 return;
01220 
01221         ls = (ssize_t)strlen(s);
01222         lp = (ssize_t)strlen(pattern);
01223         li = (ssize_t)strlen(insert);
01224 
01225         if (!*pattern)
01226                 return;
01227         
01228         if (len == 0)
01229                 len = ls + 1; /* len is number of *bytes* */
01230         
01231         while (lp <= ls && (p = strstr_m(s,pattern))) {
01232                 if (ls + (li-lp) >= len) {
01233                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
01234                                  (int)(ls + (li-lp) - len),
01235                                  pattern, (int)len));
01236                         break;
01237                 }
01238                 if (li != lp) {
01239                         memmove(p+li,p+lp,strlen(p+lp)+1);
01240                 }
01241                 memcpy(p, insert, li);
01242                 s = p + li;
01243                 ls += (li-lp);
01244         }
01245 }
01246 
01247 /**
01248  Similar to all_string_sub but for unicode strings.
01249  Return a new allocated unicode string.
01250  similar to string_sub() but allows for any character to be substituted.
01251  Use with caution!
01252 **/
01253 
01254 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
01255                                 const smb_ucs2_t *insert)
01256 {
01257         smb_ucs2_t *r, *rp;
01258         const smb_ucs2_t *sp;
01259         size_t  lr, lp, li, lt;
01260 
01261         if (!insert || !pattern || !*pattern || !s)
01262                 return NULL;
01263 
01264         lt = (size_t)strlen_w(s);
01265         lp = (size_t)strlen_w(pattern);
01266         li = (size_t)strlen_w(insert);
01267 
01268         if (li > lp) {
01269                 const smb_ucs2_t *st = s;
01270                 int ld = li - lp;
01271                 while ((sp = strstr_w(st, pattern))) {
01272                         st = sp + lp;
01273                         lt += ld;
01274                 }
01275         }
01276 
01277         r = rp = SMB_MALLOC_ARRAY(smb_ucs2_t, lt + 1);
01278         if (!r) {
01279                 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
01280                 return NULL;
01281         }
01282 
01283         while ((sp = strstr_w(s, pattern))) {
01284                 memcpy(rp, s, (sp - s));
01285                 rp += ((sp - s) / sizeof(smb_ucs2_t));
01286                 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
01287                 s = sp + lp;
01288                 rp += li;
01289         }
01290         lr = ((rp - r) / sizeof(smb_ucs2_t));
01291         if (lr < lt) {
01292                 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
01293                 rp += (lt - lr);
01294         }
01295         *rp = 0;
01296 
01297         return r;
01298 }
01299 
01300 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
01301                                              const char *insert)
01302 {
01303         wpstring p, i;
01304 
01305         if (!insert || !pattern || !s)
01306                 return NULL;
01307         push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
01308         push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
01309         return all_string_sub_w(s, p, i);
01310 }
01311 
01312 #if 0
01313 /**
01314  Splits out the front and back at a separator.
01315 **/
01316 
01317 static void split_at_last_component(char *path, char *front, char sep, char *back)
01318 {
01319         char *p = strrchr_m(path, sep);
01320 
01321         if (p != NULL)
01322                 *p = 0;
01323 
01324         if (front != NULL)
01325                 pstrcpy(front, path);
01326 
01327         if (p != NULL) {
01328                 if (back != NULL)
01329                         pstrcpy(back, p+1);
01330                 *p = '\\';
01331         } else {
01332                 if (back != NULL)
01333                         back[0] = 0;
01334         }
01335 }
01336 #endif
01337 
01338 /**
01339  Write an octal as a string.
01340 **/
01341 
01342 const char *octal_string(int i)
01343 {
01344         static char ret[64];
01345         if (i == -1)
01346                 return "-1";
01347         slprintf(ret, sizeof(ret)-1, "0%o", i);
01348         return ret;
01349 }
01350 
01351 
01352 /**
01353  Truncate a string at a specified length.
01354 **/
01355 
01356 char *string_truncate(char *s, unsigned int length)
01357 {
01358         if (s && strlen(s) > length)
01359                 s[length] = 0;
01360         return s;
01361 }
01362 
01363 /**
01364  Strchr and strrchr_m are very hard to do on general multi-byte strings. 
01365  We convert via ucs2 for now.
01366 **/
01367 
01368 char *strchr_m(const char *src, char c)
01369 {
01370         wpstring ws;
01371         pstring s2;
01372         smb_ucs2_t *p;
01373         const char *s;
01374 
01375         /* characters below 0x3F are guaranteed to not appear in
01376            non-initial position in multi-byte charsets */
01377         if ((c & 0xC0) == 0) {
01378                 return strchr(src, c);
01379         }
01380 
01381         /* this is quite a common operation, so we want it to be
01382            fast. We optimise for the ascii case, knowing that all our
01383            supported multi-byte character sets are ascii-compatible
01384            (ie. they match for the first 128 chars) */
01385 
01386         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
01387                 if (*s == c)
01388                         return (char *)s;
01389         }
01390 
01391         if (!*s)
01392                 return NULL;
01393 
01394 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
01395         /* With compose characters we must restart from the beginning. JRA. */
01396         s = src;
01397 #endif
01398 
01399         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
01400         p = strchr_w(ws, UCS2_CHAR(c));
01401         if (!p)
01402                 return NULL;
01403         *p = 0;
01404         pull_ucs2_pstring(s2, ws);
01405         return (char *)(s+strlen(s2));
01406 }
01407 
01408 char *strrchr_m(const char *s, char c)
01409 {
01410         /* characters below 0x3F are guaranteed to not appear in
01411            non-initial position in multi-byte charsets */
01412         if ((c & 0xC0) == 0) {
01413                 return strrchr(s, c);
01414         }
01415 
01416         /* this is quite a common operation, so we want it to be
01417            fast. We optimise for the ascii case, knowing that all our
01418            supported multi-byte character sets are ascii-compatible
01419            (ie. they match for the first 128 chars). Also, in Samba
01420            we only search for ascii characters in 'c' and that
01421            in all mb character sets with a compound character
01422            containing c, if 'c' is not a match at position
01423            p, then p[-1] > 0x7f. JRA. */
01424 
01425         {
01426                 size_t len = strlen(s);
01427                 const char *cp = s;
01428                 BOOL got_mb = False;
01429 
01430                 if (len == 0)
01431                         return NULL;
01432                 cp += (len - 1);
01433                 do {
01434                         if (c == *cp) {
01435                                 /* Could be a match. Part of a multibyte ? */
01436                                 if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
01437                                         /* Yep - go slow :-( */
01438                                         got_mb = True;
01439                                         break;
01440                                 }
01441                                 /* No - we have a match ! */
01442                                 return (char *)cp;
01443                         }
01444                 } while (cp-- != s);
01445                 if (!got_mb)
01446                         return NULL;
01447         }
01448 
01449         /* String contained a non-ascii char. Slow path. */
01450         {
01451                 wpstring ws;
01452                 pstring s2;
01453                 smb_ucs2_t *p;
01454 
01455                 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
01456                 p = strrchr_w(ws, UCS2_CHAR(c));
01457                 if (!p)
01458                         return NULL;
01459                 *p = 0;
01460                 pull_ucs2_pstring(s2, ws);
01461                 return (char *)(s+strlen(s2));
01462         }
01463 }
01464 
01465 /***********************************************************************
01466  Return the equivalent of doing strrchr 'n' times - always going
01467  backwards.
01468 ***********************************************************************/
01469 
01470 char *strnrchr_m(const char *s, char c, unsigned int n)
01471 {
01472         wpstring ws;
01473         pstring s2;
01474         smb_ucs2_t *p;
01475 
01476         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
01477         p = strnrchr_w(ws, UCS2_CHAR(c), n);
01478         if (!p)
01479                 return NULL;
01480         *p = 0;
01481         pull_ucs2_pstring(s2, ws);
01482         return (char *)(s+strlen(s2));
01483 }
01484 
01485 /***********************************************************************
01486  strstr_m - We convert via ucs2 for now.
01487 ***********************************************************************/
01488 
01489 char *strstr_m(const char *src, const char *findstr)
01490 {
01491         smb_ucs2_t *p;
01492         smb_ucs2_t *src_w, *find_w;
01493         const char *s;
01494         char *s2;
01495         char *retp;
01496 
01497         size_t findstr_len = 0;
01498 
01499         /* for correctness */
01500         if (!findstr[0]) {
01501                 return (char*)src;
01502         }
01503 
01504         /* Samba does single character findstr calls a *lot*. */
01505         if (findstr[1] == '\0')
01506                 return strchr_m(src, *findstr);
01507 
01508         /* We optimise for the ascii case, knowing that all our
01509            supported multi-byte character sets are ascii-compatible
01510            (ie. they match for the first 128 chars) */
01511 
01512         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
01513                 if (*s == *findstr) {
01514                         if (!findstr_len) 
01515                                 findstr_len = strlen(findstr);
01516 
01517                         if (strncmp(s, findstr, findstr_len) == 0) {
01518                                 return (char *)s;
01519                         }
01520                 }
01521         }
01522 
01523         if (!*s)
01524                 return NULL;
01525 
01526 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
01527         /* 'make check' fails unless we do this */
01528 
01529         /* With compose characters we must restart from the beginning. JRA. */
01530         s = src;
01531 #endif
01532 
01533         if (push_ucs2_allocate(&src_w, src) == (size_t)-1) {
01534                 DEBUG(0,("strstr_m: src malloc fail\n"));
01535                 return NULL;
01536         }
01537         
01538         if (push_ucs2_allocate(&find_w, findstr) == (size_t)-1) {
01539                 SAFE_FREE(src_w);
01540                 DEBUG(0,("strstr_m: find malloc fail\n"));
01541                 return NULL;
01542         }
01543 
01544         p = strstr_w(src_w, find_w);
01545 
01546         if (!p) {
01547                 SAFE_FREE(src_w);
01548                 SAFE_FREE(find_w);
01549                 return NULL;
01550         }
01551         
01552         *p = 0;
01553         if (pull_ucs2_allocate(&s2, src_w) == (size_t)-1) {
01554                 SAFE_FREE(src_w);
01555                 SAFE_FREE(find_w);
01556                 DEBUG(0,("strstr_m: dest malloc fail\n"));
01557                 return NULL;
01558         }
01559         retp = (char *)(s+strlen(s2));
01560         SAFE_FREE(src_w);
01561         SAFE_FREE(find_w);
01562         SAFE_FREE(s2);
01563         return retp;
01564 }
01565 
01566 /**
01567  Convert a string to lower case.
01568 **/
01569 
01570 void strlower_m(char *s)
01571 {
01572         size_t len;
01573         int errno_save;
01574 
01575         /* this is quite a common operation, so we want it to be
01576            fast. We optimise for the ascii case, knowing that all our
01577            supported multi-byte character sets are ascii-compatible
01578            (ie. they match for the first 128 chars) */
01579 
01580         while (*s && !(((unsigned char)s[0]) & 0x80)) {
01581                 *s = tolower_ascii((unsigned char)*s);
01582                 s++;
01583         }
01584 
01585         if (!*s)
01586                 return;
01587 
01588         /* I assume that lowercased string takes the same number of bytes
01589          * as source string even in UTF-8 encoding. (VIV) */
01590         len = strlen(s) + 1;
01591         errno_save = errno;
01592         errno = 0;
01593         unix_strlower(s,len,s,len);     
01594         /* Catch mb conversion errors that may not terminate. */
01595         if (errno)
01596                 s[len-1] = '\0';
01597         errno = errno_save;
01598 }
01599 
01600 /**
01601  Convert a string to upper case.
01602 **/
01603 
01604 void strupper_m(char *s)
01605 {
01606         size_t len;
01607         int errno_save;
01608 
01609         /* this is quite a common operation, so we want it to be
01610            fast. We optimise for the ascii case, knowing that all our
01611            supported multi-byte character sets are ascii-compatible
01612            (ie. they match for the first 128 chars) */
01613 
01614         while (*s && !(((unsigned char)s[0]) & 0x80)) {
01615                 *s = toupper_ascii((unsigned char)*s);
01616                 s++;
01617         }
01618 
01619         if (!*s)
01620                 return;
01621 
01622         /* I assume that lowercased string takes the same number of bytes
01623          * as source string even in multibyte encoding. (VIV) */
01624         len = strlen(s) + 1;
01625         errno_save = errno;
01626         errno = 0;
01627         unix_strupper(s,len,s,len);     
01628         /* Catch mb conversion errors that may not terminate. */
01629         if (errno)
01630                 s[len-1] = '\0';
01631         errno = errno_save;
01632 }
01633 
01634 /**
01635  Count the number of UCS2 characters in a string. Normally this will
01636  be the same as the number of bytes in a string for single byte strings,
01637  but will be different for multibyte.
01638 **/
01639 
01640 size_t strlen_m(const char *s)
01641 {
01642         size_t count = 0;
01643 
01644         if (!s) {
01645                 return 0;
01646         }
01647 
01648         while (*s && !(((uint8_t)*s) & 0x80)) {
01649                 s++;
01650                 count++;
01651         }
01652 
01653         if (!*s) {
01654                 return count;
01655         }
01656 
01657         while (*s) {
01658                 size_t c_size;
01659                 codepoint_t c = next_codepoint(s, &c_size);
01660                 if (c < 0x10000) {
01661                         /* Unicode char fits into 16 bits. */
01662                         count += 1;
01663                 } else {
01664                         /* Double-width unicode char - 32 bits. */
01665                         count += 2;
01666                 }
01667                 s += c_size;
01668         }
01669 
01670         return count;
01671 }
01672 
01673 /**
01674  Count the number of UCS2 characters in a string including the null
01675  terminator.
01676 **/
01677 
01678 size_t strlen_m_term(const char *s)
01679 {
01680         if (!s) {
01681                 return 0;
01682         }
01683         return strlen_m(s) + 1;
01684 }
01685 
01686 /*
01687  * Weird helper routine for the winreg pipe: If nothing is around, return 0,
01688  * if a string is there, include the terminator.
01689  */
01690 
01691 size_t strlen_m_term_null(const char *s)
01692 {
01693         size_t len;
01694         if (!s) {
01695                 return 0;
01696         }
01697         len = strlen_m(s);
01698         if (len == 0) {
01699                 return 0;
01700         }
01701 
01702         return len+1;
01703 }
01704 /**
01705  Return a RFC2254 binary string representation of a buffer.
01706  Used in LDAP filters.
01707  Caller must free.
01708 **/
01709 
01710 char *binary_string_rfc2254(char *buf, int len)
01711 {
01712         char *s;
01713         int i, j;
01714         const char *hex = "0123456789ABCDEF";
01715         s = (char *)SMB_MALLOC(len * 3 + 1);
01716         if (!s)
01717                 return NULL;
01718         for (j=i=0;i<len;i++) {
01719                 s[j] = '\\';
01720                 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
01721                 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
01722                 j += 3;
01723         }
01724         s[j] = 0;
01725         return s;
01726 }
01727 
01728 char *binary_string(char *buf, int len)
01729 {
01730         char *s;
01731         int i, j;
01732         const char *hex = "0123456789ABCDEF";
01733         s = (char *)SMB_MALLOC(len * 2 + 1);
01734         if (!s)
01735                 return NULL;
01736         for (j=i=0;i<len;i++) {
01737                 s[j]   = hex[((unsigned char)buf[i]) >> 4];
01738                 s[j+1] = hex[((unsigned char)buf[i]) & 0xF];
01739                 j += 2;
01740         }
01741         s[j] = 0;
01742         return s;
01743 }
01744 /**
01745  Just a typesafety wrapper for snprintf into a pstring.
01746 **/
01747 
01748  int pstr_sprintf(pstring s, const char *fmt, ...)
01749 {
01750         va_list ap;
01751         int ret;
01752 
01753         va_start(ap, fmt);
01754         ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
01755         va_end(ap);
01756         return ret;
01757 }
01758 
01759 
01760 /**
01761  Just a typesafety wrapper for snprintf into a fstring.
01762 **/
01763 
01764 int fstr_sprintf(fstring s, const char *fmt, ...)
01765 {
01766         va_list ap;
01767         int ret;
01768 
01769         va_start(ap, fmt);
01770         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
01771         va_end(ap);
01772         return ret;
01773 }
01774 
01775 /**
01776  List of Strings manipulation functions
01777 **/
01778 
01779 #define S_LIST_ABS 16 /* List Allocation Block Size */
01780 
01781 static char **str_list_make_internal(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
01782 {
01783         char **list, **rlist;
01784         const char *str;
01785         char *s;
01786         int num, lsize;
01787         pstring tok;
01788         
01789         if (!string || !*string)
01790                 return NULL;
01791         if (mem_ctx) {
01792                 s = talloc_strdup(mem_ctx, string);
01793         } else {
01794                 s = SMB_STRDUP(string);
01795         }
01796         if (!s) {
01797                 DEBUG(0,("str_list_make: Unable to allocate memory"));
01798                 return NULL;
01799         }
01800         if (!sep) sep = LIST_SEP;
01801         
01802         num = lsize = 0;
01803         list = NULL;
01804         
01805         str = s;
01806         while (next_token(&str, tok, sep, sizeof(tok))) {               
01807                 if (num == lsize) {
01808                         lsize += S_LIST_ABS;
01809                         if (mem_ctx) {
01810                                 rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *, lsize +1);
01811                         } else {
01812                                 /* We need to keep the old list on error so we can free the elements
01813                                    if the realloc fails. */
01814                                 rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, char *, lsize +1);
01815                         }
01816                         if (!rlist) {
01817                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
01818                                 str_list_free(&list);
01819                                 if (mem_ctx) {
01820                                         TALLOC_FREE(s);
01821                                 } else {
01822                                         SAFE_FREE(s);
01823                                 }
01824                                 return NULL;
01825                         } else {
01826                                 list = rlist;
01827                         }
01828                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
01829                 }
01830 
01831                 if (mem_ctx) {
01832                         list[num] = talloc_strdup(mem_ctx, tok);
01833                 } else {
01834                         list[num] = SMB_STRDUP(tok);
01835                 }
01836                 
01837                 if (!list[num]) {
01838                         DEBUG(0,("str_list_make: Unable to allocate memory"));
01839                         str_list_free(&list);
01840                         if (mem_ctx) {
01841                                 TALLOC_FREE(s);
01842                         } else {
01843                                 SAFE_FREE(s);
01844                         }
01845                         return NULL;
01846                 }
01847         
01848                 num++;  
01849         }
01850 
01851         if (mem_ctx) {
01852                 TALLOC_FREE(s);
01853         } else {
01854                 SAFE_FREE(s);
01855         }
01856 
01857         return list;
01858 }
01859 
01860 char **str_list_make_talloc(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
01861 {
01862         return str_list_make_internal(mem_ctx, string, sep);
01863 }
01864 
01865 char **str_list_make(const char *string, const char *sep)
01866 {
01867         return str_list_make_internal(NULL, string, sep);
01868 }
01869 
01870 BOOL str_list_copy(char ***dest, const char **src)
01871 {
01872         char **list, **rlist;
01873         int num, lsize;
01874         
01875         *dest = NULL;
01876         if (!src)
01877                 return False;
01878         
01879         num = lsize = 0;
01880         list = NULL;
01881                 
01882         while (src[num]) {
01883                 if (num == lsize) {
01884                         lsize += S_LIST_ABS;
01885                         rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, char *, lsize +1);
01886                         if (!rlist) {
01887                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
01888                                 str_list_free(&list);
01889                                 return False;
01890                         } else {
01891                                 list = rlist;
01892                         }
01893                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
01894                 }
01895                 
01896                 list[num] = SMB_STRDUP(src[num]);
01897                 if (!list[num]) {
01898                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
01899                         str_list_free(&list);
01900                         return False;
01901                 }
01902 
01903                 num++;
01904         }
01905         
01906         *dest = list;
01907         return True;    
01908 }
01909 
01910 /**
01911  * Return true if all the elements of the list match exactly.
01912  **/
01913 BOOL str_list_compare(char **list1, char **list2)
01914 {
01915         int num;
01916         
01917         if (!list1 || !list2)
01918                 return (list1 == list2); 
01919         
01920         for (num = 0; list1[num]; num++) {
01921                 if (!list2[num])
01922                         return False;
01923                 if (!strcsequal(list1[num], list2[num]))
01924                         return False;
01925         }
01926         if (list2[num])
01927                 return False; /* if list2 has more elements than list1 fail */
01928         
01929         return True;
01930 }
01931 
01932 static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list)
01933 {
01934         char **tlist;
01935         
01936         if (!list || !*list)
01937                 return;
01938         tlist = *list;
01939         for(; *tlist; tlist++) {
01940                 if (mem_ctx) {
01941                         TALLOC_FREE(*tlist);
01942                 } else {
01943                         SAFE_FREE(*tlist);
01944                 }
01945         }
01946         if (mem_ctx) {
01947                 TALLOC_FREE(*tlist);
01948         } else {
01949                 SAFE_FREE(*list);
01950         }
01951 }
01952 
01953 void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list)
01954 {
01955         str_list_free_internal(mem_ctx, list);
01956 }
01957 
01958 void str_list_free(char ***list)
01959 {
01960         str_list_free_internal(NULL, list);
01961 }
01962 
01963 /******************************************************************************
01964  *****************************************************************************/
01965 
01966 int str_list_count( const char **list )
01967 {
01968         int i = 0;
01969 
01970         if ( ! list )
01971                 return 0;
01972 
01973         /* count the number of list members */
01974         
01975         for ( i=0; *list; i++, list++ );
01976         
01977         return i;
01978 }
01979 
01980 /******************************************************************************
01981  version of standard_sub_basic() for string lists; uses alloc_sub_basic() 
01982  for the work
01983  *****************************************************************************/
01984  
01985 BOOL str_list_sub_basic( char **list, const char *smb_name,
01986                          const char *domain_name )
01987 {
01988         char *s, *tmpstr;
01989         
01990         while ( *list ) {
01991                 s = *list;
01992                 tmpstr = alloc_sub_basic(smb_name, domain_name, s);
01993                 if ( !tmpstr ) {
01994                         DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
01995                         return False;
01996                 }
01997 
01998                 SAFE_FREE(*list);
01999                 *list = tmpstr;
02000                         
02001                 list++;
02002         }
02003 
02004         return True;
02005 }
02006 
02007 /******************************************************************************
02008  substritute a specific pattern in a string list
02009  *****************************************************************************/
02010  
02011 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
02012 {
02013         char *p, *s, *t;
02014         ssize_t ls, lp, li, ld, i, d;
02015 
02016         if (!list)
02017                 return False;
02018         if (!pattern)
02019                 return False;
02020         if (!insert)
02021                 return False;
02022 
02023         lp = (ssize_t)strlen(pattern);
02024         li = (ssize_t)strlen(insert);
02025         ld = li -lp;
02026                         
02027         while (*list) {
02028                 s = *list;
02029                 ls = (ssize_t)strlen(s);
02030 
02031                 while ((p = strstr_m(s, pattern))) {
02032                         t = *list;
02033                         d = p -t;
02034                         if (ld) {
02035                                 t = (char *) SMB_MALLOC(ls +ld +1);
02036                                 if (!t) {
02037                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
02038                                         return False;
02039                                 }
02040                                 memcpy(t, *list, d);
02041                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
02042                                 SAFE_FREE(*list);
02043                                 *list = t;
02044                                 ls += ld;
02045                                 s = t +d +li;
02046                         }
02047                         
02048                         for (i = 0; i < li; i++) {
02049                                 switch (insert[i]) {
02050                                         case '`':
02051                                         case '"':
02052                                         case '\'':
02053                                         case ';':
02054                                         case '$':
02055                                         case '%':
02056                                         case '\r':
02057                                         case '\n':
02058                                                 t[d +i] = '_';
02059                                                 break;
02060                                         default:
02061                                                 t[d +i] = insert[i];
02062                                 }
02063                         }       
02064                 }
02065                 
02066                 
02067                 list++;
02068         }
02069         
02070         return True;
02071 }
02072 
02073 
02074 #define IPSTR_LIST_SEP  ","
02075 #define IPSTR_LIST_CHAR ','
02076 
02077 /**
02078  * Add ip string representation to ipstr list. Used also
02079  * as part of @function ipstr_list_make
02080  *
02081  * @param ipstr_list pointer to string containing ip list;
02082  *        MUST BE already allocated and IS reallocated if necessary
02083  * @param ipstr_size pointer to current size of ipstr_list (might be changed
02084  *        as a result of reallocation)
02085  * @param ip IP address which is to be added to list
02086  * @return pointer to string appended with new ip and possibly
02087  *         reallocated to new length
02088  **/
02089 
02090 char* ipstr_list_add(char** ipstr_list, const struct ip_service *service)
02091 {
02092         char* new_ipstr = NULL;
02093         
02094         /* arguments checking */
02095         if (!ipstr_list || !service) return NULL;
02096 
02097         /* attempt to convert ip to a string and append colon separator to it */
02098         if (*ipstr_list) {
02099                 asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP,
02100                         inet_ntoa(service->ip), service->port);
02101                 SAFE_FREE(*ipstr_list);
02102         } else {
02103                 asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port);
02104         }
02105         *ipstr_list = new_ipstr;
02106         return *ipstr_list;
02107 }
02108 
02109 
02110 /**
02111  * Allocate and initialise an ipstr list using ip adresses
02112  * passed as arguments.
02113  *
02114  * @param ipstr_list pointer to string meant to be allocated and set
02115  * @param ip_list array of ip addresses to place in the list
02116  * @param ip_count number of addresses stored in ip_list
02117  * @return pointer to allocated ip string
02118  **/
02119  
02120 char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count)
02121 {
02122         int i;
02123         
02124         /* arguments checking */
02125         if (!ip_list || !ipstr_list) return 0;
02126 
02127         *ipstr_list = NULL;
02128         
02129         /* process ip addresses given as arguments */
02130         for (i = 0; i < ip_count; i++)
02131                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
02132         
02133         return (*ipstr_list);
02134 }
02135 
02136 
02137 /**
02138  * Parse given ip string list into array of ip addresses
02139  * (as ip_service structures)  
02140  *    e.g. 192.168.1.100:389,192.168.1.78, ...
02141  *
02142  * @param ipstr ip string list to be parsed 
02143  * @param ip_list pointer to array of ip addresses which is
02144  *        allocated by this function and must be freed by caller
02145  * @return number of successfully parsed addresses
02146  **/
02147  
02148 int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list)
02149 {
02150         fstring token_str;
02151         size_t count;
02152         int i;
02153 
02154         if (!ipstr_list || !ip_list) 
02155                 return 0;
02156         
02157         count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
02158         if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
02159                 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count));
02160                 return 0;
02161         }
02162         
02163         for ( i=0; 
02164                 next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count; 
02165                 i++ ) 
02166         {
02167                 struct in_addr addr;
02168                 unsigned port = 0;      
02169                 char *p = strchr(token_str, ':');
02170                 
02171                 if (p) {
02172                         *p = 0;
02173                         port = atoi(p+1);
02174                 }
02175 
02176                 /* convert single token to ip address */
02177                 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
02178                         break;
02179                                 
02180                 (*ip_list)[i].ip = addr;
02181                 (*ip_list)[i].port = port;
02182         }
02183         
02184         return count;
02185 }
02186 
02187 
02188 /**
02189  * Safely free ip string list
02190  *
02191  * @param ipstr_list ip string list to be freed
02192  **/
02193 
02194 void ipstr_list_free(char* ipstr_list)
02195 {
02196         SAFE_FREE(ipstr_list);
02197 }
02198 
02199 
02200 /**
02201  Unescape a URL encoded string, in place.
02202 **/
02203 
02204 void rfc1738_unescape(char *buf)
02205 {
02206         char *p=buf;
02207 
02208         while (p && *p && (p=strchr_m(p,'%'))) {
02209                 int c1 = p[1];
02210                 int c2 = p[2];
02211 
02212                 if (c1 >= '0' && c1 <= '9')
02213                         c1 = c1 - '0';
02214                 else if (c1 >= 'A' && c1 <= 'F')
02215                         c1 = 10 + c1 - 'A';
02216                 else if (c1 >= 'a' && c1 <= 'f')
02217                         c1 = 10 + c1 - 'a';
02218                 else {p++; continue;}
02219 
02220                 if (c2 >= '0' && c2 <= '9')
02221                         c2 = c2 - '0';
02222                 else if (c2 >= 'A' && c2 <= 'F')
02223                         c2 = 10 + c2 - 'A';
02224                 else if (c2 >= 'a' && c2 <= 'f')
02225                         c2 = 10 + c2 - 'a';
02226                 else {p++; continue;}
02227                         
02228                 *p = (c1<<4) | c2;
02229 
02230                 memmove(p+1, p+3, strlen(p+3)+1);
02231                 p++;
02232         }
02233 }
02234 
02235 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
02236 
02237 /**
02238  * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
02239  **/
02240 DATA_BLOB base64_decode_data_blob(const char *s)
02241 {
02242         int bit_offset, byte_offset, idx, i, n;
02243         DATA_BLOB decoded = data_blob(s, strlen(s)+1);
02244         unsigned char *d = decoded.data;
02245         char *p;
02246 
02247         n=i=0;
02248 
02249         while (*s && (p=strchr_m(b64,*s))) {
02250                 idx = (int)(p - b64);
02251                 byte_offset = (i*6)/8;
02252                 bit_offset = (i*6)%8;
02253                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
02254                 if (bit_offset < 3) {
02255                         d[byte_offset] |= (idx << (2-bit_offset));
02256                         n = byte_offset+1;
02257                 } else {
02258                         d[byte_offset] |= (idx >> (bit_offset-2));
02259                         d[byte_offset+1] = 0;
02260                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
02261                         n = byte_offset+2;
02262                 }
02263                 s++; i++;
02264         }
02265 
02266         if ((n > 0) && (*s == '=')) {
02267                 n -= 1;
02268         }
02269 
02270         /* fix up length */
02271         decoded.length = n;
02272         return decoded;
02273 }
02274 
02275 /**
02276  * Decode a base64 string in-place - wrapper for the above
02277  **/
02278 void base64_decode_inplace(char *s)
02279 {
02280         DATA_BLOB decoded = base64_decode_data_blob(s);
02281 
02282         if ( decoded.length != 0 ) {
02283                 memcpy(s, decoded.data, decoded.length);
02284 
02285                 /* null terminate */
02286                 s[decoded.length] = '\0';
02287         } else {
02288                 *s = '\0';
02289         }
02290 
02291         data_blob_free(&decoded);
02292 }
02293 
02294 /**
02295  * Encode a base64 string into a malloc()ed string caller to free.
02296  *
02297  *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
02298  **/
02299 char * base64_encode_data_blob(DATA_BLOB data)
02300 {
02301         int bits = 0;
02302         int char_count = 0;
02303         size_t out_cnt, len, output_len;
02304         char *result;
02305 
02306         if (!data.length || !data.data)
02307                 return NULL;
02308 
02309         out_cnt = 0;
02310         len = data.length;
02311         output_len = data.length * 2 + 4; /* Account for closing bytes. 4 is
02312                                            * random but should be enough for
02313                                            * the = and \0 */
02314         result = (char *)SMB_MALLOC(output_len); /* get us plenty of space */
02315 
02316         while (len-- && out_cnt < (data.length * 2) - 5) {
02317                 int c = (unsigned char) *(data.data++);
02318                 bits += c;
02319                 char_count++;
02320                 if (char_count == 3) {
02321                         result[out_cnt++] = b64[bits >> 18];
02322                         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
02323                         result[out_cnt++] = b64[(bits >> 6) & 0x3f];
02324             result[out_cnt++] = b64[bits & 0x3f];
02325             bits = 0;
02326             char_count = 0;
02327         } else {
02328             bits <<= 8;
02329         }
02330     }
02331     if (char_count != 0) {
02332         bits <<= 16 - (8 * char_count);
02333         result[out_cnt++] = b64[bits >> 18];
02334         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
02335         if (char_count == 1) {
02336             result[out_cnt++] = '=';
02337             result[out_cnt++] = '=';
02338         } else {
02339             result[out_cnt++] = b64[(bits >> 6) & 0x3f];
02340             result[out_cnt++] = '=';
02341         }
02342     }
02343     result[out_cnt] = '\0';     /* terminate */
02344     return result;
02345 }
02346 
02347 /* read a SMB_BIG_UINT from a string */
02348 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
02349 {
02350 
02351         SMB_BIG_UINT val = -1;
02352         const char *p = nptr;
02353         
02354         if (!p) {
02355                 if (entptr) {
02356                         *entptr = p;
02357                 }
02358                 return val;
02359         }
02360 
02361         while (*p && isspace(*p))
02362                 p++;
02363 
02364 #ifdef LARGE_SMB_OFF_T
02365         sscanf(p,"%llu",&val);  
02366 #else /* LARGE_SMB_OFF_T */
02367         sscanf(p,"%lu",&val);
02368 #endif /* LARGE_SMB_OFF_T */
02369         if (entptr) {
02370                 while (*p && isdigit(*p))
02371                         p++;
02372                 *entptr = p;
02373         }
02374 
02375         return val;
02376 }
02377 
02378 /* Convert a size specification to a count of bytes. We accept the following
02379  * suffixes:
02380  *          bytes if there is no suffix
02381  *      kK  kibibytes
02382  *      mM  mebibytes
02383  *      gG  gibibytes
02384  *      tT  tibibytes
02385  *      pP  whatever the ISO name for petabytes is
02386  *
02387  *  Returns 0 if the string can't be converted.
02388  */
02389 SMB_OFF_T conv_str_size(const char * str)
02390 {
02391         SMB_OFF_T lval;
02392         char * end;
02393 
02394         if (str == NULL || *str == '\0') {
02395                 return 0;
02396         }
02397 
02398 #ifdef HAVE_STRTOULL
02399         if (sizeof(SMB_OFF_T) == 8) {
02400             lval = strtoull(str, &end, 10 /* base */);
02401         } else {
02402             lval = strtoul(str, &end, 10 /* base */);
02403         }
02404 #else
02405         lval = strtoul(str, &end, 10 /* base */);
02406 #endif
02407 
02408         if (end == NULL || end == str) {
02409                 return 0;
02410         }
02411 
02412         if (*end) {
02413                 SMB_OFF_T lval_orig = lval;
02414 
02415                 if (strwicmp(end, "K") == 0) {
02416                         lval *= (SMB_OFF_T)1024;
02417                 } else if (strwicmp(end, "M") == 0) {
02418                         lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
02419                 } else if (strwicmp(end, "G") == 0) {
02420                         lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
02421                                 (SMB_OFF_T)1024);
02422                 } else if (strwicmp(end, "T") == 0) {
02423                         lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
02424                                 (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
02425                 } else if (strwicmp(end, "P") == 0) {
02426                         lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
02427                                 (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
02428                                 (SMB_OFF_T)1024);
02429                 } else {
02430                         return 0;
02431                 }
02432 
02433                 /* Primitive attempt to detect wrapping on platforms with
02434                  * 4-byte SMB_OFF_T. It's better to let the caller handle
02435                  * a failure than some random number.
02436                  */
02437                 if (lval_orig <= lval) {
02438                         return 0;
02439                 }
02440         }
02441 
02442         return lval;
02443 }
02444 
02445 void string_append(char **left, const char *right)
02446 {
02447         int new_len = strlen(right) + 1;
02448 
02449         if (*left == NULL) {
02450                 *left = (char *)SMB_MALLOC(new_len);
02451                 *left[0] = '\0';
02452         } else {
02453                 new_len += strlen(*left);
02454                 *left = (char *)SMB_REALLOC(*left, new_len);
02455         }
02456 
02457         if (*left == NULL) {
02458                 return;
02459         }
02460 
02461         safe_strcat(*left, right, new_len-1);
02462 }
02463 
02464 BOOL add_string_to_array(TALLOC_CTX *mem_ctx,
02465                          const char *str, const char ***strings,
02466                          int *num)
02467 {
02468         char *dup_str = talloc_strdup(mem_ctx, str);
02469 
02470         *strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings, const char *, (*num)+1);
02471 
02472         if ((*strings == NULL) || (dup_str == NULL)) {
02473                 *num = 0;
02474                 return False;
02475         }
02476 
02477         (*strings)[*num] = dup_str;
02478         *num += 1;
02479         return True;
02480 }
02481 
02482 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
02483  * error checking in between. The indiation that something weird happened is
02484  * string==NULL */
02485 
02486 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
02487                     size_t *bufsize, const char *fmt, ...)
02488 {
02489         va_list ap;
02490         char *newstr;
02491         int ret;
02492         BOOL increased;
02493 
02494         /* len<0 is an internal marker that something failed */
02495         if (*len < 0)
02496                 goto error;
02497 
02498         if (*string == NULL) {
02499                 if (*bufsize == 0)
02500                         *bufsize = 128;
02501 
02502                 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
02503                 if (*string == NULL)
02504                         goto error;
02505         }
02506 
02507         va_start(ap, fmt);
02508         ret = vasprintf(&newstr, fmt, ap);
02509         va_end(ap);
02510 
02511         if (ret < 0)
02512                 goto error;
02513 
02514         increased = False;
02515 
02516         while ((*len)+ret >= *bufsize) {
02517                 increased = True;
02518                 *bufsize *= 2;
02519                 if (*bufsize >= (1024*1024*256))
02520                         goto error;
02521         }
02522 
02523         if (increased) {
02524                 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
02525                                                *bufsize);
02526                 if (*string == NULL) {
02527                         goto error;
02528                 }
02529         }
02530 
02531         StrnCpy((*string)+(*len), newstr, ret);
02532         (*len) += ret;
02533         free(newstr);
02534         return;
02535 
02536  error:
02537         *len = -1;
02538         *string = NULL;
02539 }
02540 
02541 /*
02542    Returns the substring from src between the first occurrence of
02543    the char "front" and the first occurence of the char "back".
02544    Mallocs the return string which must be freed.  Not for use
02545    with wide character strings.
02546 */
02547 char *sstring_sub(const char *src, char front, char back)
02548 {
02549         char *temp1, *temp2, *temp3;
02550         ptrdiff_t len;
02551 
02552         temp1 = strchr(src, front);
02553         if (temp1 == NULL) return NULL;
02554         temp2 = strchr(src, back);
02555         if (temp2 == NULL) return NULL;
02556         len = temp2 - temp1;
02557         if (len <= 0) return NULL;
02558         temp3 = (char*)SMB_MALLOC(len);
02559         if (temp3 == NULL) {
02560                 DEBUG(1,("Malloc failure in sstring_sub\n"));
02561                 return NULL;
02562         }
02563         memcpy(temp3, temp1+1, len-1);
02564         temp3[len-1] = '\0';
02565         return temp3;
02566 }
02567 
02568 /********************************************************************
02569  Check a string for any occurrences of a specified list of invalid
02570  characters.
02571 ********************************************************************/
02572 
02573 BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len )
02574 {
02575         int i;
02576 
02577         for ( i=0; i<max_len && name[i]; i++ ) {
02578                 /* fail if strchr_m() finds one of the invalid characters */
02579                 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
02580                         return False;
02581                 }
02582         }
02583 
02584         return True;
02585 }
02586 
02587 
02588 /**
02589 return the number of bytes occupied by a buffer in ASCII format
02590 the result includes the null termination
02591 limited by 'n' bytes
02592 **/
02593 size_t ascii_len_n(const char *src, size_t n)
02594 {
02595         size_t len;
02596 
02597         len = strnlen(src, n);
02598         if (len+1 <= n) {
02599                 len += 1;
02600         }
02601 
02602         return len;
02603 }
02604 
02605 /**
02606 return the number of bytes occupied by a buffer in CH_UTF16 format
02607 the result includes the null termination
02608 **/
02609 size_t utf16_len(const void *buf)
02610 {
02611         size_t len;
02612 
02613         for (len = 0; SVAL(buf,len); len += 2) ;
02614 
02615         return len + 2;
02616 }
02617 
02618 /**
02619 return the number of bytes occupied by a buffer in CH_UTF16 format
02620 the result includes the null termination
02621 limited by 'n' bytes
02622 **/
02623 size_t utf16_len_n(const void *src, size_t n)
02624 {
02625         size_t len;
02626 
02627         for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
02628 
02629         if (len+2 <= n) {
02630                 len += 2;
02631         }
02632 
02633         return len;
02634 }
02635 
02636 /*******************************************************************
02637  Add a shell escape character '\' to any character not in a known list
02638  of characters. UNIX charset format.
02639 *******************************************************************/
02640 
02641 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
02642 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
02643 
02644 char *escape_shell_string(const char *src)
02645 {
02646         size_t srclen = strlen(src);
02647         char *ret = SMB_MALLOC((srclen * 2) + 1);
02648         char *dest = ret;
02649         BOOL in_s_quote = False;
02650         BOOL in_d_quote = False;
02651         BOOL next_escaped = False;
02652 
02653         if (!ret) {
02654                 return NULL;
02655         }
02656 
02657         while (*src) {
02658                 size_t c_size;
02659                 codepoint_t c = next_codepoint(src, &c_size);
02660 
02661                 if (c == INVALID_CODEPOINT) {
02662                         SAFE_FREE(ret);
02663                         return NULL;
02664                 }
02665 
02666                 if (c_size > 1) {
02667                         memcpy(dest, src, c_size);
02668                         src += c_size;
02669                         dest += c_size;
02670                         next_escaped = False;
02671                         continue;
02672                 }
02673 
02674                 /*
02675                  * Deal with backslash escaped state.
02676                  * This only lasts for one character.
02677                  */
02678 
02679                 if (next_escaped) {
02680                         *dest++ = *src++;
02681                         next_escaped = False;
02682                         continue;
02683                 }
02684 
02685                 /*
02686                  * Deal with single quote state. The
02687                  * only thing we care about is exiting
02688                  * this state.
02689                  */
02690 
02691                 if (in_s_quote) {
02692                         if (*src == '\'') {
02693                                 in_s_quote = False;
02694                         }
02695                         *dest++ = *src++;
02696                         continue;
02697                 }
02698 
02699                 /* 
02700                  * Deal with double quote state. The most
02701                  * complex state. We must cope with \, meaning
02702                  * possibly escape next char (depending what it
02703                  * is), ", meaning exit this state, and possibly
02704                  * add an \ escape to any unprotected character
02705                  * (listed in INSIDE_DQUOTE_LIST).
02706                  */
02707 
02708                 if (in_d_quote) {
02709                         if (*src == '\\') {
02710                                 /* 
02711                                  * Next character might be escaped.
02712                                  * We have to peek. Inside double
02713                                  * quotes only INSIDE_DQUOTE_LIST
02714                                  * characters are escaped by a \.
02715                                  */
02716 
02717                                 char nextchar;
02718 
02719                                 c = next_codepoint(&src[1], &c_size);
02720                                 if (c == INVALID_CODEPOINT) {
02721                                         SAFE_FREE(ret);
02722                                         return NULL;
02723                                 }
02724                                 if (c_size > 1) {
02725                                         /*
02726                                          * Don't escape the next char.
02727                                          * Just copy the \.
02728                                          */
02729                                         *dest++ = *src++;
02730                                         continue;
02731                                 }
02732 
02733                                 nextchar = src[1];
02734 
02735                                 if (nextchar && strchr(INSIDE_DQUOTE_LIST, (int)nextchar)) {
02736                                         next_escaped = True;
02737                                 }
02738                                 *dest++ = *src++;
02739                                 continue;
02740                         }
02741 
02742                         if (*src == '\"') {
02743                                 /* Exit double quote state. */
02744                                 in_d_quote = False;
02745                                 *dest++ = *src++;
02746                                 continue;
02747                         }
02748 
02749                         /*
02750                          * We know the character isn't \ or ",
02751                          * so escape it if it's any of the other
02752                          * possible unprotected characters.
02753                          */
02754 
02755                         if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
02756                                 *dest++ = '\\';
02757                         }
02758                         *dest++ = *src++;
02759                         continue;
02760                 }
02761 
02762                 /* 
02763                  * From here to the end of the loop we're
02764                  * not in the single or double quote state.
02765                  */
02766 
02767                 if (*src == '\\') {
02768                         /* Next character must be escaped. */
02769                         next_escaped = True;
02770                         *dest++ = *src++;
02771                         continue;
02772                 }
02773 
02774                 if (*src == '\'') {
02775                         /* Go into single quote state. */
02776                         in_s_quote = True;
02777                         *dest++ = *src++;
02778                         continue;
02779                 }
02780 
02781                 if (*src == '\"') {
02782                         /* Go into double quote state. */
02783                         in_d_quote = True;
02784                         *dest++ = *src++;
02785                         continue;
02786                 }
02787 
02788                 /* Check if we need to escape the character. */
02789 
02790                 if (!strchr(INCLUDE_LIST, (int)*src)) {
02791                         *dest++ = '\\';
02792                 }
02793                 *dest++ = *src++;
02794         }
02795         *dest++ = '\0';
02796         return ret;
02797 }

Sambaに対してSat Aug 29 21:23:00 2009に生成されました。  doxygen 1.4.7