1998-11-05 19:48:35 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-11-05 19:48:35 +03:00
Samba utility functions
2003-03-19 00:21:21 +03:00
2001-07-04 11:15:53 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 2001
2002-01-25 03:35:14 +03:00
Copyright ( C ) Simo Sorce 2001 - 2002
2003-03-19 00:21:21 +03:00
Copyright ( C ) Martin Pool 2003
1998-11-05 19:48:35 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2003-03-19 00:21:21 +03:00
/**
* @ file
* @ brief String utilities .
* */
2003-03-18 04:48:11 +03:00
2003-02-24 06:09:08 +03:00
/**
* Get the next token from a string , return False if none found .
* Handles double - quotes .
*
* Based on a routine by GJC @ VILLAGE . COM .
* Extensively modified by Andrew . Tridgell @ anu . edu . au
* */
2003-08-15 08:42:05 +04:00
BOOL next_token ( const char * * ptr , char * buff , const char * sep , size_t bufsize )
1998-11-05 19:48:35 +03:00
{
2003-08-15 06:25:41 +04:00
char * s ;
2003-06-25 21:41:05 +04:00
char * pbuf ;
2001-06-21 13:10:42 +04:00
BOOL quoted ;
size_t len = 1 ;
2002-10-02 23:12:14 +04:00
if ( ! ptr )
return ( False ) ;
2001-06-21 13:10:42 +04:00
2005-03-31 09:06:04 +04:00
s = CONST_DISCARD ( char * , * ptr ) ;
2001-06-21 13:10:42 +04:00
/* default to simple separators */
2002-10-02 23:12:14 +04:00
if ( ! sep )
sep = " \t \n \r " ;
2001-06-21 13:10:42 +04:00
/* find the first non sep char */
2002-10-02 23:12:14 +04:00
while ( * s & & strchr_m ( sep , * s ) )
s + + ;
2001-06-21 13:10:42 +04:00
/* nothing left? */
2002-10-02 23:12:14 +04:00
if ( ! * s )
return ( False ) ;
2001-06-21 13:10:42 +04:00
/* copy over the token */
2003-06-25 21:41:05 +04:00
pbuf = buff ;
2001-07-04 11:36:09 +04:00
for ( quoted = False ; len < bufsize & & * s & & ( quoted | | ! strchr_m ( sep , * s ) ) ; s + + ) {
2004-06-09 00:10:26 +04:00
if ( * s = = ' \" ' ) {
2001-06-21 13:10:42 +04:00
quoted = ! quoted ;
} else {
len + + ;
2003-06-25 21:41:05 +04:00
* pbuf + + = * s ;
2001-06-21 13:10:42 +04:00
}
}
* ptr = ( * s ) ? s + 1 : s ;
2003-06-25 21:41:05 +04:00
* pbuf = 0 ;
2001-06-21 13:10:42 +04:00
return ( True ) ;
}
1998-11-05 19:48:35 +03:00
2003-02-24 06:09:08 +03:00
/**
2001-06-21 13:10:42 +04:00
This is like next_token but is not re - entrant and " remembers " the first
parameter so you can pass NULL . This is useful for user interface code
but beware the fact that it is not re - entrant !
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2003-08-15 08:42:05 +04:00
static const char * last_ptr = NULL ;
1998-11-05 19:48:35 +03:00
2003-08-15 08:42:05 +04:00
BOOL next_token_nr ( const char * * ptr , char * buff , const char * sep , size_t bufsize )
2001-06-21 13:10:42 +04:00
{
BOOL ret ;
2002-10-02 23:12:14 +04:00
if ( ! ptr )
2003-08-15 08:42:05 +04:00
ptr = & last_ptr ;
1998-11-05 19:48:35 +03:00
2001-06-21 13:10:42 +04:00
ret = next_token ( ptr , buff , sep , bufsize ) ;
last_ptr = * ptr ;
return ret ;
}
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
static uint16 tmpbuf [ sizeof ( pstring ) ] ;
2001-06-21 13:10:42 +04:00
void set_first_token ( char * ptr )
{
last_ptr = ptr ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Convert list of tokens to array ; dependent on above routine .
Uses last_ptr from above - bit of a hack .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
char * * toktocliplist ( int * ctok , const char * sep )
1998-11-05 19:48:35 +03:00
{
2005-03-31 09:06:04 +04:00
char * s = CONST_DISCARD ( char * , last_ptr ) ;
2001-06-21 13:10:42 +04:00
int ictok = 0 ;
char * * ret , * * iret ;
2002-10-02 23:12:14 +04:00
if ( ! sep )
sep = " \t \n \r " ;
2001-06-21 13:10:42 +04:00
2002-10-02 23:12:14 +04:00
while ( * s & & strchr_m ( sep , * s ) )
s + + ;
2001-06-21 13:10:42 +04:00
/* nothing left? */
2002-10-02 23:12:14 +04:00
if ( ! * s )
return ( NULL ) ;
2001-06-21 13:10:42 +04:00
do {
ictok + + ;
2002-10-02 23:12:14 +04:00
while ( * s & & ( ! strchr_m ( sep , * s ) ) )
s + + ;
while ( * s & & strchr_m ( sep , * s ) )
* s + + = 0 ;
2001-06-21 13:10:42 +04:00
} while ( * s ) ;
* ctok = ictok ;
2005-03-31 09:06:04 +04:00
s = CONST_DISCARD ( char * , last_ptr ) ;
2001-06-21 13:10:42 +04:00
2004-12-07 21:25:53 +03:00
if ( ! ( ret = iret = SMB_MALLOC_ARRAY ( char * , ictok + 1 ) ) )
2002-10-02 23:12:14 +04:00
return NULL ;
2001-06-21 13:10:42 +04:00
while ( ictok - - ) {
* iret + + = s ;
2004-09-16 02:49:23 +04:00
if ( ictok > 0 ) {
while ( * s + + )
;
while ( ! * s )
s + + ;
}
2001-06-21 13:10:42 +04:00
}
2004-09-16 02:49:23 +04:00
ret [ * ctok ] = NULL ;
2001-06-21 13:10:42 +04:00
return ret ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2003-03-19 00:21:21 +03:00
* Case insensitive string compararison .
*
* iconv does not directly give us a way to compare strings in
* arbitrary unix character sets - - all we can is convert and then
* compare . This is expensive .
*
* As an optimization , we do a first pass that considers only the
* prefix of the strings that is entirely 7 - bit . Within this , we
* check whether they have the same value .
*
* Hopefully this will often give the answer without needing to copy .
* In particular it should speed comparisons to literal ascii strings
* or comparisons of strings that are " obviously " different .
*
* If we find a non - ascii character we fall back to converting via
* iconv .
*
* This should never be slower than convering the whole thing , and
* often faster .
*
* A different optimization would be to compare for bitwise equality
* in the binary encoding . ( It would be possible thought hairy to do
* both simultaneously . ) But in that case if they turn out to be
* different , we ' d need to restart the whole thing .
*
* Even better is to implement strcasecmp for each encoding and use a
* function pointer .
* */
1998-11-12 09:12:19 +03:00
int StrCaseCmp ( const char * s , const char * t )
1998-11-05 19:48:35 +03:00
{
2003-03-19 00:21:21 +03:00
const char * ps , * pt ;
2003-07-19 04:36:43 +04:00
size_t size ;
smb_ucs2_t * buffer_s , * buffer_t ;
int ret ;
2003-03-19 00:21:21 +03:00
for ( ps = s , pt = t ; ; ps + + , pt + + ) {
char us , ut ;
if ( ! * ps & & ! * pt )
return 0 ; /* both ended */
else if ( ! * ps )
return - 1 ; /* s is a prefix */
else if ( ! * pt )
return + 1 ; /* t is a prefix */
else if ( ( * ps & 0x80 ) | | ( * pt & 0x80 ) )
/* not ascii anymore, do it the hard way from here on in */
break ;
us = toupper ( * ps ) ;
ut = toupper ( * pt ) ;
if ( us = = ut )
continue ;
else if ( us < ut )
return - 1 ;
else if ( us > ut )
return + 1 ;
}
2003-07-27 06:40:06 +04:00
size = push_ucs2_allocate ( & buffer_s , s ) ;
if ( size = = ( size_t ) - 1 ) {
2003-07-19 04:36:43 +04:00
return strcmp ( s , t ) ;
/* Not quite the right answer, but finding the right one
under this failure case is expensive , and it ' s pretty close */
}
2003-07-27 06:40:06 +04:00
size = push_ucs2_allocate ( & buffer_t , t ) ;
if ( size = = ( size_t ) - 1 ) {
2003-07-19 04:36:43 +04:00
SAFE_FREE ( buffer_s ) ;
return strcmp ( s , t ) ;
/* Not quite the right answer, but finding the right one
under this failure case is expensive , and it ' s pretty close */
}
ret = strcasecmp_w ( buffer_s , buffer_t ) ;
SAFE_FREE ( buffer_s ) ;
SAFE_FREE ( buffer_t ) ;
return ret ;
1998-11-05 19:48:35 +03:00
}
2003-03-19 00:21:21 +03:00
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Case insensitive string compararison , length limited .
2003-02-24 06:09:08 +03:00
* */
1998-11-17 23:50:07 +03:00
int StrnCaseCmp ( const char * s , const char * t , size_t n )
1998-11-05 19:48:35 +03:00
{
2001-10-03 16:18:20 +04:00
pstring buf1 , buf2 ;
unix_strupper ( s , strlen ( s ) + 1 , buf1 , sizeof ( buf1 ) ) ;
unix_strupper ( t , strlen ( t ) + 1 , buf2 , sizeof ( buf2 ) ) ;
return strncmp ( buf1 , buf2 , n ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2003-03-18 01:42:01 +03:00
* Compare 2 strings .
*
* @ note The comparison is case - insensitive .
* */
1998-11-12 09:12:19 +03:00
BOOL strequal ( const char * s1 , const char * s2 )
1998-11-05 19:48:35 +03:00
{
2002-10-02 23:12:14 +04:00
if ( s1 = = s2 )
return ( True ) ;
if ( ! s1 | | ! s2 )
return ( False ) ;
1998-11-05 19:48:35 +03:00
2001-07-06 15:50:45 +04:00
return ( StrCaseCmp ( s1 , s2 ) = = 0 ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2003-03-18 01:42:01 +03:00
* Compare 2 strings up to and including the nth char .
*
* @ note The comparison is case - insensitive .
* */
1998-11-17 23:50:07 +03:00
BOOL strnequal ( const char * s1 , const char * s2 , size_t n )
1998-11-05 19:48:35 +03:00
{
2002-10-02 23:12:14 +04:00
if ( s1 = = s2 )
return ( True ) ;
if ( ! s1 | | ! s2 | | ! n )
return ( False ) ;
1998-11-05 19:48:35 +03:00
return ( StrnCaseCmp ( s1 , s2 , n ) = = 0 ) ;
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Compare 2 strings ( case sensitive ) .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-17 23:50:07 +03:00
BOOL strcsequal ( const char * s1 , const char * s2 )
1998-11-05 19:48:35 +03:00
{
2002-10-02 23:12:14 +04:00
if ( s1 = = s2 )
return ( True ) ;
if ( ! s1 | | ! s2 )
return ( False ) ;
1998-11-05 19:48:35 +03:00
return ( strcmp ( s1 , s2 ) = = 0 ) ;
}
2003-02-24 06:09:08 +03:00
/**
2000-08-29 18:33:39 +04:00
Do a case - insensitive , whitespace - ignoring string compare .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2001-10-31 09:22:19 +03:00
int strwicmp ( const char * psz1 , const char * psz2 )
2000-08-29 18:33:39 +04:00
{
/* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
/* appropriate value. */
if ( psz1 = = psz2 )
return ( 0 ) ;
else if ( psz1 = = NULL )
return ( - 1 ) ;
else if ( psz2 = = NULL )
return ( 1 ) ;
/* sync the strings on first non-whitespace */
2002-10-02 23:12:14 +04:00
while ( 1 ) {
2001-12-20 13:02:30 +03:00
while ( isspace ( ( int ) * psz1 ) )
2000-08-29 18:33:39 +04:00
psz1 + + ;
2001-12-20 13:02:30 +03:00
while ( isspace ( ( int ) * psz2 ) )
2000-08-29 18:33:39 +04:00
psz2 + + ;
if ( toupper ( * psz1 ) ! = toupper ( * psz2 ) | | * psz1 = = ' \0 '
| | * psz2 = = ' \0 ' )
break ;
psz1 + + ;
psz2 + + ;
}
return ( * psz1 - * psz2 ) ;
}
1998-11-05 19:48:35 +03:00
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Convert a string to upper case , but don ' t modify it .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
char * strupper_static ( const char * s )
{
static pstring str ;
pstrcpy ( str , s ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( str ) ;
2002-08-17 21:00:51 +04:00
return str ;
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Convert a string to " normal " form .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2004-05-07 22:37:47 +04:00
void strnorm ( char * s , int case_default )
1998-11-05 19:48:35 +03:00
{
2002-10-02 23:12:14 +04:00
if ( case_default = = CASE_UPPER )
2003-07-03 23:11:31 +04:00
strupper_m ( s ) ;
2002-10-02 23:12:14 +04:00
else
2003-07-03 23:11:31 +04:00
strlower_m ( s ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Check if a string is in " normal " case .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2004-05-07 22:37:47 +04:00
BOOL strisnormal ( const char * s , int case_default )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
if ( case_default = = CASE_UPPER )
return ( ! strhaslower ( s ) ) ;
return ( ! strhasupper ( s ) ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
String replace .
NOTE : oldc and newc must be 7 bit characters
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2005-03-22 19:39:09 +03:00
void string_replace ( pstring s , char oldc , char newc )
1998-11-05 19:48:35 +03:00
{
2005-03-22 19:39:09 +03:00
char * p ;
2003-09-05 23:59:55 +04:00
/* this is quite a common operation, so we want it to be
fast . We optimise for the ascii case , knowing that all our
supported multi - byte character sets are ascii - compatible
( ie . they match for the first 128 chars ) */
2005-03-22 19:39:09 +03:00
for ( p = s ; * p ; p + + ) {
2003-09-05 23:59:55 +04:00
if ( * p & 0x80 ) /* mb string - slow path. */
break ;
if ( * p = = oldc )
* p = newc ;
}
if ( ! * p )
return ;
/* Slow (mb) path. */
2003-09-14 02:41:21 +04:00
# ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
/* With compose characters we must restart from the beginning. JRA. */
p = s ;
# endif
2003-09-05 23:59:55 +04:00
push_ucs2 ( NULL , tmpbuf , p , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
2001-11-04 21:26:53 +03:00
string_replace_w ( tmpbuf , UCS2_CHAR ( oldc ) , UCS2_CHAR ( newc ) ) ;
2003-09-05 23:59:55 +04:00
pull_ucs2 ( NULL , p , tmpbuf , - 1 , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Skip past some strings in a buffer .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-26 00:17:20 +03:00
char * skip_string ( char * buf , size_t n )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
while ( n - - )
buf + = strlen ( buf ) + 1 ;
return ( buf ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
1998-11-05 19:48:35 +03:00
Count the number of characters in a string . Normally this will
be the same as the number of bytes in a string for single byte strings ,
but will be different for multibyte .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-17 23:50:07 +03:00
size_t str_charnum ( const char * s )
1998-11-05 19:48:35 +03:00
{
2003-01-15 21:57:41 +03:00
uint16 tmpbuf2 [ sizeof ( pstring ) ] ;
push_ucs2 ( NULL , tmpbuf2 , s , sizeof ( tmpbuf2 ) , STR_TERMINATE ) ;
return strlen_w ( tmpbuf2 ) ;
}
2003-02-24 06:09:08 +03:00
/**
2003-01-15 21:57:41 +03:00
Count the number of characters in a string . Normally this will
be the same as the number of bytes in a string for single byte strings ,
but will be different for multibyte .
2003-02-24 06:09:08 +03:00
* */
2003-01-15 21:57:41 +03:00
size_t str_ascii_charnum ( const char * s )
{
pstring tmpbuf2 ;
push_ascii ( tmpbuf2 , s , sizeof ( tmpbuf2 ) , STR_TERMINATE ) ;
return strlen ( tmpbuf2 ) ;
1998-11-05 19:48:35 +03:00
}
2003-09-05 23:59:55 +04:00
BOOL trim_char ( char * s , char cfront , char cback )
{
BOOL ret = False ;
char * ep ;
char * fp = s ;
/* Ignore null or empty strings. */
if ( ! s | | ( s [ 0 ] = = ' \0 ' ) )
return False ;
if ( cfront ) {
while ( * fp & & * fp = = cfront )
fp + + ;
if ( ! * fp ) {
/* We ate the string. */
s [ 0 ] = ' \0 ' ;
return True ;
}
if ( fp ! = s )
ret = True ;
}
ep = fp + strlen ( fp ) - 1 ;
if ( cback ) {
/* Attempt ascii only. Bail for mb strings. */
while ( ( ep > = fp ) & & ( * ep = = cback ) ) {
ret = True ;
if ( ( ep > fp ) & & ( ( ( unsigned char ) ep [ - 1 ] ) & 0x80 ) ) {
/* Could be mb... bail back to tim_string. */
char fs [ 2 ] , bs [ 2 ] ;
if ( cfront ) {
fs [ 0 ] = cfront ;
fs [ 1 ] = ' \0 ' ;
}
bs [ 0 ] = cback ;
bs [ 1 ] = ' \0 ' ;
return trim_string ( s , cfront ? fs : NULL , bs ) ;
} else {
ep - - ;
}
}
if ( ep < fp ) {
/* We ate the string. */
s [ 0 ] = ' \0 ' ;
return True ;
}
}
ep [ 1 ] = ' \0 ' ;
memmove ( s , fp , ep - fp + 2 ) ;
return ret ;
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Trim the specified elements off the front and back of a string .
2003-02-24 06:09:08 +03:00
* */
1998-11-05 19:48:35 +03:00
1998-11-17 23:50:07 +03:00
BOOL trim_string ( char * s , const char * front , const char * back )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
BOOL ret = False ;
size_t front_len ;
size_t back_len ;
size_t len ;
2001-04-16 02:21:04 +04:00
2001-05-11 03:17:46 +04:00
/* Ignore null or empty strings. */
2001-07-04 11:15:53 +04:00
if ( ! s | | ( s [ 0 ] = = ' \0 ' ) )
return False ;
2001-05-11 03:17:46 +04:00
2001-07-04 11:15:53 +04:00
front_len = front ? strlen ( front ) : 0 ;
back_len = back ? strlen ( back ) : 0 ;
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
len = strlen ( s ) ;
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
if ( front_len ) {
while ( len & & strncmp ( s , front , front_len ) = = 0 ) {
2003-09-03 04:56:43 +04:00
/* Must use memmove here as src & dest can
* easily overlap . Found by valgrind . JRA . */
memmove ( s , s + front_len , ( len - front_len ) + 1 ) ;
2001-07-04 11:15:53 +04:00
len - = front_len ;
ret = True ;
}
}
if ( back_len ) {
2002-08-17 21:00:51 +04:00
while ( ( len > = back_len ) & & strncmp ( s + len - back_len , back , back_len ) = = 0 ) {
2001-07-04 11:15:53 +04:00
s [ len - back_len ] = ' \0 ' ;
len - = back_len ;
ret = True ;
}
}
return ret ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Does a string have any uppercase chars in it ?
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-17 23:50:07 +03:00
BOOL strhasupper ( const char * s )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
smb_ucs2_t * ptr ;
push_ucs2 ( NULL , tmpbuf , s , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
for ( ptr = tmpbuf ; * ptr ; ptr + + )
2002-10-02 23:12:14 +04:00
if ( isupper_w ( * ptr ) )
return True ;
2001-07-04 11:15:53 +04:00
return ( False ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Does a string have any lowercase chars in it ?
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-17 23:50:07 +03:00
BOOL strhaslower ( const char * s )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
smb_ucs2_t * ptr ;
push_ucs2 ( NULL , tmpbuf , s , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
for ( ptr = tmpbuf ; * ptr ; ptr + + )
2002-10-02 23:12:14 +04:00
if ( islower_w ( * ptr ) )
return True ;
2001-07-04 11:15:53 +04:00
return ( False ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Find the number of ' c ' chars in a string
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-17 23:50:07 +03:00
size_t count_chars ( const char * s , char c )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
smb_ucs2_t * ptr ;
int count ;
2004-02-14 01:34:29 +03:00
smb_ucs2_t * alloc_tmpbuf = NULL ;
2004-02-14 01:06:25 +03:00
if ( push_ucs2_allocate ( & alloc_tmpbuf , s ) = = ( size_t ) - 1 ) {
return 0 ;
}
for ( count = 0 , ptr = alloc_tmpbuf ; * ptr ; ptr + + )
2002-10-02 23:12:14 +04:00
if ( * ptr = = UCS2_CHAR ( c ) )
count + + ;
2004-02-14 01:06:25 +03:00
2004-02-14 01:34:29 +03:00
SAFE_FREE ( alloc_tmpbuf ) ;
2001-07-04 11:15:53 +04:00
return ( count ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Safe string copy into a known length string . maxlength does not
include the terminating zero .
2003-02-24 06:09:08 +03:00
* */
1999-12-13 16:27:58 +03:00
2003-03-18 04:48:11 +03:00
char * safe_strcpy_fn ( const char * fn , int line , char * dest , const char * src , size_t maxlength )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
size_t len ;
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
if ( ! dest ) {
2003-11-20 01:56:02 +03:00
DEBUG ( 0 , ( " ERROR: NULL dest in safe_strcpy, called from [%s][%d] \n " , fn , line ) ) ;
2001-07-04 11:15:53 +04:00
return NULL ;
}
1998-11-05 19:48:35 +03:00
2003-09-04 05:12:39 +04:00
# ifdef DEVELOPER
2003-03-18 04:48:11 +03:00
clobber_region ( fn , line , dest , maxlength + 1 ) ;
2003-09-04 05:12:39 +04:00
# endif
2003-02-24 06:09:08 +03:00
2001-07-04 11:15:53 +04:00
if ( ! src ) {
* dest = 0 ;
return dest ;
}
1998-11-05 19:48:35 +03:00
2003-03-19 23:50:56 +03:00
len = strnlen ( src , maxlength + 1 ) ;
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
if ( len > maxlength ) {
2003-11-03 17:34:25 +03:00
DEBUG ( 0 , ( " ERROR: string overflow by %lu (%lu - %lu) in safe_strcpy [%.50s] \n " ,
( unsigned long ) ( len - maxlength ) , ( unsigned long ) len ,
( unsigned long ) maxlength , src ) ) ;
2001-07-04 11:15:53 +04:00
len = maxlength ;
}
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
memmove ( dest , src , len ) ;
dest [ len ] = 0 ;
return dest ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Safe string cat into a string . maxlength does not
include the terminating zero .
2003-02-24 06:09:08 +03:00
* */
2003-03-18 04:48:11 +03:00
char * safe_strcat_fn ( const char * fn , int line , char * dest , const char * src , size_t maxlength )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
size_t src_len , dest_len ;
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
if ( ! dest ) {
2003-11-20 01:56:02 +03:00
DEBUG ( 0 , ( " ERROR: NULL dest in safe_strcat, called from [%s][%d] \n " , fn , line ) ) ;
2001-07-04 11:15:53 +04:00
return NULL ;
}
1998-11-05 19:48:35 +03:00
2002-10-02 23:12:14 +04:00
if ( ! src )
2001-07-04 11:15:53 +04:00
return dest ;
2003-03-19 23:50:56 +03:00
src_len = strnlen ( src , maxlength + 1 ) ;
dest_len = strnlen ( dest , maxlength + 1 ) ;
2003-02-07 07:11:36 +03:00
2003-09-04 05:12:39 +04:00
# ifdef DEVELOPER
2003-03-18 04:48:11 +03:00
clobber_region ( fn , line , dest + dest_len , maxlength + 1 - dest_len ) ;
2003-09-04 05:12:39 +04:00
# endif
2003-03-18 04:48:11 +03:00
2001-07-04 11:15:53 +04:00
if ( src_len + dest_len > maxlength ) {
DEBUG ( 0 , ( " ERROR: string overflow by %d in safe_strcat [%.50s] \n " ,
( int ) ( src_len + dest_len - maxlength ) , src ) ) ;
2003-02-07 07:11:36 +03:00
if ( maxlength > dest_len ) {
memcpy ( & dest [ dest_len ] , src , maxlength - dest_len ) ;
}
dest [ maxlength ] = 0 ;
return NULL ;
2001-07-04 11:15:53 +04:00
}
2003-03-18 04:48:11 +03:00
2001-07-04 11:15:53 +04:00
memcpy ( & dest [ dest_len ] , src , src_len ) ;
dest [ dest_len + src_len ] = 0 ;
return dest ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
1999-12-13 16:27:58 +03:00
Paranoid strcpy into a buffer of given length ( includes terminating
2001-06-23 11:22:16 +04:00
zero . Strips out all but ' a - Z0 - 9 ' and the character in other_safe_chars
and replaces with ' _ ' . Deliberately does * NOT * check for multibyte
characters . Don ' t change it !
2003-02-24 06:09:08 +03:00
* */
2003-03-18 04:48:11 +03:00
char * alpha_strcpy_fn ( const char * fn , int line , char * dest , const char * src , const char * other_safe_chars , size_t maxlength )
1998-11-05 19:48:35 +03:00
{
1999-12-13 16:27:58 +03:00
size_t len , i ;
1998-11-05 19:48:35 +03:00
2003-09-04 05:12:39 +04:00
# ifdef DEVELOPER
2003-03-18 04:48:11 +03:00
clobber_region ( fn , line , dest , maxlength ) ;
2003-09-04 05:12:39 +04:00
# endif
2003-03-18 04:48:11 +03:00
1999-12-13 16:27:58 +03:00
if ( ! dest ) {
2003-11-20 01:56:02 +03:00
DEBUG ( 0 , ( " ERROR: NULL dest in alpha_strcpy, called from [%s][%d] \n " , fn , line ) ) ;
1999-12-13 16:27:58 +03:00
return NULL ;
}
1998-11-05 19:48:35 +03:00
1999-12-13 16:27:58 +03:00
if ( ! src ) {
* dest = 0 ;
return dest ;
}
len = strlen ( src ) ;
if ( len > = maxlength )
len = maxlength - 1 ;
2001-06-23 11:22:16 +04:00
if ( ! other_safe_chars )
other_safe_chars = " " ;
1999-12-13 16:27:58 +03:00
for ( i = 0 ; i < len ; i + + ) {
int val = ( src [ i ] & 0xff ) ;
2002-10-01 22:26:00 +04:00
if ( isupper ( val ) | | islower ( val ) | | isdigit ( val ) | | strchr_m ( other_safe_chars , val ) )
1999-12-13 16:27:58 +03:00
dest [ i ] = src [ i ] ;
else
dest [ i ] = ' _ ' ;
}
dest [ i ] = ' \0 ' ;
return dest ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
1999-12-13 16:27:58 +03:00
Like strncpy but always null terminates . Make sure there is room !
The variable n should always be one less than the available size .
2003-02-24 06:09:08 +03:00
* */
2003-03-18 04:48:11 +03:00
char * StrnCpy_fn ( const char * fn , int line , char * dest , const char * src , size_t n )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
char * d = dest ;
2003-03-18 04:48:11 +03:00
2003-09-04 05:12:39 +04:00
# ifdef DEVELOPER
2003-03-18 04:48:11 +03:00
clobber_region ( fn , line , dest , n + 1 ) ;
2003-09-04 05:12:39 +04:00
# endif
2003-03-18 04:48:11 +03:00
2003-11-18 22:15:29 +03:00
if ( ! dest ) {
2003-11-20 01:56:02 +03:00
DEBUG ( 0 , ( " ERROR: NULL dest in StrnCpy, called from [%s][%d] \n " , fn , line ) ) ;
2002-10-02 23:12:14 +04:00
return ( NULL ) ;
2003-11-18 22:15:29 +03:00
}
2001-07-04 11:15:53 +04:00
if ( ! src ) {
* dest = 0 ;
return ( dest ) ;
}
2003-03-24 12:54:13 +03:00
while ( n - - & & ( * d = * src ) ) {
d + + ;
src + + ;
}
2001-07-04 11:15:53 +04:00
* d = 0 ;
return ( dest ) ;
1998-11-05 19:48:35 +03:00
}
2003-03-18 04:48:11 +03:00
#if 0
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Like strncpy but copies up to the character marker . always null terminates .
returns a pointer to the character marker in the source string ( src ) .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2003-03-18 04:48:11 +03:00
static char * strncpyn ( char * dest , const char * src , size_t n , char c )
1998-11-05 19:48:35 +03:00
{
char * p ;
1998-11-17 23:50:07 +03:00
size_t str_len ;
1998-11-05 19:48:35 +03:00
2003-09-04 05:12:39 +04:00
# ifdef DEVELOPER
2003-03-18 04:48:11 +03:00
clobber_region ( dest , n + 1 ) ;
2003-09-04 05:12:39 +04:00
# endif
2001-07-04 11:36:09 +04:00
p = strchr_m ( src , c ) ;
2002-10-02 23:12:14 +04:00
if ( p = = NULL ) {
1998-11-05 19:48:35 +03:00
DEBUG ( 5 , ( " strncpyn: separator character (%c) not found \n " , c ) ) ;
return NULL ;
}
str_len = PTR_DIFF ( p , src ) ;
strncpy ( dest , src , MIN ( n , str_len ) ) ;
dest [ str_len ] = ' \0 ' ;
return p ;
}
2003-03-18 04:48:11 +03:00
# endif
1998-11-05 19:48:35 +03:00
2003-02-24 06:09:08 +03:00
/**
1998-11-10 22:05:00 +03:00
Routine to get hex characters and turn them into a 16 byte array .
the array can be variable length , and any non - hex - numeric
characters are skipped . " 0xnn " or " 0Xnn " is specially catered
for .
valid examples : " 0A5D15 " ; " 0x15, 0x49, 0xa2 " ; " 59 \t a9 \t e3 \n "
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-17 23:50:07 +03:00
size_t strhex_to_str ( char * p , size_t len , const char * strhex )
1998-11-10 22:05:00 +03:00
{
1998-11-17 23:50:07 +03:00
size_t i ;
size_t num_chars = 0 ;
1998-11-10 22:05:00 +03:00
unsigned char lonybble , hinybble ;
2003-01-03 11:28:12 +03:00
const char * hexchars = " 0123456789ABCDEF " ;
1998-11-10 22:05:00 +03:00
char * p1 = NULL , * p2 = NULL ;
2002-10-02 23:12:14 +04:00
for ( i = 0 ; i < len & & strhex [ i ] ! = 0 ; i + + ) {
if ( strnequal ( hexchars , " 0x " , 2 ) ) {
1998-11-10 22:05:00 +03:00
i + + ; /* skip two chars */
continue ;
}
2001-07-04 11:36:09 +04:00
if ( ! ( p1 = strchr_m ( hexchars , toupper ( strhex [ i ] ) ) ) )
1999-03-23 17:56:25 +03:00
break ;
1998-11-10 22:05:00 +03:00
i + + ; /* next hex digit */
2001-07-04 11:36:09 +04:00
if ( ! ( p2 = strchr_m ( hexchars , toupper ( strhex [ i ] ) ) ) )
1999-03-23 17:56:25 +03:00
break ;
1998-11-10 22:05:00 +03:00
/* get the two nybbles */
hinybble = PTR_DIFF ( p1 , hexchars ) ;
lonybble = PTR_DIFF ( p2 , hexchars ) ;
p [ num_chars ] = ( hinybble < < 4 ) | lonybble ;
num_chars + + ;
p1 = NULL ;
p2 = NULL ;
}
return num_chars ;
}
2004-04-07 13:27:50 +04:00
DATA_BLOB strhex_to_data_blob ( const char * strhex )
{
DATA_BLOB ret_blob = data_blob ( NULL , strlen ( strhex ) / 2 + 1 ) ;
2005-03-22 21:07:58 +03:00
ret_blob . length = strhex_to_str ( ( char * ) ret_blob . data ,
2004-04-07 13:27:50 +04:00
strlen ( strhex ) ,
strhex ) ;
return ret_blob ;
}
2003-03-24 12:54:13 +03:00
/**
* Routine to print a buffer as HEX digits , into an allocated string .
*/
void hex_encode ( const unsigned char * buff_in , size_t len , char * * out_hex_buffer )
{
int i ;
char * hex_buffer ;
2004-12-07 21:25:53 +03:00
* out_hex_buffer = SMB_XMALLOC_ARRAY ( char , ( len * 2 ) + 1 ) ;
2003-03-24 12:54:13 +03:00
hex_buffer = * out_hex_buffer ;
for ( i = 0 ; i < len ; i + + )
slprintf ( & hex_buffer [ i * 2 ] , 3 , " %02X " , buff_in [ i ] ) ;
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Check if a string is part of a list .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2005-03-22 18:45:38 +03:00
BOOL in_list ( const char * s , const char * list , BOOL casesensitive )
1998-11-05 19:48:35 +03:00
{
2002-10-02 23:12:14 +04:00
pstring tok ;
2002-11-13 02:20:50 +03:00
const char * p = list ;
2002-10-02 23:12:14 +04:00
if ( ! list )
return ( False ) ;
while ( next_token ( & p , tok , LIST_SEP , sizeof ( tok ) ) ) {
if ( casesensitive ) {
if ( strcmp ( tok , s ) = = 0 )
return ( True ) ;
} else {
if ( StrCaseCmp ( tok , s ) = = 0 )
return ( True ) ;
}
}
return ( False ) ;
1998-11-05 19:48:35 +03:00
}
/* this is used to prevent lots of mallocs of size 1 */
static char * null_string = NULL ;
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Set a string value , allocing the space for the string
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2000-01-16 14:07:11 +03:00
static BOOL string_init ( char * * dest , const char * src )
1998-11-05 19:48:35 +03:00
{
2002-10-02 23:12:14 +04:00
size_t l ;
if ( ! src )
src = " " ;
l = strlen ( src ) ;
if ( l = = 0 ) {
if ( ! null_string ) {
2004-12-07 21:25:53 +03:00
if ( ( null_string = ( char * ) SMB_MALLOC ( 1 ) ) = = NULL ) {
2002-10-02 23:12:14 +04:00
DEBUG ( 0 , ( " string_init: malloc fail for null_string. \n " ) ) ;
return False ;
}
* null_string = 0 ;
}
* dest = null_string ;
} else {
2004-12-07 21:25:53 +03:00
( * dest ) = SMB_STRDUP ( src ) ;
2002-10-02 23:12:14 +04:00
if ( ( * dest ) = = NULL ) {
DEBUG ( 0 , ( " Out of memory in string_init \n " ) ) ;
return False ;
}
}
return ( True ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Free a string value .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-05 19:48:35 +03:00
void string_free ( char * * s )
{
2002-10-02 23:12:14 +04:00
if ( ! s | | ! ( * s ) )
return ;
if ( * s = = null_string )
* s = NULL ;
SAFE_FREE ( * s ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Set a string value , deallocating any existing space , and allocing the space
for the string
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-17 23:50:07 +03:00
BOOL string_set ( char * * dest , const char * src )
1998-11-05 19:48:35 +03:00
{
2002-10-02 23:12:14 +04:00
string_free ( dest ) ;
return ( string_init ( dest , src ) ) ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Substitute a string for a pattern in another string . Make sure there is
enough room !
1998-11-05 19:48:35 +03:00
2002-10-02 23:12:14 +04:00
This routine looks for pattern in s and replaces it with
insert . It may do multiple replacements .
1998-11-05 19:48:35 +03:00
2002-10-02 23:12:14 +04:00
Any of " ; ' $ or ` in the insert string are replaced with _
if len = = 0 then the string cannot be extended . This is different from the old
use of len = = 0 which was for no length checks to be done .
2003-02-24 06:09:08 +03:00
* */
2002-07-15 14:35:28 +04:00
void string_sub ( char * s , const char * pattern , const char * insert , size_t len )
1998-11-05 19:48:35 +03:00
{
1998-11-23 06:36:10 +03:00
char * p ;
1999-12-13 16:27:58 +03:00
ssize_t ls , lp , li , i ;
1998-11-23 06:36:10 +03:00
2002-07-15 14:35:28 +04:00
if ( ! insert | | ! pattern | | ! * pattern | | ! s )
return ;
1998-11-23 06:36:10 +03:00
1999-12-13 16:27:58 +03:00
ls = ( ssize_t ) strlen ( s ) ;
lp = ( ssize_t ) strlen ( pattern ) ;
li = ( ssize_t ) strlen ( insert ) ;
1998-11-23 06:36:10 +03:00
2002-07-15 14:35:28 +04:00
if ( len = = 0 )
2002-08-17 21:00:51 +04:00
len = ls + 1 ; /* len is number of *bytes* */
2002-07-15 14:35:28 +04:00
2004-03-09 03:17:14 +03:00
while ( lp < = ls & & ( p = strstr_m ( s , pattern ) ) ) {
2002-07-15 14:35:28 +04:00
if ( ls + ( li - lp ) > = len ) {
1999-12-13 16:27:58 +03:00
DEBUG ( 0 , ( " ERROR: string overflow by %d in string_sub(%.50s, %d) \n " ,
( int ) ( ls + ( li - lp ) - len ) ,
pattern , ( int ) len ) ) ;
break ;
}
if ( li ! = lp ) {
memmove ( p + li , p + lp , strlen ( p + lp ) + 1 ) ;
}
1998-11-23 06:36:10 +03:00
for ( i = 0 ; i < li ; i + + ) {
switch ( insert [ i ] ) {
case ' ` ' :
case ' " ' :
1998-11-23 06:46:51 +03:00
case ' \' ' :
1998-11-23 06:36:10 +03:00
case ' ; ' :
1999-12-13 16:27:58 +03:00
case ' $ ' :
case ' % ' :
case ' \r ' :
case ' \n ' :
1998-11-23 06:36:10 +03:00
p [ i ] = ' _ ' ;
break ;
default :
p [ i ] = insert [ i ] ;
}
}
s = p + li ;
ls + = ( li - lp ) ;
}
}
1998-11-05 19:48:35 +03:00
1999-12-13 16:27:58 +03:00
void fstring_sub ( char * s , const char * pattern , const char * insert )
{
string_sub ( s , pattern , insert , sizeof ( fstring ) ) ;
}
void pstring_sub ( char * s , const char * pattern , const char * insert )
{
string_sub ( s , pattern , insert , sizeof ( pstring ) ) ;
}
1998-11-05 19:48:35 +03:00
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Similar to string_sub , but it will accept only allocated strings
and may realloc them so pay attention at what you pass on no
pointers inside strings , no pstrings or const may be passed
as string .
2003-02-24 06:09:08 +03:00
* */
2002-07-15 14:35:28 +04:00
char * realloc_string_sub ( char * string , const char * pattern , const char * insert )
{
char * p , * in ;
char * s ;
ssize_t ls , lp , li , ld , i ;
if ( ! insert | | ! pattern | | ! * pattern | | ! string | | ! * string )
return NULL ;
s = string ;
2004-12-07 21:25:53 +03:00
in = SMB_STRDUP ( insert ) ;
2002-07-15 14:35:28 +04:00
if ( ! in ) {
DEBUG ( 0 , ( " realloc_string_sub: out of memory! \n " ) ) ;
return NULL ;
}
ls = ( ssize_t ) strlen ( s ) ;
lp = ( ssize_t ) strlen ( pattern ) ;
li = ( ssize_t ) strlen ( insert ) ;
ld = li - lp ;
for ( i = 0 ; i < li ; i + + ) {
switch ( in [ i ] ) {
case ' ` ' :
case ' " ' :
case ' \' ' :
case ' ; ' :
case ' $ ' :
case ' % ' :
case ' \r ' :
case ' \n ' :
in [ i ] = ' _ ' ;
default :
/* ok */
break ;
}
}
2004-03-09 03:17:14 +03:00
while ( ( p = strstr_m ( s , pattern ) ) ) {
2002-07-15 14:35:28 +04:00
if ( ld > 0 ) {
2003-08-26 00:42:24 +04:00
int offset = PTR_DIFF ( s , string ) ;
2004-12-07 21:25:53 +03:00
char * t = SMB_REALLOC ( string , ls + ld + 1 ) ;
2002-07-15 14:35:28 +04:00
if ( ! t ) {
DEBUG ( 0 , ( " realloc_string_sub: out of memory! \n " ) ) ;
SAFE_FREE ( in ) ;
return NULL ;
}
string = t ;
2003-08-26 00:42:24 +04:00
p = t + offset + ( p - s ) ;
2002-07-15 14:35:28 +04:00
}
if ( li ! = lp ) {
memmove ( p + li , p + lp , strlen ( p + lp ) + 1 ) ;
}
memcpy ( p , in , li ) ;
s = p + li ;
ls + = ld ;
}
SAFE_FREE ( in ) ;
return string ;
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Similar to string_sub ( ) but allows for any character to be substituted .
Use with caution !
if len = = 0 then the string cannot be extended . This is different from the old
use of len = = 0 which was for no length checks to be done .
2003-02-24 06:09:08 +03:00
* */
2002-07-15 14:35:28 +04:00
1999-12-13 16:27:58 +03:00
void all_string_sub ( char * s , const char * pattern , const char * insert , size_t len )
1998-11-23 06:36:10 +03:00
{
char * p ;
1999-12-13 16:27:58 +03:00
ssize_t ls , lp , li ;
1998-11-05 19:48:35 +03:00
2002-07-15 14:35:28 +04:00
if ( ! insert | | ! pattern | | ! s )
return ;
1998-11-05 19:48:35 +03:00
1999-12-13 16:27:58 +03:00
ls = ( ssize_t ) strlen ( s ) ;
lp = ( ssize_t ) strlen ( pattern ) ;
li = ( ssize_t ) strlen ( insert ) ;
1998-11-23 06:36:10 +03:00
2002-07-15 14:35:28 +04:00
if ( ! * pattern )
return ;
if ( len = = 0 )
2002-08-17 21:00:51 +04:00
len = ls + 1 ; /* len is number of *bytes* */
1998-11-23 06:36:10 +03:00
2004-03-09 03:17:14 +03:00
while ( lp < = ls & & ( p = strstr_m ( s , pattern ) ) ) {
2002-07-15 14:35:28 +04:00
if ( ls + ( li - lp ) > = len ) {
1999-12-13 16:27:58 +03:00
DEBUG ( 0 , ( " ERROR: string overflow by %d in all_string_sub(%.50s, %d) \n " ,
( int ) ( ls + ( li - lp ) - len ) ,
pattern , ( int ) len ) ) ;
break ;
}
if ( li ! = lp ) {
memmove ( p + li , p + lp , strlen ( p + lp ) + 1 ) ;
}
1998-11-23 06:36:10 +03:00
memcpy ( p , insert , li ) ;
s = p + li ;
ls + = ( li - lp ) ;
}
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Similar to all_string_sub but for unicode strings .
Return a new allocated unicode string .
similar to string_sub ( ) but allows for any character to be substituted .
Use with caution !
2003-02-24 06:09:08 +03:00
* */
2001-11-04 21:26:53 +03:00
2003-03-18 04:48:11 +03:00
static smb_ucs2_t * all_string_sub_w ( const smb_ucs2_t * s , const smb_ucs2_t * pattern ,
2002-01-25 03:35:14 +03:00
const smb_ucs2_t * insert )
2001-11-04 21:26:53 +03:00
{
2002-08-17 21:00:51 +04:00
smb_ucs2_t * r , * rp ;
const smb_ucs2_t * sp ;
2001-11-18 19:12:11 +03:00
size_t lr , lp , li , lt ;
2001-11-04 21:26:53 +03:00
2002-10-02 23:12:14 +04:00
if ( ! insert | | ! pattern | | ! * pattern | | ! s )
return NULL ;
2001-11-04 21:26:53 +03:00
2001-11-18 19:12:11 +03:00
lt = ( size_t ) strlen_w ( s ) ;
lp = ( size_t ) strlen_w ( pattern ) ;
li = ( size_t ) strlen_w ( insert ) ;
2001-11-04 21:26:53 +03:00
if ( li > lp ) {
2002-08-17 21:00:51 +04:00
const smb_ucs2_t * st = s ;
2001-11-04 21:26:53 +03:00
int ld = li - lp ;
2001-11-18 19:12:11 +03:00
while ( ( sp = strstr_w ( st , pattern ) ) ) {
2001-11-04 21:26:53 +03:00
st = sp + lp ;
lt + = ld ;
}
}
2004-12-07 21:25:53 +03:00
r = rp = SMB_MALLOC_ARRAY ( smb_ucs2_t , lt + 1 ) ;
2001-11-04 21:26:53 +03:00
if ( ! r ) {
DEBUG ( 0 , ( " all_string_sub_w: out of memory! \n " ) ) ;
return NULL ;
}
2001-11-18 19:12:11 +03:00
while ( ( sp = strstr_w ( s , pattern ) ) ) {
memcpy ( rp , s , ( sp - s ) ) ;
rp + = ( ( sp - s ) / sizeof ( smb_ucs2_t ) ) ;
memcpy ( rp , insert , ( li * sizeof ( smb_ucs2_t ) ) ) ;
2001-11-04 21:26:53 +03:00
s = sp + lp ;
rp + = li ;
}
2001-11-18 19:12:11 +03:00
lr = ( ( rp - r ) / sizeof ( smb_ucs2_t ) ) ;
if ( lr < lt ) {
memcpy ( rp , s , ( ( lt - lr ) * sizeof ( smb_ucs2_t ) ) ) ;
rp + = ( lt - lr ) ;
}
2001-11-04 21:26:53 +03:00
* rp = 0 ;
return r ;
}
smb_ucs2_t * all_string_sub_wa ( smb_ucs2_t * s , const char * pattern ,
const char * insert )
{
wpstring p , i ;
2002-10-02 23:12:14 +04:00
if ( ! insert | | ! pattern | | ! s )
return NULL ;
2001-11-04 21:26:53 +03:00
push_ucs2 ( NULL , p , pattern , sizeof ( wpstring ) - 1 , STR_TERMINATE ) ;
push_ucs2 ( NULL , i , insert , sizeof ( wpstring ) - 1 , STR_TERMINATE ) ;
return all_string_sub_w ( s , p , i ) ;
}
2003-03-18 04:48:11 +03:00
#if 0
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Splits out the front and back at a separator .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2003-03-18 04:48:11 +03:00
static void split_at_last_component ( char * path , char * front , char sep , char * back )
1998-11-11 17:23:55 +03:00
{
2001-07-04 11:36:09 +04:00
char * p = strrchr_m ( path , sep ) ;
1998-11-11 17:23:55 +03:00
if ( p ! = NULL )
* p = 0 ;
2002-08-17 21:00:51 +04:00
1998-11-11 17:23:55 +03:00
if ( front ! = NULL )
pstrcpy ( front , path ) ;
2002-08-17 21:00:51 +04:00
if ( p ! = NULL ) {
1998-11-11 17:23:55 +03:00
if ( back ! = NULL )
pstrcpy ( back , p + 1 ) ;
1999-12-13 16:27:58 +03:00
* p = ' \\ ' ;
2002-08-17 21:00:51 +04:00
} else {
1998-11-11 17:23:55 +03:00
if ( back ! = NULL )
back [ 0 ] = 0 ;
}
}
2003-03-18 04:48:11 +03:00
# endif
1999-02-16 21:02:50 +03:00
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Write an octal as a string .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2003-01-03 11:28:12 +03:00
const char * octal_string ( int i )
1999-02-16 21:02:50 +03:00
{
1999-12-13 16:27:58 +03:00
static char ret [ 64 ] ;
2002-08-17 21:00:51 +04:00
if ( i = = - 1 )
1999-12-13 16:27:58 +03:00
return " -1 " ;
2001-04-09 00:22:39 +04:00
slprintf ( ret , sizeof ( ret ) - 1 , " 0%o " , i ) ;
1999-12-13 16:27:58 +03:00
return ret ;
1999-02-16 21:02:50 +03:00
}
1999-12-13 16:27:58 +03:00
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Truncate a string at a specified length .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2003-03-18 04:48:11 +03:00
char * string_truncate ( char * s , unsigned int length )
1999-02-16 21:02:50 +03:00
{
2002-08-17 21:00:51 +04:00
if ( s & & strlen ( s ) > length )
1999-12-13 16:27:58 +03:00
s [ length ] = 0 ;
return s ;
1999-02-16 21:02:50 +03:00
}
2001-07-04 11:15:53 +04:00
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Strchr and strrchr_m are very hard to do on general multi - byte strings .
We convert via ucs2 for now .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2003-09-14 02:41:21 +04:00
char * strchr_m ( const char * src , char c )
2001-07-04 11:15:53 +04:00
{
wpstring ws ;
pstring s2 ;
smb_ucs2_t * p ;
2003-09-14 02:41:21 +04:00
const char * s ;
2001-07-04 11:15:53 +04:00
2004-09-24 05:32:19 +04:00
/* characters below 0x3F are guaranteed to not appear in
non - initial position in multi - byte charsets */
if ( ( c & 0xC0 ) = = 0 ) {
2004-09-25 00:06:13 +04:00
return strchr ( src , c ) ;
2004-09-24 05:32:19 +04:00
}
2003-09-05 03:26:13 +04:00
/* this is quite a common operation, so we want it to be
fast . We optimise for the ascii case , knowing that all our
supported multi - byte character sets are ascii - compatible
( ie . they match for the first 128 chars ) */
2003-09-14 02:41:21 +04:00
for ( s = src ; * s & & ! ( ( ( unsigned char ) s [ 0 ] ) & 0x80 ) ; s + + ) {
2003-09-05 03:26:13 +04:00
if ( * s = = c )
2005-03-31 09:06:04 +04:00
return CONST_DISCARD ( char * , s ) ;
2003-09-05 03:26:13 +04:00
}
if ( ! * s )
return NULL ;
2003-09-14 02:41:21 +04:00
# ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
/* With compose characters we must restart from the beginning. JRA. */
s = src ;
# endif
2001-07-04 11:15:53 +04:00
push_ucs2 ( NULL , ws , s , sizeof ( ws ) , STR_TERMINATE ) ;
2001-11-04 21:26:53 +03:00
p = strchr_w ( ws , UCS2_CHAR ( c ) ) ;
2002-08-17 21:00:51 +04:00
if ( ! p )
return NULL ;
2001-07-04 11:15:53 +04:00
* p = 0 ;
pull_ucs2_pstring ( s2 , ws ) ;
2005-03-31 09:06:04 +04:00
return CONST_DISCARD ( char * , ( s + strlen ( s2 ) ) ) ;
2001-07-04 11:15:53 +04:00
}
char * strrchr_m ( const char * s , char c )
{
2004-09-24 05:32:19 +04:00
/* characters below 0x3F are guaranteed to not appear in
non - initial position in multi - byte charsets */
if ( ( c & 0xC0 ) = = 0 ) {
return strrchr ( s , c ) ;
}
2003-09-05 05:33:22 +04:00
/* this is quite a common operation, so we want it to be
fast . We optimise for the ascii case , knowing that all our
supported multi - byte character sets are ascii - compatible
( ie . they match for the first 128 chars ) . Also , in Samba
we only search for ascii characters in ' c ' and that
in all mb character sets with a compound character
containing c , if ' c ' is not a match at position
p , then p [ - 1 ] > 0x7f . JRA . */
{
size_t len = strlen ( s ) ;
const char * cp = s ;
BOOL got_mb = False ;
if ( len = = 0 )
return NULL ;
cp + = ( len - 1 ) ;
do {
if ( c = = * cp ) {
/* Could be a match. Part of a multibyte ? */
if ( ( cp > s ) & & ( ( ( unsigned char ) cp [ - 1 ] ) & 0x80 ) ) {
/* Yep - go slow :-( */
got_mb = True ;
break ;
}
/* No - we have a match ! */
2005-03-31 09:06:04 +04:00
return CONST_DISCARD ( char * , cp ) ;
2003-09-05 05:33:22 +04:00
}
} while ( cp - - ! = s ) ;
if ( ! got_mb )
return NULL ;
}
2001-07-04 11:15:53 +04:00
2003-09-05 05:33:22 +04:00
/* String contained a non-ascii char. Slow path. */
{
wpstring ws ;
pstring s2 ;
smb_ucs2_t * p ;
push_ucs2 ( NULL , ws , s , sizeof ( ws ) , STR_TERMINATE ) ;
p = strrchr_w ( ws , UCS2_CHAR ( c ) ) ;
if ( ! p )
return NULL ;
* p = 0 ;
pull_ucs2_pstring ( s2 , ws ) ;
2005-03-31 09:06:04 +04:00
return CONST_DISCARD ( char * , ( s + strlen ( s2 ) ) ) ;
2003-09-05 05:33:22 +04:00
}
2001-07-04 11:15:53 +04:00
}
2003-07-03 00:01:51 +04:00
/***********************************************************************
Return the equivalent of doing strrchr ' n ' times - always going
backwards .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * strnrchr_m ( const char * s , char c , unsigned int n )
{
wpstring ws ;
pstring s2 ;
smb_ucs2_t * p ;
push_ucs2 ( NULL , ws , s , sizeof ( ws ) , STR_TERMINATE ) ;
p = strnrchr_w ( ws , UCS2_CHAR ( c ) , n ) ;
if ( ! p )
return NULL ;
* p = 0 ;
pull_ucs2_pstring ( s2 , ws ) ;
2005-03-31 09:06:04 +04:00
return CONST_DISCARD ( char * , ( s + strlen ( s2 ) ) ) ;
2003-07-03 00:01:51 +04:00
}
2004-03-09 03:17:14 +03:00
/***********************************************************************
strstr_m - We convert via ucs2 for now .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * strstr_m ( const char * src , const char * findstr )
{
smb_ucs2_t * p ;
smb_ucs2_t * src_w , * find_w ;
const char * s ;
char * s2 ;
char * retp ;
2004-03-09 12:56:33 +03:00
size_t findstr_len = 0 ;
2004-03-09 14:15:44 +03:00
/* for correctness */
if ( ! findstr [ 0 ] ) {
2005-03-31 09:06:04 +04:00
return CONST_DISCARD ( char * , src ) ;
2004-03-09 14:15:44 +03:00
}
2004-03-09 03:17:14 +03:00
/* Samba does single character findstr calls a *lot*. */
if ( findstr [ 1 ] = = ' \0 ' )
return strchr_m ( src , * findstr ) ;
/* We optimise for the ascii case, knowing that all our
supported multi - byte character sets are ascii - compatible
( ie . they match for the first 128 chars ) */
for ( s = src ; * s & & ! ( ( ( unsigned char ) s [ 0 ] ) & 0x80 ) ; s + + ) {
if ( * s = = * findstr ) {
2004-03-09 12:56:33 +03:00
if ( ! findstr_len )
findstr_len = strlen ( findstr ) ;
if ( strncmp ( s , findstr , findstr_len ) = = 0 ) {
2005-03-31 09:06:04 +04:00
return CONST_DISCARD ( char * , s ) ;
2004-03-09 03:17:14 +03:00
}
}
}
if ( ! * s )
return NULL ;
2004-03-09 14:15:44 +03:00
# if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
/* 'make check' fails unless we do this */
2004-03-09 03:17:14 +03:00
/* With compose characters we must restart from the beginning. JRA. */
s = src ;
# endif
if ( push_ucs2_allocate ( & src_w , src ) = = ( size_t ) - 1 ) {
DEBUG ( 0 , ( " strstr_m: src malloc fail \n " ) ) ;
return NULL ;
}
if ( push_ucs2_allocate ( & find_w , findstr ) = = ( size_t ) - 1 ) {
SAFE_FREE ( src_w ) ;
DEBUG ( 0 , ( " strstr_m: find malloc fail \n " ) ) ;
return NULL ;
}
2004-03-09 12:56:33 +03:00
2004-03-09 14:15:44 +03:00
p = strstr_w ( src_w , find_w ) ;
2004-03-09 03:17:14 +03:00
if ( ! p ) {
SAFE_FREE ( src_w ) ;
SAFE_FREE ( find_w ) ;
return NULL ;
}
2004-03-09 14:15:44 +03:00
2004-03-09 03:17:14 +03:00
* p = 0 ;
if ( pull_ucs2_allocate ( & s2 , src_w ) = = ( size_t ) - 1 ) {
SAFE_FREE ( src_w ) ;
SAFE_FREE ( find_w ) ;
DEBUG ( 0 , ( " strstr_m: dest malloc fail \n " ) ) ;
return NULL ;
}
2005-03-31 09:06:04 +04:00
retp = CONST_DISCARD ( char * , ( s + strlen ( s2 ) ) ) ;
2004-03-09 03:17:14 +03:00
SAFE_FREE ( src_w ) ;
SAFE_FREE ( find_w ) ;
SAFE_FREE ( s2 ) ;
return retp ;
}
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Convert a string to lower case .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2001-07-04 11:15:53 +04:00
void strlower_m ( char * s )
{
2004-02-04 23:28:51 +03:00
size_t len ;
2004-09-01 21:39:27 +04:00
int errno_save ;
2004-02-04 23:28:51 +03:00
2002-04-11 13:56:38 +04:00
/* this is quite a common operation, so we want it to be
fast . We optimise for the ascii case , knowing that all our
supported multi - byte character sets are ascii - compatible
( ie . they match for the first 128 chars ) */
2002-08-17 21:00:51 +04:00
2004-01-08 02:21:36 +03:00
while ( * s & & ! ( ( ( unsigned char ) s [ 0 ] ) & 0x80 ) ) {
2003-01-17 09:40:12 +03:00
* s = tolower ( ( unsigned char ) * s ) ;
s + + ;
}
2002-04-11 13:56:38 +04:00
2002-08-17 21:00:51 +04:00
if ( ! * s )
return ;
2002-04-11 13:56:38 +04:00
2001-07-04 11:15:53 +04:00
/* I assume that lowercased string takes the same number of bytes
* as source string even in UTF - 8 encoding . ( VIV ) */
2004-02-04 23:28:51 +03:00
len = strlen ( s ) + 1 ;
2004-09-01 21:39:27 +04:00
errno_save = errno ;
2004-02-04 23:28:51 +03:00
errno = 0 ;
unix_strlower ( s , len , s , len ) ;
/* Catch mb conversion errors that may not terminate. */
if ( errno )
s [ len - 1 ] = ' \0 ' ;
2004-09-01 21:39:27 +04:00
errno = errno_save ;
2001-07-04 11:15:53 +04:00
}
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Convert a string to upper case .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2001-07-04 11:15:53 +04:00
void strupper_m ( char * s )
{
2004-02-04 23:28:51 +03:00
size_t len ;
2004-09-01 21:39:27 +04:00
int errno_save ;
2004-02-04 23:28:51 +03:00
2002-04-11 13:56:38 +04:00
/* this is quite a common operation, so we want it to be
fast . We optimise for the ascii case , knowing that all our
supported multi - byte character sets are ascii - compatible
( ie . they match for the first 128 chars ) */
2002-08-17 21:00:51 +04:00
2004-01-08 02:21:36 +03:00
while ( * s & & ! ( ( ( unsigned char ) s [ 0 ] ) & 0x80 ) ) {
2003-01-17 09:40:12 +03:00
* s = toupper ( ( unsigned char ) * s ) ;
s + + ;
}
2002-04-11 13:56:38 +04:00
2002-08-17 21:00:51 +04:00
if ( ! * s )
return ;
2002-04-11 13:56:38 +04:00
2001-07-04 11:15:53 +04:00
/* I assume that lowercased string takes the same number of bytes
* as source string even in multibyte encoding . ( VIV ) */
2004-02-04 23:28:51 +03:00
len = strlen ( s ) + 1 ;
2004-09-01 21:39:27 +04:00
errno_save = errno ;
2004-02-04 23:28:51 +03:00
errno = 0 ;
unix_strupper ( s , len , s , len ) ;
/* Catch mb conversion errors that may not terminate. */
if ( errno )
s [ len - 1 ] = ' \0 ' ;
2004-09-01 21:39:27 +04:00
errno = errno_save ;
2001-07-04 11:15:53 +04:00
}
2001-12-10 03:39:01 +03:00
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Return a RFC2254 binary string representation of a buffer .
Used in LDAP filters .
Caller must free .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2001-12-10 03:39:01 +03:00
char * binary_string ( char * buf , int len )
{
char * s ;
int i , j ;
const char * hex = " 0123456789ABCDEF " ;
2004-12-07 21:25:53 +03:00
s = SMB_MALLOC ( len * 3 + 1 ) ;
2002-08-17 21:00:51 +04:00
if ( ! s )
return NULL ;
2001-12-10 03:39:01 +03:00
for ( j = i = 0 ; i < len ; i + + ) {
s [ j ] = ' \\ ' ;
s [ j + 1 ] = hex [ ( ( unsigned char ) buf [ i ] ) > > 4 ] ;
s [ j + 2 ] = hex [ ( ( unsigned char ) buf [ i ] ) & 0xF ] ;
j + = 3 ;
}
s [ j ] = 0 ;
return s ;
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Just a typesafety wrapper for snprintf into a pstring .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2003-01-03 06:24:23 +03:00
int pstr_sprintf ( pstring s , const char * fmt , . . . )
2002-01-15 04:37:12 +03:00
{
va_list ap ;
int ret ;
va_start ( ap , fmt ) ;
2002-01-16 05:42:07 +03:00
ret = vsnprintf ( s , PSTRING_LEN , fmt , ap ) ;
2002-01-15 04:37:12 +03:00
va_end ( ap ) ;
return ret ;
}
2003-04-15 23:51:17 +04:00
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Just a typesafety wrapper for snprintf into a fstring .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2003-04-15 23:51:17 +04:00
int fstr_sprintf ( fstring s , const char * fmt , . . . )
2002-01-15 04:37:12 +03:00
{
va_list ap ;
int ret ;
va_start ( ap , fmt ) ;
2002-01-16 05:42:07 +03:00
ret = vsnprintf ( s , FSTRING_LEN , fmt , ap ) ;
2002-01-15 04:37:12 +03:00
va_end ( ap ) ;
return ret ;
}
2003-04-15 23:51:17 +04:00
2002-04-11 19:27:22 +04:00
2004-08-25 18:24:16 +04:00
# if !defined(HAVE_STRNDUP) || defined(BROKEN_STRNDUP)
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Some platforms don ' t have strndup .
2003-02-24 06:09:08 +03:00
* */
2004-12-23 01:07:04 +03:00
# if defined(PARANOID_MALLOC_CHECKER)
# undef strndup
# endif
2002-08-17 21:00:51 +04:00
2002-04-11 19:27:22 +04:00
char * strndup ( const char * s , size_t n )
{
char * ret ;
2002-07-15 14:35:28 +04:00
n = strnlen ( s , n ) ;
2004-12-07 21:25:53 +03:00
ret = SMB_MALLOC ( n + 1 ) ;
2002-08-17 21:00:51 +04:00
if ( ! ret )
return NULL ;
2002-07-15 14:35:28 +04:00
memcpy ( ret , s , n ) ;
ret [ n ] = 0 ;
2002-04-11 19:27:22 +04:00
return ret ;
}
2004-12-23 01:07:04 +03:00
# if defined(PARANOID_MALLOC_CHECKER)
# define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
# endif
2002-04-11 19:27:22 +04:00
# endif
2002-07-15 14:35:28 +04:00
2004-08-25 18:24:16 +04:00
# if !defined(HAVE_STRNLEN) || defined(BROKEN_STRNLEN)
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Some platforms don ' t have strnlen
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2002-07-15 14:35:28 +04:00
size_t strnlen ( const char * s , size_t n )
{
2005-01-29 00:55:45 +03:00
size_t i ;
for ( i = 0 ; i < n & & s [ i ] ! = ' \0 ' ; i + + )
2002-08-17 21:00:51 +04:00
/* noop */ ;
2002-07-15 14:35:28 +04:00
return i ;
}
# endif
2003-02-24 06:09:08 +03:00
/**
2002-07-15 14:35:28 +04:00
List of Strings manipulation functions
2003-02-24 06:09:08 +03:00
* */
2002-07-15 14:35:28 +04:00
# define S_LIST_ABS 16 /* List Allocation Block Size */
2002-08-17 21:00:51 +04:00
char * * str_list_make ( const char * string , const char * sep )
2002-07-15 14:35:28 +04:00
{
char * * list , * * rlist ;
2002-11-13 02:20:50 +03:00
const char * str ;
char * s ;
2002-07-15 14:35:28 +04:00
int num , lsize ;
pstring tok ;
2002-08-17 21:00:51 +04:00
if ( ! string | | ! * string )
return NULL ;
2004-12-07 21:25:53 +03:00
s = SMB_STRDUP ( string ) ;
2002-07-15 14:35:28 +04:00
if ( ! s ) {
DEBUG ( 0 , ( " str_list_make: Unable to allocate memory " ) ) ;
return NULL ;
}
2002-08-17 21:00:51 +04:00
if ( ! sep ) sep = LIST_SEP ;
2002-07-15 14:35:28 +04:00
num = lsize = 0 ;
list = NULL ;
str = s ;
2002-08-17 21:00:51 +04:00
while ( next_token ( & str , tok , sep , sizeof ( tok ) ) ) {
2002-07-15 14:35:28 +04:00
if ( num = = lsize ) {
lsize + = S_LIST_ABS ;
2004-12-07 21:25:53 +03:00
rlist = SMB_REALLOC_ARRAY ( list , char * , lsize + 1 ) ;
2002-07-15 14:35:28 +04:00
if ( ! rlist ) {
DEBUG ( 0 , ( " str_list_make: Unable to allocate memory " ) ) ;
str_list_free ( & list ) ;
SAFE_FREE ( s ) ;
return NULL ;
2002-10-02 23:12:14 +04:00
} else
list = rlist ;
2002-07-15 14:35:28 +04:00
memset ( & list [ num ] , 0 , ( ( sizeof ( char * * ) ) * ( S_LIST_ABS + 1 ) ) ) ;
}
2004-12-07 21:25:53 +03:00
list [ num ] = SMB_STRDUP ( tok ) ;
2002-07-15 14:35:28 +04:00
if ( ! list [ num ] ) {
DEBUG ( 0 , ( " str_list_make: Unable to allocate memory " ) ) ;
str_list_free ( & list ) ;
SAFE_FREE ( s ) ;
return NULL ;
}
num + + ;
}
SAFE_FREE ( s ) ;
return list ;
}
2002-11-13 02:20:50 +03:00
BOOL str_list_copy ( char * * * dest , const char * * src )
2002-07-15 14:35:28 +04:00
{
char * * list , * * rlist ;
int num , lsize ;
* dest = NULL ;
2002-08-17 21:00:51 +04:00
if ( ! src )
return False ;
2002-07-15 14:35:28 +04:00
num = lsize = 0 ;
list = NULL ;
2002-08-17 21:00:51 +04:00
while ( src [ num ] ) {
2002-07-15 14:35:28 +04:00
if ( num = = lsize ) {
lsize + = S_LIST_ABS ;
2004-12-07 21:25:53 +03:00
rlist = SMB_REALLOC_ARRAY ( list , char * , lsize + 1 ) ;
2002-07-15 14:35:28 +04:00
if ( ! rlist ) {
2002-10-01 17:10:57 +04:00
DEBUG ( 0 , ( " str_list_copy: Unable to re-allocate memory " ) ) ;
2002-07-15 14:35:28 +04:00
str_list_free ( & list ) ;
return False ;
2002-10-02 23:12:14 +04:00
} else
list = rlist ;
2002-07-15 14:35:28 +04:00
memset ( & list [ num ] , 0 , ( ( sizeof ( char * * ) ) * ( S_LIST_ABS + 1 ) ) ) ;
}
2004-12-07 21:25:53 +03:00
list [ num ] = SMB_STRDUP ( src [ num ] ) ;
2002-07-15 14:35:28 +04:00
if ( ! list [ num ] ) {
DEBUG ( 0 , ( " str_list_copy: Unable to allocate memory " ) ) ;
str_list_free ( & list ) ;
return False ;
}
num + + ;
}
* dest = list ;
return True ;
}
2003-02-24 06:09:08 +03:00
/**
* Return true if all the elements of the list match exactly .
* */
2002-07-15 14:35:28 +04:00
BOOL str_list_compare ( char * * list1 , char * * list2 )
{
int num ;
2002-08-17 21:00:51 +04:00
if ( ! list1 | | ! list2 )
return ( list1 = = list2 ) ;
2002-07-15 14:35:28 +04:00
for ( num = 0 ; list1 [ num ] ; num + + ) {
2002-08-17 21:00:51 +04:00
if ( ! list2 [ num ] )
return False ;
if ( ! strcsequal ( list1 [ num ] , list2 [ num ] ) )
return False ;
2002-07-15 14:35:28 +04:00
}
2002-08-17 21:00:51 +04:00
if ( list2 [ num ] )
return False ; /* if list2 has more elements than list1 fail */
2002-07-15 14:35:28 +04:00
return True ;
}
void str_list_free ( char * * * list )
{
char * * tlist ;
2002-08-17 21:00:51 +04:00
if ( ! list | | ! * list )
return ;
2002-07-15 14:35:28 +04:00
tlist = * list ;
2002-08-17 21:00:51 +04:00
for ( ; * tlist ; tlist + + )
SAFE_FREE ( * tlist ) ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( * list ) ;
}
2005-03-24 02:26:33 +03:00
/******************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int str_list_count ( const char * * list )
{
int i = 0 ;
/* count the number of list members */
for ( i = 0 ; * list ; i + + , list + + ) ;
return i ;
}
2003-09-05 09:32:32 +04:00
/******************************************************************************
version of standard_sub_basic ( ) for string lists ; uses alloc_sub_basic ( )
for the work
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL str_list_sub_basic ( char * * list , const char * smb_name )
{
char * s , * tmpstr ;
while ( * list ) {
s = * list ;
tmpstr = alloc_sub_basic ( smb_name , s ) ;
if ( ! tmpstr ) {
DEBUG ( 0 , ( " str_list_sub_basic: alloc_sub_basic() return NULL! \n " ) ) ;
return False ;
}
2004-08-30 22:27:07 +04:00
SAFE_FREE ( * list ) ;
2003-09-05 09:32:32 +04:00
* list = tmpstr ;
list + + ;
}
return True ;
}
/******************************************************************************
substritute a specific pattern in a string list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
BOOL str_list_substitute ( char * * list , const char * pattern , const char * insert )
{
char * p , * s , * t ;
ssize_t ls , lp , li , ld , i , d ;
2002-08-17 21:00:51 +04:00
if ( ! list )
return False ;
if ( ! pattern )
return False ;
if ( ! insert )
return False ;
2002-07-15 14:35:28 +04:00
lp = ( ssize_t ) strlen ( pattern ) ;
li = ( ssize_t ) strlen ( insert ) ;
ld = li - lp ;
2002-08-17 21:00:51 +04:00
while ( * list ) {
2002-07-15 14:35:28 +04:00
s = * list ;
ls = ( ssize_t ) strlen ( s ) ;
2004-03-09 03:17:14 +03:00
while ( ( p = strstr_m ( s , pattern ) ) ) {
2002-07-15 14:35:28 +04:00
t = * list ;
d = p - t ;
2002-08-17 21:00:51 +04:00
if ( ld ) {
2004-12-07 21:25:53 +03:00
t = ( char * ) SMB_MALLOC ( ls + ld + 1 ) ;
2002-07-15 14:35:28 +04:00
if ( ! t ) {
DEBUG ( 0 , ( " str_list_substitute: Unable to allocate memory " ) ) ;
return False ;
}
memcpy ( t , * list , d ) ;
memcpy ( t + d + li , p + lp , ls - d - lp + 1 ) ;
SAFE_FREE ( * list ) ;
* list = t ;
ls + = ld ;
s = t + d + li ;
}
for ( i = 0 ; i < li ; i + + ) {
switch ( insert [ i ] ) {
case ' ` ' :
case ' " ' :
case ' \' ' :
case ' ; ' :
case ' $ ' :
case ' % ' :
case ' \r ' :
case ' \n ' :
t [ d + i ] = ' _ ' ;
break ;
default :
t [ d + i ] = insert [ i ] ;
}
}
}
2003-09-05 09:32:32 +04:00
2002-07-15 14:35:28 +04:00
list + + ;
}
return True ;
}
2002-12-12 02:54:40 +03:00
2003-01-04 11:48:15 +03:00
# define IPSTR_LIST_SEP ","
2003-06-25 21:41:05 +04:00
# define IPSTR_LIST_CHAR ','
2003-01-04 11:48:15 +03:00
/**
* Add ip string representation to ipstr list . Used also
* as part of @ function ipstr_list_make
*
* @ param ipstr_list pointer to string containing ip list ;
* MUST BE already allocated and IS reallocated if necessary
* @ param ipstr_size pointer to current size of ipstr_list ( might be changed
* as a result of reallocation )
* @ param ip IP address which is to be added to list
* @ return pointer to string appended with new ip and possibly
* reallocated to new length
* */
2003-06-25 21:41:05 +04:00
char * ipstr_list_add ( char * * ipstr_list , const struct ip_service * service )
2003-01-04 11:48:15 +03:00
{
char * new_ipstr = NULL ;
/* arguments checking */
2003-06-25 21:41:05 +04:00
if ( ! ipstr_list | | ! service ) return NULL ;
2003-01-04 11:48:15 +03:00
/* attempt to convert ip to a string and append colon separator to it */
if ( * ipstr_list ) {
2003-06-25 21:41:05 +04:00
asprintf ( & new_ipstr , " %s%s%s:%d " , * ipstr_list , IPSTR_LIST_SEP ,
inet_ntoa ( service - > ip ) , service - > port ) ;
2003-01-04 11:48:15 +03:00
SAFE_FREE ( * ipstr_list ) ;
} else {
2003-06-25 21:41:05 +04:00
asprintf ( & new_ipstr , " %s:%d " , inet_ntoa ( service - > ip ) , service - > port ) ;
2003-01-04 11:48:15 +03:00
}
* ipstr_list = new_ipstr ;
return * ipstr_list ;
}
/**
* Allocate and initialise an ipstr list using ip adresses
* passed as arguments .
*
* @ param ipstr_list pointer to string meant to be allocated and set
* @ param ip_list array of ip addresses to place in the list
* @ param ip_count number of addresses stored in ip_list
* @ return pointer to allocated ip string
* */
2003-06-25 21:41:05 +04:00
char * ipstr_list_make ( char * * ipstr_list , const struct ip_service * ip_list , int ip_count )
2003-01-04 11:48:15 +03:00
{
int i ;
/* arguments checking */
if ( ! ip_list & & ! ipstr_list ) return 0 ;
* ipstr_list = NULL ;
/* process ip addresses given as arguments */
for ( i = 0 ; i < ip_count ; i + + )
* ipstr_list = ipstr_list_add ( ipstr_list , & ip_list [ i ] ) ;
return ( * ipstr_list ) ;
}
/**
* Parse given ip string list into array of ip addresses
2003-06-25 21:41:05 +04:00
* ( as ip_service structures )
* e . g . 192.168 .1 .100 : 389 , 192.168 .1 .78 , . . .
2003-01-04 11:48:15 +03:00
*
* @ param ipstr ip string list to be parsed
* @ param ip_list pointer to array of ip addresses which is
* allocated by this function and must be freed by caller
* @ return number of succesfully parsed addresses
* */
2003-06-25 21:41:05 +04:00
int ipstr_list_parse ( const char * ipstr_list , struct ip_service * * ip_list )
2003-01-04 11:48:15 +03:00
{
fstring token_str ;
2003-06-25 21:41:05 +04:00
size_t count ;
int i ;
2003-01-04 11:48:15 +03:00
2003-06-25 21:41:05 +04:00
if ( ! ipstr_list | | ! ip_list )
return 0 ;
count = count_chars ( ipstr_list , IPSTR_LIST_CHAR ) + 1 ;
2004-12-07 21:25:53 +03:00
if ( ( * ip_list = SMB_MALLOC_ARRAY ( struct ip_service , count ) ) = = NULL ) {
2003-07-25 08:24:40 +04:00
DEBUG ( 0 , ( " ipstr_list_parse: malloc failed for %lu entries \n " , ( unsigned long ) count ) ) ;
2003-06-25 21:41:05 +04:00
return 0 ;
}
2003-01-04 11:48:15 +03:00
2003-06-25 21:41:05 +04:00
for ( i = 0 ;
next_token ( & ipstr_list , token_str , IPSTR_LIST_SEP , FSTRING_LEN ) & & i < count ;
i + + )
{
2003-01-04 11:48:15 +03:00
struct in_addr addr ;
2003-06-25 21:41:05 +04:00
unsigned port = 0 ;
char * p = strchr ( token_str , ' : ' ) ;
if ( p ) {
* p = 0 ;
port = atoi ( p + 1 ) ;
}
2003-01-04 11:48:15 +03:00
/* convert single token to ip address */
if ( ( addr . s_addr = inet_addr ( token_str ) ) = = INADDR_NONE )
break ;
2003-06-25 21:41:05 +04:00
( * ip_list ) [ i ] . ip = addr ;
( * ip_list ) [ i ] . port = port ;
2003-01-04 11:48:15 +03:00
}
return count ;
}
/**
* Safely free ip string list
*
* @ param ipstr_list ip string list to be freed
* */
void ipstr_list_free ( char * ipstr_list )
{
SAFE_FREE ( ipstr_list ) ;
}
2003-02-24 06:09:08 +03:00
/**
2003-01-04 11:48:15 +03:00
Unescape a URL encoded string , in place .
2003-02-24 06:09:08 +03:00
* */
2003-01-04 11:48:15 +03:00
void rfc1738_unescape ( char * buf )
{
char * p = buf ;
while ( p & & * p & & ( p = strchr_m ( p , ' % ' ) ) ) {
int c1 = p [ 1 ] ;
int c2 = p [ 2 ] ;
if ( c1 > = ' 0 ' & & c1 < = ' 9 ' )
c1 = c1 - ' 0 ' ;
else if ( c1 > = ' A ' & & c1 < = ' F ' )
c1 = 10 + c1 - ' A ' ;
else if ( c1 > = ' a ' & & c1 < = ' f ' )
c1 = 10 + c1 - ' a ' ;
else { p + + ; continue ; }
if ( c2 > = ' 0 ' & & c2 < = ' 9 ' )
c2 = c2 - ' 0 ' ;
else if ( c2 > = ' A ' & & c2 < = ' F ' )
c2 = 10 + c2 - ' A ' ;
else if ( c2 > = ' a ' & & c2 < = ' f ' )
c2 = 10 + c2 - ' a ' ;
else { p + + ; continue ; }
* p = ( c1 < < 4 ) | c2 ;
memmove ( p + 1 , p + 3 , strlen ( p + 3 ) + 1 ) ;
p + + ;
}
}
2003-01-28 15:07:02 +03:00
static const char * b64 = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ " ;
2003-02-24 06:09:08 +03:00
/**
* Decode a base64 string into a DATA_BLOB - simple and slow algorithm
* */
2003-01-28 15:07:02 +03:00
DATA_BLOB base64_decode_data_blob ( const char * s )
{
int bit_offset , byte_offset , idx , i , n ;
DATA_BLOB decoded = data_blob ( s , strlen ( s ) + 1 ) ;
unsigned char * d = decoded . data ;
char * p ;
n = i = 0 ;
while ( * s & & ( p = strchr_m ( b64 , * s ) ) ) {
idx = ( int ) ( p - b64 ) ;
byte_offset = ( i * 6 ) / 8 ;
bit_offset = ( i * 6 ) % 8 ;
d [ byte_offset ] & = ~ ( ( 1 < < ( 8 - bit_offset ) ) - 1 ) ;
if ( bit_offset < 3 ) {
d [ byte_offset ] | = ( idx < < ( 2 - bit_offset ) ) ;
n = byte_offset + 1 ;
} else {
d [ byte_offset ] | = ( idx > > ( bit_offset - 2 ) ) ;
d [ byte_offset + 1 ] = 0 ;
d [ byte_offset + 1 ] | = ( idx < < ( 8 - ( bit_offset - 2 ) ) ) & 0xFF ;
n = byte_offset + 2 ;
}
s + + ; i + + ;
}
2004-07-22 17:39:43 +04:00
if ( ( n > 0 ) & & ( * s = = ' = ' ) ) {
n - = 1 ;
}
2004-01-23 15:04:07 +03:00
2003-01-28 15:07:02 +03:00
/* fix up length */
decoded . length = n ;
return decoded ;
}
2003-02-24 06:09:08 +03:00
/**
* Decode a base64 string in - place - wrapper for the above
* */
2003-02-19 02:17:59 +03:00
void base64_decode_inplace ( char * s )
2003-01-28 15:07:02 +03:00
{
DATA_BLOB decoded = base64_decode_data_blob ( s ) ;
2004-07-22 17:39:43 +04:00
if ( decoded . length ! = 0 ) {
memcpy ( s , decoded . data , decoded . length ) ;
/* null terminate */
s [ decoded . length ] = ' \0 ' ;
} else {
* s = ' \0 ' ;
}
2003-04-02 04:17:03 +04:00
data_blob_free ( & decoded ) ;
2003-01-28 15:07:02 +03:00
}
2003-02-24 06:09:08 +03:00
/**
* Encode a base64 string into a malloc ( ) ed string caller to free .
*
* From SQUID : adopted from http : //ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
* */
2003-01-28 15:07:02 +03:00
char * base64_encode_data_blob ( DATA_BLOB data )
{
int bits = 0 ;
int char_count = 0 ;
2005-02-01 21:24:39 +03:00
size_t out_cnt , len , output_len ;
char * result ;
if ( ! data . length | | ! data . data )
return NULL ;
out_cnt = 0 ;
len = data . length ;
output_len = data . length * 2 ;
result = SMB_MALLOC ( output_len ) ; /* get us plenty of space */
2003-01-28 15:07:02 +03:00
while ( len - - & & out_cnt < ( data . length * 2 ) - 5 ) {
int c = ( unsigned char ) * ( data . data + + ) ;
bits + = c ;
char_count + + ;
if ( char_count = = 3 ) {
result [ out_cnt + + ] = b64 [ bits > > 18 ] ;
result [ out_cnt + + ] = b64 [ ( bits > > 12 ) & 0x3f ] ;
result [ out_cnt + + ] = b64 [ ( bits > > 6 ) & 0x3f ] ;
result [ out_cnt + + ] = b64 [ bits & 0x3f ] ;
bits = 0 ;
char_count = 0 ;
} else {
bits < < = 8 ;
}
}
if ( char_count ! = 0 ) {
bits < < = 16 - ( 8 * char_count ) ;
result [ out_cnt + + ] = b64 [ bits > > 18 ] ;
result [ out_cnt + + ] = b64 [ ( bits > > 12 ) & 0x3f ] ;
if ( char_count = = 1 ) {
result [ out_cnt + + ] = ' = ' ;
result [ out_cnt + + ] = ' = ' ;
} else {
result [ out_cnt + + ] = b64 [ ( bits > > 6 ) & 0x3f ] ;
result [ out_cnt + + ] = ' = ' ;
}
}
result [ out_cnt ] = ' \0 ' ; /* terminate */
return result ;
}
2003-05-12 05:20:17 +04:00
/* read a SMB_BIG_UINT from a string */
SMB_BIG_UINT STR_TO_SMB_BIG_UINT ( const char * nptr , const char * * entptr )
{
SMB_BIG_UINT val = - 1 ;
const char * p = nptr ;
while ( p & & * p & & isspace ( * p ) )
p + + ;
# ifdef LARGE_SMB_OFF_T
sscanf ( p , " %llu " , & val ) ;
# else /* LARGE_SMB_OFF_T */
sscanf ( p , " %lu " , & val ) ;
# endif /* LARGE_SMB_OFF_T */
if ( entptr ) {
while ( p & & * p & & isdigit ( * p ) )
p + + ;
* entptr = p ;
}
return val ;
}
2004-04-07 16:43:44 +04:00
void string_append ( char * * left , const char * right )
{
int new_len = strlen ( right ) + 1 ;
if ( * left = = NULL ) {
2004-12-07 21:25:53 +03:00
* left = SMB_MALLOC ( new_len ) ;
2004-04-07 16:43:44 +04:00
* left [ 0 ] = ' \0 ' ;
} else {
new_len + = strlen ( * left ) ;
2004-12-07 21:25:53 +03:00
* left = SMB_REALLOC ( * left , new_len ) ;
2004-04-07 16:43:44 +04:00
}
if ( * left = = NULL )
return ;
safe_strcat ( * left , right , new_len - 1 ) ;
}
2005-01-15 06:54:03 +03:00
BOOL add_string_to_array ( TALLOC_CTX * mem_ctx ,
const char * str , const char * * * strings ,
int * num )
{
char * dup_str = talloc_strdup ( mem_ctx , str ) ;
* strings = TALLOC_REALLOC_ARRAY ( mem_ctx , * strings , const char * , ( * num ) + 1 ) ;
if ( ( * strings = = NULL ) | | ( dup_str = = NULL ) )
return False ;
( * strings ) [ * num ] = dup_str ;
* num + = 1 ;
return True ;
}