added support for big-endian ucs2 strings (as used by big-endian
authorAndrew Tridgell <tridge@samba.org>
Tue, 16 Dec 2003 09:20:34 +0000 (09:20 +0000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 16 Dec 2003 09:20:34 +0000 (09:20 +0000)
msrpc).

this was easier than I expected!

source/include/charset.h
source/lib/charcnv.c
source/lib/iconv.c
source/librpc/ndr/ndr_basic.c

index 3b3e613fd3ac1291e1bc074a113235ec770499b1..daf10e23c13519a46cae4241d5ff754a297bf6e9 100644 (file)
@@ -20,9 +20,9 @@
 */
 
 /* this defines the charset types used in samba */
-typedef enum {CH_UCS2=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4} charset_t;
+typedef enum {CH_UCS2=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4, CH_UCS2BE=5} charset_t;
 
-#define NUM_CHARSETS 5
+#define NUM_CHARSETS 6
 
 /*
  *   for each charset we have a function that pulls from that charset to
index 72277b4f2e665cdbdad4fa6bc80d42174b2d3ad7..11b0e64dce907316722c72f761aef0b6aa370e28 100644 (file)
@@ -52,6 +52,7 @@ static const char *charset_name(charset_t ch)
        else if (ch == CH_DOS) ret = lp_dos_charset();
        else if (ch == CH_DISPLAY) ret = lp_display_charset();
        else if (ch == CH_UTF8) ret = "UTF8";
+       else if (ch == CH_UCS2BE) ret = "UCS-2BE";
 
        if (!ret || !*ret) ret = "ASCII";
        return ret;
index 2a0b013257adaeb333f2cfc1daabaf866fb046a0..3f37583e3930d5b557b11b6792df417ec62ecc68 100644 (file)
  * @sa Samba Developers Guide
  **/
 
-static size_t ascii_pull(void *,const char **, size_t *, char **, size_t *);
-static size_t ascii_push(void *,const char **, size_t *, char **, size_t *);
-static size_t  utf8_pull(void *,const char **, size_t *, char **, size_t *);
-static size_t  utf8_push(void *,const char **, size_t *, char **, size_t *);
+static size_t ascii_pull  (void *,const char **, size_t *, char **, size_t *);
+static size_t ascii_push  (void *,const char **, size_t *, char **, size_t *);
+static size_t utf8_pull   (void *,const char **, size_t *, char **, size_t *);
+static size_t utf8_push   (void *,const char **, size_t *, char **, size_t *);
 static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *);
 static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *);
-static size_t iconv_copy(void *,const char **, size_t *, char **, size_t *);
+static size_t iconv_copy  (void *,const char **, size_t *, char **, size_t *);
+static size_t iconv_swab  (void *,const char **, size_t *, char **, size_t *);
 
 static struct charset_functions builtin_functions[] = {
        {"UCS-2LE",  iconv_copy, iconv_copy},
+       {"UCS-2BE",  iconv_swab, iconv_swab},
        {"UTF8",   utf8_pull,  utf8_push},
        {"ASCII", ascii_pull, ascii_push},
        {"UCS2-HEX", ucs2hex_pull, ucs2hex_push},
@@ -404,6 +406,31 @@ static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft,
        return 0;
 }
 
+static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft,
+                        char **outbuf, size_t *outbytesleft)
+{
+       int n;
+
+       n = MIN(*inbytesleft, *outbytesleft);
+
+       swab(*inbuf, *outbuf, (n&~1));
+       if (n&1) {
+               (*outbuf)[n-1] = 0;
+       }
+
+       (*inbytesleft) -= n;
+       (*outbytesleft) -= n;
+       (*inbuf) += n;
+       (*outbuf) += n;
+
+       if (*inbytesleft > 0) {
+               errno = E2BIG;
+               return -1;
+       }
+
+       return 0;
+}
+
 
 static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft,
                         char **outbuf, size_t *outbytesleft)
index ed75b8c27c0990c11e2a166b8c980dfa51fc7d9f..cde0b52f3beea1855cb15c73fd5d656a55625009 100644 (file)
@@ -344,11 +344,16 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
        uint32 len1, ofs, len2;
        uint16 len3;
        int ret;
+       int chset = CH_UCS2;
 
        if (!(ndr_flags & NDR_SCALARS)) {
                return NT_STATUS_OK;
        }
 
+       if (ndr->flags & LIBNDR_FLAG_BIGENDIAN) {
+               chset = CH_UCS2BE;
+       }
+
        switch (ndr->flags & LIBNDR_STRING_FLAGS) {
        case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
        case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
@@ -365,7 +370,7 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
                        break;
                }
                NDR_PULL_NEED_BYTES(ndr, len2*2);
-               ret = convert_string_talloc(ndr->mem_ctx, CH_UCS2, CH_UNIX, 
+               ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, 
                                            ndr->data+ndr->offset, 
                                            len2*2,
                                            (const void **)&as);
@@ -384,7 +389,7 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
                        *s = talloc_strdup(ndr->mem_ctx, "");
                        break;
                }
-               ret = convert_string_talloc(ndr->mem_ctx, CH_UCS2, CH_UNIX, 
+               ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, 
                                            ndr->data+ndr->offset, 
                                            len1*2,
                                            (const void **)&as);
@@ -402,7 +407,7 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
                if (len1*2+2 <= ndr->data_size - ndr->offset) {
                        len1++;
                }
-               ret = convert_string_talloc(ndr->mem_ctx, CH_UCS2, CH_UNIX, 
+               ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, 
                                            ndr->data+ndr->offset, 
                                            len1*2,
                                            (const void **)s);
@@ -461,10 +466,15 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
 {
        ssize_t s_len, c_len;
        int ret;
+       int chset = CH_UCS2;
 
        if (!(ndr_flags & NDR_SCALARS)) {
                return NT_STATUS_OK;
        }
+
+       if (ndr->flags & LIBNDR_FLAG_BIGENDIAN) {
+               chset = CH_UCS2BE;
+       }
        
        s_len = s?strlen(s):0;
        c_len = s?strlen_m(s):0;
@@ -475,7 +485,7 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
                NDR_CHECK(ndr_push_uint32(ndr, 0));
                NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
                NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
-               ret = convert_string(CH_UNIX, CH_UCS2
+               ret = convert_string(CH_UNIX, chset
                                     s, s_len+1,
                                     ndr->data+ndr->offset, c_len*2 + 2);
                if (ret == -1) {
@@ -490,7 +500,7 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
                NDR_CHECK(ndr_push_uint32(ndr, 0));
                NDR_CHECK(ndr_push_uint32(ndr, c_len));
                NDR_PUSH_NEED_BYTES(ndr, c_len*2);
-               ret = convert_string(CH_UNIX, CH_UCS2
+               ret = convert_string(CH_UNIX, chset
                                     s, s_len,
                                     ndr->data+ndr->offset, c_len*2);
                if (ret == -1) {
@@ -503,7 +513,7 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
        case LIBNDR_FLAG_STR_SIZE4:
                NDR_CHECK(ndr_push_uint32(ndr, c_len + 1));
                NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
-               ret = convert_string(CH_UNIX, CH_UCS2
+               ret = convert_string(CH_UNIX, chset
                                     s, s_len + 1,
                                     ndr->data+ndr->offset, c_len*2 + 2);
                if (ret == -1) {
@@ -515,7 +525,7 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
 
        case LIBNDR_FLAG_STR_NULLTERM:
                NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
-               ret = convert_string(CH_UNIX, CH_UCS2
+               ret = convert_string(CH_UNIX, chset
                                     s, s_len+1,
                                     ndr->data+ndr->offset, c_len*2 + 2);
                if (ret == -1) {