]> git.sur5r.net Git - openldap/commitdiff
ITS#6870 move ldif.c and fetch.c from liblutil to libldap
authorHoward Chu <hyc@openldap.org>
Thu, 24 Mar 2011 06:49:04 +0000 (06:49 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 24 Mar 2011 06:49:04 +0000 (06:49 +0000)
libraries/libldap/Makefile.in
libraries/libldap/fetch.c [new file with mode: 0644]
libraries/libldap/ldif.c [new file with mode: 0644]
libraries/libldap_r/Makefile.in
libraries/liblutil/Makefile.in
libraries/liblutil/fetch.c [deleted file]
libraries/liblutil/ldif.c [deleted file]

index 4b71ddd800229609b6fd17823d5c0f7cee284efe..782101d992e2053aa8483fafcd42366aa373b84d 100644 (file)
@@ -28,7 +28,7 @@ SRCS  = bind.c open.c result.c error.c compare.c search.c \
        charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
        tls2.c tls_o.c tls_g.c tls_m.c \
        turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
-       assertion.c deref.c ldifutil.c
+       assertion.c deref.c ldifutil.c ldif.c fetch.c
 
 OBJS   = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        controls.lo messages.lo references.lo extended.lo cyrus.lo \
@@ -41,7 +41,7 @@ OBJS  = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
        tls2.lo tls_o.lo tls_g.lo tls_m.lo \
        turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
-       assertion.lo deref.lo ldifutil.lo
+       assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
diff --git a/libraries/libldap/fetch.c b/libraries/libldap/fetch.c
new file mode 100644 (file)
index 0000000..fe73429
--- /dev/null
@@ -0,0 +1,133 @@
+/* fetch.c - routines for fetching data at URLs */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1999-2011 The OpenLDAP Foundation.
+ * Portions Copyright 1999-2003 Kurt D. Zeilenga.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* This work was initially developed by Kurt D. Zeilenga for
+ * inclusion in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
+#ifdef HAVE_FETCH
+#include <fetch.h>
+#endif
+
+#include "lber_pvt.h"
+#include "ldap_pvt.h"
+#include "ldap_config.h"
+#include "ldif.h"
+
+FILE *
+ldif_open_url(
+       LDAP_CONST char *urlstr )
+{
+       FILE *url;
+
+       if( strncasecmp( "file:", urlstr, sizeof("file:")-1 ) == 0 ) {
+               char *p;
+               urlstr += sizeof("file:")-1;
+
+               /* we don't check for LDAP_DIRSEP since URLs should contain '/' */
+               if ( urlstr[0] == '/' && urlstr[1] == '/' ) {
+                       urlstr += 2;
+                       /* path must be absolute if authority is present */
+                       if ( urlstr[0] != '/' )
+                               return NULL;
+               }
+
+               p = ber_strdup( urlstr );
+
+               /* But we should convert to LDAP_DIRSEP before use */
+               if ( LDAP_DIRSEP[0] != '/' ) {
+                       char *s = p;
+                       while (( s = strchr( s, '/' )))
+                               *s++ = LDAP_DIRSEP[0];
+               }
+
+               ldap_pvt_hex_unescape( p );
+
+               url = fopen( p, "rb" );
+
+               ber_memfree( p );
+       } else {
+#ifdef HAVE_FETCH
+               url = fetchGetURL( (char*) urlstr, "" );
+#else
+               url = NULL;
+#endif
+       }
+       return url;
+}
+
+int
+ldif_fetch_url(
+    LDAP_CONST char    *urlstr,
+    char       **valuep,
+    ber_len_t *vlenp )
+{
+       FILE *url;
+       char buffer[1024];
+       char *p = NULL;
+       size_t total;
+       size_t bytes;
+
+       *valuep = NULL;
+       *vlenp = 0;
+
+       url = ldif_open_url( urlstr );
+
+       if( url == NULL ) {
+               return -1;
+       }
+
+       total = 0;
+
+       while( (bytes = fread( buffer, 1, sizeof(buffer), url )) != 0 ) {
+               char *newp = ber_memrealloc( p, total + bytes + 1 );
+               if( newp == NULL ) {
+                       ber_memfree( p );
+                       fclose( url );
+                       return -1;
+               }
+               p = newp;
+               AC_MEMCPY( &p[total], buffer, bytes );
+               total += bytes;
+       }
+
+       fclose( url );
+
+       if( total == 0 ) {
+               char *newp = ber_memrealloc( p, 1 );
+               if( newp == NULL ) {
+                       ber_memfree( p );
+                       return -1;
+               }
+               p = newp;
+       }
+
+       p[total] = '\0';
+       *valuep = p;
+       *vlenp = total;
+
+       return 0;
+}
diff --git a/libraries/libldap/ldif.c b/libraries/libldap/ldif.c
new file mode 100644 (file)
index 0000000..0ee7849
--- /dev/null
@@ -0,0 +1,932 @@
+/* ldif.c - routines for dealing with LDIF files */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2011 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.  This
+ * software is provided ``as is'' without express or implied warranty.
+ */
+/* This work was originally developed by the University of Michigan
+ * and distributed as part of U-MICH LDAP.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+#include <ac/ctype.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+
+int ldif_debug = 0;
+
+#include "ldap_log.h"
+#include "lber_pvt.h"
+#include "ldif.h"
+
+#define RIGHT2                 0x03
+#define RIGHT4                 0x0f
+#define CONTINUED_LINE_MARKER  '\r'
+
+#ifdef CSRIMALLOC
+#define ber_memalloc malloc
+#define ber_memcalloc calloc
+#define ber_memrealloc realloc
+#define ber_strdup strdup
+#endif
+
+static const char nib2b64[0x40] =
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const unsigned char b642nib[0x80] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+       0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+       0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+       0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+       0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+       0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+       0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+       0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+       0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+/*
+ * ldif_parse_line - takes a line of the form "type:[:] value" and splits it
+ * into components "type" and "value".  if a double colon separates type from
+ * value, then value is encoded in base 64, and parse_line un-decodes it
+ * (in place) before returning. The type and value are stored in malloc'd
+ * memory which must be freed by the caller.
+ *
+ * ldif_parse_line2 - operates in-place on input buffer, returning type
+ * in-place. Will return value in-place if possible, (must malloc for
+ * fetched URLs). If freeval is NULL, all return data will be malloc'd
+ * and the input line will be unmodified. Otherwise freeval is set to
+ * True if the value was malloc'd.
+ */
+
+int
+ldif_parse_line(
+    LDAP_CONST char    *line,
+    char       **typep,
+    char       **valuep,
+    ber_len_t *vlenp
+)
+{
+       struct berval type, value;
+       int rc = ldif_parse_line2( (char *)line, &type, &value, NULL );
+
+       *typep = type.bv_val;
+       *valuep = value.bv_val;
+       *vlenp = value.bv_len;
+       return rc;
+}
+
+int
+ldif_parse_line2(
+    char       *line,
+       struct berval *type,
+       struct berval *value,
+       int             *freeval
+)
+{
+       char    *s, *p, *d; 
+       char    nib;
+       int     b64, url;
+
+       BER_BVZERO( type );
+       BER_BVZERO( value );
+
+       /* skip any leading space */
+       while ( isspace( (unsigned char) *line ) ) {
+               line++;
+       }
+
+       if ( freeval ) {
+               *freeval = 0;
+       } else {
+               line = ber_strdup( line );
+
+               if( line == NULL ) {
+                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+                               _("ldif_parse_line: line malloc failed\n"));
+                       return( -1 );
+               }
+       }
+
+       type->bv_val = line;
+
+       s = strchr( type->bv_val, ':' );
+
+       if ( s == NULL ) {
+               ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
+                       _("ldif_parse_line: missing ':' after %s\n"),
+                       type->bv_val );
+               if ( !freeval ) ber_memfree( line );
+               return( -1 );
+       }
+
+       /* trim any space between type and : */
+       for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) {
+               *p = '\0';
+       }
+       *s++ = '\0';
+       type->bv_len = s - type->bv_val - 1;
+
+       url = 0;
+       b64 = 0;
+
+       if ( *s == '<' ) {
+               s++;
+               url = 1;
+
+       } else if ( *s == ':' ) {
+               /* base 64 encoded value */
+               s++;
+               b64 = 1;
+       }
+
+       /* skip space between : and value */
+       while ( isspace( (unsigned char) *s ) ) {
+               s++;
+       }
+
+       /* check for continued line markers that should be deleted */
+       for ( p = s, d = s; *p; p++ ) {
+               if ( *p != CONTINUED_LINE_MARKER )
+                       *d++ = *p;
+       }
+       *d = '\0';
+
+       if ( b64 ) {
+               char *byte = s;
+
+               if ( *s == '\0' ) {
+                       /* no value is present, error out */
+                       ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
+                               _("ldif_parse_line: %s missing base64 value\n"),
+                               type->bv_val );
+                       if ( !freeval ) ber_memfree( line );
+                       return( -1 );
+               }
+
+               byte = value->bv_val = s;
+
+               for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) {
+                       int i;
+                       for ( i = 0; i < 4; i++ ) {
+                               if ( p[i] != '=' && (p[i] & 0x80 ||
+                                   b642nib[ p[i] & 0x7f ] > 0x3f) ) {
+                                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+                                               _("ldif_parse_line: %s: invalid base64 encoding"
+                                               " char (%c) 0x%x\n"),
+                                           type->bv_val, p[i], p[i] );
+                                       if ( !freeval ) ber_memfree( line );
+                                       return( -1 );
+                               }
+                       }
+
+                       /* first digit */
+                       nib = b642nib[ p[0] & 0x7f ];
+                       byte[0] = nib << 2;
+                       /* second digit */
+                       nib = b642nib[ p[1] & 0x7f ];
+                       byte[0] |= nib >> 4;
+                       byte[1] = (nib & RIGHT4) << 4;
+                       /* third digit */
+                       if ( p[2] == '=' ) {
+                               value->bv_len += 1;
+                               break;
+                       }
+                       nib = b642nib[ p[2] & 0x7f ];
+                       byte[1] |= nib >> 2;
+                       byte[2] = (nib & RIGHT2) << 6;
+                       /* fourth digit */
+                       if ( p[3] == '=' ) {
+                               value->bv_len += 2;
+                               break;
+                       }
+                       nib = b642nib[ p[3] & 0x7f ];
+                       byte[2] |= nib;
+
+                       byte += 3;
+               }
+               s[ value->bv_len ] = '\0';
+
+       } else if ( url ) {
+               if ( *s == '\0' ) {
+                       /* no value is present, error out */
+                       ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
+                               _("ldif_parse_line: %s missing URL value\n"),
+                               type->bv_val );
+                       if ( !freeval ) ber_memfree( line );
+                       return( -1 );
+               }
+
+               if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) {
+                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+                               _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
+                               type->bv_val, s );
+                       if ( !freeval ) ber_memfree( line );
+                       return( -1 );
+               }
+               if ( freeval ) *freeval = 1;
+
+       } else {
+               value->bv_val = s;
+               value->bv_len = (int) (d - s);
+       }
+
+       if ( !freeval ) {
+               struct berval bv = *type;
+
+               ber_dupbv( type, &bv );
+
+               if( BER_BVISNULL( type )) {
+                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+                               _("ldif_parse_line: type malloc failed\n"));
+                       if( url ) ber_memfree( value->bv_val );
+                       ber_memfree( line );
+                       return( -1 );
+               }
+
+               if( !url ) {
+                       bv = *value;
+                       ber_dupbv( value, &bv );
+                       if( BER_BVISNULL( value )) {
+                               ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+                                       _("ldif_parse_line: value malloc failed\n"));
+                               ber_memfree( type->bv_val );
+                               ber_memfree( line );
+                               return( -1 );
+                       }
+               }
+
+               ber_memfree( line );
+       }
+
+       return( 0 );
+}
+
+/*
+ * ldif_getline - return the next "line" (minus newline) of input from a
+ * string buffer of lines separated by newlines, terminated by \n\n
+ * or \0.  this routine handles continued lines, bundling them into
+ * a single big line before returning.  if a line begins with a white
+ * space character, it is a continuation of the previous line. the white
+ * space character (nb: only one char), and preceeding newline are changed
+ * into CONTINUED_LINE_MARKER chars, to be deleted later by the
+ * ldif_parse_line() routine above.
+ *
+ * ldif_getline will skip over any line which starts '#'.
+ *
+ * ldif_getline takes a pointer to a pointer to the buffer on the first call,
+ * which it updates and must be supplied on subsequent calls.
+ */
+
+int
+ldif_countlines( LDAP_CONST char *buf )
+{
+       char *nl;
+       int ret = 0;
+
+       if ( !buf ) return ret;
+
+       for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) {
+               nl++;
+               if ( *nl != ' ' ) ret++;
+       }
+       return ret;
+}
+
+char *
+ldif_getline( char **next )
+{
+       char *line;
+
+       do {
+               if ( *next == NULL || **next == '\n' || **next == '\0' ) {
+                       return( NULL );
+               }
+
+               line = *next;
+
+               while ( (*next = strchr( *next, '\n' )) != NULL ) {
+#if CONTINUED_LINE_MARKER != '\r'
+                       if ( (*next)[-1] == '\r' ) {
+                               (*next)[-1] = CONTINUED_LINE_MARKER;
+                       }
+#endif
+
+                       if ( (*next)[1] != ' ' ) {
+                               if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
+                                       *(*next)++ = '\0';
+                               }
+                               *(*next)++ = '\0';
+                               break;
+                       }
+
+                       **next = CONTINUED_LINE_MARKER;
+                       (*next)[1] = CONTINUED_LINE_MARKER;
+                       (*next)++;
+               }
+       } while( *line == '#' );
+
+       return( line );
+}
+
+/*
+ * name and OID of attributeTypes that must be base64 encoded in any case
+ */
+typedef struct must_b64_encode_s {
+       struct berval   name;
+       struct berval   oid;
+} must_b64_encode_s;
+
+static must_b64_encode_s       default_must_b64_encode[] = {
+       { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) },
+       { BER_BVNULL, BER_BVNULL }
+};
+
+static must_b64_encode_s       *must_b64_encode = default_must_b64_encode;
+
+/*
+ * register name and OID of attributeTypes that must always be base64 
+ * encoded
+ *
+ * NOTE: this routine mallocs memory in a static struct which must 
+ * be explicitly freed when no longer required
+ */
+int
+ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid )
+{
+       int             i;
+       ber_len_t       len;
+
+       assert( must_b64_encode != NULL );
+       assert( name != NULL );
+       assert( oid != NULL );
+
+       len = strlen( name );
+
+       for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
+               if ( len != must_b64_encode[i].name.bv_len ) {
+                       continue;
+               }
+
+               if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) {
+                       break;
+               }
+       }
+
+       if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) {
+               return 1;
+       }
+
+       for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ )
+               /* just count */ ;
+
+       if ( must_b64_encode == default_must_b64_encode ) {
+               must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) );
+
+               for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) {
+                       ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name );
+                       ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid );
+               }
+
+       } else {
+               must_b64_encode_s       *tmp;
+
+               tmp = ber_memrealloc( must_b64_encode,
+                       sizeof( must_b64_encode_s ) * ( i + 2 ) );
+               if ( tmp == NULL ) {
+                       return 1;
+               }
+               must_b64_encode = tmp;
+       }
+
+       ber_str2bv( name, len, 1, &must_b64_encode[i].name );
+       ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid );
+
+       BER_BVZERO( &must_b64_encode[i + 1].name );
+
+       return 0;
+}
+
+void
+ldif_must_b64_encode_release( void )
+{
+       int     i;
+
+       assert( must_b64_encode != NULL );
+
+       if ( must_b64_encode == default_must_b64_encode ) {
+               return;
+       }
+
+       for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
+               ber_memfree( must_b64_encode[i].name.bv_val );
+               ber_memfree( must_b64_encode[i].oid.bv_val );
+       }
+
+       ber_memfree( must_b64_encode );
+
+       must_b64_encode = default_must_b64_encode;
+}
+
+/*
+ * returns 1 iff the string corresponds to the name or the OID of any 
+ * of the attributeTypes listed in must_b64_encode
+ */
+static int
+ldif_must_b64_encode( LDAP_CONST char *s )
+{
+       int             i;
+       struct berval   bv;
+
+       assert( must_b64_encode != NULL );
+       assert( s != NULL );
+
+       ber_str2bv( s, 0, 0, &bv );
+
+       for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
+               if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0
+                       || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 )
+               {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/* compatibility with U-Mich off by one bug */
+#define LDIF_KLUDGE 1
+
+/* NOTE: only preserved for binary compatibility */
+void
+ldif_sput(
+       char **out,
+       int type,
+       LDAP_CONST char *name,
+       LDAP_CONST char *val,
+       ber_len_t vlen )
+{
+       ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH );
+}
+
+void
+ldif_sput_wrap(
+       char **out,
+       int type,
+       LDAP_CONST char *name,
+       LDAP_CONST char *val,
+       ber_len_t vlen,
+        ber_len_t wrap )
+{
+       const unsigned char *byte, *stop;
+       unsigned char   buf[3];
+       unsigned long   bits;
+       char            *save;
+       int             pad;
+       int             namelen = 0;
+
+       ber_len_t savelen;
+       ber_len_t len=0;
+       ber_len_t i;
+
+       wrap = LDIF_LINE_WIDTH_WRAP( wrap );
+
+       /* prefix */
+       switch( type ) {
+       case LDIF_PUT_COMMENT:
+               *(*out)++ = '#';
+               len++;
+
+               if( vlen ) {
+                       *(*out)++ = ' ';
+                       len++;
+               }
+
+               break;
+
+       case LDIF_PUT_SEP:
+               *(*out)++ = '\n';
+               return;
+       }
+
+       /* name (attribute type) */
+       if( name != NULL ) {
+               /* put the name + ":" */
+               namelen = strlen(name);
+               strcpy(*out, name);
+               *out += namelen;
+               len += namelen;
+
+               if( type != LDIF_PUT_COMMENT ) {
+                       *(*out)++ = ':';
+                       len++;
+               }
+
+       }
+#ifdef LDAP_DEBUG
+       else {
+               assert( type == LDIF_PUT_COMMENT );
+       }
+#endif
+
+       if( vlen == 0 ) {
+               *(*out)++ = '\n';
+               return;
+       }
+
+       switch( type ) {
+       case LDIF_PUT_NOVALUE:
+               *(*out)++ = '\n';
+               return;
+
+       case LDIF_PUT_URL: /* url value */
+               *(*out)++ = '<';
+               len++;
+               break;
+
+       case LDIF_PUT_B64: /* base64 value */
+               *(*out)++ = ':';
+               len++;
+               break;
+       }
+
+       switch( type ) {
+       case LDIF_PUT_TEXT:
+       case LDIF_PUT_URL:
+       case LDIF_PUT_B64:
+               *(*out)++ = ' ';
+               len++;
+               /* fall-thru */
+
+       case LDIF_PUT_COMMENT:
+               /* pre-encoded names */
+               for ( i=0; i < vlen; i++ ) {
+                       if ( len > wrap ) {
+                               *(*out)++ = '\n';
+                               *(*out)++ = ' ';
+                               len = 1;
+                       }
+
+                       *(*out)++ = val[i];
+                       len++;
+               }
+               *(*out)++ = '\n';
+               return;
+       }
+
+       save = *out;
+       savelen = len;
+
+       *(*out)++ = ' ';
+       len++;
+
+       stop = (const unsigned char *) (val + vlen);
+
+       if ( type == LDIF_PUT_VALUE
+               && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
+               && isgraph( (unsigned char) val[vlen-1] )
+#ifndef LDAP_BINARY_DEBUG
+               && strstr( name, ";binary" ) == NULL
+#endif
+#ifndef LDAP_PASSWD_DEBUG
+               && !ldif_must_b64_encode( name )
+#endif
+       ) {
+               int b64 = 0;
+
+               for ( byte = (const unsigned char *) val; byte < stop;
+                   byte++, len++ )
+               {
+                       if ( !isascii( *byte ) || !isprint( *byte ) ) {
+                               b64 = 1;
+                               break;
+                       }
+                       if ( len - LDIF_KLUDGE > wrap ) {
+                               *(*out)++ = '\n';
+                               *(*out)++ = ' ';
+                               len = 1;
+                       }
+                       *(*out)++ = *byte;
+               }
+
+               if( !b64 ) {
+                       *(*out)++ = '\n';
+                       return;
+               }
+       }
+
+       *out = save;
+       *(*out)++ = ':';
+       *(*out)++ = ' ';
+       len = savelen + 2;
+
+       /* convert to base 64 (3 bytes => 4 base 64 digits) */
+       for ( byte = (const unsigned char *) val;
+               byte < stop - 2;
+           byte += 3 )
+       {
+               bits = (byte[0] & 0xff) << 16;
+               bits |= (byte[1] & 0xff) << 8;
+               bits |= (byte[2] & 0xff);
+
+               for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
+                       if ( len - LDIF_KLUDGE > wrap ) {
+                               *(*out)++ = '\n';
+                               *(*out)++ = ' ';
+                               len = 1;
+                       }
+
+                       /* get b64 digit from high order 6 bits */
+                       *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
+               }
+       }
+
+       /* add padding if necessary */
+       if ( byte < stop ) {
+               for ( i = 0; byte + i < stop; i++ ) {
+                       buf[i] = byte[i];
+               }
+               for ( pad = 0; i < 3; i++, pad++ ) {
+                       buf[i] = '\0';
+               }
+               byte = buf;
+               bits = (byte[0] & 0xff) << 16;
+               bits |= (byte[1] & 0xff) << 8;
+               bits |= (byte[2] & 0xff);
+
+               for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
+                       if ( len - LDIF_KLUDGE > wrap ) {
+                               *(*out)++ = '\n';
+                               *(*out)++ = ' ';
+                               len = 1;
+                       }
+
+                       if( i + pad < 4 ) {
+                               /* get b64 digit from low order 6 bits */
+                               *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
+                       } else {
+                               *(*out)++ = '=';
+                       }
+               }
+       }
+       *(*out)++ = '\n';
+}
+
+
+/*
+ * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
+ */
+
+/* NOTE: only preserved for binary compatibility */
+char *
+ldif_put(
+       int type,
+       LDAP_CONST char *name,
+       LDAP_CONST char *val,
+       ber_len_t vlen )
+{
+       return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH );
+}
+
+char *
+ldif_put_wrap(
+       int type,
+       LDAP_CONST char *name,
+       LDAP_CONST char *val,
+       ber_len_t vlen,
+       ber_len_t wrap )
+{
+    char       *buf, *p;
+    ber_len_t nlen;
+
+    nlen = ( name != NULL ) ? strlen( name ) : 0;
+
+       buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 );
+
+    if ( buf == NULL ) {
+               ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+                       _("ldif_type_and_value: malloc failed!"));
+               return NULL;
+    }
+
+    p = buf;
+    ldif_sput_wrap( &p, type, name, val, vlen, wrap );
+    *p = '\0';
+
+    return( buf );
+}
+
+int ldif_is_not_printable(
+       LDAP_CONST char *val,
+       ber_len_t vlen )
+{
+       if( vlen == 0 || val == NULL  ) {
+               return -1;
+       }
+
+       if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
+               isgraph( (unsigned char) val[vlen-1] ) )
+       {
+               ber_len_t i;
+
+               for ( i = 0; val[i]; i++ ) {
+                       if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) {
+                               return 1;
+                       }
+               }
+
+               return 0;
+       }
+
+       return 1;
+}
+
+LDIFFP *
+ldif_open(
+       LDAP_CONST char *file,
+       LDAP_CONST char *mode
+)
+{
+       FILE *fp = fopen( file, mode );
+       LDIFFP *lfp = NULL;
+
+       if ( fp ) {
+               lfp = ber_memalloc( sizeof( LDIFFP ));
+               lfp->fp = fp;
+               lfp->prev = NULL;
+       }
+       return lfp;
+}
+
+void
+ldif_close(
+       LDIFFP *lfp
+)
+{
+       LDIFFP *prev;
+
+       while ( lfp ) {
+               fclose( lfp->fp );
+               prev = lfp->prev;
+               ber_memfree( lfp );
+               lfp = prev;
+       }
+}
+
+#define        LDIF_MAXLINE    4096
+
+/*
+ * ldif_read_record - read an ldif record.  Return 1 for success, 0 for EOF,
+ * -1 for error.
+ */
+int
+ldif_read_record(
+       LDIFFP      *lfp,
+       int         *lno,               /* ptr to line number counter              */
+       char        **bufp,     /* ptr to malloced output buffer           */
+       int         *buflenp )  /* ptr to length of *bufp                  */
+{
+       char        line[LDIF_MAXLINE], *nbufp;
+       ber_len_t   lcur = 0, len;
+       int         last_ch = '\n', found_entry = 0, stop, top_comment = 0;
+
+       for ( stop = 0;  !stop;  last_ch = line[len-1] ) {
+               /* If we're at the end of this file, see if we should pop
+                * back to a previous file. (return from an include)
+                */
+               while ( feof( lfp->fp )) {
+                       if ( lfp->prev ) {
+                               LDIFFP *tmp = lfp->prev;
+                               fclose( lfp->fp );
+                               *lfp = *tmp;
+                               ber_memfree( tmp );
+                       } else {
+                               stop = 1;
+                               break;
+                       }
+               }
+               if ( stop )
+                       break;
+
+               if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) {
+                       stop = 1;
+                       /* Add \n in case the file does not end with newline */
+                       line[0] = '\n';
+                       line[1] = '\0';
+               }
+               len = strlen( line );
+
+               if ( last_ch == '\n' ) {
+                       (*lno)++;
+
+                       if ( line[0] == '\n' ||
+                               ( line[0] == '\r' && line[1] == '\n' )) {
+                               if ( !found_entry ) {
+                                       lcur = 0;
+                                       top_comment = 0;
+                                       continue;
+                               }
+                               break;
+                       }
+
+                       if ( !found_entry ) {
+                               if ( line[0] == '#' ) {
+                                       top_comment = 1;
+                               } else if ( ! ( top_comment && line[0] == ' ' ) ) {
+                                       /* Found a new entry */
+                                       found_entry = 1;
+
+                                       if ( isdigit( (unsigned char) line[0] ) ) {
+                                               /* skip index */
+                                               continue;
+                                       }
+                                       if ( !strncasecmp( line, "include:",
+                                               STRLENOF("include:"))) {
+                                               FILE *fp2;
+                                               char *ptr;
+                                               found_entry = 0;
+
+                                               if ( line[len-1] == '\n' ) {
+                                                       len--;
+                                                       line[len] = '\0';
+                                               }
+                                               if ( line[len-1] == '\r' ) {
+                                                       len--;
+                                                       line[len] = '\0';
+                                               }
+
+                                               ptr = line + STRLENOF("include:");
+                                               while (isspace((unsigned char) *ptr)) ptr++;
+                                               fp2 = ldif_open_url( ptr );
+                                               if ( fp2 ) {
+                                                       LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP ));
+                                                       if ( lnew == NULL ) {
+                                                               fclose( fp2 );
+                                                               return 0;
+                                                       }
+                                                       lnew->prev = lfp->prev;
+                                                       lnew->fp = lfp->fp;
+                                                       lfp->prev = lnew;
+                                                       lfp->fp = fp2;
+                                                       line[len] = '\n';
+                                                       len++;
+                                                       continue;
+                                               } else {
+                                                       /* We failed to open the file, this should
+                                                        * be reported as an error somehow.
+                                                        */
+                                                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
+                                                               _("ldif_read_record: include %s failed\n"), ptr );
+                                                       return -1;
+                                               }
+                                       }
+                               }
+                       }                       
+               }
+
+               if ( *buflenp - lcur <= len ) {
+                       *buflenp += len + LDIF_MAXLINE;
+                       nbufp = ber_memrealloc( *bufp, *buflenp );
+                       if( nbufp == NULL ) {
+                               return 0;
+                       }
+                       *bufp = nbufp;
+               }
+               strcpy( *bufp + lcur, line );
+               lcur += len;
+       }
+
+       return( found_entry );
+}
index f5e9e8963bd0a59da065e2d1947120a6936fd408..de0d67b6f34587970d522fa8f6b5ccafc0e11cfd 100644 (file)
@@ -30,7 +30,7 @@ XXSRCS    = apitest.c test.c \
        charray.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
        tls2.c tls_o.c tls_g.c tls_m.c \
        turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c \
-       assertion.c deref.c ldifutil.c
+       assertion.c deref.c ldifutil.c ldif.c fetch.c
 SRCS   = threads.c rdwr.c rmutex.c tpool.c rq.c \
        thr_posix.c thr_cthreads.c thr_thr.c thr_nt.c \
        thr_pth.c thr_stub.c thr_debug.c
@@ -48,7 +48,7 @@ OBJS  = threads.lo rdwr.lo rmutex.lo tpool.lo  rq.lo \
        charray.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
        tls2.lo tls_o.lo tls_g.lo tls_m.lo \
        turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo \
-       assertion.lo deref.lo ldifutil.lo
+       assertion.lo deref.lo ldifutil.lo ldif.lo fetch.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
index ff7bc3a88017b68b883b2986d35d9a3775f7a1bc..06da05c9518506fba10911eb5a3b83b7fcc09fe5 100644 (file)
@@ -14,9 +14,6 @@
 ## <http://www.OpenLDAP.org/license.html>.
 
 LIBRARY        = liblutil.a
-
-SHAREDLIB = libldif.la
-
 PROGRAM = testavl
 
 LDAP_INCDIR= ../../include       
@@ -32,19 +29,17 @@ XLIBS = $(LIBRARY) $(LDAP_LIBLBER_LA)
 
 SRCS   = base64.c entropy.c sasl.c signal.c hash.c passfile.c \
        md5.c passwd.c sha1.c getpass.c lockf.c utils.c uuid.c sockpair.c \
-       avl.c tavl.c ldif.c fetch.c \
+       avl.c tavl.c \
        testavl.c \
        meter.c \
        @LIBSRCS@ $(@PLAT@_SRCS)
 
 OBJS   = base64.o entropy.o sasl.o signal.o hash.o passfile.o \
        md5.o passwd.o sha1.o getpass.o lockf.o utils.o uuid.o sockpair.o \
-       avl.o tavl.o ldif.o fetch.o \
+       avl.o tavl.o \
        meter.o \
        @LIBOBJS@ $(@PLAT@_OBJS)
 
-SHAREDLIBOBJS = ldif.lo fetch.lo
-
 testavl: $(XLIBS) testavl.o
        (LTLINK) -o $@ testavl.o $(LIBS)
 
@@ -64,19 +59,3 @@ slapdmsg.res: slapdmsg.rc slapdmsg.bin
 clean-local:
        $(RM) *.res
 
-all-local: $(SHAREDLIB)
-
-.SUFFIXES: .c .o .lo
-
-.c.lo:
-       $(LTCOMPILE_LIB) $<
-
-$(LIBRARY): $(SHAREDLIBOBJS) version.lo
-
-$(SHAREDLIB): $(SHAREDLIBOBJS) version.lo
-       $(LTLINK_LIB) -o $(SHAREDLIB) $(SHAREDLIBOBJS) version.lo $(LINK_LIBS)
-
-install-local: FORCE
-       -$(MKDIR) $(DESTDIR)$(libdir)
-       $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(SHAREDLIB) $(DESTDIR)$(libdir)
-       $(LTFINISH) $(DESTDIR)$(libdir)
diff --git a/libraries/liblutil/fetch.c b/libraries/liblutil/fetch.c
deleted file mode 100644 (file)
index fe73429..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* fetch.c - routines for fetching data at URLs */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1999-2011 The OpenLDAP Foundation.
- * Portions Copyright 1999-2003 Kurt D. Zeilenga.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* This work was initially developed by Kurt D. Zeilenga for
- * inclusion in OpenLDAP Software.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-
-#include <ac/string.h>
-#include <ac/socket.h>
-#include <ac/time.h>
-
-#ifdef HAVE_FETCH
-#include <fetch.h>
-#endif
-
-#include "lber_pvt.h"
-#include "ldap_pvt.h"
-#include "ldap_config.h"
-#include "ldif.h"
-
-FILE *
-ldif_open_url(
-       LDAP_CONST char *urlstr )
-{
-       FILE *url;
-
-       if( strncasecmp( "file:", urlstr, sizeof("file:")-1 ) == 0 ) {
-               char *p;
-               urlstr += sizeof("file:")-1;
-
-               /* we don't check for LDAP_DIRSEP since URLs should contain '/' */
-               if ( urlstr[0] == '/' && urlstr[1] == '/' ) {
-                       urlstr += 2;
-                       /* path must be absolute if authority is present */
-                       if ( urlstr[0] != '/' )
-                               return NULL;
-               }
-
-               p = ber_strdup( urlstr );
-
-               /* But we should convert to LDAP_DIRSEP before use */
-               if ( LDAP_DIRSEP[0] != '/' ) {
-                       char *s = p;
-                       while (( s = strchr( s, '/' )))
-                               *s++ = LDAP_DIRSEP[0];
-               }
-
-               ldap_pvt_hex_unescape( p );
-
-               url = fopen( p, "rb" );
-
-               ber_memfree( p );
-       } else {
-#ifdef HAVE_FETCH
-               url = fetchGetURL( (char*) urlstr, "" );
-#else
-               url = NULL;
-#endif
-       }
-       return url;
-}
-
-int
-ldif_fetch_url(
-    LDAP_CONST char    *urlstr,
-    char       **valuep,
-    ber_len_t *vlenp )
-{
-       FILE *url;
-       char buffer[1024];
-       char *p = NULL;
-       size_t total;
-       size_t bytes;
-
-       *valuep = NULL;
-       *vlenp = 0;
-
-       url = ldif_open_url( urlstr );
-
-       if( url == NULL ) {
-               return -1;
-       }
-
-       total = 0;
-
-       while( (bytes = fread( buffer, 1, sizeof(buffer), url )) != 0 ) {
-               char *newp = ber_memrealloc( p, total + bytes + 1 );
-               if( newp == NULL ) {
-                       ber_memfree( p );
-                       fclose( url );
-                       return -1;
-               }
-               p = newp;
-               AC_MEMCPY( &p[total], buffer, bytes );
-               total += bytes;
-       }
-
-       fclose( url );
-
-       if( total == 0 ) {
-               char *newp = ber_memrealloc( p, 1 );
-               if( newp == NULL ) {
-                       ber_memfree( p );
-                       return -1;
-               }
-               p = newp;
-       }
-
-       p[total] = '\0';
-       *valuep = p;
-       *vlenp = total;
-
-       return 0;
-}
diff --git a/libraries/liblutil/ldif.c b/libraries/liblutil/ldif.c
deleted file mode 100644 (file)
index 0ee7849..0000000
+++ /dev/null
@@ -1,932 +0,0 @@
-/* ldif.c - routines for dealing with LDIF files */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 1998-2011 The OpenLDAP Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of Michigan at Ann Arbor.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.  This
- * software is provided ``as is'' without express or implied warranty.
- */
-/* This work was originally developed by the University of Michigan
- * and distributed as part of U-MICH LDAP.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-#include <ac/ctype.h>
-
-#include <ac/string.h>
-#include <ac/socket.h>
-#include <ac/time.h>
-
-int ldif_debug = 0;
-
-#include "ldap_log.h"
-#include "lber_pvt.h"
-#include "ldif.h"
-
-#define RIGHT2                 0x03
-#define RIGHT4                 0x0f
-#define CONTINUED_LINE_MARKER  '\r'
-
-#ifdef CSRIMALLOC
-#define ber_memalloc malloc
-#define ber_memcalloc calloc
-#define ber_memrealloc realloc
-#define ber_strdup strdup
-#endif
-
-static const char nib2b64[0x40] =
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static const unsigned char b642nib[0x80] = {
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
-       0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
-       0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-       0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
-       0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
-       0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
-       0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
-       0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
-       0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-/*
- * ldif_parse_line - takes a line of the form "type:[:] value" and splits it
- * into components "type" and "value".  if a double colon separates type from
- * value, then value is encoded in base 64, and parse_line un-decodes it
- * (in place) before returning. The type and value are stored in malloc'd
- * memory which must be freed by the caller.
- *
- * ldif_parse_line2 - operates in-place on input buffer, returning type
- * in-place. Will return value in-place if possible, (must malloc for
- * fetched URLs). If freeval is NULL, all return data will be malloc'd
- * and the input line will be unmodified. Otherwise freeval is set to
- * True if the value was malloc'd.
- */
-
-int
-ldif_parse_line(
-    LDAP_CONST char    *line,
-    char       **typep,
-    char       **valuep,
-    ber_len_t *vlenp
-)
-{
-       struct berval type, value;
-       int rc = ldif_parse_line2( (char *)line, &type, &value, NULL );
-
-       *typep = type.bv_val;
-       *valuep = value.bv_val;
-       *vlenp = value.bv_len;
-       return rc;
-}
-
-int
-ldif_parse_line2(
-    char       *line,
-       struct berval *type,
-       struct berval *value,
-       int             *freeval
-)
-{
-       char    *s, *p, *d; 
-       char    nib;
-       int     b64, url;
-
-       BER_BVZERO( type );
-       BER_BVZERO( value );
-
-       /* skip any leading space */
-       while ( isspace( (unsigned char) *line ) ) {
-               line++;
-       }
-
-       if ( freeval ) {
-               *freeval = 0;
-       } else {
-               line = ber_strdup( line );
-
-               if( line == NULL ) {
-                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
-                               _("ldif_parse_line: line malloc failed\n"));
-                       return( -1 );
-               }
-       }
-
-       type->bv_val = line;
-
-       s = strchr( type->bv_val, ':' );
-
-       if ( s == NULL ) {
-               ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
-                       _("ldif_parse_line: missing ':' after %s\n"),
-                       type->bv_val );
-               if ( !freeval ) ber_memfree( line );
-               return( -1 );
-       }
-
-       /* trim any space between type and : */
-       for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) {
-               *p = '\0';
-       }
-       *s++ = '\0';
-       type->bv_len = s - type->bv_val - 1;
-
-       url = 0;
-       b64 = 0;
-
-       if ( *s == '<' ) {
-               s++;
-               url = 1;
-
-       } else if ( *s == ':' ) {
-               /* base 64 encoded value */
-               s++;
-               b64 = 1;
-       }
-
-       /* skip space between : and value */
-       while ( isspace( (unsigned char) *s ) ) {
-               s++;
-       }
-
-       /* check for continued line markers that should be deleted */
-       for ( p = s, d = s; *p; p++ ) {
-               if ( *p != CONTINUED_LINE_MARKER )
-                       *d++ = *p;
-       }
-       *d = '\0';
-
-       if ( b64 ) {
-               char *byte = s;
-
-               if ( *s == '\0' ) {
-                       /* no value is present, error out */
-                       ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
-                               _("ldif_parse_line: %s missing base64 value\n"),
-                               type->bv_val );
-                       if ( !freeval ) ber_memfree( line );
-                       return( -1 );
-               }
-
-               byte = value->bv_val = s;
-
-               for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) {
-                       int i;
-                       for ( i = 0; i < 4; i++ ) {
-                               if ( p[i] != '=' && (p[i] & 0x80 ||
-                                   b642nib[ p[i] & 0x7f ] > 0x3f) ) {
-                                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
-                                               _("ldif_parse_line: %s: invalid base64 encoding"
-                                               " char (%c) 0x%x\n"),
-                                           type->bv_val, p[i], p[i] );
-                                       if ( !freeval ) ber_memfree( line );
-                                       return( -1 );
-                               }
-                       }
-
-                       /* first digit */
-                       nib = b642nib[ p[0] & 0x7f ];
-                       byte[0] = nib << 2;
-                       /* second digit */
-                       nib = b642nib[ p[1] & 0x7f ];
-                       byte[0] |= nib >> 4;
-                       byte[1] = (nib & RIGHT4) << 4;
-                       /* third digit */
-                       if ( p[2] == '=' ) {
-                               value->bv_len += 1;
-                               break;
-                       }
-                       nib = b642nib[ p[2] & 0x7f ];
-                       byte[1] |= nib >> 2;
-                       byte[2] = (nib & RIGHT2) << 6;
-                       /* fourth digit */
-                       if ( p[3] == '=' ) {
-                               value->bv_len += 2;
-                               break;
-                       }
-                       nib = b642nib[ p[3] & 0x7f ];
-                       byte[2] |= nib;
-
-                       byte += 3;
-               }
-               s[ value->bv_len ] = '\0';
-
-       } else if ( url ) {
-               if ( *s == '\0' ) {
-                       /* no value is present, error out */
-                       ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
-                               _("ldif_parse_line: %s missing URL value\n"),
-                               type->bv_val );
-                       if ( !freeval ) ber_memfree( line );
-                       return( -1 );
-               }
-
-               if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) {
-                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
-                               _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
-                               type->bv_val, s );
-                       if ( !freeval ) ber_memfree( line );
-                       return( -1 );
-               }
-               if ( freeval ) *freeval = 1;
-
-       } else {
-               value->bv_val = s;
-               value->bv_len = (int) (d - s);
-       }
-
-       if ( !freeval ) {
-               struct berval bv = *type;
-
-               ber_dupbv( type, &bv );
-
-               if( BER_BVISNULL( type )) {
-                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
-                               _("ldif_parse_line: type malloc failed\n"));
-                       if( url ) ber_memfree( value->bv_val );
-                       ber_memfree( line );
-                       return( -1 );
-               }
-
-               if( !url ) {
-                       bv = *value;
-                       ber_dupbv( value, &bv );
-                       if( BER_BVISNULL( value )) {
-                               ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
-                                       _("ldif_parse_line: value malloc failed\n"));
-                               ber_memfree( type->bv_val );
-                               ber_memfree( line );
-                               return( -1 );
-                       }
-               }
-
-               ber_memfree( line );
-       }
-
-       return( 0 );
-}
-
-/*
- * ldif_getline - return the next "line" (minus newline) of input from a
- * string buffer of lines separated by newlines, terminated by \n\n
- * or \0.  this routine handles continued lines, bundling them into
- * a single big line before returning.  if a line begins with a white
- * space character, it is a continuation of the previous line. the white
- * space character (nb: only one char), and preceeding newline are changed
- * into CONTINUED_LINE_MARKER chars, to be deleted later by the
- * ldif_parse_line() routine above.
- *
- * ldif_getline will skip over any line which starts '#'.
- *
- * ldif_getline takes a pointer to a pointer to the buffer on the first call,
- * which it updates and must be supplied on subsequent calls.
- */
-
-int
-ldif_countlines( LDAP_CONST char *buf )
-{
-       char *nl;
-       int ret = 0;
-
-       if ( !buf ) return ret;
-
-       for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) {
-               nl++;
-               if ( *nl != ' ' ) ret++;
-       }
-       return ret;
-}
-
-char *
-ldif_getline( char **next )
-{
-       char *line;
-
-       do {
-               if ( *next == NULL || **next == '\n' || **next == '\0' ) {
-                       return( NULL );
-               }
-
-               line = *next;
-
-               while ( (*next = strchr( *next, '\n' )) != NULL ) {
-#if CONTINUED_LINE_MARKER != '\r'
-                       if ( (*next)[-1] == '\r' ) {
-                               (*next)[-1] = CONTINUED_LINE_MARKER;
-                       }
-#endif
-
-                       if ( (*next)[1] != ' ' ) {
-                               if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
-                                       *(*next)++ = '\0';
-                               }
-                               *(*next)++ = '\0';
-                               break;
-                       }
-
-                       **next = CONTINUED_LINE_MARKER;
-                       (*next)[1] = CONTINUED_LINE_MARKER;
-                       (*next)++;
-               }
-       } while( *line == '#' );
-
-       return( line );
-}
-
-/*
- * name and OID of attributeTypes that must be base64 encoded in any case
- */
-typedef struct must_b64_encode_s {
-       struct berval   name;
-       struct berval   oid;
-} must_b64_encode_s;
-
-static must_b64_encode_s       default_must_b64_encode[] = {
-       { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) },
-       { BER_BVNULL, BER_BVNULL }
-};
-
-static must_b64_encode_s       *must_b64_encode = default_must_b64_encode;
-
-/*
- * register name and OID of attributeTypes that must always be base64 
- * encoded
- *
- * NOTE: this routine mallocs memory in a static struct which must 
- * be explicitly freed when no longer required
- */
-int
-ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid )
-{
-       int             i;
-       ber_len_t       len;
-
-       assert( must_b64_encode != NULL );
-       assert( name != NULL );
-       assert( oid != NULL );
-
-       len = strlen( name );
-
-       for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
-               if ( len != must_b64_encode[i].name.bv_len ) {
-                       continue;
-               }
-
-               if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) {
-                       break;
-               }
-       }
-
-       if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) {
-               return 1;
-       }
-
-       for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ )
-               /* just count */ ;
-
-       if ( must_b64_encode == default_must_b64_encode ) {
-               must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) );
-
-               for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) {
-                       ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name );
-                       ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid );
-               }
-
-       } else {
-               must_b64_encode_s       *tmp;
-
-               tmp = ber_memrealloc( must_b64_encode,
-                       sizeof( must_b64_encode_s ) * ( i + 2 ) );
-               if ( tmp == NULL ) {
-                       return 1;
-               }
-               must_b64_encode = tmp;
-       }
-
-       ber_str2bv( name, len, 1, &must_b64_encode[i].name );
-       ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid );
-
-       BER_BVZERO( &must_b64_encode[i + 1].name );
-
-       return 0;
-}
-
-void
-ldif_must_b64_encode_release( void )
-{
-       int     i;
-
-       assert( must_b64_encode != NULL );
-
-       if ( must_b64_encode == default_must_b64_encode ) {
-               return;
-       }
-
-       for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
-               ber_memfree( must_b64_encode[i].name.bv_val );
-               ber_memfree( must_b64_encode[i].oid.bv_val );
-       }
-
-       ber_memfree( must_b64_encode );
-
-       must_b64_encode = default_must_b64_encode;
-}
-
-/*
- * returns 1 iff the string corresponds to the name or the OID of any 
- * of the attributeTypes listed in must_b64_encode
- */
-static int
-ldif_must_b64_encode( LDAP_CONST char *s )
-{
-       int             i;
-       struct berval   bv;
-
-       assert( must_b64_encode != NULL );
-       assert( s != NULL );
-
-       ber_str2bv( s, 0, 0, &bv );
-
-       for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
-               if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0
-                       || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 )
-               {
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-/* compatibility with U-Mich off by one bug */
-#define LDIF_KLUDGE 1
-
-/* NOTE: only preserved for binary compatibility */
-void
-ldif_sput(
-       char **out,
-       int type,
-       LDAP_CONST char *name,
-       LDAP_CONST char *val,
-       ber_len_t vlen )
-{
-       ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH );
-}
-
-void
-ldif_sput_wrap(
-       char **out,
-       int type,
-       LDAP_CONST char *name,
-       LDAP_CONST char *val,
-       ber_len_t vlen,
-        ber_len_t wrap )
-{
-       const unsigned char *byte, *stop;
-       unsigned char   buf[3];
-       unsigned long   bits;
-       char            *save;
-       int             pad;
-       int             namelen = 0;
-
-       ber_len_t savelen;
-       ber_len_t len=0;
-       ber_len_t i;
-
-       wrap = LDIF_LINE_WIDTH_WRAP( wrap );
-
-       /* prefix */
-       switch( type ) {
-       case LDIF_PUT_COMMENT:
-               *(*out)++ = '#';
-               len++;
-
-               if( vlen ) {
-                       *(*out)++ = ' ';
-                       len++;
-               }
-
-               break;
-
-       case LDIF_PUT_SEP:
-               *(*out)++ = '\n';
-               return;
-       }
-
-       /* name (attribute type) */
-       if( name != NULL ) {
-               /* put the name + ":" */
-               namelen = strlen(name);
-               strcpy(*out, name);
-               *out += namelen;
-               len += namelen;
-
-               if( type != LDIF_PUT_COMMENT ) {
-                       *(*out)++ = ':';
-                       len++;
-               }
-
-       }
-#ifdef LDAP_DEBUG
-       else {
-               assert( type == LDIF_PUT_COMMENT );
-       }
-#endif
-
-       if( vlen == 0 ) {
-               *(*out)++ = '\n';
-               return;
-       }
-
-       switch( type ) {
-       case LDIF_PUT_NOVALUE:
-               *(*out)++ = '\n';
-               return;
-
-       case LDIF_PUT_URL: /* url value */
-               *(*out)++ = '<';
-               len++;
-               break;
-
-       case LDIF_PUT_B64: /* base64 value */
-               *(*out)++ = ':';
-               len++;
-               break;
-       }
-
-       switch( type ) {
-       case LDIF_PUT_TEXT:
-       case LDIF_PUT_URL:
-       case LDIF_PUT_B64:
-               *(*out)++ = ' ';
-               len++;
-               /* fall-thru */
-
-       case LDIF_PUT_COMMENT:
-               /* pre-encoded names */
-               for ( i=0; i < vlen; i++ ) {
-                       if ( len > wrap ) {
-                               *(*out)++ = '\n';
-                               *(*out)++ = ' ';
-                               len = 1;
-                       }
-
-                       *(*out)++ = val[i];
-                       len++;
-               }
-               *(*out)++ = '\n';
-               return;
-       }
-
-       save = *out;
-       savelen = len;
-
-       *(*out)++ = ' ';
-       len++;
-
-       stop = (const unsigned char *) (val + vlen);
-
-       if ( type == LDIF_PUT_VALUE
-               && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
-               && isgraph( (unsigned char) val[vlen-1] )
-#ifndef LDAP_BINARY_DEBUG
-               && strstr( name, ";binary" ) == NULL
-#endif
-#ifndef LDAP_PASSWD_DEBUG
-               && !ldif_must_b64_encode( name )
-#endif
-       ) {
-               int b64 = 0;
-
-               for ( byte = (const unsigned char *) val; byte < stop;
-                   byte++, len++ )
-               {
-                       if ( !isascii( *byte ) || !isprint( *byte ) ) {
-                               b64 = 1;
-                               break;
-                       }
-                       if ( len - LDIF_KLUDGE > wrap ) {
-                               *(*out)++ = '\n';
-                               *(*out)++ = ' ';
-                               len = 1;
-                       }
-                       *(*out)++ = *byte;
-               }
-
-               if( !b64 ) {
-                       *(*out)++ = '\n';
-                       return;
-               }
-       }
-
-       *out = save;
-       *(*out)++ = ':';
-       *(*out)++ = ' ';
-       len = savelen + 2;
-
-       /* convert to base 64 (3 bytes => 4 base 64 digits) */
-       for ( byte = (const unsigned char *) val;
-               byte < stop - 2;
-           byte += 3 )
-       {
-               bits = (byte[0] & 0xff) << 16;
-               bits |= (byte[1] & 0xff) << 8;
-               bits |= (byte[2] & 0xff);
-
-               for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
-                       if ( len - LDIF_KLUDGE > wrap ) {
-                               *(*out)++ = '\n';
-                               *(*out)++ = ' ';
-                               len = 1;
-                       }
-
-                       /* get b64 digit from high order 6 bits */
-                       *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
-               }
-       }
-
-       /* add padding if necessary */
-       if ( byte < stop ) {
-               for ( i = 0; byte + i < stop; i++ ) {
-                       buf[i] = byte[i];
-               }
-               for ( pad = 0; i < 3; i++, pad++ ) {
-                       buf[i] = '\0';
-               }
-               byte = buf;
-               bits = (byte[0] & 0xff) << 16;
-               bits |= (byte[1] & 0xff) << 8;
-               bits |= (byte[2] & 0xff);
-
-               for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
-                       if ( len - LDIF_KLUDGE > wrap ) {
-                               *(*out)++ = '\n';
-                               *(*out)++ = ' ';
-                               len = 1;
-                       }
-
-                       if( i + pad < 4 ) {
-                               /* get b64 digit from low order 6 bits */
-                               *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
-                       } else {
-                               *(*out)++ = '=';
-                       }
-               }
-       }
-       *(*out)++ = '\n';
-}
-
-
-/*
- * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
- */
-
-/* NOTE: only preserved for binary compatibility */
-char *
-ldif_put(
-       int type,
-       LDAP_CONST char *name,
-       LDAP_CONST char *val,
-       ber_len_t vlen )
-{
-       return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH );
-}
-
-char *
-ldif_put_wrap(
-       int type,
-       LDAP_CONST char *name,
-       LDAP_CONST char *val,
-       ber_len_t vlen,
-       ber_len_t wrap )
-{
-    char       *buf, *p;
-    ber_len_t nlen;
-
-    nlen = ( name != NULL ) ? strlen( name ) : 0;
-
-       buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 );
-
-    if ( buf == NULL ) {
-               ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
-                       _("ldif_type_and_value: malloc failed!"));
-               return NULL;
-    }
-
-    p = buf;
-    ldif_sput_wrap( &p, type, name, val, vlen, wrap );
-    *p = '\0';
-
-    return( buf );
-}
-
-int ldif_is_not_printable(
-       LDAP_CONST char *val,
-       ber_len_t vlen )
-{
-       if( vlen == 0 || val == NULL  ) {
-               return -1;
-       }
-
-       if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
-               isgraph( (unsigned char) val[vlen-1] ) )
-       {
-               ber_len_t i;
-
-               for ( i = 0; val[i]; i++ ) {
-                       if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) {
-                               return 1;
-                       }
-               }
-
-               return 0;
-       }
-
-       return 1;
-}
-
-LDIFFP *
-ldif_open(
-       LDAP_CONST char *file,
-       LDAP_CONST char *mode
-)
-{
-       FILE *fp = fopen( file, mode );
-       LDIFFP *lfp = NULL;
-
-       if ( fp ) {
-               lfp = ber_memalloc( sizeof( LDIFFP ));
-               lfp->fp = fp;
-               lfp->prev = NULL;
-       }
-       return lfp;
-}
-
-void
-ldif_close(
-       LDIFFP *lfp
-)
-{
-       LDIFFP *prev;
-
-       while ( lfp ) {
-               fclose( lfp->fp );
-               prev = lfp->prev;
-               ber_memfree( lfp );
-               lfp = prev;
-       }
-}
-
-#define        LDIF_MAXLINE    4096
-
-/*
- * ldif_read_record - read an ldif record.  Return 1 for success, 0 for EOF,
- * -1 for error.
- */
-int
-ldif_read_record(
-       LDIFFP      *lfp,
-       int         *lno,               /* ptr to line number counter              */
-       char        **bufp,     /* ptr to malloced output buffer           */
-       int         *buflenp )  /* ptr to length of *bufp                  */
-{
-       char        line[LDIF_MAXLINE], *nbufp;
-       ber_len_t   lcur = 0, len;
-       int         last_ch = '\n', found_entry = 0, stop, top_comment = 0;
-
-       for ( stop = 0;  !stop;  last_ch = line[len-1] ) {
-               /* If we're at the end of this file, see if we should pop
-                * back to a previous file. (return from an include)
-                */
-               while ( feof( lfp->fp )) {
-                       if ( lfp->prev ) {
-                               LDIFFP *tmp = lfp->prev;
-                               fclose( lfp->fp );
-                               *lfp = *tmp;
-                               ber_memfree( tmp );
-                       } else {
-                               stop = 1;
-                               break;
-                       }
-               }
-               if ( stop )
-                       break;
-
-               if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) {
-                       stop = 1;
-                       /* Add \n in case the file does not end with newline */
-                       line[0] = '\n';
-                       line[1] = '\0';
-               }
-               len = strlen( line );
-
-               if ( last_ch == '\n' ) {
-                       (*lno)++;
-
-                       if ( line[0] == '\n' ||
-                               ( line[0] == '\r' && line[1] == '\n' )) {
-                               if ( !found_entry ) {
-                                       lcur = 0;
-                                       top_comment = 0;
-                                       continue;
-                               }
-                               break;
-                       }
-
-                       if ( !found_entry ) {
-                               if ( line[0] == '#' ) {
-                                       top_comment = 1;
-                               } else if ( ! ( top_comment && line[0] == ' ' ) ) {
-                                       /* Found a new entry */
-                                       found_entry = 1;
-
-                                       if ( isdigit( (unsigned char) line[0] ) ) {
-                                               /* skip index */
-                                               continue;
-                                       }
-                                       if ( !strncasecmp( line, "include:",
-                                               STRLENOF("include:"))) {
-                                               FILE *fp2;
-                                               char *ptr;
-                                               found_entry = 0;
-
-                                               if ( line[len-1] == '\n' ) {
-                                                       len--;
-                                                       line[len] = '\0';
-                                               }
-                                               if ( line[len-1] == '\r' ) {
-                                                       len--;
-                                                       line[len] = '\0';
-                                               }
-
-                                               ptr = line + STRLENOF("include:");
-                                               while (isspace((unsigned char) *ptr)) ptr++;
-                                               fp2 = ldif_open_url( ptr );
-                                               if ( fp2 ) {
-                                                       LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP ));
-                                                       if ( lnew == NULL ) {
-                                                               fclose( fp2 );
-                                                               return 0;
-                                                       }
-                                                       lnew->prev = lfp->prev;
-                                                       lnew->fp = lfp->fp;
-                                                       lfp->prev = lnew;
-                                                       lfp->fp = fp2;
-                                                       line[len] = '\n';
-                                                       len++;
-                                                       continue;
-                                               } else {
-                                                       /* We failed to open the file, this should
-                                                        * be reported as an error somehow.
-                                                        */
-                                                       ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
-                                                               _("ldif_read_record: include %s failed\n"), ptr );
-                                                       return -1;
-                                               }
-                                       }
-                               }
-                       }                       
-               }
-
-               if ( *buflenp - lcur <= len ) {
-                       *buflenp += len + LDIF_MAXLINE;
-                       nbufp = ber_memrealloc( *bufp, *buflenp );
-                       if( nbufp == NULL ) {
-                               return 0;
-                       }
-                       *bufp = nbufp;
-               }
-               strcpy( *bufp + lcur, line );
-               lcur += len;
-       }
-
-       return( found_entry );
-}