]> git.sur5r.net Git - openldap/blob - libraries/libldap/ldif.c
ITS#8753 Move base64 decoding to separate file
[openldap] / libraries / libldap / ldif.c
1 /* ldif.c - routines for dealing with LDIF files */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2017 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms are permitted
20  * provided that this notice is preserved and that due credit is given
21  * to the University of Michigan at Ann Arbor.  The name of the
22  * University may not be used to endorse or promote products derived
23  * from this software without specific prior written permission.  This
24  * software is provided ``as is'' without express or implied warranty.
25  */
26 /* This work was originally developed by the University of Michigan
27  * and distributed as part of U-MICH LDAP.
28  */
29
30 #include "portable.h"
31
32 #include <stdio.h>
33
34 #include <ac/stdlib.h>
35 #include <ac/ctype.h>
36
37 #include <ac/string.h>
38 #include <ac/socket.h>
39 #include <ac/time.h>
40
41 int ldif_debug = 0;
42
43 #include "ldap-int.h"
44 #include "ldif.h"
45
46 #define CONTINUED_LINE_MARKER   '\r'
47
48 #ifdef CSRIMALLOC
49 #define ber_memalloc malloc
50 #define ber_memcalloc calloc
51 #define ber_memrealloc realloc
52 #define ber_strdup strdup
53 #endif
54
55 static const char nib2b64[0x40] =
56         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57
58 /*
59  * ldif_parse_line - takes a line of the form "type:[:] value" and splits it
60  * into components "type" and "value".  if a double colon separates type from
61  * value, then value is encoded in base 64, and parse_line un-decodes it
62  * (in place) before returning. The type and value are stored in malloc'd
63  * memory which must be freed by the caller.
64  *
65  * ldif_parse_line2 - operates in-place on input buffer, returning type
66  * in-place. Will return value in-place if possible, (must malloc for
67  * fetched URLs). If freeval is NULL, all return data will be malloc'd
68  * and the input line will be unmodified. Otherwise freeval is set to
69  * True if the value was malloc'd.
70  */
71
72 int
73 ldif_parse_line(
74     LDAP_CONST char     *line,
75     char        **typep,
76     char        **valuep,
77     ber_len_t *vlenp
78 )
79 {
80         struct berval type, value;
81         int rc = ldif_parse_line2( (char *)line, &type, &value, NULL );
82
83         *typep = type.bv_val;
84         *valuep = value.bv_val;
85         *vlenp = value.bv_len;
86         return rc;
87 }
88
89 int
90 ldif_parse_line2(
91     char        *line,
92         struct berval *type,
93         struct berval *value,
94         int             *freeval
95 )
96 {
97         char    *s, *p, *d; 
98         int     b64, url;
99
100         BER_BVZERO( type );
101         BER_BVZERO( value );
102
103         /* skip any leading space */
104         while ( isspace( (unsigned char) *line ) ) {
105                 line++;
106         }
107
108         if ( freeval ) {
109                 *freeval = 0;
110         } else {
111                 line = ber_strdup( line );
112
113                 if( line == NULL ) {
114                         ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
115                                 _("ldif_parse_line: line malloc failed\n"));
116                         return( -1 );
117                 }
118         }
119
120         type->bv_val = line;
121
122         s = strchr( type->bv_val, ':' );
123
124         if ( s == NULL ) {
125                 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
126                         _("ldif_parse_line: missing ':' after %s\n"),
127                         type->bv_val );
128                 if ( !freeval ) ber_memfree( line );
129                 return( -1 );
130         }
131
132         /* trim any space between type and : */
133         for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) {
134                 *p = '\0';
135         }
136         *s++ = '\0';
137         type->bv_len = s - type->bv_val - 1;
138
139         url = 0;
140         b64 = 0;
141
142         if ( *s == '<' ) {
143                 s++;
144                 url = 1;
145
146         } else if ( *s == ':' ) {
147                 /* base 64 encoded value */
148                 s++;
149                 b64 = 1;
150         }
151
152         /* skip space between : and value */
153         while ( isspace( (unsigned char) *s ) ) {
154                 s++;
155         }
156
157         /* check for continued line markers that should be deleted */
158         for ( p = s, d = s; *p; p++ ) {
159                 if ( *p != CONTINUED_LINE_MARKER )
160                         *d++ = *p;
161         }
162         *d = '\0';
163
164         if ( b64 ) {
165                 char *byte = s;
166
167                 if ( *s == '\0' ) {
168                         /* no value is present, error out */
169                         ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
170                                 _("ldif_parse_line: %s missing base64 value\n"),
171                                 type->bv_val );
172                         if ( !freeval ) ber_memfree( line );
173                         return( -1 );
174                 }
175
176                 value->bv_val = s;
177                 value->bv_len = d - s;
178                 if ( ldap_int_decode_b64_inplace( value ) != LDAP_SUCCESS ) {
179                         ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
180                                 _("ldif_parse_line: %s base64 decode failed\n"),
181                                 type->bv_val );
182                         if ( !freeval ) ber_memfree( line );
183                         return( -1 );
184                 }
185         } else if ( url ) {
186                 if ( *s == '\0' ) {
187                         /* no value is present, error out */
188                         ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
189                                 _("ldif_parse_line: %s missing URL value\n"),
190                                 type->bv_val );
191                         if ( !freeval ) ber_memfree( line );
192                         return( -1 );
193                 }
194
195                 if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) {
196                         ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
197                                 _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
198                                 type->bv_val, s );
199                         if ( !freeval ) ber_memfree( line );
200                         return( -1 );
201                 }
202                 if ( freeval ) *freeval = 1;
203
204         } else {
205                 value->bv_val = s;
206                 value->bv_len = (int) (d - s);
207         }
208
209         if ( !freeval ) {
210                 struct berval bv = *type;
211
212                 ber_dupbv( type, &bv );
213
214                 if( BER_BVISNULL( type )) {
215                         ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
216                                 _("ldif_parse_line: type malloc failed\n"));
217                         if( url ) ber_memfree( value->bv_val );
218                         ber_memfree( line );
219                         return( -1 );
220                 }
221
222                 if( !url ) {
223                         bv = *value;
224                         ber_dupbv( value, &bv );
225                         if( BER_BVISNULL( value )) {
226                                 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
227                                         _("ldif_parse_line: value malloc failed\n"));
228                                 ber_memfree( type->bv_val );
229                                 ber_memfree( line );
230                                 return( -1 );
231                         }
232                 }
233
234                 ber_memfree( line );
235         }
236
237         return( 0 );
238 }
239
240 /*
241  * ldif_getline - return the next "line" (minus newline) of input from a
242  * string buffer of lines separated by newlines, terminated by \n\n
243  * or \0.  this routine handles continued lines, bundling them into
244  * a single big line before returning.  if a line begins with a white
245  * space character, it is a continuation of the previous line. the white
246  * space character (nb: only one char), and preceeding newline are changed
247  * into CONTINUED_LINE_MARKER chars, to be deleted later by the
248  * ldif_parse_line() routine above.
249  *
250  * ldif_getline will skip over any line which starts '#'.
251  *
252  * ldif_getline takes a pointer to a pointer to the buffer on the first call,
253  * which it updates and must be supplied on subsequent calls.
254  */
255
256 int
257 ldif_countlines( LDAP_CONST char *buf )
258 {
259         char *nl;
260         int ret = 0;
261
262         if ( !buf ) return ret;
263
264         for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) {
265                 nl++;
266                 if ( *nl != ' ' ) ret++;
267         }
268         return ret;
269 }
270
271 char *
272 ldif_getline( char **next )
273 {
274         char *line;
275
276         do {
277                 if ( *next == NULL || **next == '\n' || **next == '\0' ) {
278                         return( NULL );
279                 }
280
281                 line = *next;
282
283                 while ( (*next = strchr( *next, '\n' )) != NULL ) {
284 #if CONTINUED_LINE_MARKER != '\r'
285                         if ( (*next)[-1] == '\r' ) {
286                                 (*next)[-1] = CONTINUED_LINE_MARKER;
287                         }
288 #endif
289
290                         if ( (*next)[1] != ' ' ) {
291                                 if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
292                                         *(*next)++ = '\0';
293                                 }
294                                 *(*next)++ = '\0';
295                                 break;
296                         }
297
298                         **next = CONTINUED_LINE_MARKER;
299                         (*next)[1] = CONTINUED_LINE_MARKER;
300                         (*next)++;
301                 }
302         } while( *line == '#' );
303
304         return( line );
305 }
306
307 /*
308  * name and OID of attributeTypes that must be base64 encoded in any case
309  */
310 typedef struct must_b64_encode_s {
311         struct berval   name;
312         struct berval   oid;
313 } must_b64_encode_s;
314
315 static must_b64_encode_s        default_must_b64_encode[] = {
316         { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) },
317         { BER_BVNULL, BER_BVNULL }
318 };
319
320 static must_b64_encode_s        *must_b64_encode = default_must_b64_encode;
321
322 /*
323  * register name and OID of attributeTypes that must always be base64 
324  * encoded
325  *
326  * NOTE: this routine mallocs memory in a static struct which must 
327  * be explicitly freed when no longer required
328  */
329 int
330 ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid )
331 {
332         int             i;
333         ber_len_t       len;
334
335         assert( must_b64_encode != NULL );
336         assert( name != NULL );
337         assert( oid != NULL );
338
339         len = strlen( name );
340
341         for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
342                 if ( len != must_b64_encode[i].name.bv_len ) {
343                         continue;
344                 }
345
346                 if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) {
347                         break;
348                 }
349         }
350
351         if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) {
352                 return 1;
353         }
354
355         for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ )
356                 /* just count */ ;
357
358         if ( must_b64_encode == default_must_b64_encode ) {
359                 must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) );
360
361                 for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) {
362                         ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name );
363                         ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid );
364                 }
365
366         } else {
367                 must_b64_encode_s       *tmp;
368
369                 tmp = ber_memrealloc( must_b64_encode,
370                         sizeof( must_b64_encode_s ) * ( i + 2 ) );
371                 if ( tmp == NULL ) {
372                         return 1;
373                 }
374                 must_b64_encode = tmp;
375         }
376
377         ber_str2bv( name, len, 1, &must_b64_encode[i].name );
378         ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid );
379
380         BER_BVZERO( &must_b64_encode[i + 1].name );
381
382         return 0;
383 }
384
385 void
386 ldif_must_b64_encode_release( void )
387 {
388         int     i;
389
390         assert( must_b64_encode != NULL );
391
392         if ( must_b64_encode == default_must_b64_encode ) {
393                 return;
394         }
395
396         for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
397                 ber_memfree( must_b64_encode[i].name.bv_val );
398                 ber_memfree( must_b64_encode[i].oid.bv_val );
399         }
400
401         ber_memfree( must_b64_encode );
402
403         must_b64_encode = default_must_b64_encode;
404 }
405
406 /*
407  * returns 1 iff the string corresponds to the name or the OID of any 
408  * of the attributeTypes listed in must_b64_encode
409  */
410 static int
411 ldif_must_b64_encode( LDAP_CONST char *s )
412 {
413         int             i;
414         struct berval   bv;
415
416         assert( must_b64_encode != NULL );
417         assert( s != NULL );
418
419         ber_str2bv( s, 0, 0, &bv );
420
421         for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
422                 if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0
423                         || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 )
424                 {
425                         return 1;
426                 }
427         }
428
429         return 0;
430 }
431
432 /* compatibility with U-Mich off by two bug */
433 #define LDIF_KLUDGE 2
434
435 /* NOTE: only preserved for binary compatibility */
436 void
437 ldif_sput(
438         char **out,
439         int type,
440         LDAP_CONST char *name,
441         LDAP_CONST char *val,
442         ber_len_t vlen )
443 {
444         ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH+LDIF_KLUDGE );
445 }
446
447 void
448 ldif_sput_wrap(
449         char **out,
450         int type,
451         LDAP_CONST char *name,
452         LDAP_CONST char *val,
453         ber_len_t vlen,
454         ber_len_t wrap )
455 {
456         const unsigned char *byte, *stop;
457         unsigned char   buf[3];
458         unsigned long   bits;
459         char            *save;
460         int             pad;
461         int             namelen = 0;
462
463         ber_len_t savelen;
464         ber_len_t len=0;
465         ber_len_t i;
466
467         if ( !wrap )
468                 wrap = LDIF_LINE_WIDTH+LDIF_KLUDGE;
469
470         /* prefix */
471         switch( type ) {
472         case LDIF_PUT_COMMENT:
473                 *(*out)++ = '#';
474                 len++;
475
476                 if( vlen ) {
477                         *(*out)++ = ' ';
478                         len++;
479                 }
480
481                 break;
482
483         case LDIF_PUT_SEP:
484                 *(*out)++ = '\n';
485                 return;
486         }
487
488         /* name (attribute type) */
489         if( name != NULL ) {
490                 /* put the name + ":" */
491                 namelen = strlen(name);
492                 strcpy(*out, name);
493                 *out += namelen;
494                 len += namelen;
495
496                 if( type != LDIF_PUT_COMMENT ) {
497                         *(*out)++ = ':';
498                         len++;
499                 }
500
501         }
502 #ifdef LDAP_DEBUG
503         else {
504                 assert( type == LDIF_PUT_COMMENT );
505         }
506 #endif
507
508         if( vlen == 0 ) {
509                 *(*out)++ = '\n';
510                 return;
511         }
512
513         switch( type ) {
514         case LDIF_PUT_NOVALUE:
515                 *(*out)++ = '\n';
516                 return;
517
518         case LDIF_PUT_URL: /* url value */
519                 *(*out)++ = '<';
520                 len++;
521                 break;
522
523         case LDIF_PUT_B64: /* base64 value */
524                 *(*out)++ = ':';
525                 len++;
526                 break;
527         }
528
529         switch( type ) {
530         case LDIF_PUT_TEXT:
531         case LDIF_PUT_URL:
532         case LDIF_PUT_B64:
533                 *(*out)++ = ' ';
534                 len++;
535                 /* fall-thru */
536
537         case LDIF_PUT_COMMENT:
538                 /* pre-encoded names */
539                 for ( i=0; i < vlen; i++ ) {
540                         if ( len > wrap ) {
541                                 *(*out)++ = '\n';
542                                 *(*out)++ = ' ';
543                                 len = 1;
544                         }
545
546                         *(*out)++ = val[i];
547                         len++;
548                 }
549                 *(*out)++ = '\n';
550                 return;
551         }
552
553         save = *out;
554         savelen = len;
555
556         *(*out)++ = ' ';
557         len++;
558
559         stop = (const unsigned char *) (val + vlen);
560
561         if ( type == LDIF_PUT_VALUE
562                 && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
563                 && isgraph( (unsigned char) val[vlen-1] )
564 #ifndef LDAP_BINARY_DEBUG
565                 && strstr( name, ";binary" ) == NULL
566 #endif
567 #ifndef LDAP_PASSWD_DEBUG
568                 && !ldif_must_b64_encode( name )
569 #endif
570         ) {
571                 int b64 = 0;
572
573                 for ( byte = (const unsigned char *) val; byte < stop;
574                     byte++, len++ )
575                 {
576                         if ( !isascii( *byte ) || !isprint( *byte ) ) {
577                                 b64 = 1;
578                                 break;
579                         }
580                         if ( len >= wrap ) {
581                                 *(*out)++ = '\n';
582                                 *(*out)++ = ' ';
583                                 len = 1;
584                         }
585                         *(*out)++ = *byte;
586                 }
587
588                 if( !b64 ) {
589                         *(*out)++ = '\n';
590                         return;
591                 }
592         }
593
594         *out = save;
595         *(*out)++ = ':';
596         *(*out)++ = ' ';
597         len = savelen + 2;
598
599         /* convert to base 64 (3 bytes => 4 base 64 digits) */
600         for ( byte = (const unsigned char *) val;
601                 byte < stop - 2;
602             byte += 3 )
603         {
604                 bits = (byte[0] & 0xff) << 16;
605                 bits |= (byte[1] & 0xff) << 8;
606                 bits |= (byte[2] & 0xff);
607
608                 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
609                         if ( len >= wrap ) {
610                                 *(*out)++ = '\n';
611                                 *(*out)++ = ' ';
612                                 len = 1;
613                         }
614
615                         /* get b64 digit from high order 6 bits */
616                         *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
617                 }
618         }
619
620         /* add padding if necessary */
621         if ( byte < stop ) {
622                 for ( i = 0; byte + i < stop; i++ ) {
623                         buf[i] = byte[i];
624                 }
625                 for ( pad = 0; i < 3; i++, pad++ ) {
626                         buf[i] = '\0';
627                 }
628                 byte = buf;
629                 bits = (byte[0] & 0xff) << 16;
630                 bits |= (byte[1] & 0xff) << 8;
631                 bits |= (byte[2] & 0xff);
632
633                 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
634                         if ( len >= wrap ) {
635                                 *(*out)++ = '\n';
636                                 *(*out)++ = ' ';
637                                 len = 1;
638                         }
639
640                         if( i + pad < 4 ) {
641                                 /* get b64 digit from low order 6 bits */
642                                 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
643                         } else {
644                                 *(*out)++ = '=';
645                         }
646                 }
647         }
648         *(*out)++ = '\n';
649 }
650
651
652 /*
653  * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
654  */
655
656 /* NOTE: only preserved for binary compatibility */
657 char *
658 ldif_put(
659         int type,
660         LDAP_CONST char *name,
661         LDAP_CONST char *val,
662         ber_len_t vlen )
663 {
664         return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH );
665 }
666
667 char *
668 ldif_put_wrap(
669         int type,
670         LDAP_CONST char *name,
671         LDAP_CONST char *val,
672         ber_len_t vlen,
673         ber_len_t wrap )
674 {
675     char        *buf, *p;
676     ber_len_t nlen;
677
678     nlen = ( name != NULL ) ? strlen( name ) : 0;
679
680         buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 );
681
682     if ( buf == NULL ) {
683                 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
684                         _("ldif_type_and_value: malloc failed!"));
685                 return NULL;
686     }
687
688     p = buf;
689     ldif_sput_wrap( &p, type, name, val, vlen, wrap );
690     *p = '\0';
691
692     return( buf );
693 }
694
695 int ldif_is_not_printable(
696         LDAP_CONST char *val,
697         ber_len_t vlen )
698 {
699         if( vlen == 0 || val == NULL  ) {
700                 return -1;
701         }
702
703         if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
704                 isgraph( (unsigned char) val[vlen-1] ) )
705         {
706                 ber_len_t i;
707
708                 for ( i = 0; val[i]; i++ ) {
709                         if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) {
710                                 return 1;
711                         }
712                 }
713
714                 return 0;
715         }
716
717         return 1;
718 }
719
720 LDIFFP *
721 ldif_open(
722         LDAP_CONST char *file,
723         LDAP_CONST char *mode
724 )
725 {
726         FILE *fp = fopen( file, mode );
727         LDIFFP *lfp = NULL;
728
729         if ( fp ) {
730                 lfp = ber_memalloc( sizeof( LDIFFP ));
731                 lfp->fp = fp;
732                 lfp->prev = NULL;
733         }
734         return lfp;
735 }
736
737 void
738 ldif_close(
739         LDIFFP *lfp
740 )
741 {
742         LDIFFP *prev;
743
744         while ( lfp ) {
745                 fclose( lfp->fp );
746                 prev = lfp->prev;
747                 ber_memfree( lfp );
748                 lfp = prev;
749         }
750 }
751
752 #define LDIF_MAXLINE    4096
753
754 /*
755  * ldif_read_record - read an ldif record.  Return 1 for success, 0 for EOF,
756  * -1 for error.
757  */
758 int
759 ldif_read_record(
760         LDIFFP      *lfp,
761         unsigned long *lno,             /* ptr to line number counter              */
762         char        **bufp,     /* ptr to malloced output buffer           */
763         int         *buflenp )  /* ptr to length of *bufp                  */
764 {
765         char        line[LDIF_MAXLINE], *nbufp;
766         ber_len_t   lcur = 0, len;
767         int         last_ch = '\n', found_entry = 0, stop, top_comment = 0;
768
769         for ( stop = 0;  !stop;  last_ch = line[len-1] ) {
770                 /* If we're at the end of this file, see if we should pop
771                  * back to a previous file. (return from an include)
772                  */
773                 while ( feof( lfp->fp )) {
774                         if ( lfp->prev ) {
775                                 LDIFFP *tmp = lfp->prev;
776                                 fclose( lfp->fp );
777                                 *lfp = *tmp;
778                                 ber_memfree( tmp );
779                         } else {
780                                 stop = 1;
781                                 break;
782                         }
783                 }
784                 if ( !stop ) {
785                         if ( fgets( line, sizeof( line ), lfp->fp ) == NULL ) {
786                                 stop = 1;
787                                 len = 0;
788                         } else {
789                                 len = strlen( line );
790                         }
791                 }
792
793                 if ( stop ) {
794                         /* Add \n in case the file does not end with newline */
795                         if (last_ch != '\n') {
796                                 len = 1;
797                                 line[0] = '\n';
798                                 line[1] = '\0';
799                                 goto last;
800                         }
801                         break;
802                 }
803
804                 /* Squash \r\n to \n */
805                 if ( len > 1 && line[len-2] == '\r' ) {
806                         len--;
807                         line[len-1] = '\n';
808                 }
809
810                 if ( last_ch == '\n' ) {
811                         (*lno)++;
812
813                         if ( line[0] == '\n' ) {
814                                 if ( !found_entry ) {
815                                         lcur = 0;
816                                         top_comment = 0;
817                                         continue;
818                                 }
819                                 break;
820                         }
821
822                         if ( !found_entry ) {
823                                 if ( line[0] == '#' ) {
824                                         top_comment = 1;
825                                 } else if ( ! ( top_comment && line[0] == ' ' ) ) {
826                                         /* Found a new entry */
827                                         found_entry = 1;
828
829                                         if ( isdigit( (unsigned char) line[0] ) ) {
830                                                 /* skip index */
831                                                 continue;
832                                         }
833                                         if ( !strncasecmp( line, "include:",
834                                                 STRLENOF("include:"))) {
835                                                 FILE *fp2;
836                                                 char *ptr;
837                                                 found_entry = 0;
838
839                                                 if ( line[len-1] == '\n' ) {
840                                                         len--;
841                                                         line[len] = '\0';
842                                                 }
843
844                                                 ptr = line + STRLENOF("include:");
845                                                 while (isspace((unsigned char) *ptr)) ptr++;
846                                                 fp2 = ldif_open_url( ptr );
847                                                 if ( fp2 ) {
848                                                         LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP ));
849                                                         if ( lnew == NULL ) {
850                                                                 fclose( fp2 );
851                                                                 return 0;
852                                                         }
853                                                         lnew->prev = lfp->prev;
854                                                         lnew->fp = lfp->fp;
855                                                         lfp->prev = lnew;
856                                                         lfp->fp = fp2;
857                                                         line[len] = '\n';
858                                                         len++;
859                                                         continue;
860                                                 } else {
861                                                         /* We failed to open the file, this should
862                                                          * be reported as an error somehow.
863                                                          */
864                                                         ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
865                                                                 _("ldif_read_record: include %s failed\n"), ptr );
866                                                         return -1;
867                                                 }
868                                         }
869                                 }
870                         }
871                 }
872
873 last:
874                 if ( *buflenp - lcur <= len ) {
875                         *buflenp += len + LDIF_MAXLINE;
876                         nbufp = ber_memrealloc( *bufp, *buflenp );
877                         if( nbufp == NULL ) {
878                                 return 0;
879                         }
880                         *bufp = nbufp;
881                 }
882                 strcpy( *bufp + lcur, line );
883                 lcur += len;
884         }
885
886         return( found_entry );
887 }