Back to index

lightning-sunbird  0.9+nobinonly
decode.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * Copyright (c) 1990 Regents of the University of Michigan.
00040  * All rights reserved.
00041  *
00042  * Redistribution and use in source and binary forms are permitted
00043  * provided that this notice is preserved and that due credit is given
00044  * to the University of Michigan at Ann Arbor. The name of the University
00045  * may not be used to endorse or promote products derived from this
00046  * software without specific prior written permission. This software
00047  * is provided ``as is'' without express or implied warranty.
00048  */
00049 
00050 /* decode.c - ber input decoding routines */
00051 
00052 #include "lber-int.h"
00053 
00054 /*
00055  * Note: ber_get_tag() only uses the ber_end and ber_ptr elements of ber.
00056  * If that changes, the ber_peek_tag() and/or ber_skip_tag() implementations
00057  * will need to be changed.
00058  */
00059 /* return the tag - LBER_DEFAULT returned means trouble */
00060 unsigned long
00061 LDAP_CALL
00062 ber_get_tag( BerElement *ber )
00063 {
00064        unsigned char xbyte;
00065        unsigned long tag;
00066        char          *tagp;
00067        int           i;
00068 
00069        if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
00070               return( LBER_DEFAULT );
00071 
00072        if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
00073               return( (unsigned long) xbyte );
00074 
00075        tagp = (char *) &tag;
00076        tagp[0] = xbyte;
00077        for ( i = 1; i < sizeof(long); i++ ) {
00078               if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
00079                      return( LBER_DEFAULT );
00080 
00081               tagp[i] = xbyte;
00082 
00083               if ( ! (xbyte & LBER_MORE_TAG_MASK) )
00084                      break;
00085        }
00086 
00087        /* tag too big! */
00088        if ( i == sizeof(long) )
00089               return( LBER_DEFAULT );
00090 
00091        /* want leading, not trailing 0's */
00092        return( tag >> (sizeof(long) - i - 1) );
00093 }
00094 
00095 /*
00096  * Note: ber_skip_tag() only uses the ber_end and ber_ptr elements of ber.
00097  * If that changes, the implementation of ber_peek_tag() will need to
00098  * be changed.
00099  */
00100 unsigned long
00101 LDAP_CALL
00102 ber_skip_tag( BerElement *ber, unsigned long *len )
00103 {
00104        unsigned long tag;
00105        unsigned char lc;
00106        int           noctets, diff;
00107        unsigned long netlen;
00108 
00109        /*
00110         * Any ber element looks like this: tag length contents.
00111         * Assuming everything's ok, we return the tag byte (we
00112         * can assume a single byte), and return the length in len.
00113         *
00114         * Assumptions:
00115         *     1) definite lengths
00116         *     2) primitive encodings used whenever possible
00117         */
00118 
00119        /*
00120         * First, we read the tag.
00121         */
00122 
00123        if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT )
00124               return( LBER_DEFAULT );
00125 
00126        /*
00127         * Next, read the length.  The first byte contains the length of
00128         * the length.  If bit 8 is set, the length is the long form,
00129         * otherwise it's the short form.  We don't allow a length that's
00130         * greater than what we can hold in an unsigned long.
00131         */
00132 
00133        *len = netlen = 0;
00134        if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
00135               return( LBER_DEFAULT );
00136        if ( lc & 0x80 ) {
00137               noctets = (lc & 0x7f);
00138               if ( noctets > sizeof(unsigned long) )
00139                      return( LBER_DEFAULT );
00140               diff = sizeof(unsigned long) - noctets;
00141               if ( ber_read( ber, (char *) &netlen + diff, noctets )
00142                   != noctets )
00143                      return( LBER_DEFAULT );
00144               *len = LBER_NTOHL( netlen );
00145        } else {
00146               *len = lc;
00147        }
00148 
00149        return( tag );
00150 }
00151 
00152 
00153 /*
00154  * Note: Previously, we passed the "ber" parameter directly to ber_skip_tag(),
00155  * saving and restoring the ber_ptr element only.  We now take advantage
00156  * of the fact that the only ber structure elements touched by ber_skip_tag()
00157  * are ber_end and ber_ptr.  If that changes, this code must change too.
00158  */
00159 unsigned long
00160 LDAP_CALL
00161 ber_peek_tag( BerElement *ber, unsigned long *len )
00162 {
00163        BerElement    bercopy;
00164 
00165        bercopy.ber_end = ber->ber_end;
00166        bercopy.ber_ptr = ber->ber_ptr;
00167        return( ber_skip_tag( &bercopy, len ));
00168 }
00169 
00170 static int
00171 ber_getnint( BerElement *ber, long *num, int len )
00172 {
00173        int i;
00174        long value;
00175        unsigned char buffer[sizeof(long)];
00176        /*
00177         * The tag and length have already been stripped off.  We should
00178         * be sitting right before len bytes of 2's complement integer,
00179         * ready to be read straight into an int.  We may have to sign
00180         * extend after we read it in.
00181         */
00182 
00183        if ( len > sizeof(long) )
00184               return( -1 );
00185 
00186        /* read into the low-order bytes of netnum */
00187        if ( ber_read( ber, (char *) buffer, len ) != len )
00188               return( -1 );
00189 
00190        /* This sets the required sign extension */
00191        if ( len != 0) {
00192               value = 0x80 & buffer[0] ? (-1L) : 0;
00193        } else {
00194               value = 0;
00195        }
00196               
00197        for ( i = 0; i < len; i++ )
00198          value = (value << 8) | buffer[i];
00199        
00200        *num = value;
00201        
00202        return( len );
00203 }
00204 
00205 unsigned long
00206 LDAP_CALL
00207 ber_get_int( BerElement *ber, long *num )
00208 {
00209        unsigned long tag, len;
00210 
00211        if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
00212               return( LBER_DEFAULT );
00213 
00214        /*
00215      * len is being demoted to a long here --  possible conversion error
00216      */
00217   
00218        if ( ber_getnint( ber, num, (int)len ) != (long)len )
00219               return( LBER_DEFAULT );
00220        else
00221               return( tag );
00222 }
00223 
00224 unsigned long
00225 LDAP_CALL
00226 ber_get_stringb( BerElement *ber, char *buf, unsigned long *len )
00227 {
00228        unsigned long datalen, tag;
00229 #ifdef STR_TRANSLATION
00230        char          *transbuf;
00231 #endif /* STR_TRANSLATION */
00232 
00233        if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
00234               return( LBER_DEFAULT );
00235        if ( datalen > (*len - 1) )
00236               return( LBER_DEFAULT );
00237 
00238        /*
00239      * datalen is being demoted to a long here --  possible conversion error
00240      */
00241 
00242        if ( ber_read( ber, buf, datalen ) != (long) datalen )
00243               return( LBER_DEFAULT );
00244 
00245        buf[datalen] = '\0';
00246 
00247 #ifdef STR_TRANSLATION
00248        if ( datalen > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS )
00249            != 0 && ber->ber_decode_translate_proc != NULL ) {
00250               transbuf = buf;
00251               ++datalen;
00252               if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen,
00253                   0 ) != 0 ) {
00254                      return( LBER_DEFAULT );
00255               }
00256               if ( datalen > *len ) {
00257                      NSLBERI_FREE( transbuf );
00258                      return( LBER_DEFAULT );
00259               }
00260               SAFEMEMCPY( buf, transbuf, datalen );
00261               NSLBERI_FREE( transbuf );
00262               --datalen;
00263        }
00264 #endif /* STR_TRANSLATION */
00265 
00266        *len = datalen;
00267        return( tag );
00268 }
00269 
00270 unsigned long
00271 LDAP_CALL
00272 ber_get_stringa( BerElement *ber, char **buf )
00273 {
00274        unsigned long datalen, ndatalen, tag;
00275 
00276        if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
00277               return( LBER_DEFAULT );
00278 
00279        if ( ((ndatalen = (size_t)datalen + 1) < (size_t) datalen) ||
00280           ( (*buf = (char *)NSLBERI_MALLOC( (size_t)ndatalen )) == NULL ))
00281               return( LBER_DEFAULT );
00282 
00283        /*
00284      * datalen is being demoted to a long here --  possible conversion error
00285      */
00286        if ( ber_read( ber, *buf, datalen ) != (long) datalen )
00287               return( LBER_DEFAULT );
00288        (*buf)[datalen] = '\0';
00289 
00290 #ifdef STR_TRANSLATION
00291        if ( datalen > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS )
00292            != 0 && ber->ber_decode_translate_proc != NULL ) {
00293               ++datalen;
00294               if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 )
00295                   != 0 ) {
00296                      NSLBERI_FREE( *buf );
00297                      return( LBER_DEFAULT );
00298               }
00299        }
00300 #endif /* STR_TRANSLATION */
00301 
00302        return( tag );
00303 }
00304 
00305 unsigned long
00306 LDAP_CALL
00307 ber_get_stringal( BerElement *ber, struct berval **bv )
00308 {
00309        unsigned long len, nlen, tag;
00310 
00311        if ( (*bv = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) ))
00312            == NULL ) {
00313               return( LBER_DEFAULT );
00314        }
00315 
00316        if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) {
00317               return( LBER_DEFAULT );
00318        }
00319 
00320        if ( ((nlen = (size_t) len + 1) < (size_t)len) ||
00321             (((*bv)->bv_val = (char *)NSLBERI_MALLOC( (size_t)nlen ))
00322            == NULL )) {
00323               return( LBER_DEFAULT );
00324        }
00325 
00326        /*
00327      * len is being demoted to a long here --  possible conversion error
00328      */
00329        if ( ber_read( ber, (*bv)->bv_val, len ) != (int) len )
00330               return( LBER_DEFAULT );
00331        ((*bv)->bv_val)[len] = '\0';
00332        (*bv)->bv_len = len;
00333 
00334 #ifdef STR_TRANSLATION
00335        if ( len > 0 && ( ber->ber_options & LBER_OPT_TRANSLATE_STRINGS ) != 0
00336            && ber->ber_decode_translate_proc != NULL ) {
00337               ++len;
00338               if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val),
00339                   &len, 1 ) != 0 ) {
00340                      NSLBERI_FREE( (*bv)->bv_val );
00341                      return( LBER_DEFAULT );
00342               }
00343               (*bv)->bv_len = len - 1;
00344        }
00345 #endif /* STR_TRANSLATION */
00346 
00347        return( tag );
00348 }
00349 
00350 unsigned long
00351 LDAP_CALL
00352 ber_get_bitstringa( BerElement *ber, char **buf, unsigned long *blen )
00353 {
00354        unsigned long datalen, tag;
00355        unsigned char unusedbits;
00356 
00357        if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
00358               return( LBER_DEFAULT );
00359        --datalen;
00360 
00361        if ( (*buf = (char *)NSLBERI_MALLOC( (size_t)datalen )) == NULL )
00362               return( LBER_DEFAULT );
00363 
00364        if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 )
00365               return( LBER_DEFAULT );
00366 
00367        /*
00368      * datalen is being demoted to a long here --  possible conversion error
00369      */
00370        if ( ber_read( ber, *buf, datalen ) != (long) datalen )
00371               return( LBER_DEFAULT );
00372 
00373        *blen = datalen * 8 - unusedbits;
00374        return( tag );
00375 }
00376 
00377 unsigned long
00378 LDAP_CALL
00379 ber_get_null( BerElement *ber )
00380 {
00381        unsigned long len, tag;
00382 
00383        if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
00384               return( LBER_DEFAULT );
00385 
00386        if ( len != 0 )
00387               return( LBER_DEFAULT );
00388 
00389        return( tag );
00390 }
00391 
00392 unsigned long
00393 LDAP_CALL
00394 ber_get_boolean( BerElement *ber, int *boolval )
00395 {
00396        long   longbool;
00397        int    rc;
00398 
00399        rc = ber_get_int( ber, &longbool );
00400        *boolval = longbool;
00401 
00402        return( rc );
00403 }
00404 
00405 unsigned long
00406 LDAP_CALL
00407 ber_first_element( BerElement *ber, unsigned long *len, char **last )
00408 {
00409        /* skip the sequence header, use the len to mark where to stop */
00410        if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) {
00411               return( LBER_ERROR );
00412        }
00413 
00414        *last = ber->ber_ptr + *len;
00415 
00416        if ( *last == ber->ber_ptr ) {
00417               return( LBER_END_OF_SEQORSET );
00418        }
00419 
00420        return( ber_peek_tag( ber, len ) );
00421 }
00422 
00423 unsigned long
00424 LDAP_CALL
00425 ber_next_element( BerElement *ber, unsigned long *len, char *last )
00426 {
00427        if ( ber->ber_ptr == last ) {
00428               return( LBER_END_OF_SEQORSET );
00429        }
00430 
00431        return( ber_peek_tag( ber, len ) );
00432 }
00433 
00434 /* VARARGS */
00435 unsigned long
00436 LDAP_C
00437 ber_scanf( BerElement *ber, const char *fmt, ... )
00438 {
00439        va_list              ap;
00440        char          *last, *p;
00441        char          *s, **ss, ***sss;
00442        struct berval        ***bv, **bvp, *bval;
00443        int           *i, j;
00444        long          *l, rc, tag;
00445        unsigned long *t;
00446        unsigned long len;
00447        size_t        array_size;
00448        
00449        va_start( ap, fmt );
00450 
00451 #ifdef LDAP_DEBUG
00452        if ( lber_debug & 64 ) {
00453               char msg[80];
00454               sprintf( msg, "ber_scanf fmt (%s) ber:\n", fmt );
00455               ber_err_print( msg );
00456               ber_dump( ber, 1 );
00457        }
00458 #endif
00459        for ( rc = 0, p = (char *) fmt; *p && rc != LBER_DEFAULT; p++ ) {
00460               switch ( *p ) {
00461               case 'a':     /* octet string - allocate storage as needed */
00462                      ss = va_arg( ap, char ** );
00463                      rc = ber_get_stringa( ber, ss );
00464                      break;
00465 
00466               case 'b':     /* boolean */
00467                      i = va_arg( ap, int * );
00468                      rc = ber_get_boolean( ber, i );
00469                      break;
00470 
00471               case 'e':     /* enumerated */
00472               case 'i':     /* int */
00473                      l = va_arg( ap, long * );
00474                      rc = ber_get_int( ber, l );
00475                      break;
00476 
00477               case 'l':     /* length of next item */
00478                      l = va_arg( ap, long * );
00479                      rc = ber_peek_tag( ber, (unsigned long *)l );
00480                      break;
00481 
00482               case 'n':     /* null */
00483                      rc = ber_get_null( ber );
00484                      break;
00485 
00486               case 's':     /* octet string - in a buffer */
00487                      s = va_arg( ap, char * );
00488                      l = va_arg( ap, long * );
00489                      rc = ber_get_stringb( ber, s, (unsigned long *)l );
00490                      break;
00491 
00492               case 'o':     /* octet string in a supplied berval */
00493                      bval = va_arg( ap, struct berval * );
00494                      ber_peek_tag( ber, &bval->bv_len );
00495                      rc = ber_get_stringa( ber, &bval->bv_val );
00496                      break;
00497 
00498               case 'O':     /* octet string - allocate & include length */
00499                      bvp = va_arg( ap, struct berval ** );
00500                      rc = ber_get_stringal( ber, bvp );
00501                      break;
00502 
00503               case 'B':     /* bit string - allocate storage as needed */
00504                      ss = va_arg( ap, char ** );
00505                      l = va_arg( ap, long * ); /* for length, in bits */
00506                      rc = ber_get_bitstringa( ber, ss, (unsigned long *)l );
00507                      break;
00508 
00509               case 't':     /* tag of next item */
00510                      t = va_arg( ap, unsigned long * );
00511                      *t = rc = ber_peek_tag( ber, &len );
00512                      break;
00513 
00514               case 'T':     /* skip tag of next item */
00515                      t = va_arg( ap, unsigned long * );
00516                      *t = rc = ber_skip_tag( ber, &len );
00517                      break;
00518 
00519               case 'v':     /* sequence of strings */
00520                      sss = va_arg( ap, char *** );
00521                      *sss = NULL;
00522                      j = 0;
00523                      array_size = 0;
00524                      for ( tag = ber_first_element( ber, &len, &last );
00525                          tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET
00526                          && rc != LBER_DEFAULT;
00527                          tag = ber_next_element( ber, &len, last ) ) {
00528                             if ( *sss == NULL ) {
00529                                 /* Make room for at least 15 strings */
00530                                 *sss = (char **)NSLBERI_MALLOC(16 * sizeof(char *) );
00531                                 array_size = 16;
00532                             } else {
00533                                 if ( (size_t)(j+2) > array_size) {
00534                                    /* We'v overflowed our buffer */
00535                                    *sss = (char **)NSLBERI_REALLOC( *sss, (array_size * 2) * sizeof(char *) );
00536                                    array_size = array_size * 2;
00537                                 }
00538                             }
00539                             rc = ber_get_stringa( ber, &((*sss)[j]) );
00540                             j++;
00541                      }
00542                      if ( rc != LBER_DEFAULT &&
00543                          tag != LBER_END_OF_SEQORSET ) {
00544                             rc = LBER_DEFAULT;
00545                      }
00546                      if ( j > 0 )
00547                             (*sss)[j] = NULL;
00548                      break;
00549 
00550               case 'V':     /* sequence of strings + lengths */
00551                      bv = va_arg( ap, struct berval *** );
00552                      *bv = NULL;
00553                      j = 0;
00554                      for ( tag = ber_first_element( ber, &len, &last );
00555                          tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET
00556                          && rc != LBER_DEFAULT;
00557                          tag = ber_next_element( ber, &len, last ) ) {
00558                             if ( *bv == NULL ) {
00559                                    *bv = (struct berval **)NSLBERI_MALLOC(
00560                                        2 * sizeof(struct berval *) );
00561                             } else {
00562                                    *bv = (struct berval **)NSLBERI_REALLOC(
00563                                        *bv,
00564                                        (j + 2) * sizeof(struct berval *) );
00565                             }
00566                             rc = ber_get_stringal( ber, &((*bv)[j]) );
00567                             j++;
00568                      }
00569                      if ( rc != LBER_DEFAULT &&
00570                          tag != LBER_END_OF_SEQORSET ) {
00571                             rc = LBER_DEFAULT;
00572                      }
00573                      if ( j > 0 )
00574                             (*bv)[j] = NULL;
00575                      break;
00576 
00577               case 'x':     /* skip the next element - whatever it is */
00578                      if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
00579                             break;
00580                      ber->ber_ptr += len;
00581                      break;
00582 
00583               case '{':     /* begin sequence */
00584               case '[':     /* begin set */
00585                      if ( *(p + 1) != 'v' && *(p + 1) != 'V' )
00586                             rc = ber_skip_tag( ber, &len );
00587                      break;
00588 
00589               case '}':     /* end sequence */
00590               case ']':     /* end set */
00591                      break;
00592 
00593               default:
00594                      {
00595                             char msg[80];
00596                             sprintf( msg, "unknown fmt %c\n", *p );
00597                             ber_err_print( msg );
00598                      }
00599                      rc = LBER_DEFAULT;
00600                      break;
00601               }
00602        }
00603 
00604        va_end( ap );
00605 
00606        if (rc == LBER_DEFAULT) {
00607          va_start( ap, fmt );
00608          for ( p--; fmt < p && *fmt; fmt++ ) {
00609               switch ( *fmt ) {
00610               case 'a':     /* octet string - allocate storage as needed */
00611                      ss = va_arg( ap, char ** );
00612                      NSLBERI_FREE(*ss);
00613                      *ss = NULL;
00614                      break;
00615 
00616               case 'b':     /* boolean */
00617                      i = va_arg( ap, int * );
00618                      break;
00619 
00620               case 'e':     /* enumerated */
00621               case 'i':     /* int */
00622                      l = va_arg( ap, long * );
00623                      break;
00624 
00625               case 'l':     /* length of next item */
00626                      l = va_arg( ap, long * );
00627                      break;
00628 
00629               case 'n':     /* null */
00630                      break;
00631 
00632               case 's':     /* octet string - in a buffer */
00633                      s = va_arg( ap, char * );
00634                      l = va_arg( ap, long * );
00635                      break;
00636 
00637               case 'o':     /* octet string in a supplied berval */
00638                      bval = va_arg( ap, struct berval * );
00639                      if (bval->bv_val) NSLBERI_FREE(bval->bv_val);
00640                      memset(bval, 0, sizeof(struct berval));
00641                      break;
00642 
00643               case 'O':     /* octet string - allocate & include length */
00644                      bvp = va_arg( ap, struct berval ** );
00645                      ber_bvfree(*bvp);
00646                      bvp = NULL;
00647                      break;
00648 
00649               case 'B':     /* bit string - allocate storage as needed */
00650                      ss = va_arg( ap, char ** );
00651                      l = va_arg( ap, long * ); /* for length, in bits */
00652                      if (*ss) NSLBERI_FREE(*ss);
00653                      *ss = NULL;
00654                      break;
00655 
00656               case 't':     /* tag of next item */
00657                      t = va_arg( ap, unsigned long * );
00658                      break;
00659 
00660               case 'T':     /* skip tag of next item */
00661                      t = va_arg( ap, unsigned long * );
00662                      break;
00663 
00664               case 'v':     /* sequence of strings */
00665                      sss = va_arg( ap, char *** );
00666                      ber_svecfree(*sss);
00667                      *sss = NULL;
00668                      break;
00669 
00670               case 'V':     /* sequence of strings + lengths */
00671                      bv = va_arg( ap, struct berval *** );
00672                      ber_bvecfree(*bv);
00673                      *bv = NULL;
00674                      break;
00675 
00676               case 'x':     /* skip the next element - whatever it is */
00677                      break;
00678 
00679               case '{':     /* begin sequence */
00680               case '[':     /* begin set */
00681                      break;
00682 
00683               case '}':     /* end sequence */
00684               case ']':     /* end set */
00685                      break;
00686 
00687               default:
00688                      break;
00689               }
00690          } /* for */
00691          va_end( ap );
00692        } /* if */
00693 
00694        return( rc );
00695 }
00696 
00697 void
00698 LDAP_CALL
00699 ber_bvfree( struct berval *bv )
00700 {
00701        if ( bv != NULL ) {
00702               if ( bv->bv_val != NULL ) {
00703                      NSLBERI_FREE( bv->bv_val );
00704               }
00705               NSLBERI_FREE( (char *) bv );
00706        }
00707 }
00708 
00709 void
00710 LDAP_CALL
00711 ber_bvecfree( struct berval **bv )
00712 {
00713        int    i;
00714 
00715        if ( bv != NULL ) {
00716               for ( i = 0; bv[i] != NULL; i++ ) {
00717                      ber_bvfree( bv[i] );
00718               }
00719               NSLBERI_FREE( (char *) bv );
00720        }
00721 }
00722 
00723 struct berval *
00724 LDAP_CALL
00725 ber_bvdup( const struct berval *bv )
00726 {
00727        struct berval *new;
00728 
00729        if ( (new = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) ))
00730            == NULL ) {
00731               return( NULL );
00732        }
00733        if ( bv->bv_val == NULL ) {
00734            new->bv_val = NULL;
00735            new->bv_len = 0;
00736        } else {
00737            if ( (new->bv_val = (char *)NSLBERI_MALLOC( bv->bv_len + 1 ))
00738               == NULL ) {
00739                   return( NULL );
00740            }
00741            SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len );
00742            new->bv_val[bv->bv_len] = '\0';
00743            new->bv_len = bv->bv_len;
00744        }
00745 
00746        return( new );
00747 }
00748 
00749 void
00750 LDAP_CALL
00751 ber_svecfree( char **vals )
00752 {
00753         int     i;
00754 
00755         if ( vals == NULL )
00756                 return;
00757         for ( i = 0; vals[i] != NULL; i++ )
00758                 NSLBERI_FREE( vals[i] );
00759         NSLBERI_FREE( (char *) vals );
00760 }
00761 
00762 #ifdef STR_TRANSLATION
00763 void
00764 LDAP_CALL
00765 ber_set_string_translators(
00766     BerElement              *ber,
00767     BERTranslateProc encode_proc,
00768     BERTranslateProc decode_proc
00769 )
00770 {
00771     ber->ber_encode_translate_proc = encode_proc;
00772     ber->ber_decode_translate_proc = decode_proc;
00773 }
00774 #endif /* STR_TRANSLATION */