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

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