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