2008-10-18 17:56:45 +04:00
/*
Unix SMB / CIFS implementation .
Samba utility functions
Copyright ( C ) Andrew Tridgell 1992 - 2001
Copyright ( C ) Simo Sorce 2001 - 2002
Copyright ( C ) Martin Pool 2003
Copyright ( C ) James Peach 2005
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
2014-09-22 14:38:52 +04:00
# include "replace.h"
# include "debug.h"
2014-09-22 14:26:24 +04:00
# ifndef SAMBA_UTIL_CORE_ONLY
2014-09-22 14:38:52 +04:00
# include "charset/charset.h"
2014-09-22 14:26:24 +04:00
# else
# include "charset_compat.h"
# endif
2014-09-22 14:38:52 +04:00
# include "substitute.h"
2008-10-18 17:56:45 +04:00
/**
* @ file
* @ brief Substitute utilities .
* */
/**
2011-04-29 07:20:51 +04:00
Substitute a string for a pattern in another string . Make sure there is
2008-10-18 17:56:45 +04:00
enough room !
2011-04-29 07:20:51 +04:00
This routine looks for pattern in s and replaces it with
insert . It may do multiple replacements or just one .
2008-10-18 17:56:45 +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 .
* */
2011-04-29 07:20:51 +04:00
static void string_sub2 ( char * s , const char * pattern , const char * insert , size_t len ,
bool remove_unsafe_characters , bool replace_once ,
bool allow_trailing_dollar )
2008-10-18 17:56:45 +04:00
{
char * p ;
ssize_t ls , lp , li , i ;
if ( ! insert | | ! pattern | | ! * pattern | | ! s )
return ;
ls = ( ssize_t ) strlen ( s ) ;
lp = ( ssize_t ) strlen ( pattern ) ;
li = ( ssize_t ) strlen ( insert ) ;
if ( len = = 0 )
len = ls + 1 ; /* len is number of *bytes* */
2011-04-29 07:20:51 +04:00
while ( lp < = ls & & ( p = strstr_m ( s , pattern ) ) ) {
2008-10-18 17:56:45 +04:00
if ( ls + ( li - lp ) > = len ) {
2011-04-29 07:20:51 +04:00
DEBUG ( 0 , ( " ERROR: string overflow by "
" %d in string_sub(%.50s, %d) \n " ,
2008-10-18 17:56:45 +04:00
( int ) ( ls + ( li - lp ) - len ) ,
pattern , ( int ) len ) ) ;
break ;
}
if ( li ! = lp ) {
memmove ( p + li , p + lp , strlen ( p + lp ) + 1 ) ;
}
for ( i = 0 ; i < li ; i + + ) {
switch ( insert [ i ] ) {
2011-04-29 07:20:51 +04:00
case ' $ ' :
/* allow a trailing $
* ( as in machine accounts ) */
if ( allow_trailing_dollar & & ( i = = li - 1 ) ) {
p [ i ] = insert [ i ] ;
break ;
}
2008-10-18 17:56:45 +04:00
case ' ` ' :
case ' " ' :
case ' \' ' :
case ' ; ' :
case ' % ' :
case ' \r ' :
case ' \n ' :
2011-04-29 07:20:51 +04:00
if ( remove_unsafe_characters ) {
p [ i ] = ' _ ' ;
/* yes this break should be here
* since we want to fall throw if
* not replacing unsafe chars */
break ;
}
2008-10-18 17:56:45 +04:00
default :
p [ i ] = insert [ i ] ;
}
}
s = p + li ;
ls + = ( li - lp ) ;
2011-04-29 07:20:51 +04:00
if ( replace_once )
break ;
2008-10-18 17:56:45 +04:00
}
}
2011-04-29 07:20:51 +04:00
void string_sub_once ( char * s , const char * pattern ,
const char * insert , size_t len )
{
string_sub2 ( s , pattern , insert , len , true , true , false ) ;
}
void string_sub ( char * s , const char * pattern , const char * insert , size_t len )
{
string_sub2 ( s , pattern , insert , len , true , false , false ) ;
}
2008-10-18 17:56:45 +04:00
/**
* Talloc ' ed version of string_sub
*/
_PUBLIC_ char * string_sub_talloc ( TALLOC_CTX * mem_ctx , const char * s ,
const char * pattern , const char * insert )
{
const char * p ;
char * ret ;
size_t len , alloc_len ;
if ( insert = = NULL | | pattern = = NULL | | ! * pattern | | s = = NULL )
return NULL ;
/* determine length needed */
len = strlen ( s ) ;
for ( p = strstr ( s , pattern ) ; p ! = NULL ;
p = strstr ( p + strlen ( pattern ) , pattern ) ) {
len + = strlen ( insert ) - strlen ( pattern ) ;
}
alloc_len = MAX ( len , strlen ( s ) ) + 1 ;
ret = talloc_array ( mem_ctx , char , alloc_len ) ;
if ( ret = = NULL )
return NULL ;
strncpy ( ret , s , alloc_len ) ;
string_sub ( ret , pattern , insert , alloc_len ) ;
ret = talloc_realloc ( mem_ctx , ret , char , len + 1 ) ;
if ( ret = = NULL )
return NULL ;
2014-09-23 22:41:25 +04:00
if ( ret [ len ] ! = ' \0 ' ) {
DEBUG ( 0 , ( " Internal error at %s(%d): string not terminated \n " ,
__FILE__ , __LINE__ ) ) ;
abort ( ) ;
}
2008-10-18 17:56:45 +04:00
2008-01-30 12:34:57 +03:00
talloc_set_name_const ( ret , ret ) ;
2008-10-18 17:56:45 +04:00
return ret ;
}
/**
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 .
* */
_PUBLIC_ void all_string_sub ( char * s , const char * pattern , const char * insert , size_t len )
{
char * p ;
ssize_t ls , lp , li ;
if ( ! insert | | ! pattern | | ! s )
return ;
ls = ( ssize_t ) strlen ( s ) ;
lp = ( ssize_t ) strlen ( pattern ) ;
li = ( ssize_t ) strlen ( insert ) ;
if ( ! * pattern )
return ;
2011-04-29 07:20:51 +04:00
2008-10-18 17:56:45 +04:00
if ( len = = 0 )
len = ls + 1 ; /* len is number of *bytes* */
2011-04-29 07:20:51 +04:00
while ( lp < = ls & & ( p = strstr_m ( s , pattern ) ) ) {
2008-10-18 17:56:45 +04:00
if ( ls + ( li - lp ) > = len ) {
2011-04-29 07:20:51 +04:00
DEBUG ( 0 , ( " ERROR: string overflow by "
" %d in all_string_sub(%.50s, %d) \n " ,
2008-10-18 17:56:45 +04:00
( int ) ( ls + ( li - lp ) - len ) ,
pattern , ( int ) len ) ) ;
break ;
}
if ( li ! = lp ) {
memmove ( p + li , p + lp , strlen ( p + lp ) + 1 ) ;
}
memcpy ( p , insert , li ) ;
s = p + li ;
ls + = ( li - lp ) ;
}
}