entry.c 14.7 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* entry.c - routines for dealing with entries */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
6
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
7

Kurt Zeilenga's avatar
Kurt Zeilenga committed
8
9
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
10
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
11
12

#include <ac/ctype.h>
13
#include <ac/errno.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
14
15
16
#include <ac/socket.h>
#include <ac/string.h>

Kurt Zeilenga's avatar
Kurt Zeilenga committed
17
#include "slap.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
18
#include "ldif.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
19

Gary Williams's avatar
Gary Williams committed
20
static unsigned char	*ebuf;	/* buf returned by entry2str		 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
21
static unsigned char	*ecur;	/* pointer to end of currently used ebuf */
Gary Williams's avatar
Gary Williams committed
22
static int		emaxsize;/* max size of ebuf			 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
23

24
25
26
/*
 * Empty root entry
 */
27
const Entry slap_entry_root = { NOID, { 0, "" }, { 0, "" }, NULL, 0, { 0, "" }, NULL };
28

29
30
int entry_destroy(void)
{
Howard Chu's avatar
Howard Chu committed
31
	if ( ebuf ) free( ebuf );
32
33
34
35
36
37
	ebuf = NULL;
	ecur = NULL;
	emaxsize = 0;
	return 0;
}

38

Kurt Zeilenga's avatar
Kurt Zeilenga committed
39
Entry *
40
str2entry( char *s )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
41
{
42
	int rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
43
44
	Entry		*e;
	char		*type;
45
	struct berval	vals[2];
46
	AttributeDescription *ad;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
47
	const char *text;
48
	char	*next;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
49
50

	/*
51
52
	 * LDIF is used as the string format.
	 * An entry looks like this:
Kurt Zeilenga's avatar
Kurt Zeilenga committed
53
54
55
56
57
58
59
60
61
62
63
64
	 *
	 *	dn: <dn>\n
	 *	[<attr>:[:] <value>\n]
	 *	[<tab><continuedvalue>\n]*
	 *	...
	 *
	 * If a double colon is used after a type, it means the
	 * following value is encoded as a base 64 string.  This
	 * happens if the value contains a non-printing character
	 * or newline.
	 */

65
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
66
	LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
67
		"str2entry: \"%s\"\n", s ? s : "NULL" ));
68
#else
69
70
	Debug( LDAP_DEBUG_TRACE, "=> str2entry\n",
		s ? s : "NULL", 0, 0 );
71
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
72

Hallvard Furuseth's avatar
Hallvard Furuseth committed
73
	/* initialize reader/writer lock */
74
	e = (Entry *) ch_calloc( 1, sizeof(Entry) );
75
76

	if( e == NULL ) {
77
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
78
		LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
79
			"str2entry: entry allocation failed.\n" ));
80
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
81
		Debug( LDAP_DEBUG_ANY,
82
83
		    "<= str2entry NULL (entry allocation failed)\n",
		    0, 0, 0 );
84
#endif
85
86
87
		return( NULL );
	}

88
	/* initialize entry */
89
	e->e_id = NOID;
Hallvard Furuseth's avatar
Hallvard Furuseth committed
90

Kurt Zeilenga's avatar
Kurt Zeilenga committed
91
	/* dn + attributes */
92
	vals[1].bv_val = NULL;
93

94
	next = s;
95
	while ( (s = ldif_getline( &next )) != NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
97
98
99
		if ( *s == '\n' || *s == '\0' ) {
			break;
		}

100
		if ( ldif_parse_line( s, &type, &vals[0].bv_val, &vals[0].bv_len ) != 0 ) {
101
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
102
103
			LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
				   "str2entry:  NULL (parse_line)\n" ));
104
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
105
106
			Debug( LDAP_DEBUG_TRACE,
			    "<= str2entry NULL (parse_line)\n", 0, 0, 0 );
107
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
108
109
110
111
			continue;
		}

		if ( strcasecmp( type, "dn" ) == 0 ) {
112
			struct berval *pdn = NULL;
113

Kurt Zeilenga's avatar
Kurt Zeilenga committed
114
115
			free( type );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
116
			if ( e->e_dn != NULL ) {
117
#ifdef NEW_LOGGING
Kurt Zeilenga's avatar
Kurt Zeilenga committed
118
				LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, "str2entry: "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
119
					"entry %ld has multiple DNs \"%s\" and \"%s\"\n",
120
					(long) e->e_id, e->e_dn,
121
					vals[0].bv_val != NULL ? vals[0].bv_val : "" ));
122
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
123
				Debug( LDAP_DEBUG_ANY, "str2entry: "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
124
					"entry %ld has multiple DNs \"%s\" and \"%s\"\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
125
				    (long) e->e_id, e->e_dn,
126
					vals[0].bv_val != NULL ? vals[0].bv_val : "" );
127
#endif
128
				if( vals[0].bv_val != NULL ) free( vals[0].bv_val );
129
130
131
132
				entry_free( e );
				return NULL;
			}

133
134
			rc = dnPrettyNormal( NULL, &vals[0], &e->e_name, &e->e_nname );
			free( vals[0].bv_val );
135
136
137
138
139
140
141
142
143
144
145
146
147
148
			if( rc != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
				LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, "str2entry: "
					"entry %ld has invalid DN \"%s\"\n",
					(long) e->e_id,
					pdn->bv_val ? pdn->bv_val : "" ));
#else
				Debug( LDAP_DEBUG_ANY, "str2entry: "
					"entry %ld has invalid DN \"%s\"\n",
					(long) e->e_id,
					pdn->bv_val ? pdn->bv_val : "", 0 );
#endif
				entry_free( e );
				return NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
149
150
151
152
			}
			continue;
		}

153
154
155
156
		ad = NULL;
		rc = slap_str2ad( type, &ad, &text );

		if( rc != LDAP_SUCCESS ) {
157
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
158
			LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
159
				"str2entry:  str2ad(%s): %s\n", type, text ));
160
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
161
162
			Debug( slapMode & SLAP_TOOL_MODE
				? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE,
163
				"<= str2entry: str2ad(%s): %s\n", type, text, 0 );
164
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
165
166
			if( slapMode & SLAP_TOOL_MODE ) {
				entry_free( e );
167
				free( vals[0].bv_val );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
168
169
170
171
				free( type );
				return NULL;
			}

172
173
			rc = slap_str2undef_ad( type, &ad, &text );
			if( rc != LDAP_SUCCESS ) {
174
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
175
				LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
176
					"str2entry:  str2undef_ad(%s): %s\n", type, text ));
177
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
178
				Debug( LDAP_DEBUG_ANY,
179
180
					"<= str2entry: str2undef_ad(%s): %s\n",
						type, text, 0 );
181
#endif
182
				entry_free( e );
183
				free( vals[0].bv_val );
184
				free( type );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
185
186
187
188
189
				return NULL;
			}
		}

		if( slapMode & SLAP_TOOL_MODE ) {
190
			struct berval pval;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
191
192
			slap_syntax_validate_func *validate =
				ad->ad_type->sat_syntax->ssyn_validate;
193
194
			slap_syntax_transform_func *pretty =
				ad->ad_type->sat_syntax->ssyn_pretty;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
195

196
197
			if( pretty ) {
				rc = pretty( ad->ad_type->sat_syntax,
198
					&vals[0], &pval );
199
200
201
202
203

			} else if( validate ) {
				/*
			 	 * validate value per syntax
			 	 */
204
				rc = validate( ad->ad_type->sat_syntax, &vals[0] );
205
206

			} else {
207
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
208
				LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
209
210
					"str2entry: no validator for syntax %s\n", 
					ad->ad_type->sat_syntax->ssyn_oid ));
211
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
212
213
214
				Debug( LDAP_DEBUG_ANY,
					"str2entry: no validator for syntax %s\n",
					ad->ad_type->sat_syntax->ssyn_oid, 0, 0 );
215
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
216
				entry_free( e );
217
				free( vals[0].bv_val );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
218
219
220
221
222
				free( type );
				return NULL;
			}

			if( rc != 0 ) {
223
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
224
				LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
225
226
					"str2entry:  invalid value for syntax %s\n",
					ad->ad_type->sat_syntax->ssyn_oid ));
227
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
228
				Debug( LDAP_DEBUG_ANY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
229
230
					"str2entry: invalid value for syntax %s\n",
					ad->ad_type->sat_syntax->ssyn_oid, 0, 0 );
231
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
232
				entry_free( e );
233
				free( vals[0].bv_val );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
234
235
				free( type );
				return NULL;
236
			}
237
238

			if( pretty ) {
239
240
				free( vals[0].bv_val );
				vals[0] = pval;
241
			}
242
243
244
245
		}

		rc = attr_merge( e, ad, vals );
		if( rc != 0 ) {
246
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
247
			LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
248
				"str2entry:  NULL (attr_merge)\n" ));
249
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
250
			Debug( LDAP_DEBUG_ANY,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
251
			    "<= str2entry NULL (attr_merge)\n", 0, 0, 0 );
252
#endif
Hallvard Furuseth's avatar
Hallvard Furuseth committed
253
			entry_free( e );
254
			free( vals[0].bv_val );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
255
			free( type );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
256
257
			return( NULL );
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
258
259

		free( type );
260
		free( vals[0].bv_val );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
261
262
263
264
	}

	/* check to make sure there was a dn: line */
	if ( e->e_dn == NULL ) {
265
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
266
		LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
267
268
			"str2entry:  entry %ld has no dn.\n",
			(long) e->e_id ));
269
#else
270
		Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
271
		    (long) e->e_id, 0, 0 );
272
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
273
274
275
276
		entry_free( e );
		return( NULL );
	}

277
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
278
	LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL2,
279
		"str2entry(%s) -> 0x%lx\n", e->e_dn, (unsigned long)e ));
280
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
281
282
	Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n",
		e->e_dn, (unsigned long) e, 0 );
283
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
284
285
286
	return( e );
}

287

Kurt Zeilenga's avatar
Kurt Zeilenga committed
288
289
290
291
#define GRABSIZE	BUFSIZ

#define MAKE_SPACE( n )	{ \
		while ( ecur + (n) > ebuf + emaxsize ) { \
292
			ptrdiff_t	offset; \
Kurt Zeilenga's avatar
Kurt Zeilenga committed
293
294
295
296
297
298
			offset = (int) (ecur - ebuf); \
			ebuf = (unsigned char *) ch_realloc( (char *) ebuf, \
			    emaxsize + GRABSIZE ); \
			emaxsize += GRABSIZE; \
			ecur = ebuf + offset; \
		} \
299
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
300
301
302
303

char *
entry2str(
    Entry	*e,
304
    int		*len )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
305
306
307
{
	Attribute	*a;
	struct berval	*bv;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
308
309
	int		i;
	ber_len_t tmplen;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
310
311
312
313
314
315
316
317
318
319
320
321

	/*
	 * In string format, an entry looks like this:
	 *	dn: <dn>\n
	 *	[<attr>: <value>\n]*
	 */

	ecur = ebuf;

	/* put the dn */
	if ( e->e_dn != NULL ) {
		/* put "dn: <dn>" */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
322
		tmplen = e->e_name.bv_len;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
323
		MAKE_SPACE( LDIF_SIZE_NEEDED( 2, tmplen ));
Kurt Zeilenga's avatar
Kurt Zeilenga committed
324
		ldif_sput( (char **) &ecur, LDIF_PUT_VALUE, "dn", e->e_dn, tmplen );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
325
326
327
328
329
	}

	/* put the attributes */
	for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
		/* put "<type>:[:] <value>" line for each value */
330
331
		for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
			bv = &a->a_vals[i];
332
			tmplen = a->a_desc->ad_cname.bv_len;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
333
			MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len ));
334
			ldif_sput( (char **) &ecur, LDIF_PUT_VALUE,
335
				a->a_desc->ad_cname.bv_val,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
336
337
338
339
340
341
342
343
344
345
346
347
348
			    bv->bv_val, bv->bv_len );
		}
	}
	MAKE_SPACE( 1 );
	*ecur = '\0';
	*len = ecur - ebuf;

	return( (char *) ebuf );
}

void
entry_free( Entry *e )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
349
350
	/* free an entry structure */
	assert( e != NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
351

Kurt Zeilenga's avatar
Kurt Zeilenga committed
352
353
354
355
356
	/* e_private must be freed by the caller */
	assert( e->e_private == NULL );
	e->e_private = NULL;

	/* free DNs */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
357
358
	if ( e->e_dn != NULL ) {
		free( e->e_dn );
359
		e->e_dn = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
360
	}
361
362
	if ( e->e_ndn != NULL ) {
		free( e->e_ndn );
363
		e->e_ndn = NULL;
364
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
365

366
367
368
369
370
	if ( e->e_bv.bv_val != NULL ) {
		free( e->e_bv.bv_val );
		e->e_bv.bv_val = NULL;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
371
372
	/* free attributes */
	attrs_free( e->e_attrs );
373
	e->e_attrs = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
374

Kurt Zeilenga's avatar
Kurt Zeilenga committed
375
376
	free( e );
}
377

378
379
380
381
382
/*
 * These routines are used only by Backend.
 *
 * the Entry has three entry points (ways to find things):
 *
Gary Williams's avatar
Gary Williams committed
383
 *	by entry	e.g., if you already have an entry from the cache
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
 *			and want to delete it. (really by entry ptr)
 *	by dn		e.g., when looking for the base object of a search
 *	by id		e.g., for search candidates
 *
 * these correspond to three different avl trees that are maintained.
 */

int
entry_cmp( Entry *e1, Entry *e2 )
{
	return( e1 < e2 ? -1 : (e1 > e2 ? 1 : 0) );
}

int
entry_dn_cmp( Entry *e1, Entry *e2 )
{
	/* compare their normalized UPPERCASED dn's */
401
402
	int rc = e1->e_nname.bv_len - e2->e_nname.bv_len;
	if (rc) return rc;
403
404
405
406
407
408
409
410
411
	return( strcmp( e1->e_ndn, e2->e_ndn ) );
}

int
entry_id_cmp( Entry *e1, Entry *e2 )
{
	return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) );
}

412
#ifdef SLAPD_BDB
Kurt Zeilenga's avatar
Kurt Zeilenga committed
413

414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
/* This is like a ber_len */
static ber_len_t
entry_lenlen(ber_len_t len)
{
	if (len <= 0x7f)
		return 1;
	if (len <= 0xff)
		return 2;
	if (len <= 0xffff)
		return 3;
	if (len <= 0xffffff)
		return 4;
	return 5;
}

static void
entry_putlen(unsigned char **buf, ber_len_t len)
{
	ber_len_t lenlen = entry_lenlen(len);

	if (lenlen == 1) {
		**buf = (unsigned char) len;
	} else {
		int i;
438
		**buf = 0x80 | ((unsigned char) lenlen - 1);
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
467
468
469
470
		for (i=lenlen-1; i>0; i--) {
			(*buf)[i] = (unsigned char) len;
			len >>= 8;
		}
	}
	*buf += lenlen;
}

static ber_len_t
entry_getlen(unsigned char **buf)
{
	ber_len_t len;
	int i;

	len = *(*buf)++;
	if (len <= 0x7f)
		return len;
	i = len & 0x7f;
	len = 0;
	for (;i > 0; i--) {
		len <<= 8;
		len |= *(*buf)++;
	}
	return len;
}

/* Flatten an Entry into a buffer. The buffer is filled with just the
 * strings/bervals of all the entry components. Each field is preceded
 * by its length, encoded the way ber_put_len works. Every field is NUL
 * terminated.  The entire buffer size is precomputed so that a single
 * malloc can be performed. The entry size is also recorded,
 * to aid in entry_decode.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
471
 */
472
int entry_encode(Entry *e, struct berval *bv)
Kurt Zeilenga's avatar
Kurt Zeilenga committed
473
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
474
475
	ber_len_t siz = sizeof(Entry);
	ber_len_t len, dnlen, ndnlen;
476
477
478
	int i;
	Attribute *a;
	unsigned char *ptr;
479

480
#ifdef NEW_LOGGING
481
482
483
	LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
		"entry_encode: id: 0x%08lx  \"%s\"\n",
		(long) e->e_id, e->e_dn ));
484
#else
485
486
	Debug( LDAP_DEBUG_TRACE, "=> entry_encode(0x%08lx): %s\n",
		(long) e->e_id, e->e_dn, 0 );
487
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
488
489
	dnlen = e->e_name.bv_len;
	ndnlen = e->e_nname.bv_len;
490
	len = dnlen + ndnlen + 2;	/* two trailing NUL bytes */
491
492
	len += entry_lenlen(dnlen);
	len += entry_lenlen(ndnlen);
493
494
495
496
	for (a=e->e_attrs; a; a=a->a_next) {
		/* For AttributeDesc, we only store the attr name */
		siz += sizeof(Attribute);
		len += a->a_desc->ad_cname.bv_len+1;
497
		len += entry_lenlen(a->a_desc->ad_cname.bv_len);
498
		for (i=0; a->a_vals[i].bv_val; i++) {
499
			siz += sizeof(struct berval);
500
501
			len += a->a_vals[i].bv_len + 1;
			len += entry_lenlen(a->a_vals[i].bv_len);
502
		}
503
		len += entry_lenlen(i);
504
		siz += sizeof(struct berval);	/* empty berval at end */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
505
	}
506
507
508
509
510
511
512
	len += 1;	/* NUL byte at end */
	len += entry_lenlen(siz);
	bv->bv_len = len;
	bv->bv_val = ch_malloc(len);
	ptr = (unsigned char *)bv->bv_val;
	entry_putlen(&ptr, siz);
	entry_putlen(&ptr, dnlen);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
513
	AC_MEMCPY(ptr, e->e_dn, dnlen);
514
515
	ptr += dnlen;
	*ptr++ = '\0';
516
	entry_putlen(&ptr, ndnlen);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
517
	AC_MEMCPY(ptr, e->e_ndn, ndnlen);
518
	ptr += ndnlen;
519
	*ptr++ = '\0';
520

521
	for (a=e->e_attrs; a; a=a->a_next) {
522
		entry_putlen(&ptr, a->a_desc->ad_cname.bv_len);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
523
		AC_MEMCPY(ptr, a->a_desc->ad_cname.bv_val,
524
525
526
527
			a->a_desc->ad_cname.bv_len);
		ptr += a->a_desc->ad_cname.bv_len;
		*ptr++ = '\0';
		if (a->a_vals) {
528
		    for (i=0; a->a_vals[i].bv_val; i++);
529
		    entry_putlen(&ptr, i);
530
531
532
533
534
		    for (i=0; a->a_vals[i].bv_val; i++) {
			entry_putlen(&ptr, a->a_vals[i].bv_len);
			memcpy(ptr, a->a_vals[i].bv_val,
				a->a_vals[i].bv_len);
			ptr += a->a_vals[i].bv_len;
535
			*ptr++ = '\0';
536
537
		    }
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
538
	}
539
	*ptr = '\0';
540
541
	return 0;
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
542

543
/* Retrieve an Entry that was stored using entry_encode above.
544
545
546
547
548
 * We malloc a single block with the size stored above for the Entry
 * and all if its Attributes. We also must lookup the stored
 * attribute names to get AttributeDescriptions. To detect if the
 * attributes of an Entry are later modified, we note that e->e_attr
 * is always a constant offset from (e).
549
550
551
552
553
554
555
 *
 * Note: everything is stored in a single contiguous block, so
 * you can not free individual attributes or names from this
 * structure. Attempting to do so will likely corrupt memory.
 */
int entry_decode(struct berval *bv, Entry **e)
{
556
557
	int i, j;
	int rc;
558
	Attribute *a;
559
	Entry *x;
560
561
	const char *text;
	AttributeDescription *ad;
562
	unsigned char *ptr = (unsigned char *)bv->bv_val;
563
	BerVarray bptr;
564
565

	i = entry_getlen(&ptr);
566
	x = ch_calloc(1, i);
567
	i = entry_getlen(&ptr);
568
569
	x->e_name.bv_val = ptr;
	x->e_name.bv_len = i;
570
571
	ptr += i+1;
	i = entry_getlen(&ptr);
572
573
	x->e_nname.bv_val = ptr;
	x->e_nname.bv_len = i;
574
	ptr += i+1;
575
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
576
	LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL2,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
577
		"entry_decode: \"%s\"\n", x->e_dn ));
578
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
579
	Debug( LDAP_DEBUG_TRACE,
580
	    "entry_decode: \"%s\"\n",
581
	    x->e_dn, 0, 0 );
582
#endif
583
	x->e_bv = *bv;
584
585
586
587
588

	/* A valid entry must have at least one attr, so this
	 * pointer can never be NULL
	 */
	x->e_attrs = (Attribute *)(x+1);
589
	bptr = (BerVarray)x->e_attrs;
590
591
592
	a = NULL;

	while (i = entry_getlen(&ptr)) {
593
594
595
		struct berval bv;
		bv.bv_len = i;
		bv.bv_val = ptr;
596
597
598
599
		if (a) {
			a->a_next = (Attribute *)bptr;
		}
		a = (Attribute *)bptr;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
600
		ad = NULL;
601
		rc = slap_bv2ad( &bv, &ad, &text );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
602

603
		if( rc != LDAP_SUCCESS ) {
604
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
605
			LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
606
				"entry_decode: str2ad(%s): %s\n", ptr, text ));
607
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
608
			Debug( LDAP_DEBUG_TRACE,
609
				"<= entry_decode: str2ad(%s): %s\n", ptr, text, 0 );
610
#endif
611
			rc = slap_bv2undef_ad( &bv, &ad, &text );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
612

613
			if( rc != LDAP_SUCCESS ) {
614
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
615
				LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
616
					"entry_decode:  str2undef_ad(%s): %s\n", ptr, text));
617
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
618
				Debug( LDAP_DEBUG_ANY,
619
					"<= entry_decode: str2undef_ad(%s): %s\n",
620
						ptr, text, 0 );
621
#endif
622
				return rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
623
624
			}
		}
625
		ptr += i + 1;
626
		a->a_desc = ad;
627
		bptr = (BerVarray)(a+1);
628
		a->a_vals = bptr;
629
		a->a_flags = 0;
630
631
632
633
		j = entry_getlen(&ptr);

		while (j) {
			i = entry_getlen(&ptr);
634
635
			bptr->bv_len = i;
			bptr->bv_val = (char *)ptr;
636
637
638
			ptr += i+1;
			bptr++;
			j--;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
639
		}
Howard Chu's avatar
Howard Chu committed
640
641
642
		bptr->bv_val = NULL;
		bptr->bv_len = 0;
		bptr++;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
643
	}
644
645
	if (a)
		a->a_next = NULL;
646
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
647
	LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
648
		"entry_decode:  %s\n", x->e_dn ));
649
#else
650
	Debug(LDAP_DEBUG_TRACE, "<= entry_decode(%s)\n",
651
		x->e_dn, 0, 0 );
652
#endif
653
654
	*e = x;
	return 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
655
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
656
#endif