summaryrefslogtreecommitdiffstats
path: root/source/libsmb/clistr.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/libsmb/clistr.c')
-rw-r--r--source/libsmb/clistr.c147
1 files changed, 140 insertions, 7 deletions
diff --git a/source/libsmb/clistr.c b/source/libsmb/clistr.c
index 3c9964368ed..72178967ed5 100644
--- a/source/libsmb/clistr.c
+++ b/source/libsmb/clistr.c
@@ -1,7 +1,9 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 3.0
client string routines
Copyright (C) Andrew Tridgell 2001
+ Copyright (C) Jeremy Allison 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
@@ -18,26 +20,157 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define NO_SYSLOG
+
#include "includes.h"
+#define UNICODE_FLAG(cli, flags) (!(flags & STR_ASCII) && \
+ ((flags & STR_UNICODE || \
+ (SVAL(cli->outbuf, 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
+cli->capabilities flag
+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
+ 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
+****************************************************************************/
+
int clistr_push(struct cli_state *cli, void *dest, const char *src, int dest_len, int flags)
{
- return push_string(cli->outbuf, dest, src, dest_len, flags);
+ int len=0;
+
+ /* treat a pstring as "unlimited" length */
+ if (dest_len == -1)
+ dest_len = sizeof(pstring);
+
+ if (clistr_align_out(cli, dest, flags)) {
+ *(char *)dest = 0;
+ dest = (void *)((char *)dest + 1);
+ dest_len--;
+ len++;
+ }
+
+ if (!UNICODE_FLAG(cli, flags)) {
+ /* the server 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);
+ if (flags & STR_UPPER)
+ strupper(dest);
+ return len;
+ }
+
+ /* the server likes unicode. give it the works */
+ if (flags & STR_CONVERT)
+ dos_PutUniCode(dest, unix_to_dos_static(src), dest_len, flags & STR_TERMINATE);
+ else
+ unix_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE);
+
+ if (flags & STR_UPPER)
+ strupper_w(dest);
+
+ len += strlen(src)*2;
+ if (flags & STR_TERMINATE)
+ len += 2;
+ return len;
}
-int clistr_pull(struct cli_state *cli, char *dest, const void *src, int dest_len, int src_len,
- int flags)
+/****************************************************************************
+copy a string from a unicode or dos codepage source (depending on
+cli->capabilities) to a unix char* destination
+flags can have:
+ STR_TERMINATE means the string in src is null terminated
+ STR_UNICODE means to force as unicode
+ STR_NOALIGN means don't do alignment
+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 clistr_pull(struct cli_state *cli, char *dest, const void *src, int dest_len, int src_len, int flags)
{
- return pull_string(cli->inbuf, dest, src, dest_len, src_len, flags);
+ int len;
+
+ if (dest_len == -1)
+ dest_len = sizeof(pstring);
+
+ if (clistr_align_in(cli, src, flags)) {
+ src = (const void *)((const char *)src + 1);
+ if (src_len > 0)
+ src_len--;
+ }
+
+ if (!UNICODE_FLAG(cli, flags)) {
+ /* 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;
+ }
+ safe_strcpy(dest,dos_to_unix_static(dest),dest_len);
+ return len;
+ }
+
+ if (flags & STR_TERMINATE) {
+ int i;
+ src_len = strlen_w(src)*2+2;
+ for (i=0; i < src_len; i += 2) {
+ const smb_ucs2_t c = (smb_ucs2_t)SVAL(src, i);
+ if (c == (smb_ucs2_t)0 || (dest_len - i < 3))
+ break;
+ dest += unicode_to_unix_char(dest, c);
+ }
+ *dest++ = 0;
+ len = src_len;
+ } else {
+ int i;
+ if (dest_len*2 < src_len)
+ src_len = 2*dest_len;
+ for (i=0; i < src_len; i += 2) {
+ const smb_ucs2_t c = (smb_ucs2_t)SVAL(src, i);
+ dest += unicode_to_unix_char(dest, c);
+ }
+ *dest++ = 0;
+ len = src_len;
+ }
+ 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.
+****************************************************************************/
+
+static int clistr_align(struct cli_state *cli, char *buf, const void *p, int flags)
+{
+ if ((flags & STR_NOALIGN) || !UNICODE_FLAG(cli, flags))
+ return 0;
+ return PTR_DIFF(p, buf) & 1;
+}
int clistr_align_out(struct cli_state *cli, const void *p, int flags)
{
- return align_string(cli->outbuf, p, flags);
+ return clistr_align(cli, cli->outbuf, p, flags);
}
int clistr_align_in(struct cli_state *cli, const void *p, int flags)
{
- return align_string(cli->inbuf, p, flags);
+ return clistr_align(cli, cli->inbuf, p, flags);
}