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