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
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
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"
/****************************************************************************
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-17 23:50:07 +03:00
BOOL next_token ( char * * ptr , char * buff , char * sep , size_t bufsize )
1998-11-05 19:48:35 +03:00
{
2001-06-21 13:10:42 +04:00
char * s ;
BOOL quoted ;
size_t len = 1 ;
if ( ! ptr ) return ( False ) ;
s = * ptr ;
/* default to simple separators */
if ( ! sep ) sep = " \t \n \r " ;
/* find the first non sep char */
2001-07-04 11:36:09 +04:00
while ( * s & & strchr_m ( sep , * s ) ) s + + ;
2001-06-21 13:10:42 +04:00
/* nothing left? */
if ( ! * s ) return ( False ) ;
/* copy over the token */
2001-07-04 11:36:09 +04:00
for ( quoted = False ; len < bufsize & & * s & & ( quoted | | ! strchr_m ( sep , * s ) ) ; s + + ) {
2001-06-21 13:10:42 +04:00
if ( * s = = ' \" ' ) {
quoted = ! quoted ;
} else {
len + + ;
* buff + + = * s ;
}
}
* ptr = ( * s ) ? s + 1 : s ;
* buff = 0 ;
return ( True ) ;
}
1998-11-05 19:48:35 +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 !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * last_ptr = NULL ;
1998-11-05 19:48:35 +03:00
2001-06-21 13:10:42 +04:00
BOOL next_token_nr ( char * * ptr , char * buff , char * sep , size_t bufsize )
{
BOOL ret ;
if ( ! ptr ) 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
}
2001-06-21 13:10:42 +04:00
1998-11-05 19:48:35 +03:00
/****************************************************************************
Convert list of tokens to array ; dependent on above routine .
Uses last_ptr from above - bit of a hack .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * * toktocliplist ( int * ctok , char * sep )
{
2001-06-21 13:10:42 +04:00
char * s = last_ptr ;
int ictok = 0 ;
char * * ret , * * iret ;
if ( ! sep ) sep = " \t \n \r " ;
2001-07-04 11:36:09 +04:00
while ( * s & & strchr_m ( sep , * s ) ) s + + ;
2001-06-21 13:10:42 +04:00
/* nothing left? */
if ( ! * s ) return ( NULL ) ;
do {
ictok + + ;
2001-07-04 11:36:09 +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 ;
s = last_ptr ;
if ( ! ( ret = iret = malloc ( ictok * sizeof ( char * ) ) ) ) return NULL ;
while ( ictok - - ) {
* iret + + = s ;
while ( * s + + ) ;
while ( ! * s ) s + + ;
}
return ret ;
1998-11-05 19:48:35 +03:00
}
/*******************************************************************
case insensitive string compararison
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-12 09:12:19 +03:00
int StrCaseCmp ( const char * s , const char * t )
1998-11-05 19:48:35 +03:00
{
2001-07-06 15:50:45 +04:00
pstring buf1 , buf2 ;
2001-10-03 16:18:20 +04:00
unix_strupper ( s , strlen ( s ) + 1 , buf1 , sizeof ( buf1 ) ) ;
unix_strupper ( t , strlen ( t ) + 1 , buf2 , sizeof ( buf2 ) ) ;
2001-07-06 15:50:45 +04:00
return strcmp ( buf1 , buf2 ) ;
1998-11-05 19:48:35 +03:00
}
/*******************************************************************
case insensitive string compararison , length limited
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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
}
/*******************************************************************
compare 2 strings
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-12 09:12:19 +03:00
BOOL strequal ( const char * s1 , const char * s2 )
1998-11-05 19:48:35 +03:00
{
2001-07-06 15:50:45 +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
}
/*******************************************************************
compare 2 strings up to and including the nth char .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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
{
if ( s1 = = s2 ) return ( True ) ;
if ( ! s1 | | ! s2 | | ! n ) return ( False ) ;
return ( StrnCaseCmp ( s1 , s2 , n ) = = 0 ) ;
}
/*******************************************************************
compare 2 strings ( case sensitive )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-17 23:50:07 +03:00
BOOL strcsequal ( const char * s1 , const char * s2 )
1998-11-05 19:48:35 +03:00
{
if ( s1 = = s2 ) return ( True ) ;
if ( ! s1 | | ! s2 ) return ( False ) ;
return ( strcmp ( s1 , s2 ) = = 0 ) ;
}
2000-08-29 18:33:39 +04:00
/***************************************************************************
Do a case - insensitive , whitespace - ignoring string compare .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 */
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
/*******************************************************************
convert a string to " normal " form
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void strnorm ( char * s )
{
extern int case_default ;
if ( case_default = = CASE_UPPER )
strupper ( s ) ;
else
strlower ( s ) ;
}
/*******************************************************************
check if a string is in " normal " case
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL strisnormal ( char * s )
{
2001-07-04 11:15:53 +04:00
extern int case_default ;
if ( case_default = = CASE_UPPER )
return ( ! strhaslower ( s ) ) ;
return ( ! strhasupper ( s ) ) ;
1998-11-05 19:48:35 +03:00
}
/****************************************************************************
string replace
2001-07-04 11:15:53 +04:00
NOTE : oldc and newc must be 7 bit characters
1998-11-05 19:48:35 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void string_replace ( char * s , char oldc , char newc )
{
2001-07-04 11:15:53 +04:00
push_ucs2 ( NULL , tmpbuf , s , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
2001-11-04 21:26:53 +03:00
string_replace_w ( tmpbuf , UCS2_CHAR ( oldc ) , UCS2_CHAR ( newc ) ) ;
2001-07-04 11:15:53 +04:00
pull_ucs2 ( NULL , s , tmpbuf , - 1 , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
1998-11-05 19:48:35 +03:00
}
/*******************************************************************
skip past some strings in a buffer
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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
}
/*******************************************************************
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-17 23:50:07 +03:00
size_t str_charnum ( const char * s )
1998-11-05 19:48:35 +03:00
{
2001-07-04 11:15:53 +04:00
push_ucs2 ( NULL , tmpbuf , s , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
return strlen_w ( tmpbuf ) ;
1998-11-05 19:48:35 +03:00
}
/*******************************************************************
trim the specified elements off the front and back of a string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 ) {
memcpy ( s , s + front_len , ( len - front_len ) + 1 ) ;
len - = front_len ;
ret = True ;
}
}
if ( back_len ) {
while ( strncmp ( s + len - back_len , back , back_len ) = = 0 ) {
s [ len - back_len ] = ' \0 ' ;
len - = back_len ;
ret = True ;
}
}
return ret ;
1998-11-05 19:48:35 +03:00
}
/****************************************************************************
does a string have any uppercase chars in it ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 + + )
if ( isupper_w ( * ptr ) ) return True ;
return ( False ) ;
1998-11-05 19:48:35 +03:00
}
/****************************************************************************
does a string have any lowercase chars in it ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 + + )
if ( islower_w ( * ptr ) ) return True ;
return ( False ) ;
1998-11-05 19:48:35 +03:00
}
/****************************************************************************
2001-07-04 11:15:53 +04:00
find the number of ' c ' chars in a string
1998-11-05 19:48:35 +03: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 ;
push_ucs2 ( NULL , tmpbuf , s , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
for ( count = 0 , ptr = tmpbuf ; * ptr ; ptr + + ) if ( * ptr = = UCS2_CHAR ( c ) ) count + + ;
return ( count ) ;
1998-11-05 19:48:35 +03:00
}
1999-12-13 16:27:58 +03:00
/*******************************************************************
Return True if a string consists only of one particular character .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-05 19:48:35 +03:00
1999-12-13 16:27:58 +03:00
BOOL str_is_all ( const char * s , char c )
{
2001-07-04 11:15:53 +04:00
smb_ucs2_t * ptr ;
if ( s = = NULL ) return False ;
if ( ! * s ) return False ;
push_ucs2 ( NULL , tmpbuf , s , sizeof ( tmpbuf ) , STR_TERMINATE ) ;
for ( ptr = tmpbuf ; * ptr ; ptr + + ) if ( * ptr ! = UCS2_CHAR ( c ) ) return False ;
return True ;
1999-12-13 16:27:58 +03:00
}
1998-11-05 19:48:35 +03:00
/*******************************************************************
safe string copy into a known length string . maxlength does not
include the terminating zero .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-11-17 23:50:07 +03:00
char * safe_strcpy ( 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 ) {
DEBUG ( 0 , ( " ERROR: NULL dest in safe_strcpy \n " ) ) ;
return NULL ;
}
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
if ( ! src ) {
* dest = 0 ;
return dest ;
}
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
len = strlen ( src ) ;
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
if ( len > maxlength ) {
DEBUG ( 0 , ( " ERROR: string overflow by %d in safe_strcpy [%.50s] \n " ,
( int ) ( len - maxlength ) , src ) ) ;
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
}
/*******************************************************************
safe string cat into a string . maxlength does not
include the terminating zero .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-11-17 23:50:07 +03:00
char * safe_strcat ( 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 ) {
DEBUG ( 0 , ( " ERROR: NULL dest in safe_strcat \n " ) ) ;
return NULL ;
}
1998-11-05 19:48:35 +03:00
2001-07-04 11:15:53 +04:00
if ( ! src ) {
return dest ;
}
src_len = strlen ( src ) ;
dest_len = strlen ( dest ) ;
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 ) ) ;
src_len = maxlength - dest_len ;
}
memcpy ( & dest [ dest_len ] , src , src_len ) ;
dest [ dest_len + src_len ] = 0 ;
return dest ;
1998-11-05 19:48:35 +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 !
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-06-23 11:22:16 +04:00
char * alpha_strcpy ( 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
1999-12-13 16:27:58 +03:00
if ( ! dest ) {
DEBUG ( 0 , ( " ERROR: NULL dest in alpha_strcpy \n " ) ) ;
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 ) ;
2001-07-04 11:36:09 +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
}
/****************************************************************************
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 .
1998-11-05 19:48:35 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-11-17 23:50:07 +03:00
char * StrnCpy ( 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 ;
if ( ! dest ) return ( NULL ) ;
if ( ! src ) {
* dest = 0 ;
return ( dest ) ;
}
while ( n - - & & ( * d + + = * src + + ) ) ;
* d = 0 ;
return ( dest ) ;
1998-11-05 19:48:35 +03: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 ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
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
2001-07-04 11:36:09 +04:00
p = strchr_m ( src , c ) ;
1998-11-05 19:48:35 +03:00
if ( p = = NULL )
{
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 ;
}
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 "
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 ;
char * hexchars = " 0123456789ABCDEF " ;
char * p1 = NULL , * p2 = NULL ;
for ( i = 0 ; i < len & & strhex [ i ] ! = 0 ; i + + )
{
if ( strnequal ( hexchars , " 0x " , 2 ) )
{
i + + ; /* skip two chars */
continue ;
}
2001-07-04 11:36:09 +04:00
if ( ! ( p1 = strchr_m ( hexchars , toupper ( strhex [ i ] ) ) ) )
1998-11-10 22:05:00 +03:00
{
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 ] ) ) ) )
1998-11-10 22:05:00 +03:00
{
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 ;
}
1998-11-05 19:48:35 +03:00
/****************************************************************************
check if a string is part of a list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL in_list ( char * s , char * list , BOOL casesensitive )
{
pstring tok ;
char * p = list ;
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 ) ;
}
/* this is used to prevent lots of mallocs of size 1 */
static char * null_string = NULL ;
/****************************************************************************
set a string value , allocing the space for the string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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
{
1998-11-17 23:50:07 +03:00
size_t l ;
1998-11-05 19:48:35 +03:00
if ( ! src )
src = " " ;
l = strlen ( src ) ;
if ( l = = 0 )
{
if ( ! null_string ) {
if ( ( null_string = ( char * ) malloc ( 1 ) ) = = NULL ) {
DEBUG ( 0 , ( " string_init: malloc fail for null_string. \n " ) ) ;
return False ;
}
* null_string = 0 ;
}
* dest = null_string ;
}
else
{
( * dest ) = ( char * ) malloc ( l + 1 ) ;
if ( ( * dest ) = = NULL ) {
DEBUG ( 0 , ( " Out of memory in string_init \n " ) ) ;
return False ;
}
pstrcpy ( * dest , src ) ;
}
return ( True ) ;
}
/****************************************************************************
free a string value
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void string_free ( char * * s )
{
if ( ! s | | ! ( * s ) ) return ;
if ( * s = = null_string )
* s = NULL ;
2001-09-17 06:19:44 +04:00
SAFE_FREE ( * s ) ;
1998-11-05 19:48:35 +03:00
}
/****************************************************************************
set a string value , allocing the space for the string , and deallocating any
existing space
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-17 23:50:07 +03:00
BOOL string_set ( char * * dest , const char * src )
1998-11-05 19:48:35 +03:00
{
string_free ( dest ) ;
return ( string_init ( dest , src ) ) ;
}
1998-11-23 06:36:10 +03:00
1998-11-05 19:48:35 +03:00
/****************************************************************************
substitute a string for a pattern in another string . Make sure there is
enough room !
This routine looks for pattern in s and replaces it with
insert . It may do multiple replacements .
1999-12-13 16:27:58 +03:00
any of " ; ' $ or ` in the insert string are replaced with _
if len = = 0 then no length check is performed
1998-11-05 19:48:35 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03: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
if ( ! insert | | ! pattern | | ! s ) return ;
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
if ( ! * pattern ) return ;
while ( lp < = ls & & ( p = strstr ( s , pattern ) ) ) {
1999-12-13 16:27:58 +03:00
if ( len & & ( ls + ( li - lp ) > = len ) ) {
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
1998-11-23 06:36:10 +03:00
/****************************************************************************
similar to string_sub ( ) but allows for any character to be substituted .
Use with caution !
1999-12-13 16:27:58 +03:00
if len = = 0 then no length check is performed
1998-11-23 06:36:10 +03: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
1998-11-23 06:36:10 +03: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
if ( ! * pattern ) return ;
while ( lp < = ls & & ( p = strstr ( s , pattern ) ) ) {
1999-12-13 16:27:58 +03:00
if ( len & & ( ls + ( li - lp ) > = len ) ) {
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
}
2001-11-04 21:26:53 +03:00
/****************************************************************************
similar to all_string_sub but for unicode strings .
return a new allocate unicode string .
len is the number of bytes , not chars
similar to string_sub ( ) but allows for any character to be substituted .
Use with caution !
if len = = 0 then no length check is performed
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-25 03:35:14 +03:00
smb_ucs2_t * all_string_sub_w ( const smb_ucs2_t * s , const smb_ucs2_t * pattern ,
const smb_ucs2_t * insert )
2001-11-04 21:26:53 +03:00
{
smb_ucs2_t * r , * rp , * sp ;
2001-11-18 19:12:11 +03:00
size_t lr , lp , li , lt ;
2001-11-04 21:26:53 +03:00
if ( ! insert | | ! pattern | | ! * pattern | | ! s ) return NULL ;
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 ) {
smb_ucs2_t * st = s ;
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 ;
}
}
r = rp = ( smb_ucs2_t * ) malloc ( ( lt + 1 ) * ( sizeof ( smb_ucs2_t ) ) ) ;
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 ;
if ( ! insert | | ! pattern | | ! s ) return NULL ;
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 ) ;
}
1998-11-11 17:23:55 +03:00
/****************************************************************************
splits out the front and back at a separator .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void split_at_last_component ( char * path , char * front , char sep , char * back )
{
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 ;
}
if ( front ! = NULL )
{
pstrcpy ( front , path ) ;
}
if ( p ! = NULL )
{
if ( back ! = NULL )
{
pstrcpy ( back , p + 1 ) ;
}
1999-12-13 16:27:58 +03:00
* p = ' \\ ' ;
1998-11-11 17:23:55 +03:00
}
else
{
if ( back ! = NULL )
{
back [ 0 ] = 0 ;
}
}
}
1999-02-16 21:02:50 +03:00
1999-12-13 16:27:58 +03:00
/****************************************************************************
write an octal as a string
1999-02-16 21:02:50 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
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 ] ;
if ( i = = - 1 ) {
return " -1 " ;
1999-02-16 21:02:50 +03:00
}
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
1999-02-16 21:02:50 +03:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
truncate a string at a specified length
1999-02-16 21:02:50 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
char * string_truncate ( char * s , int length )
1999-02-16 21:02:50 +03:00
{
1999-12-13 16:27:58 +03:00
if ( s & & strlen ( s ) > length ) {
s [ length ] = 0 ;
1999-02-16 21:02:50 +03:00
}
1999-12-13 16:27:58 +03:00
return s ;
1999-02-16 21:02:50 +03:00
}
2001-07-04 11:15:53 +04:00
/****************************************************************************
2001-07-04 11:36:09 +04:00
strchr and strrchr_m are very hard to do on general multi - byte strings .
2001-07-04 11:15:53 +04:00
we convert via ucs2 for now
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * strchr_m ( const char * s , char c )
{
wpstring ws ;
pstring s2 ;
smb_ucs2_t * p ;
push_ucs2 ( NULL , ws , s , sizeof ( ws ) , STR_TERMINATE ) ;
2001-11-04 21:26:53 +03:00
p = strchr_w ( ws , UCS2_CHAR ( c ) ) ;
2001-07-04 11:15:53 +04:00
if ( ! p ) return NULL ;
* p = 0 ;
pull_ucs2_pstring ( s2 , ws ) ;
return ( char * ) ( s + strlen ( s2 ) ) ;
}
char * strrchr_m ( const char * s , char c )
{
wpstring ws ;
pstring s2 ;
smb_ucs2_t * p ;
push_ucs2 ( NULL , ws , s , sizeof ( ws ) , STR_TERMINATE ) ;
2001-11-04 21:26:53 +03:00
p = strrchr_w ( ws , UCS2_CHAR ( c ) ) ;
2001-07-04 11:15:53 +04:00
if ( ! p ) return NULL ;
* p = 0 ;
pull_ucs2_pstring ( s2 , ws ) ;
return ( char * ) ( s + strlen ( s2 ) ) ;
}
/*******************************************************************
convert a string to lower case
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void strlower_m ( char * s )
{
/* I assume that lowercased string takes the same number of bytes
* as source string even in UTF - 8 encoding . ( VIV ) */
unix_strlower ( s , strlen ( s ) + 1 , s , strlen ( s ) + 1 ) ;
}
/*******************************************************************
convert a string to upper case
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void strupper_m ( char * s )
{
/* I assume that lowercased string takes the same number of bytes
* as source string even in multibyte encoding . ( VIV ) */
unix_strupper ( s , strlen ( s ) + 1 , s , strlen ( s ) + 1 ) ;
}
2001-12-10 03:39:01 +03:00
/*
return a RFC2254 binary string representation of a buffer
used in LDAP filters
caller must free
*/
char * binary_string ( char * buf , int len )
{
char * s ;
int i , j ;
const char * hex = " 0123456789ABCDEF " ;
s = malloc ( len * 3 + 1 ) ;
if ( ! s ) return NULL ;
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 ;
}
2002-01-15 04:37:12 +03:00
/* Just a typesafety wrapper for snprintf into a pstring */
int pstr_sprintf ( pstring s , const char * fmt , . . . )
{
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 ;
}
2002-01-25 03:35:14 +03:00
/* Just a typesafety wrapper for snprintf into a fstring */
2002-01-15 04:37:12 +03:00
int fstr_sprintf ( fstring s , const char * fmt , . . . )
{
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 ;
}