root/source3/librpc/ndr/ndr_string.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ndr_pull_string
  2. ndr_push_string
  3. ndr_string_array_size
  4. ndr_print_string
  5. ndr_size_string
  6. ndr_pull_string_array
  7. ndr_push_string_array
  8. ndr_print_string_array
  9. ndr_size_string_array
  10. ndr_string_length
  11. ndr_check_string_terminator
  12. ndr_pull_charset
  13. ndr_push_charset
  14. ndr_charset_length

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    routines for marshalling/unmarshalling string types
   5 
   6    Copyright (C) Andrew Tridgell 2003
   7    
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "librpc/ndr/libndr.h"
  24 
  25 /**
  26   pull a general string from the wire
  27 */
  28 _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
     /* [<][>][^][v][top][bottom][index][help] */
  29 {
  30         char *as=NULL;
  31         uint32_t len1, ofs, len2;
  32         uint16_t len3;
  33         size_t converted_size;
  34         int chset = CH_UTF16;
  35         unsigned byte_mul = 2;
  36         unsigned flags = ndr->flags;
  37         unsigned c_len_term = 0;
  38 
  39         if (!(ndr_flags & NDR_SCALARS)) {
  40                 return NDR_ERR_SUCCESS;
  41         }
  42 
  43         if (NDR_BE(ndr)) {
  44                 chset = CH_UTF16BE;
  45         }
  46 
  47         if (flags & LIBNDR_FLAG_STR_ASCII) {
  48                 chset = CH_DOS;
  49                 byte_mul = 1;
  50                 flags &= ~LIBNDR_FLAG_STR_ASCII;
  51         }
  52 
  53         if (flags & LIBNDR_FLAG_STR_UTF8) {
  54                 chset = CH_UTF8;
  55                 byte_mul = 1;
  56                 flags &= ~LIBNDR_FLAG_STR_UTF8;
  57         }
  58 
  59         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
  60         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
  61                 c_len_term = 1;
  62                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
  63         }
  64 
  65         switch (flags & LIBNDR_STRING_FLAGS) {
  66         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
  67         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
  68                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
  69                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
  70                 if (ofs != 0) {
  71                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
  72                                               ndr->flags & LIBNDR_STRING_FLAGS);
  73                 }
  74                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
  75                 if (len2 > len1) {
  76                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
  77                                               "Bad string lengths len1=%u ofs=%u len2=%u\n", 
  78                                               len1, ofs, len2);
  79                 }
  80                 NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
  81                 if (len2 == 0) {
  82                         as = talloc_strdup(ndr->current_mem_ctx, "");
  83                 } else {
  84                         if (!convert_string_talloc(ndr->current_mem_ctx, chset,
  85                                                    CH_UNIX,
  86                                                    ndr->data+ndr->offset,
  87                                                    (len2 + c_len_term)*byte_mul,
  88                                                    (void **)(void *)&as,
  89                                                    &converted_size, false))
  90                         {
  91                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
  92                                                       "Bad character conversion");
  93                         }
  94                 }
  95                 NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
  96 
  97                 if (len1 != len2) {
  98                         DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
  99                 }
 100 
 101                 /* this is a way of detecting if a string is sent with the wrong
 102                    termination */
 103                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
 104                         if (strlen(as) < (len2 + c_len_term)) {
 105                                 DEBUG(6,("short string '%s'\n", as));
 106                         }
 107                 } else {
 108                         if (strlen(as) == (len2 + c_len_term)) {
 109                                 DEBUG(6,("long string '%s'\n", as));
 110                         }
 111                 }
 112                 *s = as;
 113                 break;
 114 
 115         case LIBNDR_FLAG_STR_SIZE4:
 116         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
 117                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
 118                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
 119                 if (len1 == 0) {
 120                         as = talloc_strdup(ndr->current_mem_ctx, "");
 121                 } else {
 122                         if (!convert_string_talloc(ndr->current_mem_ctx, chset,
 123                                                    CH_UNIX,
 124                                                    ndr->data+ndr->offset,
 125                                                    (len1 + c_len_term)*byte_mul,
 126                                                    (void **)(void *)&as,
 127                                                    &converted_size, false))
 128                         {
 129                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
 130                                                       "Bad character conversion");
 131                         }
 132                 }
 133                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
 134 
 135                 /* this is a way of detecting if a string is sent with the wrong
 136                    termination */
 137                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
 138                         if (strlen(as) < (len1 + c_len_term)) {
 139                                 DEBUG(6,("short string '%s'\n", as));
 140                         }
 141                 } else {
 142                         if (strlen(as) == (len1 + c_len_term)) {
 143                                 DEBUG(6,("long string '%s'\n", as));
 144                         }
 145                 }
 146                 *s = as;
 147                 break;
 148 
 149         case LIBNDR_FLAG_STR_LEN4:
 150         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
 151                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
 152                 if (ofs != 0) {
 153                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
 154                                               ndr->flags & LIBNDR_STRING_FLAGS);
 155                 }
 156                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
 157                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
 158                 if (len1 == 0) {
 159                         as = talloc_strdup(ndr->current_mem_ctx, "");
 160                 } else {
 161                         if (!convert_string_talloc(ndr->current_mem_ctx, chset,
 162                                                    CH_UNIX,
 163                                                    ndr->data+ndr->offset,
 164                                                    (len1 + c_len_term)*byte_mul,
 165                                                    (void **)(void *)&as,
 166                                                    &converted_size, false))
 167                         {
 168                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
 169                                                       "Bad character conversion");
 170                         }
 171                 }
 172                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
 173 
 174                 /* this is a way of detecting if a string is sent with the wrong
 175                    termination */
 176                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
 177                         if (strlen(as) < (len1 + c_len_term)) {
 178                                 DEBUG(6,("short string '%s'\n", as));
 179                         }
 180                 } else {
 181                         if (strlen(as) == (len1 + c_len_term)) {
 182                                 DEBUG(6,("long string '%s'\n", as));
 183                         }
 184                 }
 185                 *s = as;
 186                 break;
 187 
 188 
 189         case LIBNDR_FLAG_STR_SIZE2:
 190         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
 191                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
 192                 NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
 193                 if (len3 == 0) {
 194                         as = talloc_strdup(ndr->current_mem_ctx, "");
 195                 } else {
 196                         if (!convert_string_talloc(ndr->current_mem_ctx, chset,
 197                                                    CH_UNIX,
 198                                                    ndr->data+ndr->offset,
 199                                                    (len3 + c_len_term)*byte_mul,
 200                                                    (void **)(void *)&as,
 201                                                    &converted_size, false))
 202                         {
 203                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
 204                                                       "Bad character conversion");
 205                         }
 206                 }
 207                 NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
 208 
 209                 /* this is a way of detecting if a string is sent with the wrong
 210                    termination */
 211                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
 212                         if (strlen(as) < (len3 + c_len_term)) {
 213                                 DEBUG(6,("short string '%s'\n", as));
 214                         }
 215                 } else {
 216                         if (strlen(as) == (len3 + c_len_term)) {
 217                                 DEBUG(6,("long string '%s'\n", as));
 218                         }
 219                 }
 220                 *s = as;
 221                 break;
 222 
 223         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
 224                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
 225                 NDR_PULL_NEED_BYTES(ndr, len3);
 226                 if (len3 == 0) {
 227                         as = talloc_strdup(ndr->current_mem_ctx, "");
 228                 } else {
 229                         if (!convert_string_talloc(ndr->current_mem_ctx, chset,
 230                                                    CH_UNIX,
 231                                                    ndr->data+ndr->offset, len3,
 232                                                    (void **)(void *)&as,
 233                                                    &converted_size, false))
 234                         {
 235                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
 236                                                       "Bad character conversion");
 237                         }
 238                 }
 239                 NDR_CHECK(ndr_pull_advance(ndr, len3));
 240                 *s = as;
 241                 break;
 242 
 243         case LIBNDR_FLAG_STR_NULLTERM:
 244                 if (byte_mul == 1) {
 245                         len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
 246                 } else {
 247                         len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
 248                 }
 249                 if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
 250                                            ndr->data+ndr->offset, len1,
 251                                            (void **)(void *)&as,
 252                                            &converted_size, false))
 253                 {
 254                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
 255                                               "Bad character conversion");
 256                 }
 257                 NDR_CHECK(ndr_pull_advance(ndr, len1));
 258                 *s = as;
 259                 break;
 260 
 261         case LIBNDR_FLAG_STR_NOTERM:
 262                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
 263                         return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
 264                                               ndr->flags & LIBNDR_STRING_FLAGS);
 265                 }
 266 
 267                 len1 = ndr->data_size - ndr->offset;
 268 
 269                 NDR_PULL_NEED_BYTES(ndr, len1);
 270                 if (len1 == 0) {
 271                         as = talloc_strdup(ndr->current_mem_ctx, "");
 272                 } else {
 273                         if (!convert_string_talloc(ndr->current_mem_ctx, chset,
 274                                                    CH_UNIX,
 275                                                    ndr->data+ndr->offset, len1,
 276                                                    (void **)(void *)&as,
 277                                                    &converted_size, false))
 278                         {
 279                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
 280                                                       "Bad character conversion");
 281                         }
 282                 }
 283                 NDR_CHECK(ndr_pull_advance(ndr, len1));
 284 
 285                 *s = as;
 286                 break;
 287 
 288         default:
 289                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
 290                                       ndr->flags & LIBNDR_STRING_FLAGS);
 291         }
 292 
 293         return NDR_ERR_SUCCESS;
 294 }
 295 
 296 
 297 /**
 298   push a general string onto the wire
 299 */
 300 _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 301 {
 302         ssize_t s_len, c_len;
 303         size_t d_len;
 304         int chset = CH_UTF16;
 305         unsigned flags = ndr->flags;
 306         unsigned byte_mul = 2;
 307         uint8_t *dest = NULL;
 308 
 309         if (!(ndr_flags & NDR_SCALARS)) {
 310                 return NDR_ERR_SUCCESS;
 311         }
 312 
 313         if (NDR_BE(ndr)) {
 314                 chset = CH_UTF16BE;
 315         }
 316         
 317         s_len = s?strlen(s):0;
 318 
 319         if (flags & LIBNDR_FLAG_STR_ASCII) {
 320                 chset = CH_DOS;
 321                 byte_mul = 1;
 322                 flags &= ~LIBNDR_FLAG_STR_ASCII;
 323         }
 324 
 325         if (flags & LIBNDR_FLAG_STR_UTF8) {
 326                 chset = CH_UTF8;
 327                 byte_mul = 1;
 328                 flags &= ~LIBNDR_FLAG_STR_UTF8;
 329         }
 330 
 331         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
 332 
 333         if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
 334                 s_len++;
 335         }
 336         if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
 337                                    (void **)(void *)&dest, &d_len, false))
 338         {
 339                 return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
 340                                       "Bad character conversion");
 341         }
 342 
 343         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
 344                 c_len = d_len;
 345                 flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
 346         } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
 347                 c_len = (d_len / byte_mul)-1;
 348                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
 349         } else {
 350                 c_len = d_len / byte_mul;
 351         }
 352 
 353         switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
 354         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
 355                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
 356                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
 357                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
 358                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
 359                 break;
 360 
 361         case LIBNDR_FLAG_STR_LEN4:
 362                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
 363                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
 364                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
 365                 break;
 366 
 367         case LIBNDR_FLAG_STR_SIZE4:
 368                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
 369                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
 370                 break;
 371 
 372         case LIBNDR_FLAG_STR_SIZE2:
 373                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
 374                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
 375                 break;
 376 
 377         case LIBNDR_FLAG_STR_NULLTERM:
 378                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
 379                 break;
 380 
 381         default:
 382                 if (ndr->flags & LIBNDR_FLAG_REMAINING) {
 383                         NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
 384                         break;          
 385                 }
 386 
 387                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
 388                                       ndr->flags & LIBNDR_STRING_FLAGS);
 389         }
 390 
 391         talloc_free(dest);
 392 
 393         return NDR_ERR_SUCCESS;
 394 }
 395 
 396 /**
 397   push a general string onto the wire
 398 */
 399 _PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 400 {
 401         size_t c_len;
 402         unsigned flags = ndr->flags;
 403         unsigned byte_mul = 2;
 404         unsigned c_len_term = 1;
 405 
 406         c_len = s?strlen_m(s):0;
 407 
 408         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
 409                 byte_mul = 1;
 410         }
 411 
 412         if (flags & LIBNDR_FLAG_STR_NOTERM) {
 413                 c_len_term = 0;
 414         }
 415 
 416         c_len = c_len + c_len_term;
 417 
 418         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
 419                 c_len = c_len * byte_mul;
 420         }
 421 
 422         return c_len;
 423 }
 424 
 425 _PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 426 {
 427         if (s) {
 428                 ndr->print(ndr, "%-25s: '%s'", name, s);
 429         } else {
 430                 ndr->print(ndr, "%-25s: NULL", name);
 431         }
 432 }
 433 
 434 _PUBLIC_ uint32_t ndr_size_string(int ret, const char * const* string, int flags) 
     /* [<][>][^][v][top][bottom][index][help] */
 435 {
 436         /* FIXME: Is this correct for all strings ? */
 437         if(!(*string)) return ret;
 438         return ret+strlen(*string)+1;
 439 }
 440 
 441 /**
 442   pull a general string array from the wire
 443 */
 444 _PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a)
     /* [<][>][^][v][top][bottom][index][help] */
 445 {
 446         const char **a = NULL;
 447         uint32_t count;
 448         unsigned flags = ndr->flags;
 449         unsigned saved_flags = ndr->flags;
 450 
 451         if (!(ndr_flags & NDR_SCALARS)) {
 452                 return NDR_ERR_SUCCESS;
 453         }
 454 
 455         switch (flags & LIBNDR_STRING_FLAGS) {
 456         case LIBNDR_FLAG_STR_NULLTERM:
 457                 /* 
 458                  * here the strings are null terminated
 459                  * but also the array is null terminated
 460                  */
 461                 for (count = 0;; count++) {
 462                         TALLOC_CTX *tmp_ctx;
 463                         const char *s = NULL;
 464                         a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
 465                         NDR_ERR_HAVE_NO_MEMORY(a);
 466                         a[count]   = NULL;
 467                         a[count+1]   = NULL;
 468 
 469                         tmp_ctx = ndr->current_mem_ctx;
 470                         ndr->current_mem_ctx = a;
 471                         NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
 472                         ndr->current_mem_ctx = tmp_ctx;
 473                         if (strcmp("", s)==0) {
 474                                 a[count] = NULL;
 475                                 break;
 476                         } else {
 477                                 a[count] = s;
 478                         }
 479                 }
 480 
 481                 *_a =a;
 482                 break;
 483 
 484         case LIBNDR_FLAG_STR_NOTERM:
 485                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
 486                         return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
 487                                               ndr->flags & LIBNDR_STRING_FLAGS);
 488                 }
 489                 /*
 490                  * here the strings are not null terminated
 491                  * but serarated by a null terminator
 492                  *
 493                  * which means the same as:
 494                  * very string is null terminated exept the last
 495                  * string is terminated by the end of the buffer
 496                  *
 497                  * as LIBNDR_FLAG_STR_NULLTERM also end at the end
 498                  * of the buffer, we can pull each string with this flag
 499                  */
 500                 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
 501                 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
 502 
 503                 for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
 504                         TALLOC_CTX *tmp_ctx;
 505                         const char *s = NULL;
 506                         a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
 507                         NDR_ERR_HAVE_NO_MEMORY(a);
 508                         a[count]   = NULL;
 509                         a[count+1]   = NULL;
 510 
 511                         tmp_ctx = ndr->current_mem_ctx;
 512                         ndr->current_mem_ctx = a;
 513                         NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
 514                         ndr->current_mem_ctx = tmp_ctx;
 515                         a[count] = s;
 516                 }
 517 
 518                 *_a =a;
 519                 break;
 520 
 521         default:
 522                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
 523                                       ndr->flags & LIBNDR_STRING_FLAGS);
 524         }
 525 
 526         ndr->flags = saved_flags;
 527         return NDR_ERR_SUCCESS;
 528 }
 529 
 530 /**
 531   push a general string array onto the wire
 532 */
 533 _PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
     /* [<][>][^][v][top][bottom][index][help] */
 534 {
 535         uint32_t count;
 536         unsigned flags = ndr->flags;
 537         unsigned saved_flags = ndr->flags;
 538 
 539         if (!(ndr_flags & NDR_SCALARS)) {
 540                 return NDR_ERR_SUCCESS;
 541         }
 542 
 543         switch (flags & LIBNDR_STRING_FLAGS) {
 544         case LIBNDR_FLAG_STR_NULLTERM:
 545                 for (count = 0; a && a[count]; count++) {
 546                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
 547                 }
 548 
 549                 NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
 550                 break;
 551 
 552         case LIBNDR_FLAG_STR_NOTERM:
 553                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
 554                         return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
 555                                               ndr->flags & LIBNDR_STRING_FLAGS);
 556                 }
 557 
 558                 for (count = 0; a && a[count]; count++) {
 559                         if (count > 0) {
 560                                 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
 561                                 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
 562                                 NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
 563                                 ndr->flags = saved_flags;
 564                         }
 565                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
 566                 }
 567 
 568                 break;
 569 
 570         default:
 571                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
 572                                       ndr->flags & LIBNDR_STRING_FLAGS);
 573         }
 574         
 575         ndr->flags = saved_flags;
 576         return NDR_ERR_SUCCESS;
 577 }
 578 
 579 _PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
     /* [<][>][^][v][top][bottom][index][help] */
 580 {
 581         uint32_t count;
 582         uint32_t i;
 583 
 584         for (count = 0; a && a[count]; count++) {}
 585 
 586         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
 587         ndr->depth++;
 588         for (i=0;i<count;i++) {
 589                 char *idx=NULL;
 590                 if (asprintf(&idx, "[%d]", i) != -1) {
 591                         ndr_print_string(ndr, idx, a[i]);
 592                         free(idx);
 593                 }
 594         }
 595         ndr->depth--;
 596 }
 597 
 598 _PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
 599 {
 600         uint32_t i;
 601         size_t size = 0;
 602 
 603         switch (flags & LIBNDR_STRING_FLAGS) {
 604         case LIBNDR_FLAG_STR_NULLTERM:
 605                 for (i = 0; i < count; i++) {
 606                         size += strlen_m_term(a[i]);
 607                 }
 608                 break;
 609         case LIBNDR_FLAG_STR_NOTERM:
 610                 for (i = 0; i < count; i++) {
 611                         size += strlen_m(a[i]);
 612                 }
 613                 break;
 614         default:
 615                 return 0;
 616         }
 617 
 618         return size;
 619 }
 620 
 621 /**
 622  * Return number of elements in a string including the last (zeroed) element 
 623  */
 624 _PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
     /* [<][>][^][v][top][bottom][index][help] */
 625 {
 626         uint32_t i;
 627         uint8_t zero[4] = {0,0,0,0};
 628         const char *var = (const char *)_var;
 629 
 630         for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
 631 
 632         return i+1;
 633 }
 634 
 635 _PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
     /* [<][>][^][v][top][bottom][index][help] */
 636 {
 637         uint32_t i;
 638         uint32_t save_offset;
 639 
 640         save_offset = ndr->offset;
 641         ndr_pull_advance(ndr, (count - 1) * element_size);
 642         NDR_PULL_NEED_BYTES(ndr, element_size);
 643 
 644         for (i = 0; i < element_size; i++) {
 645                  if (ndr->data[ndr->offset+i] != 0) {
 646                         ndr->offset = save_offset;
 647 
 648                         return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
 649                  }
 650         }
 651 
 652         ndr->offset = save_offset;
 653 
 654         return NDR_ERR_SUCCESS;
 655 }
 656 
 657 _PUBLIC_ enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
     /* [<][>][^][v][top][bottom][index][help] */
 658 {
 659         size_t converted_size;
 660 
 661         if (length == 0) {
 662                 *var = talloc_strdup(ndr->current_mem_ctx, "");
 663                 return NDR_ERR_SUCCESS;
 664         }
 665 
 666         if (NDR_BE(ndr) && chset == CH_UTF16) {
 667                 chset = CH_UTF16BE;
 668         }
 669 
 670         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
 671 
 672         if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
 673                                    ndr->data+ndr->offset, length*byte_mul,
 674                                    discard_const_p(void *, var),
 675                                    &converted_size, false))
 676         {
 677                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
 678                                       "Bad character conversion");
 679         }
 680         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
 681 
 682         return NDR_ERR_SUCCESS;
 683 }
 684 
 685 _PUBLIC_ enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
     /* [<][>][^][v][top][bottom][index][help] */
 686 {
 687         ssize_t ret, required;
 688 
 689         if (NDR_BE(ndr) && chset == CH_UTF16) {
 690                 chset = CH_UTF16BE;
 691         }
 692 
 693         required = byte_mul * length;
 694         
 695         NDR_PUSH_NEED_BYTES(ndr, required);
 696         ret = convert_string(CH_UNIX, chset, 
 697                              var, strlen(var),
 698                              ndr->data+ndr->offset, required, false);
 699         if (ret == -1) {
 700                 return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
 701                                       "Bad character conversion");
 702         }
 703 
 704         /* Make sure the remaining part of the string is filled with zeroes */
 705         if (ret < required) {
 706                 memset(ndr->data+ndr->offset+ret, 0, required-ret);
 707         }
 708 
 709         ndr->offset += required;
 710 
 711         return NDR_ERR_SUCCESS;
 712 }
 713 
 714 /* Return number of elements in a string in the specified charset */
 715 _PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset)
     /* [<][>][^][v][top][bottom][index][help] */
 716 {
 717         /* FIXME: Treat special chars special here, taking chset into account */
 718         /* Also include 0 byte */
 719         return strlen((const char *)var)+1;
 720 }

/* [<][>][^][v][top][bottom][index][help] */