mirror of
https://github.com/samba-team/samba.git
synced 2025-01-04 05:18:06 +03:00
8177fc778b
internal unicode conversion of Samba.
Jeremy.
(This used to be commit 302412df64
)
767 lines
21 KiB
C
767 lines
21 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
Samba utility functions
|
|
Copyright (C) Andrew Tridgell 1992-1998
|
|
|
|
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 02139, USA.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
|
|
extern int DEBUGLEVEL;
|
|
|
|
/*
|
|
* The following are the codepage to ucs2 and vica versa maps.
|
|
* These are dynamically loaded from a unicode translation file.
|
|
*/
|
|
|
|
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
|
|
|
|
/*******************************************************************
|
|
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.
|
|
|
|
the return value is the length of the string *without* the trailing
|
|
two bytes of zero
|
|
********************************************************************/
|
|
|
|
int dos_PutUniCode(char *dst,const char *src, ssize_t len)
|
|
{
|
|
int ret = 0;
|
|
while (*src && (len > 2)) {
|
|
size_t skip = skip_multibyte_char(*src);
|
|
smb_ucs2_t val = (*src & 0xff);
|
|
|
|
/*
|
|
* If this is a multibyte character (and all DOS/Windows
|
|
* codepages have at maximum 2 byte multibyte characters)
|
|
* then work out the index value for the unicode conversion.
|
|
*/
|
|
|
|
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++;
|
|
}
|
|
SSVAL(dst,ret,0);
|
|
return(ret);
|
|
}
|
|
|
|
/*******************************************************************
|
|
Skip past some unicode strings in a buffer.
|
|
********************************************************************/
|
|
|
|
char *skip_unicode_string(char *buf,int n)
|
|
{
|
|
while (n--) {
|
|
while (*buf)
|
|
buf += 2;
|
|
buf += 2;
|
|
}
|
|
return(buf);
|
|
}
|
|
|
|
/*******************************************************************
|
|
Return a DOS codepage version of a little-endian unicode string.
|
|
Hack alert: uses fixed buffer(s).
|
|
********************************************************************/
|
|
|
|
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;
|
|
|
|
/*******************************************************************
|
|
Return a DOS codepage version of a little-endian unicode string.
|
|
Hack alert: uses fixed buffer(s).
|
|
********************************************************************/
|
|
|
|
char *dos_unistr2(uint16 *src)
|
|
{
|
|
char *lbuf = lbufs[nexti];
|
|
char *p;
|
|
|
|
nexti = (nexti+1)%8;
|
|
|
|
for (p = lbuf; *src && (p-lbuf < MAXUNI-3); 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;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Return a DOS codepage version of a little-endian unicode string
|
|
********************************************************************/
|
|
|
|
char *dos_unistr2_to_str(UNISTR2 *str)
|
|
{
|
|
char *lbuf = lbufs[nexti];
|
|
char *p;
|
|
uint16 *src = str->buffer;
|
|
int max_size = MIN(sizeof(str->buffer)-3, str->uni_str_len);
|
|
|
|
nexti = (nexti+1)%8;
|
|
|
|
for (p = lbuf; *src && p-lbuf < max_size; 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;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Return a number stored in a buffer
|
|
********************************************************************/
|
|
|
|
uint32 buffer2_to_uint32(BUFFER2 *str)
|
|
{
|
|
if (str->buf_len == 4)
|
|
return IVAL(str->buffer, 0);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Return a DOS codepage version of a NOTunicode string
|
|
********************************************************************/
|
|
|
|
char *dos_buffer2_to_str(BUFFER2 *str)
|
|
{
|
|
char *lbuf = lbufs[nexti];
|
|
char *p;
|
|
uint16 *src = str->buffer;
|
|
int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
|
|
|
|
nexti = (nexti+1)%8;
|
|
|
|
for (p = lbuf; *src && p-lbuf < max_size; 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;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Return a dos codepage version of a NOTunicode string
|
|
********************************************************************/
|
|
|
|
char *dos_buffer2_to_multistr(BUFFER2 *str)
|
|
{
|
|
char *lbuf = lbufs[nexti];
|
|
char *p;
|
|
uint16 *src = str->buffer;
|
|
int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
|
|
|
|
nexti = (nexti+1)%8;
|
|
|
|
for (p = lbuf; p-lbuf < max_size; 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;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Create a null-terminated unicode string from a null-terminated DOS
|
|
codepage string.
|
|
Return number of unicode chars copied, excluding the null character.
|
|
Unicode strings created are in little-endian format.
|
|
********************************************************************/
|
|
|
|
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 (; *src && len < max_len-2; len++, dst +=2) {
|
|
size_t skip = skip_multibyte_char(*src);
|
|
smb_ucs2_t val = (*src & 0xff);
|
|
|
|
/*
|
|
* If this is a multibyte character (and all DOS/Windows
|
|
* codepages have at maximum 2 byte multibyte characters)
|
|
* then work out the index value for the unicode conversion.
|
|
*/
|
|
|
|
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;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Return a DOS codepage version of a little-endian unicode string.
|
|
Hack alert: uses fixed buffer(s).
|
|
********************************************************************/
|
|
|
|
char *dos_unistr(char *buf)
|
|
{
|
|
char *lbuf = lbufs[nexti];
|
|
uint16 *src = (uint16 *)buf;
|
|
char *p;
|
|
|
|
nexti = (nexti+1)%8;
|
|
|
|
for (p = lbuf; *src && p-lbuf < MAXUNI-3; 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;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Strcpy for unicode strings. returns length (in num of wide chars)
|
|
********************************************************************/
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
Free any existing maps.
|
|
********************************************************************/
|
|
|
|
static void free_maps(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
|
|
{
|
|
/* this handles identity mappings where we share the pointer */
|
|
if (*pp_ucs2_to_cp == *pp_cp_to_ucs2) {
|
|
*pp_ucs2_to_cp = NULL;
|
|
}
|
|
|
|
if (*pp_cp_to_ucs2) {
|
|
free(*pp_cp_to_ucs2);
|
|
*pp_cp_to_ucs2 = NULL;
|
|
}
|
|
|
|
if (*pp_ucs2_to_cp) {
|
|
free(*pp_ucs2_to_cp);
|
|
*pp_ucs2_to_cp = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
Build a default (null) codepage to unicode map.
|
|
********************************************************************/
|
|
|
|
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; /* Default map is an identity. */
|
|
for (i = 0; i < 65536; i++)
|
|
(*pp_cp_to_ucs2)[i] = i;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Load a codepage to unicode and vica-versa map.
|
|
********************************************************************/
|
|
|
|
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(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, 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;
|
|
}
|
|
|
|
/* Check the version value */
|
|
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;
|
|
}
|
|
|
|
/* Check the codepage value */
|
|
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) {
|
|
/*
|
|
* This is a multibyte code page.
|
|
*/
|
|
cp_to_ucs2_size = 2*65536;
|
|
} else {
|
|
/*
|
|
* Single byte code page.
|
|
*/
|
|
cp_to_ucs2_size = 2*256;
|
|
}
|
|
|
|
/*
|
|
* Free any old translation tables.
|
|
*/
|
|
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* Now ensure the 16 bit values are in the correct endianness.
|
|
*/
|
|
|
|
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:
|
|
|
|
/* pseudo destructor :-) */
|
|
|
|
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;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Load a dos codepage to unicode and vica-versa map.
|
|
********************************************************************/
|
|
|
|
BOOL load_dos_unicode_map(int codepage)
|
|
{
|
|
fstring codepage_str;
|
|
|
|
slprintf(codepage_str, sizeof(fstring)-1, "%03d", codepage);
|
|
return load_unicode_map(codepage_str, &doscp_to_ucs2, &ucs2_to_doscp);
|
|
}
|
|
|
|
/*******************************************************************
|
|
Load a UNIX codepage to unicode and vica-versa map.
|
|
********************************************************************/
|
|
|
|
BOOL load_unix_unicode_map(const char *unix_char_set)
|
|
{
|
|
fstring upper_unix_char_set;
|
|
|
|
fstrcpy(upper_unix_char_set, unix_char_set);
|
|
strupper(upper_unix_char_set);
|
|
return load_unicode_map(upper_unix_char_set, &unixcp_to_ucs2, &ucs2_to_unixcp);
|
|
}
|
|
|
|
/*******************************************************************
|
|
The following functions reproduce many of the non-UNICODE standard
|
|
string functions in Samba.
|
|
********************************************************************/
|
|
|
|
/*******************************************************************
|
|
Convert a UNICODE string to multibyte format. Note that the 'src' is in
|
|
native byte order, not little endian. Always zero terminates.
|
|
dst_len is in bytes.
|
|
********************************************************************/
|
|
|
|
static char *unicode_to_multibyte(char *dst, const smb_ucs2_t *src,
|
|
size_t dst_len, const uint16 *ucs2_to_cp)
|
|
{
|
|
size_t i;
|
|
|
|
for(i = 0; (i < (dst_len - 1)) && src[i];) {
|
|
smb_ucs2_t val = ucs2_to_cp[*src];
|
|
if(val < 256) {
|
|
dst[i++] = (char)val;
|
|
} else if (i < (dst_len - 2)) {
|
|
|
|
/*
|
|
* A 2 byte value is always written as
|
|
* high/low into the buffer stream.
|
|
*/
|
|
|
|
dst[i++] = (char)((val >> 8) & 0xff);
|
|
dst[i++] = (char)(val & 0xff);
|
|
}
|
|
}
|
|
|
|
dst[i] = '\0';
|
|
|
|
return dst;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Convert a multibyte string to UNICODE format. Note that the 'dst' is in
|
|
native byte order, not little endian. Always zero terminates.
|
|
dst_len is in bytes.
|
|
********************************************************************/
|
|
|
|
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); /* Convert to smb_ucs2_t units. */
|
|
|
|
for(i = 0; (i < (dst_len - 1)) && src[i];) {
|
|
size_t skip = skip_multibyte_char(*src);
|
|
smb_ucs2_t val = (*src & 0xff);
|
|
|
|
/*
|
|
* If this is a multibyte character
|
|
* then work out the index value for the unicode conversion.
|
|
*/
|
|
|
|
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;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Convert a UNICODE string to multibyte format. Note that the 'src' is in
|
|
native byte order, not little endian. Always zero terminates.
|
|
This function may be replaced if the MB codepage format is an
|
|
encoded one (ie. utf8, hex). See the code in lib/kanji.c
|
|
for details. dst_len is in bytes.
|
|
********************************************************************/
|
|
|
|
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);
|
|
}
|
|
|
|
/*******************************************************************
|
|
Convert a UNIX string to UNICODE format. Note that the 'dst' is in
|
|
native byte order, not little endian. Always zero terminates.
|
|
This function may be replaced if the UNIX codepage format is a
|
|
multi-byte one (ie. JIS, SJIS or utf8). See the code in lib/kanji.c
|
|
for details. dst_len is in bytes, not ucs2 units.
|
|
********************************************************************/
|
|
|
|
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);
|
|
}
|
|
|
|
/*******************************************************************
|
|
Convert a UNICODE string to DOS format. Note that the 'src' is in
|
|
native byte order, not little endian. Always zero terminates.
|
|
dst_len is in bytes.
|
|
********************************************************************/
|
|
|
|
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);
|
|
}
|
|
|
|
/*******************************************************************
|
|
Convert a DOS string to UNICODE format. Note that the 'dst' is in
|
|
native byte order, not little endian. Always zero terminates.
|
|
This function may be replaced if the DOS codepage format is a
|
|
multi-byte one (ie. JIS, SJIS or utf8). See the code in lib/kanji.c
|
|
for details. dst_len is in bytes, not ucs2 units.
|
|
********************************************************************/
|
|
|
|
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);
|
|
}
|
|
|
|
/*******************************************************************
|
|
Count the number of characters in a smb_ucs2_t string.
|
|
********************************************************************/
|
|
|
|
size_t wstrlen(const smb_ucs2_t *src)
|
|
{
|
|
size_t len;
|
|
|
|
for(len = 0; *src; len++)
|
|
;
|
|
|
|
return len;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Safe wstring copy into a known length string. maxlength includes
|
|
the terminating zero. maxlength is in bytes.
|
|
********************************************************************/
|
|
|
|
smb_ucs2_t *safe_wstrcpy(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_wstrcpy\n"));
|
|
return NULL;
|
|
}
|
|
|
|
if (!src) {
|
|
*dest = 0;
|
|
return dest;
|
|
}
|
|
|
|
ucs2_len = wstrlen(src);
|
|
|
|
if (ucs2_len >= (maxlength/sizeof(smb_ucs2_t))) {
|
|
fstring out;
|
|
DEBUG(0,("ERROR: string overflow by %u bytes in safe_wstrcpy [%.50s]\n",
|
|
(unsigned int)((ucs2_len*sizeof(smb_ucs2_t))-maxlength),
|
|
unicode_to_unix(out,src,sizeof(out))) );
|
|
ucs2_len = (maxlength/sizeof(smb_ucs2_t)) - 1;
|
|
}
|
|
|
|
memcpy(dest, src, ucs2_len*sizeof(smb_ucs2_t));
|
|
dest[ucs2_len] = 0;
|
|
return dest;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Safe string cat into a string. maxlength includes the terminating zero.
|
|
maxlength is in bytes.
|
|
********************************************************************/
|
|
|
|
smb_ucs2_t *safe_wstrcat(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_wstrcat\n"));
|
|
return NULL;
|
|
}
|
|
|
|
if (!src) {
|
|
return dest;
|
|
}
|
|
|
|
ucs2_src_len = wstrlen(src);
|
|
ucs2_dest_len = wstrlen(dest);
|
|
|
|
if (ucs2_src_len + ucs2_dest_len >= (maxlength/sizeof(smb_ucs2_t))) {
|
|
fstring out;
|
|
int new_len = (maxlength/sizeof(smb_ucs2_t)) - ucs2_dest_len - 1;
|
|
DEBUG(0,("ERROR: string overflow by %u characters in safe_wstrcat [%.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;
|
|
}
|