0001-01-01 02:30:17 +02:30
/*
Unix SMB / Netbios implementation .
0001-01-01 02:30:17 +02:30
Version 3.0
0001-01-01 02:30:17 +02:30
Samba utility functions
0001-01-01 02:30:17 +02:30
Copyright ( C ) Andrew Tridgell 1992 - 2001
0001-01-01 02:30:17 +02:30
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"
0001-01-01 02:30:17 +02:30
# ifndef MAXUNI
# define MAXUNI 1024
# endif
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*******************************************************************
0001-01-01 02:30:17 +02:30
Write a string in ( little - endian ) unicode format . src is in
the current DOS codepage . len is the length in bytes of the
string pointed to by dst .
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if null_terminate is True then null terminate the packet ( adds 2 bytes )
0001-01-01 02:30:17 +02:30
the return value is the length in bytes consumed by the string , including the
0001-01-01 02:30:17 +02:30
null termination if applied
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
size_t dos_PutUniCode ( char * dst , const char * src , ssize_t len , BOOL null_terminate )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
return push_ucs2 ( NULL , dst , src , len ,
STR_UNICODE | STR_NOALIGN | ( null_terminate ? STR_TERMINATE : 0 ) ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*******************************************************************
0001-01-01 02:30:17 +02:30
Skip past a unicode string , but not more than len . Always move
past a terminating zero if found .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
char * skip_unibuf ( char * src , size_t len )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
char * srcend = src + len ;
while ( src < srcend & & SVAL ( src , 0 ) )
src + = 2 ;
if ( ! SVAL ( src , 0 ) )
src + = 2 ;
return src ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/* Copy a string from little-endian or big-endian unicode source (depending
* on flags ) to internal samba format destination
*/
int rpcstr_pull ( char * dest , void * src , int dest_len , int src_len , int flags )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
if ( dest_len = = - 1 ) dest_len = MAXUNI - 3 ;
return pull_ucs2 ( NULL , dest , src , dest_len , src_len , flags | STR_UNICODE | STR_NOALIGN ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/* Copy a string from a unistr2 source to internal samba format
destination . Use this instead of direct calls to rpcstr_pull ( ) to avoid
having to determine whether the source string is null terminated . */
int rpcstr_pull_unistr2_fstring ( char * dest , UNISTR2 * src )
{
return pull_ucs2 ( NULL , dest , src - > buffer , sizeof ( fstring ) ,
src - > uni_str_len * 2 , 0 ) ;
}
0001-01-01 02:30:17 +02:30
/* Converts a string from internal samba format to unicode
*/
int rpcstr_push ( void * dest , const char * src , int dest_len , int flags )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
return push_ucs2 ( NULL , dest , src , dest_len , flags | STR_UNICODE | STR_NOALIGN ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/*******************************************************************
0001-01-01 02:30:17 +02:30
Return a DOS codepage version of a little - endian unicode string .
0001-01-01 02:30:17 +02:30
len is the filename length ( ignoring any terminating zero ) in uin16
units . Always null terminates .
Hack alert : uses fixed buffer ( s ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
char * dos_unistrn2 ( const uint16 * src , int len )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
static char lbufs [ 8 ] [ MAXUNI ] ;
static int nexti ;
char * lbuf = lbufs [ nexti ] ;
nexti = ( nexti + 1 ) % 8 ;
pull_ucs2 ( NULL , lbuf , src , MAXUNI - 3 , len * 2 , STR_NOALIGN ) ;
return lbuf ;
0001-01-01 02:30:17 +02:30
}
/*******************************************************************
0001-01-01 02:30:17 +02:30
Convert a ( little - endian ) UNISTR2 structure to an ASCII string
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
void unistr2_to_ascii ( char * dest , const UNISTR2 * str , size_t maxlen )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
if ( str = = NULL ) {
* dest = ' \0 ' ;
return ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
pull_ucs2 ( NULL , dest , str - > buffer , maxlen , str - > uni_str_len * 2 , STR_NOALIGN ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*******************************************************************
0001-01-01 02:30:17 +02:30
Return a number stored in a buffer
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
uint32 buffer2_to_uint32 ( BUFFER2 * str )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
if ( str - > buf_len = = 4 )
return IVAL ( str - > buffer , 0 ) ;
else
return 0 ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/*******************************************************************
Mapping tables for UNICODE character . Allows toupper / tolower and
isXXX functions to work .
0001-01-01 02:30:17 +02:30
tridge : split into 2 pieces . This saves us 5 / 6 of the memory
with a small speed penalty
The magic constants are the lower / upper range of the tables two
parts
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
typedef struct {
smb_ucs2_t lower ;
smb_ucs2_t upper ;
unsigned char flags ;
} smb_unicode_table_t ;
0001-01-01 02:30:17 +02:30
# define TABLE1_BOUNDARY 9450
# define TABLE2_BOUNDARY 64256
0001-01-01 02:30:17 +02:30
static smb_unicode_table_t map_table1 [ ] = {
# include "unicode_map_table1.h"
} ;
static smb_unicode_table_t map_table2 [ ] = {
# include "unicode_map_table2.h"
0001-01-01 02:30:17 +02:30
} ;
0001-01-01 02:30:17 +02:30
static unsigned char map_table_flags ( smb_ucs2_t v )
{
0001-01-01 02:30:17 +02:30
v = SVAL ( & v , 0 ) ;
0001-01-01 02:30:17 +02:30
if ( v < TABLE1_BOUNDARY ) return map_table1 [ v ] . flags ;
if ( v > = TABLE2_BOUNDARY ) return map_table2 [ v - TABLE2_BOUNDARY ] . flags ;
0001-01-01 02:30:17 +02:30
return 0 ;
}
static smb_ucs2_t map_table_lower ( smb_ucs2_t v )
{
0001-01-01 02:30:17 +02:30
v = SVAL ( & v , 0 ) ;
0001-01-01 02:30:17 +02:30
if ( v < TABLE1_BOUNDARY ) return map_table1 [ v ] . lower ;
if ( v > = TABLE2_BOUNDARY ) return map_table2 [ v - TABLE2_BOUNDARY ] . lower ;
0001-01-01 02:30:17 +02:30
return v ;
}
static smb_ucs2_t map_table_upper ( smb_ucs2_t v )
{
0001-01-01 02:30:17 +02:30
v = SVAL ( & v , 0 ) ;
0001-01-01 02:30:17 +02:30
if ( v < TABLE1_BOUNDARY ) return map_table1 [ v ] . upper ;
if ( v > = TABLE2_BOUNDARY ) return map_table2 [ v - TABLE2_BOUNDARY ] . upper ;
0001-01-01 02:30:17 +02:30
return v ;
}
0001-01-01 02:30:17 +02:30
/*******************************************************************
Is an upper case wchar .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
int isupper_w ( smb_ucs2_t val )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
return ( map_table_flags ( val ) & UNI_UPPER ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*******************************************************************
Is a lower case wchar .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
int islower_w ( smb_ucs2_t val )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
return ( map_table_flags ( val ) & UNI_LOWER ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*******************************************************************
Convert a wchar to upper case .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
smb_ucs2_t toupper_w ( smb_ucs2_t val )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
val = map_table_upper ( val ) ;
val = SVAL ( & val , 0 ) ;
return val ;
0001-01-01 02:30:17 +02:30
}
/*******************************************************************
Convert a wchar to lower case .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
smb_ucs2_t tolower_w ( smb_ucs2_t val )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
val = map_table_lower ( val ) ;
val = SVAL ( & val , 0 ) ;
return val ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/*******************************************************************
0001-01-01 02:30:17 +02:30
Count the number of characters in a smb_ucs2_t string .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
size_t strlen_w ( const smb_ucs2_t * src )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
size_t len ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
for ( len = 0 ; * src + + ; len + + ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
return len ;
0001-01-01 02:30:17 +02:30
}
/*******************************************************************
0001-01-01 02:30:17 +02:30
wide strchr ( )
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
smb_ucs2_t * strchr_w ( const smb_ucs2_t * s , smb_ucs2_t c )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
while ( * s ! = 0 ) {
if ( c = = * s ) return ( smb_ucs2_t * ) s ;
0001-01-01 02:30:17 +02:30
s + + ;
}
0001-01-01 02:30:17 +02:30
return NULL ;
0001-01-01 02:30:17 +02:30
}
/*******************************************************************
Convert a string to lower case .
0001-01-01 02:30:17 +02:30
return True if any char is converted
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
BOOL strlower_w ( smb_ucs2_t * s )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
BOOL ret = False ;
0001-01-01 02:30:17 +02:30
while ( * s ) {
0001-01-01 02:30:17 +02:30
if ( isupper_w ( * s ) ) {
0001-01-01 02:30:17 +02:30
* s = tolower_w ( * s ) ;
0001-01-01 02:30:17 +02:30
ret = True ;
}
0001-01-01 02:30:17 +02:30
s + + ;
}
0001-01-01 02:30:17 +02:30
return ret ;
0001-01-01 02:30:17 +02:30
}
/*******************************************************************
Convert a string to upper case .
0001-01-01 02:30:17 +02:30
return True if any char is converted
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
BOOL strupper_w ( smb_ucs2_t * s )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
BOOL ret = False ;
0001-01-01 02:30:17 +02:30
while ( * s ) {
0001-01-01 02:30:17 +02:30
if ( islower_w ( * s ) ) {
0001-01-01 02:30:17 +02:30
* s = toupper_w ( * s ) ;
0001-01-01 02:30:17 +02:30
ret = True ;
}
0001-01-01 02:30:17 +02:30
s + + ;
}
0001-01-01 02:30:17 +02:30
return ret ;
0001-01-01 02:30:17 +02:30
}
/*******************************************************************
0001-01-01 02:30:17 +02:30
case insensitive string comparison
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
int strcasecmp_w ( const smb_ucs2_t * a , const smb_ucs2_t * b )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
while ( * b & & tolower_w ( * a ) = = tolower_w ( * b ) ) { a + + ; b + + ; }
return ( tolower_w ( * a ) - tolower_w ( * b ) ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/*******************************************************************
duplicate string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
smb_ucs2_t * strdup_w ( const smb_ucs2_t * src )
{
smb_ucs2_t * dest ;
uint32 len ;
len = strlen_w ( src ) ;
dest = ( smb_ucs2_t * ) malloc ( ( len + 1 ) * sizeof ( smb_ucs2_t ) ) ;
if ( ! dest ) {
DEBUG ( 0 , ( " strdup_w: out of memory! \n " ) ) ;
return NULL ;
}
memcpy ( dest , src , ( len + 1 ) * sizeof ( smb_ucs2_t ) ) ;
return dest ;
}
/*******************************************************************
copy a string with max len
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
smb_ucs2_t * strncpy_w ( smb_ucs2_t * dest , const smb_ucs2_t * src , const size_t max )
{
size_t len ;
if ( ! dest | | ! src ) return NULL ;
for ( len = 0 ; ( src [ len ] ! = 0 ) & & ( len < max ) ; len + + )
dest [ len ] = src [ len ] ;
while ( len < max )
dest [ len + + ] = 0 ;
return dest ;
}
/*******************************************************************
append a string of len bytes and add a terminator
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
smb_ucs2_t * strncat_w ( smb_ucs2_t * dest , const smb_ucs2_t * src , const size_t max )
{
size_t start ;
size_t len ;
if ( ! dest | | ! src ) return NULL ;
start = strlen_w ( dest ) ;
len = strlen_w ( src ) ;
if ( len > max ) len = max ;
memcpy ( & dest [ start ] , src , len ) ;
dest [ start + len + 1 ] = 0 ;
return dest ;
}
0001-01-01 02:30:17 +02:30
/*
The * _wa ( ) functions take a combination of 7 bit ascii
and wide characters They are used so that you can use string
functions combining C string constants with ucs2 strings
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
The char * arguments must NOT be multibyte - to be completely sure
of this only pass string constants */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
void pstrcpy_wa ( smb_ucs2_t * dest , const char * src )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
int i ;
for ( i = 0 ; i < PSTRING_LEN ; i + + ) {
dest [ i ] = UCS2_CHAR ( src [ i ] ) ;
if ( src [ i ] = = 0 ) return ;
0001-01-01 02:30:17 +02:30
}
}
0001-01-01 02:30:17 +02:30
int strcmp_wa ( const smb_ucs2_t * a , const char * b )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
while ( * b & & * a = = UCS2_CHAR ( * b ) ) { a + + ; b + + ; }
return ( * a - UCS2_CHAR ( * b ) ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
smb_ucs2_t * strchr_wa ( const smb_ucs2_t * s , char c )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
while ( * s ! = 0 ) {
if ( UCS2_CHAR ( c ) = = * s ) return ( smb_ucs2_t * ) s ;
0001-01-01 02:30:17 +02:30
s + + ;
}
0001-01-01 02:30:17 +02:30
return NULL ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
smb_ucs2_t * strrchr_wa ( const smb_ucs2_t * s , char c )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
const smb_ucs2_t * p = s ;
int len = strlen_w ( s ) ;
if ( len = = 0 ) return NULL ;
p + = ( len - 1 ) ;
0001-01-01 02:30:17 +02:30
do {
0001-01-01 02:30:17 +02:30
if ( UCS2_CHAR ( c ) = = * p ) return ( smb_ucs2_t * ) p ;
0001-01-01 02:30:17 +02:30
} while ( p - - ! = s ) ;
0001-01-01 02:30:17 +02:30
return NULL ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
smb_ucs2_t * strpbrk_wa ( const smb_ucs2_t * s , const char * p )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
while ( * s ! = 0 ) {
int i ;
for ( i = 0 ; p [ i ] & & * s ! = UCS2_CHAR ( p [ i ] ) ; i + + )
;
if ( p [ i ] ) return ( smb_ucs2_t * ) s ;
0001-01-01 02:30:17 +02:30
s + + ;
}
0001-01-01 02:30:17 +02:30
return NULL ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/*******************************************************************
copy a string with max len
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
smb_ucs2_t * strncpy_wa ( smb_ucs2_t * dest , const char * src , const size_t max )
{
smb_ucs2_t * ucs2_src ;
if ( ! dest | | ! src ) return NULL ;
ucs2_src = ( smb_ucs2_t * ) malloc ( ( strlen ( src ) + 1 ) * sizeof ( smb_ucs2_t ) ) ;
if ( ! ucs2_src ) {
DEBUG ( 0 , ( " strncpy_wa: out of memory! \n " ) ) ;
return NULL ;
}
push_ucs2 ( NULL , ucs2_src , src , - 1 , STR_TERMINATE | STR_NOALIGN ) ;
strncpy_w ( dest , ucs2_src , max ) ;
SAFE_FREE ( ucs2_src ) ;
return dest ;
}
/*******************************************************************
append a string of len bytes and add a terminator
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
smb_ucs2_t * strncat_wa ( smb_ucs2_t * dest , const char * src , const size_t max )
{
smb_ucs2_t * ucs2_src ;
if ( ! dest | | ! src ) return NULL ;
ucs2_src = ( smb_ucs2_t * ) malloc ( ( strlen ( src ) + 1 ) * sizeof ( smb_ucs2_t ) ) ;
if ( ! ucs2_src ) {
DEBUG ( 0 , ( " strncat_wa: out of memory! \n " ) ) ;
return NULL ;
}
push_ucs2 ( NULL , ucs2_src , src , - 1 , STR_TERMINATE | STR_NOALIGN ) ;
strncat_w ( dest , ucs2_src , max ) ;
SAFE_FREE ( ucs2_src ) ;
return dest ;
}