summaryrefslogtreecommitdiff
path: root/librpc
diff options
context:
space:
mode:
authorSean Finney <seanius@seanius.net>2011-05-31 09:49:19 +0200
committerAndrew Bartlett <abartlet@samba.org>2011-06-01 00:30:40 +0200
commit08abd1f5e851c4f40a863f5c3ff6acc93d691efb (patch)
tree04bef33f02528f120dd726aaf3f959fb453501de /librpc
parentc51795c747198f9e002505ffa39ad710beff0358 (diff)
downloadsamba-08abd1f5e851c4f40a863f5c3ff6acc93d691efb.tar.gz
librpc/ndr: add new LIBNDR_FLAG_STR_RAW8 for ndr_pull_string
Introduce a new flag, LIBNDR_FLAG_STR_RAW8, which indicates that libndr should not attempt to convert the corresponding byte sequence, and place the responsibility on the caller to do so later. This is needed in cases where the string is known to be 8-bit and either NULL terminated or of known length, but in an unspecified character set. For example, when pulling PT_STRING8 properties from an exchange server via libmapi + libndr, the codepage is neither known nor in the control of the caller, and is determined by subsequent properties requested from the server. Therefore the client would like to fetch all properties in one large batch, and convert the resulting strings locally. This commit also includes some (basic) tests of each of the flags' respective behaviors with the ndr push/pull string functions, in a new source4 torture test suite ndr.ndr_string. Signed-off-by: Sean Finney <seanius@seanius.net>
Diffstat (limited to 'librpc')
-rw-r--r--librpc/idl/idl_types.h6
-rw-r--r--librpc/ndr/libndr.h1
-rw-r--r--librpc/ndr/ndr_string.c46
3 files changed, 45 insertions, 8 deletions
diff --git a/librpc/idl/idl_types.h b/librpc/idl/idl_types.h
index 023c04020ea..c50eface0d1 100644
--- a/librpc/idl/idl_types.h
+++ b/librpc/idl/idl_types.h
@@ -8,6 +8,7 @@
#define STR_CONFORMANT LIBNDR_FLAG_STR_CONFORMANT
#define STR_CHARLEN LIBNDR_FLAG_STR_CHARLEN
#define STR_UTF8 LIBNDR_FLAG_STR_UTF8
+#define STR_RAW8 LIBNDR_FLAG_STR_RAW8
/*
a null terminated UCS2 string
@@ -25,6 +26,11 @@
#define utf8string [flag(STR_UTF8|STR_NULLTERM)] string
/*
+ a null terminated "raw" string (null terminated byte sequence)
+*/
+#define raw8string [flag(STR_RAW8|STR_NULLTERM)] string
+
+/*
a null terminated UCS2 string
*/
#define nstring_array [flag(STR_NULLTERM|NDR_ALIGN2)] string_array
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index cbe9b40440e..ca3710bc986 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -122,6 +122,7 @@ struct ndr_print {
#define LIBNDR_FLAG_STR_CONFORMANT (1<<10)
#define LIBNDR_FLAG_STR_CHARLEN (1<<11)
#define LIBNDR_FLAG_STR_UTF8 (1<<12)
+#define LIBNDR_FLAG_STR_RAW8 (1<<13)
#define LIBNDR_STRING_FLAGS (0x7FFC)
/* set if relative pointers should *not* be marshalled in reverse order */
diff --git a/librpc/ndr/ndr_string.c b/librpc/ndr/ndr_string.c
index d0d83032409..207d55bb1b1 100644
--- a/librpc/ndr/ndr_string.c
+++ b/librpc/ndr/ndr_string.c
@@ -31,7 +31,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags,
uint32_t len1, ofs, len2;
uint16_t len3;
size_t conv_src_len = 0, converted_size;
- int chset = CH_UTF16;
+ int do_convert = 1, chset = CH_UTF16;
unsigned byte_mul = 2;
unsigned flags = ndr->flags;
unsigned c_len_term = 0;
@@ -56,6 +56,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags,
flags &= ~LIBNDR_FLAG_STR_UTF8;
}
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ do_convert = 0;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
+
flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
if (flags & LIBNDR_FLAG_STR_CHARLEN) {
c_len_term = 1;
@@ -138,7 +144,11 @@ _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags,
if (conv_src_len == 0) {
as = talloc_strdup(ndr->current_mem_ctx, "");
} else {
- if (!convert_string_talloc(ndr->current_mem_ctx, chset,
+ if (!do_convert) {
+ as = talloc_strndup(ndr->current_mem_ctx,
+ ndr->data + ndr->offset,
+ conv_src_len);
+ } else if (!convert_string_talloc(ndr->current_mem_ctx, chset,
CH_UNIX, ndr->data + ndr->offset,
conv_src_len * byte_mul,
(void **)(void *)&as,
@@ -174,7 +184,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags,
{
ssize_t s_len, c_len;
size_t d_len;
- int chset = CH_UTF16;
+ int do_convert = 1, chset = CH_UTF16;
unsigned flags = ndr->flags;
unsigned byte_mul = 2;
uint8_t *dest = NULL;
@@ -201,12 +211,22 @@ _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags,
flags &= ~LIBNDR_FLAG_STR_UTF8;
}
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ do_convert = 0;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
+
flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
s_len++;
}
- if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
+
+ if (!do_convert) {
+ d_len = s_len;
+ dest = talloc_strndup(ndr, s, s_len);
+ } else if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
(void **)(void *)&dest, &d_len))
{
return ndr_push_error(ndr, NDR_ERR_CHARCNV,
@@ -276,9 +296,13 @@ _PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
unsigned byte_mul = 2;
unsigned c_len_term = 1;
- c_len = s?strlen_m(s):0;
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ c_len = s?strlen(s):0;
+ } else {
+ c_len = s?strlen_m(s):0;
+ }
- if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
+ if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_RAW8|LIBNDR_FLAG_STR_UTF8)) {
byte_mul = 1;
}
@@ -484,16 +508,22 @@ _PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, int flags)
{
uint32_t i;
size_t size = 0;
+ int rawbytes = 0;
+
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ rawbytes = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
switch (flags & LIBNDR_STRING_FLAGS) {
case LIBNDR_FLAG_STR_NULLTERM:
for (i = 0; i < count; i++) {
- size += strlen_m_term(a[i]);
+ size += rawbytes?strlen(a[i]) + 1:strlen_m_term(a[i]);
}
break;
case LIBNDR_FLAG_STR_NOTERM:
for (i = 0; i < count; i++) {
- size += strlen_m(a[i]);
+ size += rawbytes?strlen(a[i]):strlen_m(a[i]);
}
break;
default: