]> git.sur5r.net Git - openldap/blobdiff - libraries/libldif/line64.c
ITS#2153, make sure sockbuf buffer is empty before returning (-2) from
[openldap] / libraries / libldif / line64.c
index aef935b755c5c9f76c14d5e68da9203607dcebb5..3f16c95d600a5a24c213d1dae8d76f0b99d04582 100644 (file)
@@ -1,6 +1,7 @@
 /* line64.c - routines for dealing with the slapd line format */
+/* $OpenLDAP$ */
 /*
- * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
@@ -23,7 +24,14 @@ int ldif_debug = 0;
 
 #define RIGHT2                 0x03
 #define RIGHT4                 0x0f
-#define CONTINUED_LINE_MARKER  '\001'
+#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+/";
@@ -103,16 +111,16 @@ ldif_parse_line(
        }
        *s++ = '\0';
 
+       url = 0;
+       b64 = 0;
+
        if ( *s == '\0' ) {
                /* no value */
-               value = NULL;
+               value = "";
                vlen = 0;
                goto done;
        }
                
-       url = 0;
-       b64 = 0;
-
        if ( *s == '<' ) {
                s++;
                url = 1;
@@ -127,6 +135,13 @@ ldif_parse_line(
                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 no value is present, error out */
        if ( *s == '\0' ) {
                ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
@@ -137,13 +152,6 @@ ldif_parse_line(
                goto done;
        }
 
-       /* 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;
 
@@ -215,14 +223,17 @@ done:
        }
 
        if( !url && value != NULL ) {
-               value = ber_strdup( value );
-               if( value == NULL ) {
+               p = ber_memalloc( vlen + 1 );
+               if( p == NULL ) {
                        ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
                                "ldif_parse_line: value malloc failed\n");
                        ber_memfree( type );
                        ber_memfree( freeme );
                        return( -1 );
                }
+               AC_MEMCPY( p, value, vlen );
+               p[vlen] = '\0';
+               value = p;
        }
 
        ber_memfree( freeme );
@@ -263,15 +274,22 @@ ldif_getline( char **next )
                line = *next;
 
                while ( (*next = strchr( *next, '\n' )) != NULL ) {
-                       unsigned char c = *(*next + 1);
+#if CONTINUED_LINE_MARKER != '\r'
+                       if ( (*next)[-1] == '\r' ) {
+                               (*next)[-1] = CONTINUED_LINE_MARKER;
+                       }
+#endif
 
-                       if ( !isspace( c ) || c == '\n' ) {
+                       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)[1] = CONTINUED_LINE_MARKER;
                        (*next)++;
                }
        } while( *line == '#' );
@@ -290,11 +308,12 @@ ldif_sput(
        LDAP_CONST char *val,
        ber_len_t vlen )
 {
-       unsigned char   *byte, *stop;
+       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;
@@ -303,18 +322,15 @@ ldif_sput(
        /* prefix */
        switch( type ) {
        case LDIF_PUT_COMMENT:
-               if( name != NULL ) break;
-
                *(*out)++ = '#';
                len++;
 
                if( vlen ) {
                        *(*out)++ = ' ';
                        len++;
-                       break;
                }
 
-               /* no value, fall-thru */
+               break;
 
        case LDIF_PUT_SEP:
                *(*out)++ = '\n';
@@ -324,20 +340,26 @@ ldif_sput(
        /* name (attribute type) */
        if( name != NULL ) {
                /* put the name + ":" */
-               for ( i=0 ; name[i]; i++ ) {
-                       *(*out)++ = name[i];
-                       len++;
-               }
+               namelen = strlen(name);
+               strcpy(*out, name);
+               *out += namelen;
+               len += namelen;
 
                if( type != LDIF_PUT_COMMENT ) {
                        *(*out)++ = ':';
                        len++;
                }
 
+       }
 #ifdef LDAP_DEBUG
-       else {
+       else {
                assert( type == LDIF_PUT_COMMENT );
+       }
 #endif
+
+       if( vlen == 0 ) {
+               *(*out)++ = '\n';
+               return;
        }
 
        switch( type ) {
@@ -386,22 +408,24 @@ ldif_sput(
        *(*out)++ = ' ';
        len++;
 
-       if( vlen == 0 ) {
-               *(*out)++ = '\n';
-               return;
-       }
-
-       stop = (unsigned char *) (val + vlen);
+       stop = (const unsigned char *) (val + vlen);
 
        if ( type == LDIF_PUT_VALUE
-               && isgraph( val[0] ) && val[0] != ':' && val[0] != '<'
-               && isgraph( val[vlen-1] )
-               && strcasecmp( name, "userPassword" ) != 0      /* encode userPassword */
-               && strcasecmp( name, "2.5.4.35" ) != 0          /* encode userPassword */
+               && 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
+               && (namelen != (sizeof("userPassword")-1)
+               || strcasecmp( name, "userPassword" ) != 0)     /* encode userPassword */
+               && (namelen != (sizeof("2.5.4.35")-1) 
+               || strcasecmp( name, "2.5.4.35" ) != 0)         /* encode userPassword */
+#endif
        ) {
                int b64 = 0;
 
-               for ( byte = (unsigned char *) val; byte < stop;
+               for ( byte = (const unsigned char *) val; byte < stop;
                    byte++, len++ )
                {
                        if ( !isascii( *byte ) || !isprint( *byte ) ) {
@@ -428,7 +452,7 @@ ldif_sput(
        len = savelen + 2;
 
        /* convert to base 64 (3 bytes => 4 base 64 digits) */
-       for ( byte = (unsigned char *) val;
+       for ( byte = (const unsigned char *) val;
                byte < stop - 2;
            byte += 3 )
        {
@@ -518,8 +542,8 @@ int ldif_is_not_printable(
                return -1;
        }
 
-       if( isgraph( val[0] ) && val[0] != ':' && val[0] != '<' &&
-               isgraph( val[vlen-1] ) )
+       if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
+               isgraph( (unsigned char) val[vlen-1] ) )
        {
                ber_len_t i;
 
@@ -534,3 +558,63 @@ int ldif_is_not_printable(
 
        return 1;
 }
+
+/*
+ * slap_read_ldif - read an ldif record.  Return 1 for success, 0 for EOF.
+ */
+int
+ldif_read_record(
+       FILE        *fp,
+       int         *lno,               /* ptr to line number counter              */
+       char        **bufp,     /* ptr to malloced output buffer           */
+       int         *buflenp )  /* ptr to length of *bufp                  */
+{
+       char        linebuf[BUFSIZ], *line, *nbufp;
+       ber_len_t   lcur = 0, len, linesize;
+       int         last_ch = '\n', found_entry = 0, stop;
+
+       line     = linebuf;
+       linesize = sizeof( linebuf );
+
+       for ( stop = feof( fp );  !stop;  last_ch = line[len-1] ) {
+               if ( fgets( line, linesize, fp ) == NULL ) {
+                       stop = 1;
+                       /* Add \n in case the file does not end with newline */
+                       line = "\n";
+               }
+               len = strlen( line );
+
+               if ( last_ch == '\n' ) {
+                       (*lno)++;
+
+                       if ( line[0] == '\n' ) {
+                               if ( !found_entry )
+                                       continue;
+                               break;
+                       }
+
+                       if ( !found_entry ) {
+                               /* Found a new entry */
+                               found_entry = 1;
+
+                               if ( isdigit( (unsigned char) line[0] ) ) {
+                                       /* skip index */
+                                       continue;
+                               }
+                       }                       
+               }
+
+               if ( *buflenp - lcur <= len ) {
+                       *buflenp += len + BUFSIZ;
+                       nbufp = ber_memrealloc( *bufp, *buflenp );
+                       if( nbufp == NULL ) {
+                               return 0;
+                       }
+                       *bufp = nbufp;
+               }
+               strcpy( *bufp + lcur, line );
+               lcur += len;
+       }
+
+       return( found_entry );
+}