ldif.c 13.6 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* ldif.c - routines for dealing with LDIF files */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
 * Copyright 1998-2003 The OpenLDAP Foundation.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of Michigan at Ann Arbor.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.  This
 * software is provided ``as is'' without express or implied warranty.
 */
/* This work was originally developed by the University of Michigan
 * and distributed as part of U-MICH LDAP.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
28
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
29

30
31
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
32
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
33
34
35

#include <ac/stdlib.h>
#include <ac/ctype.h>
36
37
38
39
40

#include <ac/string.h>
#include <ac/socket.h>
#include <ac/time.h>

41
42
int ldif_debug = 0;

43
#include "ldap_log.h"
44
#include "lber_pvt.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
45
46
47
48
#include "ldif.h"

#define RIGHT2			0x03
#define RIGHT4			0x0f
Kurt Zeilenga's avatar
Kurt Zeilenga committed
49
#define CONTINUED_LINE_MARKER	'\r'
Kurt Zeilenga's avatar
Kurt Zeilenga committed
50

51
52
53
54
55
56
57
#ifdef CSRIMALLOC
#define ber_memalloc malloc
#define ber_memcalloc calloc
#define ber_memrealloc realloc
#define ber_strdup strdup
#endif

58
static const char nib2b64[0x40] =
Kurt Zeilenga's avatar
Kurt Zeilenga committed
59
60
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

61
static const unsigned char b642nib[0x80] = {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
	0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
	0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
	0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
	0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
	0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
	0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
};

/*
81
 * ldif_parse_line - takes a line of the form "type:[:] value" and splits it
Kurt Zeilenga's avatar
Kurt Zeilenga committed
82
83
84
85
86
87
 * into components "type" and "value".  if a double colon separates type from
 * value, then value is encoded in base 64, and parse_line un-decodes it
 * (in place) before returning.
 */

int
88
ldif_parse_line(
Kurt Zeilenga's avatar
Kurt Zeilenga committed
89
    LDAP_CONST char	*line,
90
91
92
    char	**typep,
    char	**valuep,
    ber_len_t *vlenp
Kurt Zeilenga's avatar
Kurt Zeilenga committed
93
94
)
{
95
	char	*s, *p, *d; 
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
	char	nib;
97
98
99
100
101
102
	int	b64, url;
	char	*freeme, *type, *value;
	ber_len_t vlen;

	*typep = NULL;
	*valuep = NULL;
103
	*vlenp = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
104
105

	/* skip any leading space */
106
	while ( isspace( (unsigned char) *line ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
107
108
109
		line++;
	}

110
111
112
113
	freeme = ber_strdup( line );

	if( freeme == NULL ) {
		ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
114
			_("ldif_parse_line: line malloc failed\n"));
115
116
117
118
119
120
121
122
		return( -1 );
	}

	type = freeme;

	s = strchr( type, ':' );

	if ( s == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
123
		ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
124
			_("ldif_parse_line: missing ':' after %s\n"),
125
126
			type );
		ber_memfree( freeme );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
127
128
129
130
		return( -1 );
	}

	/* trim any space between type and : */
131
	for ( p = &s[-1]; p > type && isspace( * (unsigned char *) p ); p-- ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
132
133
134
135
		*p = '\0';
	}
	*s++ = '\0';

136
137
138
	url = 0;
	b64 = 0;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
139
	if ( *s == '<' ) {
140
141
		s++;
		url = 1;
142

143
144
	} else if ( *s == ':' ) {
		/* base 64 encoded value */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
145
146
147
148
149
		s++;
		b64 = 1;
	}

	/* skip space between : and value */
150
	while ( isspace( (unsigned char) *s ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
151
152
153
		s++;
	}

154
155
156
157
158
159
160
	/* 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';

Kurt Zeilenga's avatar
Kurt Zeilenga committed
161
	if ( b64 ) {
162
163
		char *byte = s;

164
165
166
		if ( *s == '\0' ) {
			/* no value is present, error out */
			ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
167
				_("ldif_parse_line: %s missing base64 value\n"), type );
168
169
			ber_memfree( freeme );
			return( -1 );
170
171
172
		}

		byte = value = s;
173
174
175

		for ( p = s, vlen = 0; p < d; p += 4, vlen += 3 ) {
			int i;
176
			for ( i = 0; i < 4; i++ ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
177
178
				if ( p[i] != '=' && (p[i] & 0x80 ||
				    b642nib[ p[i] & 0x7f ] > 0x3f) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
179
					ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
180
181
						_("ldif_parse_line: %s: invalid base64 encoding"
						" char (%c) 0x%x\n"),
182
183
					    type, p[i], p[i] );
					ber_memfree( freeme );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
184
185
186
187
188
189
190
191
192
193
194
195
196
					return( -1 );
				}
			}

			/* first digit */
			nib = b642nib[ p[0] & 0x7f ];
			byte[0] = nib << 2;
			/* second digit */
			nib = b642nib[ p[1] & 0x7f ];
			byte[0] |= nib >> 4;
			byte[1] = (nib & RIGHT4) << 4;
			/* third digit */
			if ( p[2] == '=' ) {
197
				vlen += 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
198
199
200
201
202
203
204
				break;
			}
			nib = b642nib[ p[2] & 0x7f ];
			byte[1] |= nib >> 2;
			byte[2] = (nib & RIGHT2) << 6;
			/* fourth digit */
			if ( p[3] == '=' ) {
205
				vlen += 2;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
206
207
208
209
210
211
212
				break;
			}
			nib = b642nib[ p[3] & 0x7f ];
			byte[2] |= nib;

			byte += 3;
		}
213
214
215
		s[ vlen ] = '\0';

	} else if ( url ) {
216
217
218
		if ( *s == '\0' ) {
			/* no value is present, error out */
			ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
219
				_("ldif_parse_line: %s missing URL value\n"), type );
220
221
			ber_memfree( freeme );
			return( -1 );
222
223
		}

224
225
		if( ldif_fetch_url( s, &value, &vlen ) ) {
			ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
226
				_("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
227
228
229
230
231
				type, s );
			ber_memfree( freeme );
			return( -1 );
		}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
232
	} else {
233
234
235
236
237
238
239
240
		value = s;
		vlen = (int) (d - s);
	}

	type = ber_strdup( type );

	if( type == NULL ) {
		ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
241
			_("ldif_parse_line: type malloc failed\n"));
Kurt Zeilenga's avatar
Kurt Zeilenga committed
242
		if( url ) ber_memfree( value );
243
244
245
246
		ber_memfree( freeme );
		return( -1 );
	}

247
	if( !url ) {
248
		p = ber_memalloc( vlen + 1 );
249
		if( p == NULL ) {
250
			ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
251
				_("ldif_parse_line: value malloc failed\n"));
252
253
254
255
			ber_memfree( type );
			ber_memfree( freeme );
			return( -1 );
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
256
		AC_MEMCPY( p, value, vlen );
257
		p[vlen] = '\0';
258
		value = p;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
259
260
	}

261
262
263
264
265
266
	ber_memfree( freeme );

	*typep = type;
	*valuep = value;
	*vlenp = vlen;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
267
268
269
270
	return( 0 );
}

/*
271
 * ldif_getline - return the next "line" (minus newline) of input from a
Kurt Zeilenga's avatar
Kurt Zeilenga committed
272
273
274
275
276
277
 * string buffer of lines separated by newlines, terminated by \n\n
 * or \0.  this routine handles continued lines, bundling them into
 * a single big line before returning.  if a line begins with a white
 * space character, it is a continuation of the previous line. the white
 * space character (nb: only one char), and preceeding newline are changed
 * into CONTINUED_LINE_MARKER chars, to be deleted later by the
Kurt Zeilenga's avatar
Kurt Zeilenga committed
278
 * ldif_parse_line() routine above.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
279
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
280
281
282
 * ldif_getline will skip over any line which starts '#'.
 *
 * ldif_getline takes a pointer to a pointer to the buffer on the first call,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
283
284
285
286
 * which it updates and must be supplied on subsequent calls.
 */

char *
287
ldif_getline( char **next )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
288
{
289
	char *line;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
290

291
292
293
294
295
296
	do {
		if ( *next == NULL || **next == '\n' || **next == '\0' ) {
			return( NULL );
		}

		line = *next;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
297

298
		while ( (*next = strchr( *next, '\n' )) != NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
299
300
301
302
303
#if CONTINUED_LINE_MARKER != '\r'
			if ( (*next)[-1] == '\r' ) {
				(*next)[-1] = CONTINUED_LINE_MARKER;
			}
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
304

Kurt Zeilenga's avatar
Kurt Zeilenga committed
305
306
			if ( (*next)[1] != ' ' ) {
				if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
307
308
309
310
					*(*next)++ = '\0';
				}
				*(*next)++ = '\0';
				break;
311
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
312
313

			**next = CONTINUED_LINE_MARKER;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
314
			(*next)[1] = CONTINUED_LINE_MARKER;
315
			(*next)++;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
316
		}
317
	} while( *line == '#' );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
318

319
	return( line );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
320
321
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
322
323
324
/* compatibility with U-Mich off by one bug */
#define LDIF_KLUDGE 1

Kurt Zeilenga's avatar
Kurt Zeilenga committed
325
void
Kurt Zeilenga's avatar
Kurt Zeilenga committed
326
ldif_sput(
Kurt Zeilenga's avatar
Kurt Zeilenga committed
327
	char **out,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
328
329
	int type,
	LDAP_CONST char *name,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
330
	LDAP_CONST char *val,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
331
	ber_len_t vlen )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
332
{
333
	const unsigned char *byte, *stop;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
334
335
336
	unsigned char	buf[3];
	unsigned long	bits;
	char		*save;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
337
	int		pad;
Howard Chu's avatar
Howard Chu committed
338
	int		namelen = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

	ber_len_t savelen;
	ber_len_t len=0;
	ber_len_t i;

	/* prefix */
	switch( type ) {
	case LDIF_PUT_COMMENT:
		*(*out)++ = '#';
		len++;

		if( vlen ) {
			*(*out)++ = ' ';
			len++;
		}

355
		break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
356

Kurt Zeilenga's avatar
Kurt Zeilenga committed
357
358
359
	case LDIF_PUT_SEP:
		*(*out)++ = '\n';
		return;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
360
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
361
362
363
364

	/* name (attribute type) */
	if( name != NULL ) {
		/* put the name + ":" */
Howard Chu's avatar
Howard Chu committed
365
366
367
368
		namelen = strlen(name);
		strcpy(*out, name);
		*out += namelen;
		len += namelen;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
369
370
371
372
373
374

		if( type != LDIF_PUT_COMMENT ) {
			*(*out)++ = ':';
			len++;
		}

Hallvard Furuseth's avatar
Hallvard Furuseth committed
375
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
376
#ifdef LDAP_DEBUG
Hallvard Furuseth's avatar
Hallvard Furuseth committed
377
	else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
378
379
		assert( type == LDIF_PUT_COMMENT );
	}
Hallvard Furuseth's avatar
Hallvard Furuseth committed
380
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
381

382
383
384
385
386
	if( vlen == 0 ) {
		*(*out)++ = '\n';
		return;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
	switch( type ) {
	case LDIF_PUT_NOVALUE:
		*(*out)++ = '\n';
		return;

	case LDIF_PUT_URL: /* url value */
		*(*out)++ = '<';
		len++;
		break;

	case LDIF_PUT_B64: /* base64 value */
		*(*out)++ = ':';
		len++;
		break;
	}

	switch( type ) {
	case LDIF_PUT_TEXT:
	case LDIF_PUT_URL:
	case LDIF_PUT_B64:
		*(*out)++ = ' ';
		len++;
		/* fall-thru */

	case LDIF_PUT_COMMENT:
		/* pre-encoded names */
		for ( i=0; i < vlen; i++ ) {
			if ( len > LDIF_LINE_WIDTH ) {
				*(*out)++ = '\n';
				*(*out)++ = ' ';
				len = 1;
			}

			*(*out)++ = val[i];
			len++;
		}
		*(*out)++ = '\n';
		return;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
427
428
	save = *out;
	savelen = len;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
429

Kurt Zeilenga's avatar
Kurt Zeilenga committed
430
	*(*out)++ = ' ';
Kurt Zeilenga's avatar
Kurt Zeilenga committed
431
432
	len++;

433
	stop = (const unsigned char *) (val + vlen);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
434

Kurt Zeilenga's avatar
Kurt Zeilenga committed
435
	if ( type == LDIF_PUT_VALUE
436
437
		&& isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
		&& isgraph( (unsigned char) val[vlen-1] )
438
439
440
#ifndef LDAP_BINARY_DEBUG
		&& strstr( name, ";binary" ) == NULL
#endif
441
#ifndef LDAP_PASSWD_DEBUG
Howard Chu's avatar
Howard Chu committed
442
443
444
445
		&& (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 */
446
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
447
	) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
448
449
		int b64 = 0;

450
		for ( byte = (const unsigned char *) val; byte < stop;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
451
452
		    byte++, len++ )
		{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
453
454
455
456
			if ( !isascii( *byte ) || !isprint( *byte ) ) {
				b64 = 1;
				break;
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
457
			if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
458
459
460
461
462
463
				*(*out)++ = '\n';
				*(*out)++ = ' ';
				len = 1;
			}
			*(*out)++ = *byte;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
464
465
466
467
468

		if( !b64 ) {
			*(*out)++ = '\n';
			return;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
469
470
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
471
472
473
474
475
476
	*out = save;
	*(*out)++ = ':';
	*(*out)++ = ' ';
	len = savelen + 2;

	/* convert to base 64 (3 bytes => 4 base 64 digits) */
477
	for ( byte = (const unsigned char *) val;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
478
479
480
481
482
483
484
485
486
487
488
489
		byte < stop - 2;
	    byte += 3 )
	{
		bits = (byte[0] & 0xff) << 16;
		bits |= (byte[1] & 0xff) << 8;
		bits |= (byte[2] & 0xff);

		for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
			if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
				*(*out)++ = '\n';
				*(*out)++ = ' ';
				len = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
490
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
491
492
493

			/* get b64 digit from high order 6 bits */
			*(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
Kurt Zeilenga's avatar
Kurt Zeilenga committed
494
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
495
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
496

Kurt Zeilenga's avatar
Kurt Zeilenga committed
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
	/* add padding if necessary */
	if ( byte < stop ) {
		for ( i = 0; byte + i < stop; i++ ) {
			buf[i] = byte[i];
		}
		for ( pad = 0; i < 3; i++, pad++ ) {
			buf[i] = '\0';
		}
		byte = buf;
		bits = (byte[0] & 0xff) << 16;
		bits |= (byte[1] & 0xff) << 8;
		bits |= (byte[2] & 0xff);

		for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
			if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
				*(*out)++ = '\n';
				*(*out)++ = ' ';
				len = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
515
516
			}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
517
518
519
520
521
			if( i + pad < 4 ) {
				/* get b64 digit from low order 6 bits */
				*(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
			} else {
				*(*out)++ = '=';
Kurt Zeilenga's avatar
Kurt Zeilenga committed
522
523
524
525
526
527
528
529
			}
		}
	}
	*(*out)++ = '\n';
}


/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
530
 * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
Kurt Zeilenga's avatar
Kurt Zeilenga committed
531
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
532
533
534
535
536
537
char *
ldif_put(
	int type,
	LDAP_CONST char *name,
	LDAP_CONST char *val,
	ber_len_t vlen )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
538
539
{
    char	*buf, *p;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
540
    ber_len_t nlen;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
541

Kurt Zeilenga's avatar
Kurt Zeilenga committed
542
543
544
545
546
    nlen = ( name != NULL ) ? strlen( name ) : 0;

	buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED( nlen, vlen ) + 1 );

    if ( buf == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
547
		ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
548
			_("ldif_type_and_value: malloc failed!"));
549
		return NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
550
551
552
    }

    p = buf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
553
    ldif_sput( &p, type, name, val, vlen );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
554
555
556
557
    *p = '\0';

    return( buf );
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
558
559
560
561
562
563
564
565
566

int ldif_is_not_printable(
	LDAP_CONST char *val,
	ber_len_t vlen )
{
	if( vlen == 0 || val == NULL  ) {
		return -1;
	}

567
568
	if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
		isgraph( (unsigned char) val[vlen-1] ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
569
570
571
572
573
574
575
576
577
578
579
580
581
582
	{
		ber_len_t i;

		for ( i = 0; val[i]; i++ ) {
			if ( !isascii( val[i] ) || !isprint( val[i] ) ) {
				return 1;
			}
		}

		return 0;
	}

	return 1;
}
583
584
585
586
587
588
589
590
591
592
593

/*
 * 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                  */
{
Hallvard Furuseth's avatar
Hallvard Furuseth committed
594
	char        linebuf[BUFSIZ], *line, *nbufp;
595
	ber_len_t   lcur = 0, len, linesize;
596
	int         last_ch = '\n', found_entry = 0, stop, top_comment = 0;
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

	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' ) {
613
614
615
				if ( !found_entry ) {
					lcur = 0;
					top_comment = 0;
616
					continue;
617
				}
618
619
620
621
				break;
			}

			if ( !found_entry ) {
622
623
624
625
626
627
628
629
630
631
				if ( line[0] == '#' ) {
					top_comment = 1;
				} else if ( ! ( top_comment && line[0] == ' ' ) ) {
					/* Found a new entry */
					found_entry = 1;

					if ( isdigit( (unsigned char) line[0] ) ) {
						/* skip index */
						continue;
					}
632
633
634
635
636
				}
			}			
		}

		if ( *buflenp - lcur <= len ) {
Hallvard Furuseth's avatar
Hallvard Furuseth committed
637
638
			*buflenp += len + BUFSIZ;
			nbufp = ber_memrealloc( *bufp, *buflenp );
639
640
641
642
643
644
645
646
647
648
			if( nbufp == NULL ) {
				return 0;
			}
			*bufp = nbufp;
		}
		strcpy( *bufp + lcur, line );
		lcur += len;
	}

	return( found_entry );
649
}