Back to index

openldap  2.4.31
ldif.c
Go to the documentation of this file.
00001 /* ldif.c - routines for dealing with LDIF files */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor.  The name of the
00022  * University may not be used to endorse or promote products derived
00023  * from this software without specific prior written permission.  This
00024  * software is provided ``as is'' without express or implied warranty.
00025  */
00026 /* This work was originally developed by the University of Michigan
00027  * and distributed as part of U-MICH LDAP.
00028  */
00029 
00030 #include "portable.h"
00031 
00032 #include <stdio.h>
00033 
00034 #include <ac/stdlib.h>
00035 #include <ac/ctype.h>
00036 
00037 #include <ac/string.h>
00038 #include <ac/socket.h>
00039 #include <ac/time.h>
00040 
00041 int ldif_debug = 0;
00042 
00043 #include "ldap_log.h"
00044 #include "lber_pvt.h"
00045 #include "ldif.h"
00046 
00047 #define RIGHT2                     0x03
00048 #define RIGHT4                     0x0f
00049 #define CONTINUED_LINE_MARKER      '\r'
00050 
00051 #ifdef CSRIMALLOC
00052 #define ber_memalloc malloc
00053 #define ber_memcalloc calloc
00054 #define ber_memrealloc realloc
00055 #define ber_strdup strdup
00056 #endif
00057 
00058 static const char nib2b64[0x40] =
00059         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00060 
00061 static const unsigned char b642nib[0x80] = {
00062        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00063        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00064        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00065        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00066        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00067        0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
00068        0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
00069        0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00070        0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
00071        0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
00072        0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
00073        0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
00074        0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
00075        0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
00076        0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
00077        0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
00078 };
00079 
00080 /*
00081  * ldif_parse_line - takes a line of the form "type:[:] value" and splits it
00082  * into components "type" and "value".  if a double colon separates type from
00083  * value, then value is encoded in base 64, and parse_line un-decodes it
00084  * (in place) before returning. The type and value are stored in malloc'd
00085  * memory which must be freed by the caller.
00086  *
00087  * ldif_parse_line2 - operates in-place on input buffer, returning type
00088  * in-place. Will return value in-place if possible, (must malloc for
00089  * fetched URLs). If freeval is NULL, all return data will be malloc'd
00090  * and the input line will be unmodified. Otherwise freeval is set to
00091  * True if the value was malloc'd.
00092  */
00093 
00094 int
00095 ldif_parse_line(
00096     LDAP_CONST char  *line,
00097     char      **typep,
00098     char      **valuep,
00099     ber_len_t *vlenp
00100 )
00101 {
00102        struct berval type, value;
00103        int rc = ldif_parse_line2( (char *)line, &type, &value, NULL );
00104 
00105        *typep = type.bv_val;
00106        *valuep = value.bv_val;
00107        *vlenp = value.bv_len;
00108        return rc;
00109 }
00110 
00111 int
00112 ldif_parse_line2(
00113     char      *line,
00114        struct berval *type,
00115        struct berval *value,
00116        int           *freeval
00117 )
00118 {
00119        char   *s, *p, *d; 
00120        char   nib;
00121        int    b64, url;
00122 
00123        BER_BVZERO( type );
00124        BER_BVZERO( value );
00125 
00126        /* skip any leading space */
00127        while ( isspace( (unsigned char) *line ) ) {
00128               line++;
00129        }
00130 
00131        if ( freeval ) {
00132               *freeval = 0;
00133        } else {
00134               line = ber_strdup( line );
00135 
00136               if( line == NULL ) {
00137                      ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
00138                             _("ldif_parse_line: line malloc failed\n"));
00139                      return( -1 );
00140               }
00141        }
00142 
00143        type->bv_val = line;
00144 
00145        s = strchr( type->bv_val, ':' );
00146 
00147        if ( s == NULL ) {
00148               ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
00149                      _("ldif_parse_line: missing ':' after %s\n"),
00150                      type->bv_val );
00151               if ( !freeval ) ber_memfree( line );
00152               return( -1 );
00153        }
00154 
00155        /* trim any space between type and : */
00156        for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) {
00157               *p = '\0';
00158        }
00159        *s++ = '\0';
00160        type->bv_len = s - type->bv_val - 1;
00161 
00162        url = 0;
00163        b64 = 0;
00164 
00165        if ( *s == '<' ) {
00166               s++;
00167               url = 1;
00168 
00169        } else if ( *s == ':' ) {
00170               /* base 64 encoded value */
00171               s++;
00172               b64 = 1;
00173        }
00174 
00175        /* skip space between : and value */
00176        while ( isspace( (unsigned char) *s ) ) {
00177               s++;
00178        }
00179 
00180        /* check for continued line markers that should be deleted */
00181        for ( p = s, d = s; *p; p++ ) {
00182               if ( *p != CONTINUED_LINE_MARKER )
00183                      *d++ = *p;
00184        }
00185        *d = '\0';
00186 
00187        if ( b64 ) {
00188               char *byte = s;
00189 
00190               if ( *s == '\0' ) {
00191                      /* no value is present, error out */
00192                      ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
00193                             _("ldif_parse_line: %s missing base64 value\n"),
00194                             type->bv_val );
00195                      if ( !freeval ) ber_memfree( line );
00196                      return( -1 );
00197               }
00198 
00199               byte = value->bv_val = s;
00200 
00201               for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) {
00202                      int i;
00203                      for ( i = 0; i < 4; i++ ) {
00204                             if ( p[i] != '=' && (p[i] & 0x80 ||
00205                                 b642nib[ p[i] & 0x7f ] > 0x3f) ) {
00206                                    ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
00207                                           _("ldif_parse_line: %s: invalid base64 encoding"
00208                                           " char (%c) 0x%x\n"),
00209                                        type->bv_val, p[i], p[i] );
00210                                    if ( !freeval ) ber_memfree( line );
00211                                    return( -1 );
00212                             }
00213                      }
00214 
00215                      /* first digit */
00216                      nib = b642nib[ p[0] & 0x7f ];
00217                      byte[0] = nib << 2;
00218                      /* second digit */
00219                      nib = b642nib[ p[1] & 0x7f ];
00220                      byte[0] |= nib >> 4;
00221                      byte[1] = (nib & RIGHT4) << 4;
00222                      /* third digit */
00223                      if ( p[2] == '=' ) {
00224                             value->bv_len += 1;
00225                             break;
00226                      }
00227                      nib = b642nib[ p[2] & 0x7f ];
00228                      byte[1] |= nib >> 2;
00229                      byte[2] = (nib & RIGHT2) << 6;
00230                      /* fourth digit */
00231                      if ( p[3] == '=' ) {
00232                             value->bv_len += 2;
00233                             break;
00234                      }
00235                      nib = b642nib[ p[3] & 0x7f ];
00236                      byte[2] |= nib;
00237 
00238                      byte += 3;
00239               }
00240               s[ value->bv_len ] = '\0';
00241 
00242        } else if ( url ) {
00243               if ( *s == '\0' ) {
00244                      /* no value is present, error out */
00245                      ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
00246                             _("ldif_parse_line: %s missing URL value\n"),
00247                             type->bv_val );
00248                      if ( !freeval ) ber_memfree( line );
00249                      return( -1 );
00250               }
00251 
00252               if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) {
00253                      ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
00254                             _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
00255                             type->bv_val, s );
00256                      if ( !freeval ) ber_memfree( line );
00257                      return( -1 );
00258               }
00259               if ( freeval ) *freeval = 1;
00260 
00261        } else {
00262               value->bv_val = s;
00263               value->bv_len = (int) (d - s);
00264        }
00265 
00266        if ( !freeval ) {
00267               struct berval bv = *type;
00268 
00269               ber_dupbv( type, &bv );
00270 
00271               if( BER_BVISNULL( type )) {
00272                      ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
00273                             _("ldif_parse_line: type malloc failed\n"));
00274                      if( url ) ber_memfree( value->bv_val );
00275                      ber_memfree( line );
00276                      return( -1 );
00277               }
00278 
00279               if( !url ) {
00280                      bv = *value;
00281                      ber_dupbv( value, &bv );
00282                      if( BER_BVISNULL( value )) {
00283                             ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
00284                                    _("ldif_parse_line: value malloc failed\n"));
00285                             ber_memfree( type->bv_val );
00286                             ber_memfree( line );
00287                             return( -1 );
00288                      }
00289               }
00290 
00291               ber_memfree( line );
00292        }
00293 
00294        return( 0 );
00295 }
00296 
00297 /*
00298  * ldif_getline - return the next "line" (minus newline) of input from a
00299  * string buffer of lines separated by newlines, terminated by \n\n
00300  * or \0.  this routine handles continued lines, bundling them into
00301  * a single big line before returning.  if a line begins with a white
00302  * space character, it is a continuation of the previous line. the white
00303  * space character (nb: only one char), and preceeding newline are changed
00304  * into CONTINUED_LINE_MARKER chars, to be deleted later by the
00305  * ldif_parse_line() routine above.
00306  *
00307  * ldif_getline will skip over any line which starts '#'.
00308  *
00309  * ldif_getline takes a pointer to a pointer to the buffer on the first call,
00310  * which it updates and must be supplied on subsequent calls.
00311  */
00312 
00313 int
00314 ldif_countlines( LDAP_CONST char *buf )
00315 {
00316        char *nl;
00317        int ret = 0;
00318 
00319        if ( !buf ) return ret;
00320 
00321        for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) {
00322               nl++;
00323               if ( *nl != ' ' ) ret++;
00324        }
00325        return ret;
00326 }
00327 
00328 char *
00329 ldif_getline( char **next )
00330 {
00331        char *line;
00332 
00333        do {
00334               if ( *next == NULL || **next == '\n' || **next == '\0' ) {
00335                      return( NULL );
00336               }
00337 
00338               line = *next;
00339 
00340               while ( (*next = strchr( *next, '\n' )) != NULL ) {
00341 #if CONTINUED_LINE_MARKER != '\r'
00342                      if ( (*next)[-1] == '\r' ) {
00343                             (*next)[-1] = CONTINUED_LINE_MARKER;
00344                      }
00345 #endif
00346 
00347                      if ( (*next)[1] != ' ' ) {
00348                             if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
00349                                    *(*next)++ = '\0';
00350                             }
00351                             *(*next)++ = '\0';
00352                             break;
00353                      }
00354 
00355                      **next = CONTINUED_LINE_MARKER;
00356                      (*next)[1] = CONTINUED_LINE_MARKER;
00357                      (*next)++;
00358               }
00359        } while( *line == '#' );
00360 
00361        return( line );
00362 }
00363 
00364 /*
00365  * name and OID of attributeTypes that must be base64 encoded in any case
00366  */
00367 typedef struct must_b64_encode_s {
00368        struct berval name;
00369        struct berval oid;
00370 } must_b64_encode_s;
00371 
00372 static must_b64_encode_s    default_must_b64_encode[] = {
00373        { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) },
00374        { BER_BVNULL, BER_BVNULL }
00375 };
00376 
00377 static must_b64_encode_s    *must_b64_encode = default_must_b64_encode;
00378 
00379 /*
00380  * register name and OID of attributeTypes that must always be base64 
00381  * encoded
00382  *
00383  * NOTE: this routine mallocs memory in a static struct which must 
00384  * be explicitly freed when no longer required
00385  */
00386 int
00387 ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid )
00388 {
00389        int           i;
00390        ber_len_t     len;
00391 
00392        assert( must_b64_encode != NULL );
00393        assert( name != NULL );
00394        assert( oid != NULL );
00395 
00396        len = strlen( name );
00397 
00398        for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
00399               if ( len != must_b64_encode[i].name.bv_len ) {
00400                      continue;
00401               }
00402 
00403               if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) {
00404                      break;
00405               }
00406        }
00407 
00408        if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) {
00409               return 1;
00410        }
00411 
00412        for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ )
00413               /* just count */ ;
00414 
00415        if ( must_b64_encode == default_must_b64_encode ) {
00416               must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) );
00417 
00418               for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) {
00419                      ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name );
00420                      ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid );
00421               }
00422 
00423        } else {
00424               must_b64_encode_s    *tmp;
00425 
00426               tmp = ber_memrealloc( must_b64_encode,
00427                      sizeof( must_b64_encode_s ) * ( i + 2 ) );
00428               if ( tmp == NULL ) {
00429                      return 1;
00430               }
00431               must_b64_encode = tmp;
00432        }
00433 
00434        ber_str2bv( name, len, 1, &must_b64_encode[i].name );
00435        ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid );
00436 
00437        BER_BVZERO( &must_b64_encode[i + 1].name );
00438 
00439        return 0;
00440 }
00441 
00442 void
00443 ldif_must_b64_encode_release( void )
00444 {
00445        int    i;
00446 
00447        assert( must_b64_encode != NULL );
00448 
00449        if ( must_b64_encode == default_must_b64_encode ) {
00450               return;
00451        }
00452 
00453        for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
00454               ber_memfree( must_b64_encode[i].name.bv_val );
00455               ber_memfree( must_b64_encode[i].oid.bv_val );
00456        }
00457 
00458        ber_memfree( must_b64_encode );
00459 
00460        must_b64_encode = default_must_b64_encode;
00461 }
00462 
00463 /*
00464  * returns 1 iff the string corresponds to the name or the OID of any 
00465  * of the attributeTypes listed in must_b64_encode
00466  */
00467 static int
00468 ldif_must_b64_encode( LDAP_CONST char *s )
00469 {
00470        int           i;
00471        struct berval bv;
00472 
00473        assert( must_b64_encode != NULL );
00474        assert( s != NULL );
00475 
00476        ber_str2bv( s, 0, 0, &bv );
00477 
00478        for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
00479               if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0
00480                      || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 )
00481               {
00482                      return 1;
00483               }
00484        }
00485 
00486        return 0;
00487 }
00488 
00489 /* compatibility with U-Mich off by one bug */
00490 #define LDIF_KLUDGE 1
00491 
00492 /* NOTE: only preserved for binary compatibility */
00493 void
00494 ldif_sput(
00495        char **out,
00496        int type,
00497        LDAP_CONST char *name,
00498        LDAP_CONST char *val,
00499        ber_len_t vlen )
00500 {
00501        ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH );
00502 }
00503 
00504 void
00505 ldif_sput_wrap(
00506        char **out,
00507        int type,
00508        LDAP_CONST char *name,
00509        LDAP_CONST char *val,
00510        ber_len_t vlen,
00511         ber_len_t wrap )
00512 {
00513        const unsigned char *byte, *stop;
00514        unsigned char buf[3];
00515        unsigned long bits;
00516        char          *save;
00517        int           pad;
00518        int           namelen = 0;
00519 
00520        ber_len_t savelen;
00521        ber_len_t len=0;
00522        ber_len_t i;
00523 
00524        wrap = LDIF_LINE_WIDTH_WRAP( wrap );
00525 
00526        /* prefix */
00527        switch( type ) {
00528        case LDIF_PUT_COMMENT:
00529               *(*out)++ = '#';
00530               len++;
00531 
00532               if( vlen ) {
00533                      *(*out)++ = ' ';
00534                      len++;
00535               }
00536 
00537               break;
00538 
00539        case LDIF_PUT_SEP:
00540               *(*out)++ = '\n';
00541               return;
00542        }
00543 
00544        /* name (attribute type) */
00545        if( name != NULL ) {
00546               /* put the name + ":" */
00547               namelen = strlen(name);
00548               strcpy(*out, name);
00549               *out += namelen;
00550               len += namelen;
00551 
00552               if( type != LDIF_PUT_COMMENT ) {
00553                      *(*out)++ = ':';
00554                      len++;
00555               }
00556 
00557        }
00558 #ifdef LDAP_DEBUG
00559        else {
00560               assert( type == LDIF_PUT_COMMENT );
00561        }
00562 #endif
00563 
00564        if( vlen == 0 ) {
00565               *(*out)++ = '\n';
00566               return;
00567        }
00568 
00569        switch( type ) {
00570        case LDIF_PUT_NOVALUE:
00571               *(*out)++ = '\n';
00572               return;
00573 
00574        case LDIF_PUT_URL: /* url value */
00575               *(*out)++ = '<';
00576               len++;
00577               break;
00578 
00579        case LDIF_PUT_B64: /* base64 value */
00580               *(*out)++ = ':';
00581               len++;
00582               break;
00583        }
00584 
00585        switch( type ) {
00586        case LDIF_PUT_TEXT:
00587        case LDIF_PUT_URL:
00588        case LDIF_PUT_B64:
00589               *(*out)++ = ' ';
00590               len++;
00591               /* fall-thru */
00592 
00593        case LDIF_PUT_COMMENT:
00594               /* pre-encoded names */
00595               for ( i=0; i < vlen; i++ ) {
00596                      if ( len > wrap ) {
00597                             *(*out)++ = '\n';
00598                             *(*out)++ = ' ';
00599                             len = 1;
00600                      }
00601 
00602                      *(*out)++ = val[i];
00603                      len++;
00604               }
00605               *(*out)++ = '\n';
00606               return;
00607        }
00608 
00609        save = *out;
00610        savelen = len;
00611 
00612        *(*out)++ = ' ';
00613        len++;
00614 
00615        stop = (const unsigned char *) (val + vlen);
00616 
00617        if ( type == LDIF_PUT_VALUE
00618               && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
00619               && isgraph( (unsigned char) val[vlen-1] )
00620 #ifndef LDAP_BINARY_DEBUG
00621               && strstr( name, ";binary" ) == NULL
00622 #endif
00623 #ifndef LDAP_PASSWD_DEBUG
00624               && !ldif_must_b64_encode( name )
00625 #endif
00626        ) {
00627               int b64 = 0;
00628 
00629               for ( byte = (const unsigned char *) val; byte < stop;
00630                   byte++, len++ )
00631               {
00632                      if ( !isascii( *byte ) || !isprint( *byte ) ) {
00633                             b64 = 1;
00634                             break;
00635                      }
00636                      if ( len - LDIF_KLUDGE > wrap ) {
00637                             *(*out)++ = '\n';
00638                             *(*out)++ = ' ';
00639                             len = 1;
00640                      }
00641                      *(*out)++ = *byte;
00642               }
00643 
00644               if( !b64 ) {
00645                      *(*out)++ = '\n';
00646                      return;
00647               }
00648        }
00649 
00650        *out = save;
00651        *(*out)++ = ':';
00652        *(*out)++ = ' ';
00653        len = savelen + 2;
00654 
00655        /* convert to base 64 (3 bytes => 4 base 64 digits) */
00656        for ( byte = (const unsigned char *) val;
00657               byte < stop - 2;
00658            byte += 3 )
00659        {
00660               bits = (byte[0] & 0xff) << 16;
00661               bits |= (byte[1] & 0xff) << 8;
00662               bits |= (byte[2] & 0xff);
00663 
00664               for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
00665                      if ( len - LDIF_KLUDGE > wrap ) {
00666                             *(*out)++ = '\n';
00667                             *(*out)++ = ' ';
00668                             len = 1;
00669                      }
00670 
00671                      /* get b64 digit from high order 6 bits */
00672                      *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
00673               }
00674        }
00675 
00676        /* add padding if necessary */
00677        if ( byte < stop ) {
00678               for ( i = 0; byte + i < stop; i++ ) {
00679                      buf[i] = byte[i];
00680               }
00681               for ( pad = 0; i < 3; i++, pad++ ) {
00682                      buf[i] = '\0';
00683               }
00684               byte = buf;
00685               bits = (byte[0] & 0xff) << 16;
00686               bits |= (byte[1] & 0xff) << 8;
00687               bits |= (byte[2] & 0xff);
00688 
00689               for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
00690                      if ( len - LDIF_KLUDGE > wrap ) {
00691                             *(*out)++ = '\n';
00692                             *(*out)++ = ' ';
00693                             len = 1;
00694                      }
00695 
00696                      if( i + pad < 4 ) {
00697                             /* get b64 digit from low order 6 bits */
00698                             *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
00699                      } else {
00700                             *(*out)++ = '=';
00701                      }
00702               }
00703        }
00704        *(*out)++ = '\n';
00705 }
00706 
00707 
00708 /*
00709  * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
00710  */
00711 
00712 /* NOTE: only preserved for binary compatibility */
00713 char *
00714 ldif_put(
00715        int type,
00716        LDAP_CONST char *name,
00717        LDAP_CONST char *val,
00718        ber_len_t vlen )
00719 {
00720        return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH );
00721 }
00722 
00723 char *
00724 ldif_put_wrap(
00725        int type,
00726        LDAP_CONST char *name,
00727        LDAP_CONST char *val,
00728        ber_len_t vlen,
00729        ber_len_t wrap )
00730 {
00731     char      *buf, *p;
00732     ber_len_t nlen;
00733 
00734     nlen = ( name != NULL ) ? strlen( name ) : 0;
00735 
00736        buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 );
00737 
00738     if ( buf == NULL ) {
00739               ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
00740                      _("ldif_type_and_value: malloc failed!"));
00741               return NULL;
00742     }
00743 
00744     p = buf;
00745     ldif_sput_wrap( &p, type, name, val, vlen, wrap );
00746     *p = '\0';
00747 
00748     return( buf );
00749 }
00750 
00751 int ldif_is_not_printable(
00752        LDAP_CONST char *val,
00753        ber_len_t vlen )
00754 {
00755        if( vlen == 0 || val == NULL  ) {
00756               return -1;
00757        }
00758 
00759        if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
00760               isgraph( (unsigned char) val[vlen-1] ) )
00761        {
00762               ber_len_t i;
00763 
00764               for ( i = 0; val[i]; i++ ) {
00765                      if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) {
00766                             return 1;
00767                      }
00768               }
00769 
00770               return 0;
00771        }
00772 
00773        return 1;
00774 }
00775 
00776 LDIFFP *
00777 ldif_open(
00778        LDAP_CONST char *file,
00779        LDAP_CONST char *mode
00780 )
00781 {
00782        FILE *fp = fopen( file, mode );
00783        LDIFFP *lfp = NULL;
00784 
00785        if ( fp ) {
00786               lfp = ber_memalloc( sizeof( LDIFFP ));
00787               lfp->fp = fp;
00788               lfp->prev = NULL;
00789        }
00790        return lfp;
00791 }
00792 
00793 void
00794 ldif_close(
00795        LDIFFP *lfp
00796 )
00797 {
00798        LDIFFP *prev;
00799 
00800        while ( lfp ) {
00801               fclose( lfp->fp );
00802               prev = lfp->prev;
00803               ber_memfree( lfp );
00804               lfp = prev;
00805        }
00806 }
00807 
00808 #define       LDIF_MAXLINE  4096
00809 
00810 /*
00811  * ldif_read_record - read an ldif record.  Return 1 for success, 0 for EOF,
00812  * -1 for error.
00813  */
00814 int
00815 ldif_read_record(
00816        LDIFFP      *lfp,
00817        int         *lno,           /* ptr to line number counter              */
00818        char        **bufp,     /* ptr to malloced output buffer           */
00819        int         *buflenp )  /* ptr to length of *bufp                  */
00820 {
00821        char        line[LDIF_MAXLINE], *nbufp;
00822        ber_len_t   lcur = 0, len;
00823        int         last_ch = '\n', found_entry = 0, stop, top_comment = 0;
00824 
00825        for ( stop = 0;  !stop;  last_ch = line[len-1] ) {
00826               /* If we're at the end of this file, see if we should pop
00827                * back to a previous file. (return from an include)
00828                */
00829               while ( feof( lfp->fp )) {
00830                      if ( lfp->prev ) {
00831                             LDIFFP *tmp = lfp->prev;
00832                             fclose( lfp->fp );
00833                             *lfp = *tmp;
00834                             ber_memfree( tmp );
00835                      } else {
00836                             stop = 1;
00837                             break;
00838                      }
00839               }
00840               if ( stop )
00841                      break;
00842 
00843               if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) {
00844                      stop = 1;
00845                      len = 0;
00846               } else {
00847                      len = strlen( line );
00848               }
00849 
00850               if ( len == 0 || line[len-1] != '\n' ) {
00851                      /* Add \n in case the line/file does not end with newline */
00852                      line[len] = '\n';
00853                      line[++len] = '\0';
00854               }
00855 
00856               if ( last_ch == '\n' ) {
00857                      (*lno)++;
00858 
00859                      if ( line[0] == '\n' ||
00860                             ( line[0] == '\r' && line[1] == '\n' )) {
00861                             if ( !found_entry ) {
00862                                    lcur = 0;
00863                                    top_comment = 0;
00864                                    continue;
00865                             }
00866                             break;
00867                      }
00868 
00869                      if ( !found_entry ) {
00870                             if ( line[0] == '#' ) {
00871                                    top_comment = 1;
00872                             } else if ( ! ( top_comment && line[0] == ' ' ) ) {
00873                                    /* Found a new entry */
00874                                    found_entry = 1;
00875 
00876                                    if ( isdigit( (unsigned char) line[0] ) ) {
00877                                           /* skip index */
00878                                           continue;
00879                                    }
00880                                    if ( !strncasecmp( line, "include:",
00881                                           STRLENOF("include:"))) {
00882                                           FILE *fp2;
00883                                           char *ptr;
00884                                           found_entry = 0;
00885 
00886                                           if ( line[len-1] == '\n' ) {
00887                                                  len--;
00888                                                  line[len] = '\0';
00889                                           }
00890                                           if ( line[len-1] == '\r' ) {
00891                                                  len--;
00892                                                  line[len] = '\0';
00893                                           }
00894 
00895                                           ptr = line + STRLENOF("include:");
00896                                           while (isspace((unsigned char) *ptr)) ptr++;
00897                                           fp2 = ldif_open_url( ptr );
00898                                           if ( fp2 ) {
00899                                                  LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP ));
00900                                                  if ( lnew == NULL ) {
00901                                                         fclose( fp2 );
00902                                                         return 0;
00903                                                  }
00904                                                  lnew->prev = lfp->prev;
00905                                                  lnew->fp = lfp->fp;
00906                                                  lfp->prev = lnew;
00907                                                  lfp->fp = fp2;
00908                                                  line[len] = '\n';
00909                                                  len++;
00910                                                  continue;
00911                                           } else {
00912                                                  /* We failed to open the file, this should
00913                                                   * be reported as an error somehow.
00914                                                   */
00915                                                  ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
00916                                                         _("ldif_read_record: include %s failed\n"), ptr );
00917                                                  return -1;
00918                                           }
00919                                    }
00920                             }
00921                      }                    
00922               }
00923 
00924               if ( *buflenp - lcur <= len ) {
00925                      *buflenp += len + LDIF_MAXLINE;
00926                      nbufp = ber_memrealloc( *bufp, *buflenp );
00927                      if( nbufp == NULL ) {
00928                             return 0;
00929                      }
00930                      *bufp = nbufp;
00931               }
00932               strcpy( *bufp + lcur, line );
00933               lcur += len;
00934        }
00935 
00936        return( found_entry );
00937 }