1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-28 07:21:54 +03:00
samba-mirror/source3/smbd/srvstr.c
Andrew Tridgell 578a9fabfb started converting some of the only-ascii code to use srvstr_*
added srvstr_push_ascii() and srvstr_pull_ascii() as convenience
routines to replace the current usage of strncpy() like fns
for packet pull/push. We need to do this in *lots* of places
in Samba in order to get our codepage handling right
(This used to be commit 8b0e3679a6)
2001-03-31 13:48:24 +00:00

165 lines
5.1 KiB
C

/*
Unix SMB/Netbios implementation.
Version 3.0
server specific string routines
Copyright (C) Andrew Tridgell 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
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.
*/
#define NO_SYSLOG
#include "includes.h"
#define UNICODE_FLAG(buf) (SVAL(buf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
/****************************************************************************
copy a string from a char* src to a unicode or ascii
dos code page destination choosing unicode or ascii based on the
FLAGS2_UNICODE_STRINGS bit in inbuf
return the number of bytes occupied by the string in the destination
flags can have:
STR_TERMINATE means include the null termination
STR_CONVERT means convert from unix to dos codepage
STR_UPPER means uppercase in the destination
STR_ASCII use ascii even with unicode servers
dest_len is the maximum length allowed in the destination. If dest_len
is -1 then no maxiumum is used
****************************************************************************/
int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int flags)
{
int len=0;
/* treat a pstring as "unlimited" length */
if (dest_len == -1) {
dest_len = sizeof(pstring);
}
if (!(flags & STR_ASCII) && srvstr_align(outbuf, PTR_DIFF(dest, outbuf))) {
*(char *)dest = 0;
dest = (void *)((char *)dest + 1);
dest_len--;
len++;
}
if ((flags & STR_ASCII) || !UNICODE_FLAG(outbuf)) {
/* the client doesn't want unicode */
safe_strcpy(dest, src, dest_len);
len = strlen(dest);
if (flags & STR_TERMINATE) len++;
if (flags & STR_CONVERT) unix_to_dos(dest,True);
if (flags & STR_UPPER) strupper(dest);
return len;
}
/* the server likes unicode. give it the works */
if (flags & STR_CONVERT) {
dos_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE);
} else {
ascii_to_unistr(dest, src, dest_len);
}
if (flags & STR_UPPER) {
strupper_w(dest);
}
len += strlen(src)*2;
if (flags & STR_TERMINATE) len += 2;
return len;
}
/****************************************************************************
copy a string from a unicode or ascii source (depending on flg2)
to a char* destination
flags can have:
STR_CONVERT means convert from dos to unix codepage
STR_TERMINATE means the string in src is null terminated
STR_UNICODE means to force as unicode
if STR_TERMINATE is set then src_len is ignored
src_len is the length of the source area in bytes
return the number of bytes occupied by the string in src
****************************************************************************/
int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_len, int flags)
{
int len;
if (dest_len == -1) {
dest_len = sizeof(pstring);
}
if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(src, inbuf))) {
src = (void *)((char *)src + 1);
if (src_len > 0) src_len--;
}
if ((flags & STR_ASCII) || (!(flags & STR_UNICODE) && !UNICODE_FLAG(inbuf))) {
/* the server doesn't want unicode */
if (flags & STR_TERMINATE) {
safe_strcpy(dest, src, dest_len);
len = strlen(src)+1;
} else {
if (src_len > dest_len) src_len = dest_len;
len = src_len;
memcpy(dest, src, len);
dest[len] = 0;
}
if (flags & STR_CONVERT) dos_to_unix(dest,True);
return len;
}
if (flags & STR_TERMINATE) {
unistr_to_ascii(dest, src, dest_len);
len = strlen(dest)*2 + 2;
} else {
int i, c;
if (dest_len*2 < src_len) src_len = 2*dest_len;
for (i=0; i < src_len; i += 2) {
c = SVAL(src, i);
*dest++ = c;
}
*dest++ = 0;
len = src_len;
}
if (flags & STR_CONVERT) dos_to_unix(dest,True);
return len;
}
/****************************************************************************
return an alignment of either 0 or 1
if unicode is not negotiated then return 0
otherwise return 1 if offset is off
****************************************************************************/
int srvstr_align(void *inbuf, int offset)
{
if (!UNICODE_FLAG(inbuf)) return 0;
return offset & 1;
}
/****************************************************************************
these are useful for replacing all those StrnCpy() ops for copying data
to/from the wire
****************************************************************************/
int srvstr_push_ascii(void *dest, const char *src, int dest_len)
{
return srvstr_push(NULL, dest, src, dest_len,
STR_ASCII|STR_CONVERT|STR_TERMINATE);
}
int srvstr_pull_ascii(char *dest, const void *src, int dest_len)
{
return srvstr_pull(NULL, dest, src, dest_len, -1,
STR_ASCII|STR_CONVERT|STR_TERMINATE);
}