ldif.c 14.8 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
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 1998-2005 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * 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
 * 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
84
85
86
87
88
 * (in place) before returning. The type and value are stored in malloc'd
 * memory which must be freed by the caller.
 *
 * ldif_parse_line2 - operates in-place on input buffer, returning type
 * in-place. Will return value in-place if possible, (must malloc for
89
90
91
 * fetched URLs). If freeval is NULL, all return data will be malloc'd
 * and the input line will be unmodified. Otherwise freeval is set to
 * True if the value was malloc'd.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
92
93
94
 */

int
95
ldif_parse_line(
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
    LDAP_CONST char	*line,
97
98
99
    char	**typep,
    char	**valuep,
    ber_len_t *vlenp
Kurt Zeilenga's avatar
Kurt Zeilenga committed
100
)
101
{
102
103
104
105
106
107
108
	struct berval type, value;
	int rc = ldif_parse_line2( (char *)line, &type, &value, NULL );

	*typep = type.bv_val;
	*valuep = value.bv_val;
	*vlenp = value.bv_len;
	return rc;
109
110
111
112
}

int
ldif_parse_line2(
113
114
115
116
    char	*line,
	struct berval *type,
	struct berval *value,
	int		*freeval
117
)
Kurt Zeilenga's avatar
Kurt Zeilenga committed
118
{
119
	char	*s, *p, *d; 
Kurt Zeilenga's avatar
Kurt Zeilenga committed
120
	char	nib;
121
122
	int	b64, url;

123
124
	BER_BVZERO( type );
	BER_BVZERO( value );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
125
126

	/* skip any leading space */
127
	while ( isspace( (unsigned char) *line ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
128
129
130
		line++;
	}

131
132
	if ( freeval ) {
		*freeval = 0;
133
134
	} else {
		line = ber_strdup( line );
135

136
137
138
139
140
		if( line == NULL ) {
			ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
				_("ldif_parse_line: line malloc failed\n"));
			return( -1 );
		}
141
142
	}

143
	type->bv_val = line;
144

145
	s = strchr( type->bv_val, ':' );
146
147

	if ( s == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
148
		ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
149
			_("ldif_parse_line: missing ':' after %s\n"),
150
			type );
151
		if ( !freeval ) ber_memfree( line );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
152
153
154
155
		return( -1 );
	}

	/* trim any space between type and : */
156
	for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
157
158
159
		*p = '\0';
	}
	*s++ = '\0';
160
	type->bv_len = s - type->bv_val - 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
161

162
163
164
	url = 0;
	b64 = 0;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
165
	if ( *s == '<' ) {
166
167
		s++;
		url = 1;
168

169
170
	} else if ( *s == ':' ) {
		/* base 64 encoded value */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
171
172
173
174
175
		s++;
		b64 = 1;
	}

	/* skip space between : and value */
176
	while ( isspace( (unsigned char) *s ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
177
178
179
		s++;
	}

180
181
182
183
184
185
186
	/* 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
187
	if ( b64 ) {
188
189
		char *byte = s;

190
191
192
		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
193
				_("ldif_parse_line: %s missing base64 value\n"), type );
194
			if ( !freeval ) ber_memfree( line );
195
			return( -1 );
196
197
		}

198
		byte = value->bv_val = s;
199

200
		for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) {
201
			int i;
202
			for ( i = 0; i < 4; i++ ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
203
204
				if ( p[i] != '=' && (p[i] & 0x80 ||
				    b642nib[ p[i] & 0x7f ] > 0x3f) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
205
					ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
206
207
						_("ldif_parse_line: %s: invalid base64 encoding"
						" char (%c) 0x%x\n"),
208
					    type, p[i], p[i] );
209
					if ( !freeval ) ber_memfree( line );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
210
211
212
213
214
215
216
217
218
219
220
221
222
					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] == '=' ) {
223
				value->bv_len += 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
224
225
226
227
228
229
230
				break;
			}
			nib = b642nib[ p[2] & 0x7f ];
			byte[1] |= nib >> 2;
			byte[2] = (nib & RIGHT2) << 6;
			/* fourth digit */
			if ( p[3] == '=' ) {
231
				value->bv_len += 2;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
232
233
234
235
236
237
238
				break;
			}
			nib = b642nib[ p[3] & 0x7f ];
			byte[2] |= nib;

			byte += 3;
		}
239
		s[ value->bv_len ] = '\0';
240
241

	} else if ( url ) {
242
243
244
		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
245
				_("ldif_parse_line: %s missing URL value\n"), type );
246
			if ( !freeval ) ber_memfree( line );
247
			return( -1 );
248
249
		}

250
		if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) {
251
			ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
252
				_("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
253
				type, s );
254
			if ( !freeval ) ber_memfree( line );
255
256
			return( -1 );
		}
257
		if ( freeval ) *freeval = 1;
258

Kurt Zeilenga's avatar
Kurt Zeilenga committed
259
	} else {
260
261
		value->bv_val = s;
		value->bv_len = (int) (d - s);
262
263
	}

264
265
266
267
	if ( !freeval ) {
		struct berval bv = *type;

		ber_dupbv( type, &bv );
268

269
		if( BER_BVISNULL( type )) {
270
			ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
271
				_("ldif_parse_line: type malloc failed\n"));
272
			if( url ) ber_memfree( value->bv_val );
273
			ber_memfree( line );
274
275
			return( -1 );
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
276

277
		if( !url ) {
278
279
280
			bv = *value;
			ber_dupbv( value, &bv );
			if( BER_BVISNULL( value )) {
281
282
				ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
					_("ldif_parse_line: value malloc failed\n"));
283
				ber_memfree( type->bv_val );
284
285
286
287
288
289
290
				ber_memfree( line );
				return( -1 );
			}
		}

		ber_memfree( line );
	}
291

Kurt Zeilenga's avatar
Kurt Zeilenga committed
292
293
294
295
	return( 0 );
}

/*
296
 * ldif_getline - return the next "line" (minus newline) of input from a
Kurt Zeilenga's avatar
Kurt Zeilenga committed
297
298
299
300
301
302
 * 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
303
 * ldif_parse_line() routine above.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
304
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
305
306
307
 * 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
308
309
310
 * which it updates and must be supplied on subsequent calls.
 */

Howard Chu's avatar
Howard Chu committed
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
int
ldif_countlines( LDAP_CONST char *buf )
{
	char *nl;
	int ret = 0;

	if ( !buf ) return ret;

	for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) {
		nl++;
		if ( *nl != ' ' ) ret++;
	}
	return ret;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
326
char *
327
ldif_getline( char **next )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
328
{
329
	char *line;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
330

331
332
333
334
335
336
	do {
		if ( *next == NULL || **next == '\n' || **next == '\0' ) {
			return( NULL );
		}

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

338
		while ( (*next = strchr( *next, '\n' )) != NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
339
340
341
342
343
#if CONTINUED_LINE_MARKER != '\r'
			if ( (*next)[-1] == '\r' ) {
				(*next)[-1] = CONTINUED_LINE_MARKER;
			}
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
344

Kurt Zeilenga's avatar
Kurt Zeilenga committed
345
346
			if ( (*next)[1] != ' ' ) {
				if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
347
348
349
350
					*(*next)++ = '\0';
				}
				*(*next)++ = '\0';
				break;
351
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
352
353

			**next = CONTINUED_LINE_MARKER;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
354
			(*next)[1] = CONTINUED_LINE_MARKER;
355
			(*next)++;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
356
		}
357
	} while( *line == '#' );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
358

359
	return( line );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
360
361
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
362
363
364
/* compatibility with U-Mich off by one bug */
#define LDIF_KLUDGE 1

Kurt Zeilenga's avatar
Kurt Zeilenga committed
365
void
Kurt Zeilenga's avatar
Kurt Zeilenga committed
366
ldif_sput(
Kurt Zeilenga's avatar
Kurt Zeilenga committed
367
	char **out,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
368
369
	int type,
	LDAP_CONST char *name,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
370
	LDAP_CONST char *val,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
371
	ber_len_t vlen )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
372
{
373
	const unsigned char *byte, *stop;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
374
375
376
	unsigned char	buf[3];
	unsigned long	bits;
	char		*save;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
377
	int		pad;
Howard Chu's avatar
Howard Chu committed
378
	int		namelen = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

	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++;
		}

395
		break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
396

Kurt Zeilenga's avatar
Kurt Zeilenga committed
397
398
399
	case LDIF_PUT_SEP:
		*(*out)++ = '\n';
		return;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
400
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
401
402
403
404

	/* name (attribute type) */
	if( name != NULL ) {
		/* put the name + ":" */
Howard Chu's avatar
Howard Chu committed
405
406
407
408
		namelen = strlen(name);
		strcpy(*out, name);
		*out += namelen;
		len += namelen;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
409
410
411
412
413
414

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

Hallvard Furuseth's avatar
Hallvard Furuseth committed
415
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
416
#ifdef LDAP_DEBUG
Hallvard Furuseth's avatar
Hallvard Furuseth committed
417
	else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
418
419
		assert( type == LDIF_PUT_COMMENT );
	}
Hallvard Furuseth's avatar
Hallvard Furuseth committed
420
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
421

422
423
424
425
426
	if( vlen == 0 ) {
		*(*out)++ = '\n';
		return;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
	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
467
468
	save = *out;
	savelen = len;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
469

Kurt Zeilenga's avatar
Kurt Zeilenga committed
470
	*(*out)++ = ' ';
Kurt Zeilenga's avatar
Kurt Zeilenga committed
471
472
	len++;

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

Kurt Zeilenga's avatar
Kurt Zeilenga committed
475
	if ( type == LDIF_PUT_VALUE
476
477
		&& isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
		&& isgraph( (unsigned char) val[vlen-1] )
478
479
480
#ifndef LDAP_BINARY_DEBUG
		&& strstr( name, ";binary" ) == NULL
#endif
481
#ifndef LDAP_PASSWD_DEBUG
Howard Chu's avatar
Howard Chu committed
482
483
484
485
		&& (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 */
486
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
487
	) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
488
489
		int b64 = 0;

490
		for ( byte = (const unsigned char *) val; byte < stop;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
491
492
		    byte++, len++ )
		{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
493
494
495
496
			if ( !isascii( *byte ) || !isprint( *byte ) ) {
				b64 = 1;
				break;
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
497
			if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
498
499
500
501
502
503
				*(*out)++ = '\n';
				*(*out)++ = ' ';
				len = 1;
			}
			*(*out)++ = *byte;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
504
505
506
507
508

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

Kurt Zeilenga's avatar
Kurt Zeilenga committed
511
512
513
514
515
516
	*out = save;
	*(*out)++ = ':';
	*(*out)++ = ' ';
	len = savelen + 2;

	/* convert to base 64 (3 bytes => 4 base 64 digits) */
517
	for ( byte = (const unsigned char *) val;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
518
519
520
521
522
523
524
525
526
527
528
529
		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
530
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
531
532
533

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

Kurt Zeilenga's avatar
Kurt Zeilenga committed
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
	/* 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
555
556
			}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
557
558
559
560
561
			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
562
563
564
565
566
567
568
569
			}
		}
	}
	*(*out)++ = '\n';
}


/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
570
 * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
Kurt Zeilenga's avatar
Kurt Zeilenga committed
571
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
572
573
574
575
576
577
char *
ldif_put(
	int type,
	LDAP_CONST char *name,
	LDAP_CONST char *val,
	ber_len_t vlen )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
578
579
{
    char	*buf, *p;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
580
    ber_len_t nlen;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
581

Kurt Zeilenga's avatar
Kurt Zeilenga committed
582
583
584
585
586
    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
587
		ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
588
			_("ldif_type_and_value: malloc failed!"));
589
		return NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
590
591
592
    }

    p = buf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
593
    ldif_sput( &p, type, name, val, vlen );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
594
595
596
597
    *p = '\0';

    return( buf );
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
598
599
600
601
602
603
604
605
606

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

607
608
	if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
		isgraph( (unsigned char) val[vlen-1] ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
609
610
611
612
613
614
615
616
617
618
619
620
621
622
	{
		ber_len_t i;

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

		return 0;
	}

	return 1;
}
623
624
625
626
627
628
629
630
631
632
633

/*
 * 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
634
	char        linebuf[BUFSIZ], *line, *nbufp;
635
	ber_len_t   lcur = 0, len, linesize;
636
	int         last_ch = '\n', found_entry = 0, stop, top_comment = 0;
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

	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' ) {
653
654
655
				if ( !found_entry ) {
					lcur = 0;
					top_comment = 0;
656
					continue;
657
				}
658
659
660
661
				break;
			}

			if ( !found_entry ) {
662
663
664
665
666
667
668
669
670
671
				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;
					}
672
673
674
675
676
				}
			}			
		}

		if ( *buflenp - lcur <= len ) {
Hallvard Furuseth's avatar
Hallvard Furuseth committed
677
678
			*buflenp += len + BUFSIZ;
			nbufp = ber_memrealloc( *bufp, *buflenp );
679
680
681
682
683
684
685
686
687
688
			if( nbufp == NULL ) {
				return 0;
			}
			*bufp = nbufp;
		}
		strcpy( *bufp + lcur, line );
		lcur += len;
	}

	return( found_entry );
689
}