2006-04-27 20:05:05 +04:00
/*
Unix SMB / CIFS implementation .
Samba utility functions
Copyright ( C ) Andrew Tridgell 1992 - 2001
Copyright ( C ) Simo Sorce 2001
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-04-27 20:05:05 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-04-27 20:05:05 +04:00
*/
# include "includes.h"
2006-05-13 23:14:12 +04:00
# include "system/locale.h"
2008-10-24 16:45:31 +04:00
struct smb_iconv_convenience * global_iconv_convenience = NULL ;
2006-04-27 20:05:05 +04:00
2008-10-24 04:51:03 +04:00
static inline struct smb_iconv_convenience * get_iconv_convenience ( void )
2006-04-27 20:05:05 +04:00
{
2008-10-24 16:45:31 +04:00
if ( global_iconv_convenience = = NULL )
global_iconv_convenience = smb_iconv_convenience_init ( talloc_autofree_context ( ) , " ASCII " , " UTF-8 " , true ) ;
return global_iconv_convenience ;
2006-04-27 20:05:05 +04:00
}
/**
Case insensitive string compararison
* */
_PUBLIC_ int strcasecmp_m ( const char * s1 , const char * s2 )
{
codepoint_t c1 = 0 , c2 = 0 ;
size_t size1 , size2 ;
2008-10-24 04:51:03 +04:00
struct smb_iconv_convenience * iconv_convenience = get_iconv_convenience ( ) ;
2006-04-27 20:05:05 +04:00
2006-09-01 08:23:24 +04:00
/* handle null ptr comparisons to simplify the use in qsort */
if ( s1 = = s2 ) return 0 ;
if ( s1 = = NULL ) return - 1 ;
if ( s2 = = NULL ) return 1 ;
2006-04-27 20:05:05 +04:00
while ( * s1 & & * s2 ) {
2008-10-24 18:00:43 +04:00
c1 = next_codepoint_convenience ( iconv_convenience , s1 , & size1 ) ;
c2 = next_codepoint_convenience ( iconv_convenience , s2 , & size2 ) ;
2006-04-27 20:05:05 +04:00
s1 + = size1 ;
s2 + = size2 ;
if ( c1 = = c2 ) {
continue ;
}
if ( c1 = = INVALID_CODEPOINT | |
c2 = = INVALID_CODEPOINT ) {
/* what else can we do?? */
return strcasecmp ( s1 , s2 ) ;
}
2008-10-24 04:51:03 +04:00
if ( toupper_m ( c1 ) ! = toupper_m ( c2 ) ) {
2006-04-27 20:05:05 +04:00
return c1 - c2 ;
}
}
return * s1 - * s2 ;
}
/**
* 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
* */
2007-08-27 22:10:19 +04:00
_PUBLIC_ bool next_token ( const char * * ptr , char * buff , const char * sep , size_t bufsize )
2006-04-27 20:05:05 +04:00
{
const char * s ;
2007-08-27 22:10:19 +04:00
bool quoted ;
2006-04-27 20:05:05 +04:00
size_t len = 1 ;
if ( ! ptr )
2007-08-27 22:43:18 +04:00
return false ;
2006-04-27 20:05:05 +04:00
s = * ptr ;
/* default to simple separators */
if ( ! sep )
sep = " \t \n \r " ;
/* find the first non sep char */
while ( * s & & strchr_m ( sep , * s ) )
s + + ;
/* nothing left? */
2007-08-27 22:43:18 +04:00
if ( ! * s )
return false ;
2006-04-27 20:05:05 +04:00
/* copy over the token */
2007-08-27 22:43:18 +04:00
for ( quoted = false ; len < bufsize & & * s & & ( quoted | | ! strchr_m ( sep , * s ) ) ; s + + ) {
2006-04-27 20:05:05 +04:00
if ( * s = = ' \" ' ) {
quoted = ! quoted ;
} else {
len + + ;
* buff + + = * s ;
}
}
* ptr = ( * s ) ? s + 1 : s ;
* buff = 0 ;
2007-08-27 22:43:18 +04:00
return true ;
2006-04-27 20:05:05 +04:00
}
/**
Case insensitive string compararison , length limited
* */
_PUBLIC_ int strncasecmp_m ( const char * s1 , const char * s2 , size_t n )
{
codepoint_t c1 = 0 , c2 = 0 ;
size_t size1 , size2 ;
2008-10-24 04:51:03 +04:00
struct smb_iconv_convenience * iconv_convenience = get_iconv_convenience ( ) ;
2006-04-27 20:05:05 +04:00
2006-09-01 08:23:24 +04:00
/* handle null ptr comparisons to simplify the use in qsort */
if ( s1 = = s2 ) return 0 ;
if ( s1 = = NULL ) return - 1 ;
if ( s2 = = NULL ) return 1 ;
2006-04-27 20:05:05 +04:00
while ( * s1 & & * s2 & & n ) {
n - - ;
2008-10-24 18:00:43 +04:00
c1 = next_codepoint_convenience ( iconv_convenience , s1 , & size1 ) ;
2008-10-24 18:12:14 +04:00
c2 = next_codepoint_convenience ( iconv_convenience , s2 , & size2 ) ;
2006-04-27 20:05:05 +04:00
s1 + = size1 ;
s2 + = size2 ;
if ( c1 = = c2 ) {
continue ;
}
if ( c1 = = INVALID_CODEPOINT | |
c2 = = INVALID_CODEPOINT ) {
/* what else can we do?? */
return strcasecmp ( s1 , s2 ) ;
}
2008-10-24 04:51:03 +04:00
if ( toupper_m ( c1 ) ! = toupper_m ( c2 ) ) {
2006-04-27 20:05:05 +04:00
return c1 - c2 ;
}
}
if ( n = = 0 ) {
return 0 ;
}
return * s1 - * s2 ;
}
/**
* Compare 2 strings .
*
* @ note The comparison is case - insensitive .
* */
2008-10-24 04:51:03 +04:00
_PUBLIC_ bool strequal_m ( const char * s1 , const char * s2 )
2006-04-27 20:05:05 +04:00
{
return strcasecmp_m ( s1 , s2 ) = = 0 ;
}
/**
Compare 2 strings ( case sensitive ) .
* */
2008-10-24 04:51:03 +04:00
_PUBLIC_ bool strcsequal_m ( const char * s1 , const char * s2 )
2006-04-27 20:05:05 +04:00
{
if ( s1 = = s2 )
2007-08-27 22:43:18 +04:00
return true ;
2006-04-27 20:05:05 +04:00
if ( ! s1 | | ! s2 )
2007-08-27 22:43:18 +04:00
return false ;
2006-04-27 20:05:05 +04:00
return strcmp ( s1 , s2 ) = = 0 ;
}
/**
String replace .
NOTE : oldc and newc must be 7 bit characters
* */
2008-10-24 03:19:33 +04:00
_PUBLIC_ void string_replace_m ( char * s , char oldc , char newc )
2006-04-27 20:05:05 +04:00
{
2008-10-24 06:39:09 +04:00
struct smb_iconv_convenience * ic = get_iconv_convenience ( ) ;
2007-03-05 03:11:46 +03:00
while ( s & & * s ) {
2006-04-27 20:05:05 +04:00
size_t size ;
2008-10-24 18:00:43 +04:00
codepoint_t c = next_codepoint_convenience ( ic , s , & size ) ;
2006-04-27 20:05:05 +04:00
if ( c = = oldc ) {
* s = newc ;
}
s + = size ;
}
}
/**
Paranoid strcpy into a buffer of given length ( includes terminating
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 !
* */
_PUBLIC_ char * alpha_strcpy ( char * dest , const char * src , const char * other_safe_chars , size_t maxlength )
{
size_t len , i ;
if ( maxlength = = 0 ) {
/* can't fit any bytes at all! */
return NULL ;
}
if ( ! dest ) {
DEBUG ( 0 , ( " ERROR: NULL dest in alpha_strcpy \n " ) ) ;
return NULL ;
}
if ( ! src ) {
* dest = 0 ;
return dest ;
}
len = strlen ( src ) ;
if ( len > = maxlength )
len = maxlength - 1 ;
if ( ! other_safe_chars )
other_safe_chars = " " ;
for ( i = 0 ; i < len ; i + + ) {
int val = ( src [ i ] & 0xff ) ;
if ( isupper ( val ) | | islower ( val ) | | isdigit ( val ) | | strchr_m ( other_safe_chars , val ) )
dest [ i ] = src [ i ] ;
else
dest [ i ] = ' _ ' ;
}
dest [ i ] = ' \0 ' ;
return dest ;
}
/**
Count the number of UCS2 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 .
* */
_PUBLIC_ size_t strlen_m ( const char * s )
{
size_t count = 0 ;
2008-10-24 06:39:09 +04:00
struct smb_iconv_convenience * ic = get_iconv_convenience ( ) ;
2006-04-27 20:05:05 +04:00
if ( ! s ) {
return 0 ;
}
while ( * s & & ! ( ( ( uint8_t ) * s ) & 0x80 ) ) {
s + + ;
count + + ;
}
if ( ! * s ) {
return count ;
}
while ( * s ) {
size_t c_size ;
2008-10-24 18:12:14 +04:00
codepoint_t c = next_codepoint_convenience ( ic , s , & c_size ) ;
2006-04-27 20:05:05 +04:00
if ( c < 0x10000 ) {
count + = 1 ;
} else {
count + = 2 ;
}
s + = c_size ;
}
return count ;
}
/**
Work out the number of multibyte chars in a string , including the NULL
terminator .
* */
_PUBLIC_ size_t strlen_m_term ( const char * s )
{
if ( ! s ) {
return 0 ;
}
return strlen_m ( s ) + 1 ;
}
2009-01-16 02:25:31 +03:00
/*
* Weird helper routine for the winreg pipe : If nothing is around , return 0 ,
* if a string is there , include the terminator .
*/
_PUBLIC_ size_t strlen_m_term_null ( const char * s )
{
size_t len ;
if ( ! s ) {
return 0 ;
}
len = strlen_m ( s ) ;
if ( len = = 0 ) {
return 0 ;
}
return len + 1 ;
}
2006-04-27 20:05:05 +04:00
/**
Strchr and strrchr_m are a bit complex on general multi - byte strings .
* */
_PUBLIC_ char * strchr_m ( const char * s , char c )
{
2008-10-24 06:39:09 +04:00
struct smb_iconv_convenience * ic = get_iconv_convenience ( ) ;
2008-10-01 00:57:23 +04:00
if ( s = = NULL ) {
return NULL ;
}
2006-04-27 20:05:05 +04:00
/* characters below 0x3F are guaranteed to not appear in
non - initial position in multi - byte charsets */
if ( ( c & 0xC0 ) = = 0 ) {
return strchr ( s , c ) ;
}
while ( * s ) {
size_t size ;
2008-10-24 18:00:43 +04:00
codepoint_t c2 = next_codepoint_convenience ( ic , s , & size ) ;
2006-04-27 20:05:05 +04:00
if ( c2 = = c ) {
2007-09-08 17:27:14 +04:00
return discard_const_p ( char , s ) ;
2006-04-27 20:05:05 +04:00
}
s + = size ;
}
return NULL ;
}
/**
* Multibyte - character version of strrchr
*/
_PUBLIC_ char * strrchr_m ( const char * s , char c )
{
2008-10-24 06:39:09 +04:00
struct smb_iconv_convenience * ic = get_iconv_convenience ( ) ;
2006-04-27 20:05:05 +04:00
char * ret = NULL ;
2008-10-01 00:57:23 +04:00
if ( s = = NULL ) {
return NULL ;
}
2006-04-27 20:05:05 +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 ) ;
}
while ( * s ) {
size_t size ;
2008-10-24 18:12:14 +04:00
codepoint_t c2 = next_codepoint_convenience ( ic , s , & size ) ;
2006-04-27 20:05:05 +04:00
if ( c2 = = c ) {
2007-09-08 17:27:14 +04:00
ret = discard_const_p ( char , s ) ;
2006-04-27 20:05:05 +04:00
}
s + = size ;
}
return ret ;
}
/**
return True if any ( multi - byte ) character is lower case
*/
2007-08-27 22:10:19 +04:00
_PUBLIC_ bool strhaslower ( const char * string )
2006-04-27 20:05:05 +04:00
{
2008-10-24 06:39:09 +04:00
struct smb_iconv_convenience * ic = get_iconv_convenience ( ) ;
2006-04-27 20:05:05 +04:00
while ( * string ) {
size_t c_size ;
codepoint_t s ;
codepoint_t t ;
2008-10-24 18:00:43 +04:00
s = next_codepoint_convenience ( ic , string , & c_size ) ;
2006-04-27 20:05:05 +04:00
string + = c_size ;
2008-10-24 04:51:03 +04:00
t = toupper_m ( s ) ;
2006-04-27 20:05:05 +04:00
if ( s ! = t ) {
2007-08-27 22:43:18 +04:00
return true ; /* that means it has lower case chars */
2006-04-27 20:05:05 +04:00
}
}
2007-08-27 22:43:18 +04:00
return false ;
2006-04-27 20:05:05 +04:00
}
/**
return True if any ( multi - byte ) character is upper case
*/
2007-08-27 22:10:19 +04:00
_PUBLIC_ bool strhasupper ( const char * string )
2006-04-27 20:05:05 +04:00
{
2008-10-24 06:39:09 +04:00
struct smb_iconv_convenience * ic = get_iconv_convenience ( ) ;
2006-04-27 20:05:05 +04:00
while ( * string ) {
size_t c_size ;
codepoint_t s ;
codepoint_t t ;
2008-10-24 18:00:43 +04:00
s = next_codepoint_convenience ( ic , string , & c_size ) ;
2006-04-27 20:05:05 +04:00
string + = c_size ;
2008-10-24 04:51:03 +04:00
t = tolower_m ( s ) ;
2006-04-27 20:05:05 +04:00
if ( s ! = t ) {
2007-08-27 22:43:18 +04:00
return true ; /* that means it has upper case chars */
2006-04-27 20:05:05 +04:00
}
}
2007-08-27 22:43:18 +04:00
return false ;
2006-04-27 20:05:05 +04:00
}
/**
Convert a string to lower case , allocated with talloc
* */
_PUBLIC_ char * strlower_talloc ( TALLOC_CTX * ctx , const char * src )
{
size_t size = 0 ;
char * dest ;
2008-10-24 04:51:03 +04:00
struct smb_iconv_convenience * iconv_convenience = get_iconv_convenience ( ) ;
2006-04-27 20:05:05 +04:00
/* this takes advantage of the fact that upper/lower can't
change the length of a character by more than 1 byte */
2007-09-08 17:27:14 +04:00
dest = talloc_array ( ctx , char , 2 * ( strlen ( src ) ) + 1 ) ;
2006-04-27 20:05:05 +04:00
if ( dest = = NULL ) {
return NULL ;
}
while ( * src ) {
size_t c_size ;
2008-10-24 18:00:43 +04:00
codepoint_t c = next_codepoint_convenience ( iconv_convenience , src , & c_size ) ;
2006-04-27 20:05:05 +04:00
src + = c_size ;
2008-10-24 04:51:03 +04:00
c = tolower_m ( c ) ;
2006-04-27 20:05:05 +04:00
2009-04-23 17:24:38 +04:00
c_size = push_codepoint_convenience ( iconv_convenience , dest + size , c ) ;
2006-04-27 20:05:05 +04:00
if ( c_size = = - 1 ) {
talloc_free ( dest ) ;
return NULL ;
}
size + = c_size ;
}
dest [ size ] = 0 ;
2007-01-10 14:47:27 +03:00
/* trim it so talloc_append_string() works */
2007-09-08 17:27:14 +04:00
dest = talloc_realloc ( ctx , dest , char , size + 1 ) ;
2007-01-10 14:47:27 +03:00
2007-05-07 17:32:34 +04:00
talloc_set_name_const ( dest , dest ) ;
2006-04-27 20:05:05 +04:00
return dest ;
}
/**
Convert a string to UPPER case , allocated with talloc
2008-08-22 11:36:56 +04:00
source length limited to n bytes
2006-04-27 20:05:05 +04:00
* */
2008-08-22 11:36:56 +04:00
_PUBLIC_ char * strupper_talloc_n ( TALLOC_CTX * ctx , const char * src , size_t n )
2006-04-27 20:05:05 +04:00
{
size_t size = 0 ;
char * dest ;
2008-10-24 04:51:03 +04:00
struct smb_iconv_convenience * iconv_convenience = get_iconv_convenience ( ) ;
2006-04-27 20:05:05 +04:00
if ( ! src ) {
return NULL ;
}
/* this takes advantage of the fact that upper/lower can't
change the length of a character by more than 1 byte */
2008-08-22 11:36:56 +04:00
dest = talloc_array ( ctx , char , 2 * ( n + 1 ) ) ;
2006-04-27 20:05:05 +04:00
if ( dest = = NULL ) {
return NULL ;
}
2009-10-22 04:03:27 +04:00
while ( n - - & & * src ) {
2006-04-27 20:05:05 +04:00
size_t c_size ;
2008-10-24 18:12:14 +04:00
codepoint_t c = next_codepoint_convenience ( iconv_convenience , src , & c_size ) ;
2006-04-27 20:05:05 +04:00
src + = c_size ;
2008-10-24 04:51:03 +04:00
c = toupper_m ( c ) ;
2006-04-27 20:05:05 +04:00
2009-04-23 17:24:38 +04:00
c_size = push_codepoint_convenience ( iconv_convenience , dest + size , c ) ;
2006-04-27 20:05:05 +04:00
if ( c_size = = - 1 ) {
talloc_free ( dest ) ;
return NULL ;
}
size + = c_size ;
}
dest [ size ] = 0 ;
2007-01-10 14:47:27 +03:00
/* trim it so talloc_append_string() works */
2007-09-08 17:27:14 +04:00
dest = talloc_realloc ( ctx , dest , char , size + 1 ) ;
2007-01-10 14:47:27 +03:00
2007-05-07 17:32:34 +04:00
talloc_set_name_const ( dest , dest ) ;
2006-04-27 20:05:05 +04:00
return dest ;
}
2008-08-22 11:36:56 +04:00
/**
Convert a string to UPPER case , allocated with talloc
* */
_PUBLIC_ char * strupper_talloc ( TALLOC_CTX * ctx , const char * src )
{
return strupper_talloc_n ( ctx , src , src ? strlen ( src ) : 0 ) ;
}
2008-09-23 10:32:42 +04:00
/**
talloc_strdup ( ) a unix string to upper case .
* */
_PUBLIC_ char * talloc_strdup_upper ( TALLOC_CTX * ctx , const char * src )
{
return strupper_talloc ( ctx , src ) ;
}
2008-08-22 11:36:56 +04:00
2006-04-27 20:05:05 +04:00
/**
Convert a string to lower case .
* */
_PUBLIC_ void strlower_m ( char * s )
{
char * d ;
2008-02-21 18:41:38 +03:00
struct smb_iconv_convenience * iconv_convenience ;
2006-04-27 20:05:05 +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 ) */
while ( * s & & ! ( ( ( uint8_t ) * s ) & 0x80 ) ) {
* s = tolower ( ( uint8_t ) * s ) ;
s + + ;
}
if ( ! * s )
return ;
2008-10-24 04:51:03 +04:00
iconv_convenience = get_iconv_convenience ( ) ;
2008-02-21 18:41:38 +03:00
2006-04-27 20:05:05 +04:00
d = s ;
while ( * s ) {
size_t c_size , c_size2 ;
2008-10-24 18:00:43 +04:00
codepoint_t c = next_codepoint_convenience ( iconv_convenience , s , & c_size ) ;
2009-04-23 17:24:38 +04:00
c_size2 = push_codepoint_convenience ( iconv_convenience , d , tolower_m ( c ) ) ;
2006-04-27 20:05:05 +04:00
if ( c_size2 > c_size ) {
DEBUG ( 0 , ( " FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m \n " ,
2008-10-24 04:51:03 +04:00
c , tolower_m ( c ) , ( int ) c_size , ( int ) c_size2 ) ) ;
2006-04-27 20:05:05 +04:00
smb_panic ( " codepoint expansion in strlower_m \n " ) ;
}
s + = c_size ;
d + = c_size2 ;
}
* d = 0 ;
}
/**
Convert a string to UPPER case .
* */
_PUBLIC_ void strupper_m ( char * s )
{
char * d ;
2008-02-21 18:41:38 +03:00
struct smb_iconv_convenience * iconv_convenience ;
2006-04-27 20:05:05 +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 ) */
while ( * s & & ! ( ( ( uint8_t ) * s ) & 0x80 ) ) {
* s = toupper ( ( uint8_t ) * s ) ;
s + + ;
}
if ( ! * s )
return ;
2008-10-24 04:51:03 +04:00
iconv_convenience = get_iconv_convenience ( ) ;
2008-02-21 18:41:38 +03:00
2006-04-27 20:05:05 +04:00
d = s ;
while ( * s ) {
size_t c_size , c_size2 ;
2008-10-24 18:00:43 +04:00
codepoint_t c = next_codepoint_convenience ( iconv_convenience , s , & c_size ) ;
2009-04-23 17:24:38 +04:00
c_size2 = push_codepoint_convenience ( iconv_convenience , d , toupper_m ( c ) ) ;
2006-04-27 20:05:05 +04:00
if ( c_size2 > c_size ) {
DEBUG ( 0 , ( " FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m \n " ,
2008-10-24 04:51:03 +04:00
c , toupper_m ( c ) , ( int ) c_size , ( int ) c_size2 ) ) ;
2006-04-27 20:05:05 +04:00
smb_panic ( " codepoint expansion in strupper_m \n " ) ;
}
s + = c_size ;
d + = c_size2 ;
}
* d = 0 ;
}
2006-04-27 23:50:13 +04:00
/**
Find the number of ' c ' chars in a string
* */
2008-10-24 04:51:03 +04:00
_PUBLIC_ size_t count_chars_m ( const char * s , char c )
2006-04-27 23:50:13 +04:00
{
2008-10-24 06:39:09 +04:00
struct smb_iconv_convenience * ic = get_iconv_convenience ( ) ;
2006-04-27 23:50:13 +04:00
size_t count = 0 ;
while ( * s ) {
size_t size ;
2008-10-24 18:00:43 +04:00
codepoint_t c2 = next_codepoint_convenience ( ic , s , & size ) ;
2006-04-27 23:50:13 +04:00
if ( c2 = = c ) count + + ;
s + = size ;
}
return count ;
}
2008-10-24 05:40:09 +04:00
/**
* Copy a string from a char * unix src to a dos codepage string destination .
*
* @ return the number of bytes occupied by the string in the destination .
*
* @ param flags can include
* < dl >
* < dt > STR_TERMINATE < / dt > < dd > means include the null termination < / dd >
* < dt > STR_UPPER < / dt > < dd > means uppercase in the destination < / dd >
* < / dl >
*
* @ param dest_len the maximum length in bytes allowed in the
* destination . If @ p dest_len is - 1 then no maximum is used .
* */
static ssize_t push_ascii ( void * dest , const char * src , size_t dest_len , int flags )
{
size_t src_len ;
ssize_t ret ;
if ( flags & STR_UPPER ) {
char * tmpbuf = strupper_talloc ( NULL , src ) ;
if ( tmpbuf = = NULL ) {
return - 1 ;
}
ret = push_ascii ( dest , tmpbuf , dest_len , flags & ~ STR_UPPER ) ;
talloc_free ( tmpbuf ) ;
return ret ;
}
src_len = strlen ( src ) ;
if ( flags & ( STR_TERMINATE | STR_TERMINATE_ASCII ) )
src_len + + ;
2009-03-01 08:33:40 +03:00
return convert_string ( CH_UNIX , CH_DOS , src , src_len , dest , dest_len , false ) ;
2008-10-24 05:40:09 +04:00
}
/**
* Copy a string from a unix char * src to an ASCII destination ,
* allocating a buffer using talloc ( ) .
*
* @ param dest always set at least to NULL
*
* @ returns The number of bytes occupied by the string in the destination
* or - 1 in case of error .
* */
2009-03-02 00:24:34 +03:00
_PUBLIC_ bool push_ascii_talloc ( TALLOC_CTX * ctx , char * * dest , const char * src , size_t * converted_size )
2008-10-24 05:40:09 +04:00
{
2009-03-02 00:24:34 +03:00
size_t src_len = strlen ( src ) + 1 ;
2008-10-24 05:40:09 +04:00
* dest = NULL ;
2009-03-02 00:24:34 +03:00
return convert_string_talloc ( ctx , CH_UNIX , CH_DOS , src , src_len , ( void * * ) dest , converted_size , false ) ;
2008-10-24 05:40:09 +04:00
}
/**
* Copy a string from a dos codepage source to a unix char * destination .
*
* The resulting string in " dest " is always null terminated .
*
* @ param flags can have :
* < dl >
* < dt > STR_TERMINATE < / dt >
* < dd > STR_TERMINATE means the string in @ p src
* is null terminated , and src_len is ignored . < / dd >
* < / dl >
*
* @ param src_len is the length of the source area in bytes .
* @ returns the number of bytes occupied by the string in @ p src .
* */
static ssize_t pull_ascii ( char * dest , const void * src , size_t dest_len , size_t src_len , int flags )
{
size_t ret ;
if ( flags & ( STR_TERMINATE | STR_TERMINATE_ASCII ) ) {
if ( src_len = = ( size_t ) - 1 ) {
src_len = strlen ( ( const char * ) src ) + 1 ;
} else {
size_t len = strnlen ( ( const char * ) src , src_len ) ;
if ( len < src_len )
len + + ;
src_len = len ;
}
}
2009-03-01 08:33:40 +03:00
ret = convert_string ( CH_DOS , CH_UNIX , src , src_len , dest , dest_len , false ) ;
2008-10-24 05:40:09 +04:00
if ( dest_len )
dest [ MIN ( ret , dest_len - 1 ) ] = 0 ;
return src_len ;
}
/**
* Copy a string from a char * src to a unicode destination .
*
* @ returns the number of bytes occupied by the string in the destination .
*
* @ param flags can have :
*
* < dl >
* < dt > STR_TERMINATE < dd > means include the null termination .
* < dt > STR_UPPER < dd > means uppercase in the destination .
* < dt > STR_NOALIGN < dd > means don ' t do alignment .
* < / dl >
*
* @ param dest_len is the maximum length allowed in the
* destination . If dest_len is - 1 then no maxiumum is used .
* */
static ssize_t push_ucs2 ( void * dest , const char * src , size_t dest_len , int flags )
{
size_t len = 0 ;
size_t src_len = strlen ( src ) ;
size_t ret ;
if ( flags & STR_UPPER ) {
char * tmpbuf = strupper_talloc ( NULL , src ) ;
if ( tmpbuf = = NULL ) {
return - 1 ;
}
ret = push_ucs2 ( dest , tmpbuf , dest_len , flags & ~ STR_UPPER ) ;
talloc_free ( tmpbuf ) ;
return ret ;
}
if ( flags & STR_TERMINATE )
src_len + + ;
if ( ucs2_align ( NULL , dest , flags ) ) {
* ( char * ) dest = 0 ;
dest = ( void * ) ( ( char * ) dest + 1 ) ;
if ( dest_len ) dest_len - - ;
len + + ;
}
/* ucs2 is always a multiple of 2 bytes */
dest_len & = ~ 1 ;
2009-03-01 08:33:40 +03:00
ret = convert_string ( CH_UNIX , CH_UTF16 , src , src_len , dest , dest_len , false ) ;
2008-10-24 05:40:09 +04:00
if ( ret = = ( size_t ) - 1 ) {
return 0 ;
}
len + = ret ;
return len ;
}
/**
* Copy a string from a unix char * src to a UCS2 destination ,
* allocating a buffer using talloc ( ) .
*
* @ param dest always set at least to NULL
*
* @ returns The number of bytes occupied by the string in the destination
* or - 1 in case of error .
* */
2009-03-02 00:24:34 +03:00
_PUBLIC_ bool push_ucs2_talloc ( TALLOC_CTX * ctx , smb_ucs2_t * * dest , const char * src , size_t * converted_size )
2008-10-24 05:40:09 +04:00
{
2009-03-02 00:24:34 +03:00
size_t src_len = strlen ( src ) + 1 ;
2008-10-24 05:40:09 +04:00
* dest = NULL ;
2009-03-02 00:24:34 +03:00
return convert_string_talloc ( ctx , CH_UNIX , CH_UTF16 , src , src_len , ( void * * ) dest , converted_size , false ) ;
2008-10-24 05:40:09 +04:00
}
/**
* Copy a string from a unix char * src to a UTF - 8 destination , allocating a buffer using talloc
*
* @ param dest always set at least to NULL
*
* @ returns The number of bytes occupied by the string in the destination
* */
2009-03-02 00:24:34 +03:00
_PUBLIC_ bool push_utf8_talloc ( TALLOC_CTX * ctx , char * * dest , const char * src , size_t * converted_size )
2008-10-24 05:40:09 +04:00
{
2009-03-02 00:24:34 +03:00
size_t src_len = strlen ( src ) + 1 ;
2008-10-24 05:40:09 +04:00
* dest = NULL ;
2009-03-02 00:24:34 +03:00
return convert_string_talloc ( ctx , CH_UNIX , CH_UTF8 , src , src_len , ( void * * ) dest , converted_size , false ) ;
2008-10-24 05:40:09 +04:00
}
/**
Copy a string from a ucs2 source to a unix char * destination .
Flags can have :
STR_TERMINATE means the string in src is null terminated .
STR_NOALIGN means don ' t try to align .
if STR_TERMINATE is set then src_len is ignored if it is - 1.
src_len is the length of the source area in bytes
Return the number of bytes occupied by the string in src .
The resulting string in " dest " is always null terminated .
* */
static size_t pull_ucs2 ( char * dest , const void * src , size_t dest_len , size_t src_len , int flags )
{
size_t ret ;
if ( ucs2_align ( NULL , src , flags ) ) {
src = ( const void * ) ( ( const char * ) src + 1 ) ;
if ( src_len > 0 )
src_len - - ;
}
if ( flags & STR_TERMINATE ) {
if ( src_len = = ( size_t ) - 1 ) {
src_len = utf16_len ( src ) ;
} else {
src_len = utf16_len_n ( src , src_len ) ;
}
}
/* ucs2 is always a multiple of 2 bytes */
if ( src_len ! = ( size_t ) - 1 )
src_len & = ~ 1 ;
2009-03-01 08:33:40 +03:00
ret = convert_string ( CH_UTF16 , CH_UNIX , src , src_len , dest , dest_len , false ) ;
2008-10-24 05:40:09 +04:00
if ( dest_len )
dest [ MIN ( ret , dest_len - 1 ) ] = 0 ;
return src_len ;
}
/**
* Copy a string from a ASCII src to a unix char * destination , allocating a buffer using talloc
*
* @ param dest always set at least to NULL
*
* @ returns The number of bytes occupied by the string in the destination
* */
2009-03-02 00:24:34 +03:00
_PUBLIC_ bool pull_ascii_talloc ( TALLOC_CTX * ctx , char * * dest , const char * src , size_t * converted_size )
2008-10-24 05:40:09 +04:00
{
2009-03-02 00:24:34 +03:00
size_t src_len = strlen ( src ) + 1 ;
2008-10-24 05:40:09 +04:00
* dest = NULL ;
2009-03-02 00:24:34 +03:00
return convert_string_talloc ( ctx , CH_DOS , CH_UNIX , src , src_len , ( void * * ) dest , converted_size , false ) ;
2008-10-24 05:40:09 +04:00
}
/**
* Copy a string from a UCS2 src to a unix char * destination , allocating a buffer using talloc
*
* @ param dest always set at least to NULL
*
* @ returns The number of bytes occupied by the string in the destination
* */
2009-03-02 00:24:34 +03:00
_PUBLIC_ bool pull_ucs2_talloc ( TALLOC_CTX * ctx , char * * dest , const smb_ucs2_t * src , size_t * converted_size )
2008-10-24 05:40:09 +04:00
{
2009-03-02 00:24:34 +03:00
size_t src_len = utf16_len ( src ) ;
2008-10-24 05:40:09 +04:00
* dest = NULL ;
2009-03-02 00:24:34 +03:00
return convert_string_talloc ( ctx , CH_UTF16 , CH_UNIX , src , src_len , ( void * * ) dest , converted_size , false ) ;
2008-10-24 05:40:09 +04:00
}
/**
* Copy a string from a UTF - 8 src to a unix char * destination , allocating a buffer using talloc
*
* @ param dest always set at least to NULL
*
* @ returns The number of bytes occupied by the string in the destination
* */
2009-03-02 00:24:34 +03:00
_PUBLIC_ bool pull_utf8_talloc ( TALLOC_CTX * ctx , char * * dest , const char * src , size_t * converted_size )
2008-10-24 05:40:09 +04:00
{
2009-03-02 00:24:34 +03:00
size_t src_len = strlen ( src ) + 1 ;
2008-10-24 05:40:09 +04:00
* dest = NULL ;
2009-03-02 00:24:34 +03:00
return convert_string_talloc ( ctx , CH_UTF8 , CH_UNIX , src , src_len , ( void * * ) dest , converted_size , false ) ;
2008-10-24 05:40:09 +04:00
}
/**
Copy a string from a char * src to a unicode or ascii
dos codepage destination choosing unicode or ascii based on the
flags in the SMB buffer starting at base_ptr .
Return the number of bytes occupied by the string in the destination .
flags can have :
STR_TERMINATE means include the null termination .
STR_UPPER means uppercase in the destination .
STR_ASCII use ascii even with unicode packet .
STR_NOALIGN means don ' t do alignment .
dest_len is the maximum length allowed in the destination . If dest_len
is - 1 then no maxiumum is used .
* */
_PUBLIC_ ssize_t push_string ( void * dest , const char * src , size_t dest_len , int flags )
{
if ( flags & STR_ASCII ) {
return push_ascii ( dest , src , dest_len , flags ) ;
} else if ( flags & STR_UNICODE ) {
return push_ucs2 ( dest , src , dest_len , flags ) ;
} else {
smb_panic ( " push_string requires either STR_ASCII or STR_UNICODE flag to be set " ) ;
return - 1 ;
}
}
/**
Copy a string from a unicode or ascii source ( depending on
the packet flags ) to a char * destination .
Flags can have :
STR_TERMINATE means the string in src is null terminated .
STR_UNICODE means to force as unicode .
STR_ASCII use ascii even with unicode packet .
STR_NOALIGN means don ' t do alignment .
if STR_TERMINATE is set then src_len is ignored is it is - 1
src_len is the length of the source area in bytes .
Return the number of bytes occupied by the string in src .
The resulting string in " dest " is always null terminated .
* */
_PUBLIC_ ssize_t pull_string ( char * dest , const void * src , size_t dest_len , size_t src_len , int flags )
{
if ( flags & STR_ASCII ) {
return pull_ascii ( dest , src , dest_len , src_len , flags ) ;
} else if ( flags & STR_UNICODE ) {
return pull_ucs2 ( dest , src , dest_len , src_len , flags ) ;
} else {
smb_panic ( " pull_string requires either STR_ASCII or STR_UNICODE flag to be set " ) ;
return - 1 ;
}
}
2008-10-24 16:26:46 +04:00
/**
* Convert string from one encoding to another , making error checking etc
*
* @ param src pointer to source string ( multibyte or singlebyte )
* @ param srclen length of the source string in bytes
* @ param dest pointer to destination string ( multibyte or singlebyte )
* @ param destlen maximal length allowed for string
* @ returns the number of bytes occupied in the destination
* */
2009-03-01 14:59:58 +03:00
_PUBLIC_ size_t convert_string ( charset_t from , charset_t to ,
2008-10-24 16:26:46 +04:00
void const * src , size_t srclen ,
2009-03-01 21:55:46 +03:00
void * dest , size_t destlen ,
bool allow_badcharcnv )
2008-10-24 16:26:46 +04:00
{
2009-03-01 21:55:46 +03:00
size_t ret ;
if ( ! convert_string_convenience ( get_iconv_convenience ( ) , from , to ,
2008-10-24 16:26:46 +04:00
src , srclen ,
2009-03-01 21:55:46 +03:00
dest , destlen , & ret ,
allow_badcharcnv ) )
return - 1 ;
return ret ;
2008-10-24 16:26:46 +04:00
}
/**
* Convert between character sets , allocating a new buffer using talloc for the result .
*
* @ param srclen length of source buffer .
* @ param dest always set at least to NULL
2009-03-01 21:55:46 +03:00
* @ param converted_size Size in bytes of the converted string
2008-10-24 16:26:46 +04:00
* @ note - 1 is not accepted for srclen .
*
2009-03-01 21:55:46 +03:00
* @ returns boolean indication whether the conversion succeeded
2008-10-24 16:26:46 +04:00
* */
2009-03-01 21:55:46 +03:00
_PUBLIC_ bool convert_string_talloc ( TALLOC_CTX * ctx ,
2008-10-24 16:26:46 +04:00
charset_t from , charset_t to ,
void const * src , size_t srclen ,
2009-03-09 23:49:44 +03:00
void * dest , size_t * converted_size ,
2009-03-01 21:55:46 +03:00
bool allow_badcharcnv )
2008-10-24 16:26:46 +04:00
{
return convert_string_talloc_convenience ( ctx , get_iconv_convenience ( ) ,
2009-03-01 08:33:40 +03:00
from , to , src , srclen , dest ,
2009-03-01 21:55:46 +03:00
converted_size ,
2009-03-01 08:33:40 +03:00
allow_badcharcnv ) ;
2008-10-24 16:26:46 +04:00
}
2008-10-24 18:00:43 +04:00
_PUBLIC_ codepoint_t next_codepoint ( const char * str , size_t * size )
{
return next_codepoint_convenience ( get_iconv_convenience ( ) , str , size ) ;
}
2009-04-23 17:24:38 +04:00
_PUBLIC_ ssize_t push_codepoint ( char * str , codepoint_t c )
{
2009-04-23 19:46:54 +04:00
return push_codepoint_convenience ( get_iconv_convenience ( ) , str , c ) ;
2009-04-23 17:24:38 +04:00
}