#include "includes.h"
smb_ucs2_t wchar_list_sep[] = { (smb_ucs2_t)' ', (smb_ucs2_t)'\t', (smb_ucs2_t)',',
(smb_ucs2_t)';', (smb_ucs2_t)':', (smb_ucs2_t)'\n',
(smb_ucs2_t)'\r', 0 };
static smb_ucs2_t *doscp_to_ucs2;
static uint16 *ucs2_to_doscp;
static smb_ucs2_t *unixcp_to_ucs2;
static uint16 *ucs2_to_unixcp;
#ifndef MAXUNI
#define MAXUNI 1024
#endif
size_t unix_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
{
size_t ret = 0;
while (*src && (len >= 2)) {
size_t skip = get_character_len(*src);
smb_ucs2_t val = (*src & 0xff);
if (skip == 2)
val = ((val << 8) | (src[1] & 0xff));
SSVAL(dst,ret,unixcp_to_ucs2[val]);
ret += 2;
len -= 2;
if (skip)
src += skip;
else
src++;
}
if (null_terminate) {
SSVAL(dst,ret,0);
ret += 2;
}
return(ret);
}
size_t dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
{
size_t ret = 0;
while (*src && (len >= 2)) {
size_t skip = get_character_len(*src);
smb_ucs2_t val = (*src & 0xff);
if (skip == 2)
val = ((val << 8) | (src[1] & 0xff));
SSVAL(dst,ret,doscp_to_ucs2[val]);
ret += 2;
len -= 2;
if (skip)
src += skip;
else
src++;
}
if (null_terminate) {
SSVAL(dst,ret,0);
ret += 2;
}
return(ret);
}
void unistr_to_dos(char *dest, const char *src, size_t len)
{
char *destend = dest + len;
while (dest < destend) {
uint16 ucs2_val = SVAL(src,0);
uint16 cp_val = ucs2_to_doscp[ucs2_val];
src += 2;
if (ucs2_val == 0)
break;
if (cp_val < 256)
*dest++ = (char)cp_val;
else {
*dest++ = (cp_val >> 8) & 0xff;
*dest++ = (cp_val & 0xff);
}
}
*dest = 0;
}
char *skip_unibuf(char *src, size_t len)
{
char *srcend = src + len;
while (src < srcend && SVAL(src,0))
src += 2;
if(!SVAL(src,0))
src += 2;
return src;
}
char *dos_unistrn2(uint16 *src, int len)
{
static char lbufs[8][MAXUNI];
static int nexti;
char *lbuf = lbufs[nexti];
char *p;
nexti = (nexti+1)%8;
for (p = lbuf; (len > 0) && (p-lbuf < MAXUNI-3) && *src; len--, src++) {
uint16 ucs2_val = SVAL(src,0);
uint16 cp_val = ucs2_to_doscp[ucs2_val];
if (cp_val < 256)
*p++ = (char)cp_val;
else {
*p++ = (cp_val >> 8) & 0xff;
*p++ = (cp_val & 0xff);
}
}
*p = 0;
return lbuf;
}
static char lbufs[8][MAXUNI];
static int nexti;
char *dos_unistr2(uint16 *src)
{
char *lbuf = lbufs[nexti];
char *p;
nexti = (nexti+1)%8;
for (p = lbuf; (p-lbuf < MAXUNI-3) && *src; src++) {
uint16 ucs2_val = SVAL(src,0);
uint16 cp_val = ucs2_to_doscp[ucs2_val];
if (cp_val < 256)
*p++ = (char)cp_val;
else {
*p++ = (cp_val >> 8) & 0xff;
*p++ = (cp_val & 0xff);
}
}
*p = 0;
return lbuf;
}
char *dos_unistr2_to_str(UNISTR2 *str)
{
char *lbuf = lbufs[nexti];
char *p;
uint16 *src = str->buffer;
nexti = (nexti+1)%8;
for (p = lbuf; (p - lbuf < MAXUNI-3) && (src - str->buffer < str->uni_str_len) && *src; src++) {
uint16 ucs2_val = SVAL(src,0);
uint16 cp_val = ucs2_to_doscp[ucs2_val];
if (cp_val < 256)
*p++ = (char)cp_val;
else {
*p++ = (cp_val >> 8) & 0xff;
*p++ = (cp_val & 0xff);
}
}
*p = 0;
return lbuf;
}
void ascii_to_unistr(uint16 *dest, const char *src, int maxlen)
{
uint16 *destend = dest + maxlen;
char c;
while (dest < destend) {
c = *(src++);
if (c == 0)
break;
SSVAL(dest, 0, c);
dest++;
}
*dest = 0;
}
void unistr_to_ascii(char *dest, const uint16 *src, int len)
{
char *destend = dest + len;
uint16 c;
if (src == NULL) {
*dest = '\0';
return;
}
while (dest < destend) {
c = SVAL(src, 0);
src++;
if (c == 0)
break;
*(dest++) = (char)c;
}
*dest = 0;
return;
}
void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
{
char *p;
uint16 *src;
size_t len;
if (str == NULL) {
*dest='\0';
return;
}
src = str->buffer;
len = MIN(str->uni_str_len, maxlen);
if (len == 0) {
*dest='\0';
return;
}
for (p = dest; (p-dest < maxlen-3) && (src - str->buffer < str->uni_str_len) && *src; src++) {
uint16 ucs2_val = SVAL(src,0);
uint16 cp_val = ucs2_to_doscp[ucs2_val];
if (cp_val < 256)
*p++ = (char)cp_val;
else {
*p++ = (cp_val >> 8) & 0xff;
*p++ = (cp_val & 0xff);
}
}
*p = 0;
}
uint32 buffer2_to_uint32(BUFFER2 *str)
{
if (str->buf_len == 4)
return IVAL(str->buffer, 0);
else
return 0;
}
char *dos_buffer2_to_str(BUFFER2 *str)
{
char *lbuf = lbufs[nexti];
char *p;
uint16 *src = str->buffer;
nexti = (nexti+1)%8;
for (p = lbuf; (p - lbuf < sizeof(str->buffer)-3) && (src - str->buffer < str->buf_len/2) && *src; src++) {
uint16 ucs2_val = SVAL(src,0);
uint16 cp_val = ucs2_to_doscp[ucs2_val];
if (cp_val < 256)
*p++ = (char)cp_val;
else {
*p++ = (cp_val >> 8) & 0xff;
*p++ = (cp_val & 0xff);
}
}
*p = 0;
return lbuf;
}
char *dos_buffer2_to_multistr(BUFFER2 *str)
{
char *lbuf = lbufs[nexti];
char *p;
uint16 *src = str->buffer;
nexti = (nexti+1)%8;
for (p = lbuf; (p - lbuf < sizeof(str->buffer)-3) && (src - str->buffer < str->buf_len/2); src++) {
if (*src == 0) {
*p++ = ' ';
} else {
uint16 ucs2_val = SVAL(src,0);
uint16 cp_val = ucs2_to_doscp[ucs2_val];
if (cp_val < 256)
*p++ = (char)cp_val;
else {
*p++ = (cp_val >> 8) & 0xff;
*p++ = (cp_val & 0xff);
}
}
}
*p = 0;
return lbuf;
}
size_t dos_struni2(char *dst, const char *src, size_t max_len)
{
size_t len = 0;
if (dst == NULL)
return 0;
if (src != NULL) {
for (; (len < max_len-2) && *src; len++, dst +=2) {
size_t skip = get_character_len(*src);
smb_ucs2_t val = (*src & 0xff);
if (skip == 2)
val = ((val << 8) | (src[1] & 0xff));
SSVAL(dst,0,doscp_to_ucs2[val]);
if (skip)
src += skip;
else
src++;
}
}
SSVAL(dst,0,0);
return len;
}
char *dos_unistr(char *buf)
{
char *lbuf = lbufs[nexti];
uint16 *src = (uint16 *)buf;
char *p;
nexti = (nexti+1)%8;
for (p = lbuf; (p-lbuf < MAXUNI-3) && *src; src++) {
uint16 ucs2_val = SVAL(src,0);
uint16 cp_val = ucs2_to_doscp[ucs2_val];
if (cp_val < 256)
*p++ = (char)cp_val;
else {
*p++ = (cp_val >> 8) & 0xff;
*p++ = (cp_val & 0xff);
}
}
*p = 0;
return lbuf;
}
int unistrcpy(char *dst, char *src)
{
int num_wchars = 0;
uint16 *wsrc = (uint16 *)src;
uint16 *wdst = (uint16 *)dst;
while (*wsrc) {
*wdst++ = *wsrc++;
num_wchars++;
}
*wdst = 0;
return num_wchars;
}
static void free_maps(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
{
if (*pp_ucs2_to_cp == *pp_cp_to_ucs2) {
*pp_ucs2_to_cp = NULL;
}
SAFE_FREE(*pp_cp_to_ucs2);
SAFE_FREE(*pp_ucs2_to_cp);
}
void default_unicode_map(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
{
int i;
free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
if ((*pp_ucs2_to_cp = (uint16 *)malloc(2*65536)) == NULL) {
DEBUG(0,("default_unicode_map: malloc fail for ucs2_to_cp size %u.\n", 2*65536));
abort();
}
*pp_cp_to_ucs2 = *pp_ucs2_to_cp;
for (i = 0; i < 65536; i++)
(*pp_cp_to_ucs2)[i] = i;
}
BOOL load_unicode_map(const char *codepage, smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
{
pstring unicode_map_file_name;
FILE *fp = NULL;
SMB_STRUCT_STAT st;
smb_ucs2_t *cp_to_ucs2 = *pp_cp_to_ucs2;
uint16 *ucs2_to_cp = *pp_ucs2_to_cp;
size_t cp_to_ucs2_size;
size_t ucs2_to_cp_size;
size_t i;
size_t size;
char buf[UNICODE_MAP_HEADER_SIZE];
DEBUG(5, ("load_unicode_map: loading unicode map for codepage %s.\n", codepage));
if (*codepage == '\0')
goto clean_and_exit;
if(strlen(lp_codepagedir()) + 13 + strlen(codepage) >
sizeof(unicode_map_file_name)) {
DEBUG(0,("load_unicode_map: filename too long to load\n"));
goto clean_and_exit;
}
pstrcpy(unicode_map_file_name, lp_codepagedir());
pstrcat(unicode_map_file_name, "/");
pstrcat(unicode_map_file_name, "unicode_map.");
pstrcat(unicode_map_file_name, codepage);
if(sys_stat(unicode_map_file_name,&st)!=0) {
DEBUG(0,("load_unicode_map: filename %s does not exist.\n",
unicode_map_file_name));
goto clean_and_exit;
}
size = st.st_size;
if ((size != UNICODE_MAP_HEADER_SIZE + 4*65536) && (size != UNICODE_MAP_HEADER_SIZE +(2*256 + 2*65536))) {
DEBUG(0,("load_unicode_map: file %s is an incorrect size for a \
unicode map file (size=%d).\n", unicode_map_file_name, (int)size));
goto clean_and_exit;
}
if((fp = sys_fopen( unicode_map_file_name, "r")) == NULL) {
DEBUG(0,("load_unicode_map: cannot open file %s. Error was %s\n",
unicode_map_file_name, strerror(errno)));
goto clean_and_exit;
}
if(fread( buf, 1, UNICODE_MAP_HEADER_SIZE, fp)!=UNICODE_MAP_HEADER_SIZE) {
DEBUG(0,("load_unicode_map: cannot read header from file %s. Error was %s\n",
unicode_map_file_name, strerror(errno)));
goto clean_and_exit;
}
if(SVAL(buf,UNICODE_MAP_VERSION_OFFSET) != UNICODE_MAP_FILE_VERSION_ID) {
DEBUG(0,("load_unicode_map: filename %s has incorrect version id. \
Needed %hu, got %hu.\n",
unicode_map_file_name, (uint16)UNICODE_MAP_FILE_VERSION_ID,
SVAL(buf,UNICODE_MAP_VERSION_OFFSET)));
goto clean_and_exit;
}
if(!strequal(&buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], codepage)) {
DEBUG(0,("load_unicode_map: codepage %s in file %s is not the same as that \
requested (%s).\n", &buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], unicode_map_file_name, codepage ));
goto clean_and_exit;
}
ucs2_to_cp_size = 2*65536;
if (size == UNICODE_MAP_HEADER_SIZE + 4*65536) {
cp_to_ucs2_size = 2*65536;
} else {
cp_to_ucs2_size = 2*256;
}
free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
if ((cp_to_ucs2 = (smb_ucs2_t *)malloc(cp_to_ucs2_size)) == NULL) {
DEBUG(0,("load_unicode_map: malloc fail for cp_to_ucs2 size %u.\n", cp_to_ucs2_size ));
goto clean_and_exit;
}
if ((ucs2_to_cp = (uint16 *)malloc(ucs2_to_cp_size)) == NULL) {
DEBUG(0,("load_unicode_map: malloc fail for ucs2_to_cp size %u.\n", ucs2_to_cp_size ));
goto clean_and_exit;
}
if(fread( (char *)cp_to_ucs2, 1, cp_to_ucs2_size, fp)!=cp_to_ucs2_size) {
DEBUG(0,("load_unicode_map: cannot read cp_to_ucs2 from file %s. Error was %s\n",
unicode_map_file_name, strerror(errno)));
goto clean_and_exit;
}
if(fread( (char *)ucs2_to_cp, 1, ucs2_to_cp_size, fp)!=ucs2_to_cp_size) {
DEBUG(0,("load_unicode_map: cannot read ucs2_to_cp from file %s. Error was %s\n",
unicode_map_file_name, strerror(errno)));
goto clean_and_exit;
}
for (i = 0; i < cp_to_ucs2_size/2; i++)
cp_to_ucs2[i] = SVAL(cp_to_ucs2,i*2);
for (i = 0; i < ucs2_to_cp_size/2; i++)
ucs2_to_cp[i] = SVAL(ucs2_to_cp,i*2);
fclose(fp);
*pp_cp_to_ucs2 = cp_to_ucs2;
*pp_ucs2_to_cp = ucs2_to_cp;
return True;
clean_and_exit:
if(fp != NULL)
fclose(fp);
free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
default_unicode_map(pp_cp_to_ucs2, pp_ucs2_to_cp);
return False;
}
BOOL load_dos_unicode_map(int codepage)
{
fstring codepage_str;
slprintf(codepage_str, sizeof(fstring)-1, "%03d", codepage);
DEBUG(10,("load_dos_unicode_map: %s\n", codepage_str));
return load_unicode_map(codepage_str, &doscp_to_ucs2, &ucs2_to_doscp);
}
BOOL load_unix_unicode_map(const char *unix_char_set, BOOL override)
{
static BOOL init_done;
fstring upper_unix_char_set;
fstrcpy(upper_unix_char_set, unix_char_set);
strupper(upper_unix_char_set);
DEBUG(10,("load_unix_unicode_map: %s (init_done=%d, override=%d)\n",
upper_unix_char_set, (int)init_done, (int)override ));
if (!init_done)
init_done = True;
else if (!override)
return True;
return load_unicode_map(upper_unix_char_set, &unixcp_to_ucs2, &ucs2_to_unixcp);
}
static char *unicode_to_multibyte(char *dst, const smb_ucs2_t *src,
size_t dst_len, const uint16 *ucs2_to_cp)
{
size_t dst_pos;
for(dst_pos = 0; (dst_pos < dst_len - 1) && *src;) {
smb_ucs2_t val = ucs2_to_cp[*src++];
if(val < 256) {
dst[dst_pos++] = (char)val;
} else {
if(dst_pos >= dst_len - 2)
break;
dst[dst_pos++] = (char)((val >> 8) & 0xff);
dst[dst_pos++] = (char)(val & 0xff);
}
}
dst[dst_pos] = '\0';
return dst;
}
smb_ucs2_t *multibyte_to_unicode(smb_ucs2_t *dst, const char *src,
size_t dst_len, smb_ucs2_t *cp_to_ucs2)
{
size_t i;
dst_len /= sizeof(smb_ucs2_t);
for(i = 0; (i < (dst_len - 1)) && *src;) {
size_t skip = skip_multibyte_char(*src);
smb_ucs2_t val = (*src & 0xff);
if (skip == 2)
val = ((val << 8) | (src[1] & 0xff));
dst[i++] = cp_to_ucs2[val];
if (skip)
src += skip;
else
src++;
}
dst[i] = 0;
return dst;
}
char *unicode_to_unix(char *dst, const smb_ucs2_t *src, size_t dst_len)
{
return unicode_to_multibyte(dst, src, dst_len, ucs2_to_unixcp);
}
smb_ucs2_t *unix_to_unicode(smb_ucs2_t *dst, const char *src, size_t dst_len)
{
return multibyte_to_unicode(dst, src, dst_len, unixcp_to_ucs2);
}
size_t unicode_to_unix_char(char *dst, const smb_ucs2_t src)
{
smb_ucs2_t val = ucs2_to_unixcp[src];
if(val < 256) {
*dst = (char)val;
return (size_t)1;
}
dst[0] = (char)((val >> 8) & 0xff);
dst[1] = (char)(val & 0xff);
return (size_t)2;
}
char *unicode_to_dos(char *dst, const smb_ucs2_t *src, size_t dst_len)
{
return unicode_to_multibyte(dst, src, dst_len, ucs2_to_doscp);
}
size_t unicode_to_dos_char(char *dst, const smb_ucs2_t src)
{
smb_ucs2_t val = ucs2_to_doscp[src];
if(val < 256) {
*dst = (char)val;
return (size_t)1;
}
dst[0] = (char)((val >> 8) & 0xff);
dst[1] = (char)(val & 0xff);
return (size_t)2;
}
smb_ucs2_t *dos_to_unicode(smb_ucs2_t *dst, const char *src, size_t dst_len)
{
return multibyte_to_unicode(dst, src, dst_len, doscp_to_ucs2);
}
size_t strlen_w(const smb_ucs2_t *src)
{
size_t len;
for(len = 0; *src++; len++)
;
return len;
}
smb_ucs2_t *safe_strcpy_w(smb_ucs2_t *dest,const smb_ucs2_t *src, size_t maxlength)
{
size_t ucs2_len;
if (!dest) {
DEBUG(0,("ERROR: NULL dest in safe_strcpy_w\n"));
return NULL;
}
if (!src) {
*dest = 0;
return dest;
}
maxlength /= sizeof(smb_ucs2_t);
ucs2_len = strlen_w(src);
if (ucs2_len >= maxlength) {
fstring out;
DEBUG(0,("ERROR: string overflow by %u bytes in safe_strcpy_w [%.50s]\n",
(unsigned int)((ucs2_len-maxlength)*sizeof(smb_ucs2_t)),
unicode_to_unix(out,src,sizeof(out))) );
ucs2_len = maxlength - 1;
}
memcpy(dest, src, ucs2_len*sizeof(smb_ucs2_t));
dest[ucs2_len] = 0;
return dest;
}
smb_ucs2_t *safe_strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxlength)
{
size_t ucs2_src_len, ucs2_dest_len;
if (!dest) {
DEBUG(0,("ERROR: NULL dest in safe_strcat_w\n"));
return NULL;
}
if (!src)
return dest;
ucs2_src_len = strlen_w(src);
ucs2_dest_len = strlen_w(dest);
if (ucs2_src_len + ucs2_dest_len >= maxlength) {
fstring out;
int new_len = maxlength - ucs2_dest_len - 1;
DEBUG(0,("ERROR: string overflow by %u characters in safe_strcat_w [%.50s]\n",
(unsigned int)(sizeof(smb_ucs2_t)*(ucs2_src_len + ucs2_dest_len - maxlength)),
unicode_to_unix(out,src,sizeof(out))) );
ucs2_src_len = (size_t)(new_len > 0 ? new_len : 0);
}
memcpy(&dest[ucs2_dest_len], src, ucs2_src_len*sizeof(smb_ucs2_t));
dest[ucs2_dest_len + ucs2_src_len] = 0;
return dest;
}
int strcmp_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
{
smb_ucs2_t c1, c2;
for (;;) {
c1 = *s1++;
c2 = *s2++;
if (c1 != c2)
return c1 - c2;
if (c1 == 0)
break;
}
return 0;
}
int strncmp_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2, size_t len)
{
smb_ucs2_t c1, c2;
for (; len != 0; --len) {
c1 = *s1++;
c2 = *s2++;
if (c1 != c2)
return c1 - c2;
if (c1 == 0)
break;
}
return 0;
}
smb_ucs2_t *strstr_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
{
size_t len = strlen_w(s2);
if (!*s2)
return (smb_ucs2_t *)s1;
for(;*s1; s1++) {
if (*s1 == *s2) {
if (strncmp_w(s1, s2, len) == 0)
return (smb_ucs2_t *)s1;
}
}
return NULL;
}
smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
{
do {
if (*s == c)
return (smb_ucs2_t *)s;
} while (*s++);
return NULL;
}
smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
{
smb_ucs2_t *retval = 0;
do {
if (*s == c)
retval = (smb_ucs2_t *)s;
} while (*s++);
return retval;
}
smb_ucs2_t *strtok_w(smb_ucs2_t *s1, const smb_ucs2_t *s2)
{
static smb_ucs2_t *s = NULL;
smb_ucs2_t *q;
if (!s1) {
if (!s)
return NULL;
s1 = s;
}
for (q = s1; *s1; s1++) {
smb_ucs2_t *p = strchr_w(s2, *s1);
if (p) {
if (s1 != q) {
s = s1 + 1;
*s1 = '\0';
return q;
}
q = s1 + 1;
}
}
s = NULL;
if (*q)
return q;
return NULL;
}
smb_ucs2_t *strdup_w(const smb_ucs2_t *s)
{
size_t newlen = (strlen_w(s)+1)*sizeof(smb_ucs2_t);
smb_ucs2_t *newstr = (smb_ucs2_t *)malloc(newlen);
if (newstr == NULL)
return NULL;
safe_strcpy_w(newstr, s, newlen);
return newstr;
}
typedef struct {
smb_ucs2_t lower;
smb_ucs2_t upper;
unsigned char flags;
} smb_unicode_table_t;
#define TABLE1_BOUNDARY 9450
#define TABLE2_BOUNDARY 64256
static smb_unicode_table_t map_table1[] = {
#include "unicode_map_table1.h"
};
static smb_unicode_table_t map_table2[] = {
#include "unicode_map_table2.h"
};
static unsigned char map_table_flags(smb_ucs2_t v)
{
if (v < TABLE1_BOUNDARY) return map_table1[v].flags;
if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].flags;
return 0;
}
static smb_ucs2_t map_table_lower(smb_ucs2_t v)
{
if (v < TABLE1_BOUNDARY) return map_table1[v].lower;
if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].lower;
return v;
}
static smb_ucs2_t map_table_upper(smb_ucs2_t v)
{
if (v < TABLE1_BOUNDARY) return map_table1[v].upper;
if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].upper;
return v;
}
int isupper_w( smb_ucs2_t val)
{
return (map_table_flags(val) & UNI_UPPER);
}
int islower_w( smb_ucs2_t val)
{
return (map_table_flags(val) & UNI_LOWER);
}
int isdigit_w( smb_ucs2_t val)
{
return (map_table_flags(val) & UNI_DIGIT);
}
int isxdigit_w( smb_ucs2_t val)
{
return (map_table_flags(val) & UNI_XDIGIT);
}
int isspace_w( smb_ucs2_t val)
{
return (map_table_flags(val) & UNI_SPACE);
}
smb_ucs2_t toupper_w( smb_ucs2_t val )
{
return map_table_upper(val);
}
smb_ucs2_t tolower_w( smb_ucs2_t val )
{
return map_table_lower(val);
}
static smb_ucs2_t *last_ptr = NULL;
void set_first_token_w(smb_ucs2_t *ptr)
{
last_ptr = ptr;
}
static smb_ucs2_t sep_list[] = { (smb_ucs2_t)' ', (smb_ucs2_t)'\t', (smb_ucs2_t)'\n', (smb_ucs2_t)'\r', 0};
static smb_ucs2_t quotechar = (smb_ucs2_t)'\"';
BOOL next_token_w(smb_ucs2_t **ptr, smb_ucs2_t *buff, smb_ucs2_t *sep, size_t bufsize)
{
smb_ucs2_t *s;
BOOL quoted;
size_t len=1;
bufsize /= sizeof(smb_ucs2_t);
if (!ptr)
ptr = &last_ptr;
if (!ptr)
return(False);
s = *ptr;
if (!sep)
sep = sep_list;
while(*s && strchr_w(sep,*s))
s++;
if (!*s)
return(False);
for (quoted = False; len < bufsize && *s && (quoted || !strchr_w(sep,*s)); s++) {
if (*s == quotechar) {
quoted = !quoted;
} else {
len++;
*buff++ = *s;
}
}
*ptr = (*s) ? s+1 : s;
*buff = 0;
last_ptr = *ptr;
return(True);
}
smb_ucs2_t **toktocliplist_w(int *ctok, smb_ucs2_t *sep)
{
smb_ucs2_t *s=last_ptr;
int ictok=0;
smb_ucs2_t **ret, **iret;
if (!sep)
sep = sep_list;
while(*s && strchr_w(sep,*s))
s++;
if (!*s)
return(NULL);
do {
ictok++;
while(*s && (!strchr_w(sep,*s)))
s++;
while(*s && strchr_w(sep,*s))
*s++=0;
} while(*s);
*ctok = ictok;
s = last_ptr;
if (!(ret=iret=malloc(ictok*sizeof(smb_ucs2_t *))))
return NULL;
while(ictok--) {
*iret++=s;
while(*s++)
;
while(!*s)
s++;
}
return ret;
}
int StrCaseCmp_w(const smb_ucs2_t *s, const smb_ucs2_t *t)
{
while (*s && *t && toupper_w(*s) == toupper_w(*t)) {
s++;
t++;
}
return(toupper_w(*s) - toupper_w(*t));
}
int StrnCaseCmp_w(const smb_ucs2_t *s, const smb_ucs2_t *t, size_t n)
{
while (n && *s && *t && toupper_w(*s) == toupper_w(*t)) {
s++;
t++;
n--;
}
if (n)
return(toupper_w(*s) - toupper_w(*t));
return(0);
}
BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
{
if (s1 == s2)
return(True);
if (!s1 || !s2)
return(False);
return(StrCaseCmp_w(s1,s2)==0);
}
BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
{
if (s1 == s2)
return(True);
if (!s1 || !s2 || !n)
return(False);
return(StrnCaseCmp_w(s1,s2,n)==0);
}
BOOL strcsequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2)
{
if (s1 == s2)
return(True);
if (!s1 || !s2)
return(False);
return(strcmp_w(s1,s2)==0);
}
void strlower_w(smb_ucs2_t *s)
{
while (*s) {
if (isupper_w(*s))
*s = tolower_w(*s);
s++;
}
}
void strupper_w(smb_ucs2_t *s)
{
while (*s) {
if (islower_w(*s))
*s = toupper_w(*s);
s++;
}
}
void strnorm_w(smb_ucs2_t *s)
{
extern int case_default;
if (case_default == CASE_UPPER)
strupper_w(s);
else
strlower_w(s);
}
BOOL strisnormal_w(smb_ucs2_t *s)
{
extern int case_default;
if (case_default == CASE_UPPER)
return(!strhaslower_w(s));
return(!strhasupper_w(s));
}
void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc)
{
while (*s) {
if (oldc == *s)
*s = newc;
s++;
}
}
smb_ucs2_t *skip_string_w(smb_ucs2_t *buf,size_t n)
{
while (n--)
buf += (strlen_w(buf)*sizeof(smb_ucs2_t)) + 1;
return(buf);
}
size_t str_charnum_w(const smb_ucs2_t *s)
{
return strlen_w(s);
}
BOOL trim_string_w(smb_ucs2_t *s,const smb_ucs2_t *front,const smb_ucs2_t *back)
{
BOOL ret = False;
size_t front_len = (front && *front) ? strlen_w(front) : 0;
size_t back_len = (back && *back) ? strlen_w(back) : 0;
size_t s_len;
while (front_len && strncmp_w(s, front, front_len) == 0) {
smb_ucs2_t *p = s;
ret = True;
while (1) {
if (!(*p = p[front_len]))
break;
p++;
}
}
if(back_len) {
s_len = strlen_w(s);
while ((s_len >= back_len) &&
(strncmp_w(s + s_len - back_len, back, back_len)==0)) {
ret = True;
s[s_len - back_len] = 0;
s_len = strlen_w(s);
}
}
return(ret);
}
BOOL strhasupper_w(const smb_ucs2_t *s)
{
while (*s) {
if (isupper_w(*s))
return(True);
s++;
}
return(False);
}
BOOL strhaslower_w(const smb_ucs2_t *s)
{
while (*s) {
if (islower(*s))
return(True);
s++;
}
return(False);
}
size_t count_chars_w(const smb_ucs2_t *s,smb_ucs2_t c)
{
size_t count=0;
while (*s) {
if (*s == c)
count++;
s++;
}
return(count);
}
BOOL str_is_all_w(const smb_ucs2_t *s,smb_ucs2_t c)
{
if(s == NULL)
return False;
if(!*s)
return False;
while (*s) {
if (*s != c)
return False;
s++;
}
return True;
}
smb_ucs2_t *alpha_strcpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const smb_ucs2_t *other_safe_chars, size_t maxlength)
{
size_t len, i;
smb_ucs2_t nullstr_w = (smb_ucs2_t)0;
if (!dest) {
DEBUG(0,("ERROR: NULL dest in alpha_strcpy_w\n"));
return NULL;
}
if (!src) {
*dest = 0;
return dest;
}
len = strlen_w(src);
if (len >= maxlength)
len = maxlength - 1;
if (!other_safe_chars)
other_safe_chars = &nullstr_w;
for(i = 0; i < len; i++) {
smb_ucs2_t val = src[i];
if(isupper_w(val) ||islower_w(val) || isdigit_w(val) || strchr_w(other_safe_chars, val))
dest[i] = src[i];
else
dest[i] = (smb_ucs2_t)'_';
}
dest[i] = 0;
return dest;
}
smb_ucs2_t *StrnCpy_w(smb_ucs2_t *dest,const smb_ucs2_t *src,size_t n)
{
smb_ucs2_t *d = dest;
if (!dest)
return(NULL);
if (!src) {
*dest = 0;
return(dest);
}
while (n-- && (*d++ = *src++))
;
*d = 0;
return(dest);
}
smb_ucs2_t *strncpyn_w(smb_ucs2_t *dest, const smb_ucs2_t *src,size_t n, smb_ucs2_t c)
{
smb_ucs2_t *p;
size_t str_len;
p = strchr_w(src, c);
if (p == NULL) {
fstring cval;
smb_ucs2_t mbcval[2];
mbcval[0] = c;
mbcval[1] = 0;
DEBUG(5, ("strncpyn_w: separator character (%s) not found\n",
unicode_to_unix(cval,mbcval,sizeof(cval)) ));
return NULL;
}
str_len = PTR_DIFF(p, src) + 1;
safe_strcpy_w(dest, src, MIN(n, str_len));
return p;
}
static smb_ucs2_t hexprefix[] = { (smb_ucs2_t)'0', (smb_ucs2_t)'x', 0 };
static smb_ucs2_t hexchars[] = { (smb_ucs2_t)'0', (smb_ucs2_t)'1', (smb_ucs2_t)'2', (smb_ucs2_t)'3',
(smb_ucs2_t)'4', (smb_ucs2_t)'5', (smb_ucs2_t)'6', (smb_ucs2_t)'7',
(smb_ucs2_t)'8', (smb_ucs2_t)'9', (smb_ucs2_t)'A', (smb_ucs2_t)'B',
(smb_ucs2_t)'C', (smb_ucs2_t)'D', (smb_ucs2_t)'E', (smb_ucs2_t)'F', 0 };
size_t strhex_to_str_w(char *p, size_t len, const smb_ucs2_t *strhex)
{
size_t i;
size_t num_chars = 0;
unsigned char lonybble, hinybble;
smb_ucs2_t *p1 = NULL, *p2 = NULL;
len /= sizeof(smb_ucs2_t);
for (i = 0; i < len && strhex[i] != 0; i++) {
if (strnequal_w(hexchars, hexprefix, 2)) {
i++;
continue;
}
if (!(p1 = strchr_w(hexchars, toupper_w(strhex[i]))))
break;
i++;
if (!(p2 = strchr_w(hexchars, toupper_w(strhex[i]))))
break;
hinybble = (PTR_DIFF(p1, hexchars)/sizeof(smb_ucs2_t));
lonybble = (PTR_DIFF(p2, hexchars)/sizeof(smb_ucs2_t));
p[num_chars] = (hinybble << 4) | lonybble;
num_chars++;
p1 = NULL;
p2 = NULL;
}
return num_chars;
}
BOOL in_list_w(smb_ucs2_t *s,smb_ucs2_t *list,BOOL casesensitive)
{
wpstring tok;
smb_ucs2_t *p=list;
if (!list)
return(False);
while (next_token_w(&p,tok,LIST_SEP_W,sizeof(tok))) {
if (casesensitive) {
if (strcmp_w(tok,s) == 0)
return(True);
} else {
if (StrCaseCmp_w(tok,s) == 0)
return(True);
}
}
return(False);
}
static smb_ucs2_t *null_string = NULL;
BOOL string_init_w(smb_ucs2_t **dest,const smb_ucs2_t *src)
{
size_t l;
if (!null_string) {
if((null_string = (smb_ucs2_t *)malloc(sizeof(smb_ucs2_t))) == NULL) {
DEBUG(0,("string_init_w: malloc fail for null_string.\n"));
return False;
}
*null_string = 0;
}
if (!src)
src = null_string;
l = strlen_w(src);
if (l == 0)
*dest = null_string;
else {
(*dest) = (smb_ucs2_t *)malloc(sizeof(smb_ucs2_t)*(l+1));
if ((*dest) == NULL) {
DEBUG(0,("Out of memory in string_init_w\n"));
return False;
}
wpstrcpy(*dest,src);
}
return(True);
}
void string_free_w(smb_ucs2_t **s)
{
if (!s || !(*s))
return;
if (*s == null_string)
*s = NULL;
SAFE_FREE(*s);
}
BOOL string_set_w(smb_ucs2_t **dest,const smb_ucs2_t *src)
{
string_free_w(dest);
return(string_init_w(dest,src));
}
void string_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert, size_t len)
{
smb_ucs2_t *p;
ssize_t ls,lp,li, i;
if (!insert || !pattern || !s)
return;
ls = (ssize_t)strlen_w(s);
lp = (ssize_t)strlen_w(pattern);
li = (ssize_t)strlen_w(insert);
if (!*pattern)
return;
while (lp <= ls && (p = strstr_w(s,pattern))) {
if (len && (ls + (li-lp) >= len)) {
fstring out;
DEBUG(0,("ERROR: string overflow by %d in string_sub_w(%.50s, %d)\n",
(int)(sizeof(smb_ucs2_t)*(ls + (li-lp) - len)),
unicode_to_unix(out,pattern,sizeof(out)), (int)len*sizeof(smb_ucs2_t)));
break;
}
if (li != lp)
memmove(p+li,p+lp,sizeof(smb_ucs2_t)*(strlen_w(p+lp)+1));
for (i=0;i<li;i++) {
switch (insert[i]) {
case (smb_ucs2_t)'`':
case (smb_ucs2_t)'"':
case (smb_ucs2_t)'\'':
case (smb_ucs2_t)';':
case (smb_ucs2_t)'$':
case (smb_ucs2_t)'%':
case (smb_ucs2_t)'\r':
case (smb_ucs2_t)'\n':
p[i] = (smb_ucs2_t)'_';
break;
default:
p[i] = insert[i];
}
}
s = p + li;
ls += (li-lp);
}
}
void fstring_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert)
{
string_sub_w(s, pattern, insert, sizeof(wfstring));
}
void pstring_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,smb_ucs2_t *insert)
{
string_sub_w(s, pattern, insert, sizeof(wpstring));
}
void all_string_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert, size_t len)
{
smb_ucs2_t *p;
ssize_t ls,lp,li;
if (!insert || !pattern || !s)
return;
ls = (ssize_t)strlen_w(s);
lp = (ssize_t)strlen_w(pattern);
li = (ssize_t)strlen_w(insert);
if (!*pattern)
return;
while (lp <= ls && (p = strstr_w(s,pattern))) {
if (len && (ls + (li-lp) >= len)) {
fstring out;
DEBUG(0,("ERROR: string overflow by %d in all_string_sub_w(%.50s, %d)\n",
(int)(sizeof(smb_ucs2_t)*(ls + (li-lp) - len)),
unicode_to_unix(out,pattern,sizeof(out)), (int)len*sizeof(smb_ucs2_t)));
break;
}
if (li != lp)
memmove(p+li,p+lp,sizeof(smb_ucs2_t)*(strlen_w(p+lp)+1));
memcpy(p, insert, li*sizeof(smb_ucs2_t));
s = p + li;
ls += (li-lp);
}
}
void split_at_last_component_w(smb_ucs2_t *path, smb_ucs2_t *front, smb_ucs2_t sep, smb_ucs2_t *back)
{
smb_ucs2_t *p = strrchr_w(path, sep);
if (p != NULL)
*p = 0;
if (front != NULL)
wpstrcpy(front, path);
if (p != NULL) {
if (back != NULL)
wpstrcpy(back, p+1);
*p = (smb_ucs2_t)'\\';
} else {
if (back != NULL)
back[0] = 0;
}
}
smb_ucs2_t *octal_string_w(int i)
{
static smb_ucs2_t wret[64];
char ret[64];
if (i == -1)
slprintf(ret, sizeof(ret)-1, "-1");
else
slprintf(ret, sizeof(ret)-1, "0%o", i);
return unix_to_unicode(wret, ret, sizeof(wret));
}
smb_ucs2_t *string_truncate_w(smb_ucs2_t *s, size_t length)
{
if (s && strlen_w(s) > length)
s[length] = 0;
return s;
}
smb_ucs2_t doscp2ucs2(int w)
{
return ((smb_ucs2_t)doscp_to_ucs2[w]);
}
int ucs2doscp(smb_ucs2_t w)
{
return ((int)ucs2_to_doscp[w]);
}
int rpcstr_pull(char* dest, void *src, int dest_len, int src_len, int flags)
{
if(dest_len==-1)
dest_len=MAXUNI-3;
unistr_to_ascii(dest, src, dest_len - 1);
return src_len;
}