slapi_utils.c 66.7 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* $OpenLDAP$ */
2
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
4
 * Copyright 2002-2019 The OpenLDAP Foundation.
5
6
7
 * Portions Copyright 1997,2002-2003 IBM Corporation.
 * All rights reserved.
 *
8
9
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
10
11
12
13
14
 * 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>.
15
 */
16
17
18
19
20
/* ACKNOWLEDGEMENTS:
 * This work was initially developed by IBM Corporation for use in
 * IBM products and subsequently ported to OpenLDAP Software by
 * Steve Omrani.  Additional significant contributors include:
 *   Luke Howard
21
 */
22
23
24

#include "portable.h"

25
#include <ac/string.h>
Pierangelo Masarati's avatar
Pierangelo Masarati committed
26
27
28
#include <ac/stdarg.h>
#include <ac/ctype.h>
#include <ac/unistd.h>
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
29
#include <lutil.h>
30

31
32
33
#include <slap.h>
#include <slapi.h>

34
35
#include <netdb.h>

36
37
#ifdef LDAP_SLAPI

38
39
40
41
42
43
44
/*
 * server start time (should we use a struct timeval also in slapd?
 */
static struct			timeval base_time;
ldap_pvt_thread_mutex_t		slapi_hn_mutex;
ldap_pvt_thread_mutex_t		slapi_time_mutex;

45
46
47
48
49
50
51
52
53
struct slapi_mutex {
	ldap_pvt_thread_mutex_t mutex;
};

struct slapi_condvar {
	ldap_pvt_thread_cond_t cond;
	ldap_pvt_thread_mutex_t mutex;
};

54
55
static int checkBVString(const struct berval *bv)
{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
56
	ber_len_t i;
57
58
59
60
61
62
63
64
65
66
67

	for ( i = 0; i < bv->bv_len; i++ ) {
		if ( bv->bv_val[i] == '\0' )
			return 0;
	}
	if ( bv->bv_val[i] != '\0' )
		return 0;

	return 1;
}

68
69
70
71
72
73
74
75
/*
 * This function converts an array of pointers to berval objects to
 * an array of berval objects.
 */

int
bvptr2obj(
	struct berval	**bvptr, 
76
77
	BerVarray	*bvobj,
	unsigned *num )
78
79
80
81
82
83
84
85
86
87
88
89
{
	int		rc = LDAP_SUCCESS;
	int		i;
	BerVarray	tmpberval;

	if ( bvptr == NULL || *bvptr == NULL ) {
		return LDAP_OTHER;
	}

	for ( i = 0; bvptr != NULL && bvptr[i] != NULL; i++ ) {
		; /* EMPTY */
	}
90
91
	if ( num )
		*num = i;
92
93
94
95
96
97
98
99
100
101

	tmpberval = (BerVarray)slapi_ch_malloc( (i + 1)*sizeof(struct berval));
	if ( tmpberval == NULL ) {
		return LDAP_NO_MEMORY;
	} 

	for ( i = 0; bvptr[i] != NULL; i++ ) {
		tmpberval[i].bv_val = bvptr[i]->bv_val;
		tmpberval[i].bv_len = bvptr[i]->bv_len;
	}
Luke Howard's avatar
Luke Howard committed
102
103
	tmpberval[i].bv_val = NULL;
	tmpberval[i].bv_len = 0;
104
105
106
107
108
109
110
111
112
113
114

	if ( rc == LDAP_SUCCESS ) {
		*bvobj = tmpberval;
	}

	return rc;
}

Slapi_Entry *
slapi_str2entry(
	char		*s, 
115
	int		flags )
116
{
117
	return str2entry( s );
118
119
120
121
122
123
124
}

char *
slapi_entry2str(
	Slapi_Entry	*e, 
	int		*len ) 
{
125
126
	char		*ret = NULL;
	char		*s;
127

128
	ldap_pvt_thread_mutex_lock( &entry2str_mutex );
129
130
131
	s = entry2str( e, len );
	if ( s != NULL )
		ret = slapi_ch_strdup( s );
132
	ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
133
134
135
136
137
138
139
140
141
142

	return ret;
}

char *
slapi_entry_get_dn( Slapi_Entry *e ) 
{
	return e->e_name.bv_val;
}

143
144
145
146
147
148
int
slapi_x_entry_get_id( Slapi_Entry *e )
{
	return e->e_id;
}

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
static int
slapi_int_dn_pretty( struct berval *in, struct berval *out )
{
	Syntax		*syntax = slap_schema.si_syn_distinguishedName;

	assert( syntax != NULL );

	return (syntax->ssyn_pretty)( syntax, in, out, NULL );
}

static int
slapi_int_dn_normalize( struct berval *in, struct berval *out )
{
	MatchingRule	*mr = slap_schema.si_mr_distinguishedNameMatch;
	Syntax		*syntax = slap_schema.si_syn_distinguishedName;

	assert( mr != NULL );

	return (mr->smr_normalize)( 0, syntax, mr, in, out, NULL );
}

170
171
172
173
174
void 
slapi_entry_set_dn(
	Slapi_Entry	*e, 
	char		*ldn )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
175
	struct berval	dn = BER_BVNULL;
176
177
178
179

	dn.bv_val = ldn;
	dn.bv_len = strlen( ldn );

180
181
	slapi_int_dn_pretty( &dn, &e->e_name );
	slapi_int_dn_normalize( &dn, &e->e_nname );
182
183
184
185
186
}

Slapi_Entry *
slapi_entry_dup( Slapi_Entry *e ) 
{
187
	return entry_dup( e );
188
189
190
191
192
193
194
}

int 
slapi_entry_attr_delete(
	Slapi_Entry	*e, 		
	char		*type ) 
{
195
	AttributeDescription	*ad = NULL;
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
	const char		*text;

	if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
		return 1;	/* LDAP_NO_SUCH_ATTRIBUTE */
	}

	if ( attr_delete( &e->e_attrs, ad ) == LDAP_SUCCESS ) {
		return 0;	/* attribute is deleted */
	} else {
		return -1;	/* something went wrong */
	}
}

Slapi_Entry *
slapi_entry_alloc( void ) 
{
212
	return (Slapi_Entry *)entry_alloc();
213
214
215
216
217
}

void 
slapi_entry_free( Slapi_Entry *e ) 
{
218
219
	if ( e != NULL )
		entry_free( e );
220
221
222
223
224
225
226
227
}

int 
slapi_entry_attr_merge(
	Slapi_Entry	*e, 
	char		*type, 
	struct berval	**vals ) 
{
228
	AttributeDescription	*ad = NULL;
229
230
231
232
	const char		*text;
	BerVarray		bv;
	int			rc;

233
	rc = slap_str2ad( type, &ad, &text );
234
235
236
237
	if ( rc != LDAP_SUCCESS ) {
		return -1;
	}
	
238
	rc = bvptr2obj( vals, &bv, NULL );
239
240
241
242
	if ( rc != LDAP_SUCCESS ) {
		return -1;
	}
	
243
	rc = attr_merge_normalize( e, ad, bv, NULL );
244
245
246
247
248
249
250
251
252
253
254
	ch_free( bv );

	return rc;
}

int
slapi_entry_attr_find(
	Slapi_Entry	*e, 
	char		*type, 
	Slapi_Attr	**attr ) 
{
255
	AttributeDescription	*ad = NULL;
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
	const char		*text;
	int			rc;

	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return -1;
	}

	*attr = attr_find( e->e_attrs, ad );
	if ( *attr == NULL ) {
		return -1;
	}

	return 0;
}

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
char *
slapi_entry_attr_get_charptr( const Slapi_Entry *e, const char *type )
{
	AttributeDescription *ad = NULL;
	const char *text;
	int rc;
	Attribute *attr;

	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return NULL;
	}

	attr = attr_find( e->e_attrs, ad );
	if ( attr == NULL ) {
		return NULL;
	}

Luke Howard's avatar
Luke Howard committed
290
	if ( attr->a_vals != NULL && attr->a_vals[0].bv_len != 0 ) {
Luke Howard's avatar
Luke Howard committed
291
292
293
294
		const char *p;

		p = slapi_value_get_string( &attr->a_vals[0] );
		if ( p != NULL ) {
Luke Howard's avatar
Luke Howard committed
295
			return slapi_ch_strdup( p );
Luke Howard's avatar
Luke Howard committed
296
		}
297
298
299
300
301
	}

	return NULL;
}

Luke Howard's avatar
Luke Howard committed
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
int
slapi_entry_attr_get_int( const Slapi_Entry *e, const char *type )
{
	AttributeDescription *ad = NULL;
	const char *text;
	int rc;
	Attribute *attr;

	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return 0;
	}

	attr = attr_find( e->e_attrs, ad );
	if ( attr == NULL ) {
		return 0;
	}

	return slapi_value_get_int( attr->a_vals );
}

323
long
Luke Howard's avatar
Luke Howard committed
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
slapi_entry_attr_get_long( const Slapi_Entry *e, const char *type )
{
	AttributeDescription *ad = NULL;
	const char *text;
	int rc;
	Attribute *attr;

	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return 0;
	}

	attr = attr_find( e->e_attrs, ad );
	if ( attr == NULL ) {
		return 0;
	}

	return slapi_value_get_long( attr->a_vals );
}

344
unsigned int
Luke Howard's avatar
Luke Howard committed
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
slapi_entry_attr_get_uint( const Slapi_Entry *e, const char *type )
{
	AttributeDescription *ad = NULL;
	const char *text;
	int rc;
	Attribute *attr;

	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return 0;
	}

	attr = attr_find( e->e_attrs, ad );
	if ( attr == NULL ) {
		return 0;
	}

	return slapi_value_get_uint( attr->a_vals );
}

365
unsigned long
Luke Howard's avatar
Luke Howard committed
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
slapi_entry_attr_get_ulong( const Slapi_Entry *e, const char *type )
{
	AttributeDescription *ad = NULL;
	const char *text;
	int rc;
	Attribute *attr;

	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return 0;
	}

	attr = attr_find( e->e_attrs, ad );
	if ( attr == NULL ) {
		return 0;
	}

	return slapi_value_get_ulong( attr->a_vals );
}

int
slapi_entry_attr_hasvalue( Slapi_Entry *e, const char *type, const char *value )
{
	struct berval bv;
390
	AttributeDescription *ad = NULL;
Luke Howard's avatar
Luke Howard committed
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
	const char *text;
	int rc;
	Attribute *attr;
	
	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return 0;
	}

	attr = attr_find( e->e_attrs, ad );
	if ( attr == NULL ) {
		return 0;
	}

	bv.bv_val = (char *)value;
	bv.bv_len = strlen( value );

Luke Howard's avatar
Luke Howard committed
408
	return ( slapi_attr_value_find( attr, &bv ) != -1 );
Luke Howard's avatar
Luke Howard committed
409
410
}

411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
void
slapi_entry_attr_set_charptr(Slapi_Entry* e, const char *type, const char *value)
{
	AttributeDescription	*ad = NULL;
	const char		*text;
	int			rc;
	struct berval		bv;
	
	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return;
	}
	
	attr_delete ( &e->e_attrs, ad );
	if ( value != NULL ) {
		bv.bv_val = (char *)value;
		bv.bv_len = strlen(value);
428
		attr_merge_normalize_one( e, ad, &bv, NULL );
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
467
468
469
470
471
472
473
	}
}

void
slapi_entry_attr_set_int( Slapi_Entry* e, const char *type, int l)
{
	char buf[64];

	snprintf( buf, sizeof( buf ), "%d", l );
	slapi_entry_attr_set_charptr( e, type, buf );
}

void
slapi_entry_attr_set_uint( Slapi_Entry* e, const char *type, unsigned int l)
{
	char buf[64];

	snprintf( buf, sizeof( buf ), "%u", l );
	slapi_entry_attr_set_charptr( e, type, buf );
}

void
slapi_entry_attr_set_long(Slapi_Entry* e, const char *type, long l)
{
	char buf[64];

	snprintf( buf, sizeof( buf ), "%ld", l );
	slapi_entry_attr_set_charptr( e, type, buf );
}

void
slapi_entry_attr_set_ulong(Slapi_Entry* e, const char *type, unsigned long l)
{
	char buf[64];

	snprintf( buf, sizeof( buf ), "%lu", l );
	slapi_entry_attr_set_charptr( e, type, buf );
}

int
slapi_is_rootdse( const char *dn )
{
	return ( dn == NULL || dn[0] == '\0' );
}

474
int
475
slapi_entry_has_children( const Slapi_Entry *e )
476
{
477
	Slapi_PBlock *pb;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
478
479
480
481
482
483
	Backend *be = select_backend( (struct berval *)&e->e_nname, 0 );
	int rc, hasSubordinates = 0;

	if ( be == NULL || be->be_has_subordinates == 0 ) {
		return 0;
	}
484

485
	pb = slapi_pblock_new();
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
486
487
488
	if ( pb == NULL ) {
		return 0;
	}
489
	slapi_int_connection_init_pb( pb, LDAP_REQ_SEARCH );
490

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
491
492
493
494
495
496
	rc = slapi_pblock_set( pb, SLAPI_TARGET_DN, slapi_entry_get_dn(
		(Entry *) e ));
	if ( rc == LDAP_SUCCESS ) {
		pb->pb_op->o_bd = be;
		rc = be->be_has_subordinates( pb->pb_op, (Entry *) e,
			&hasSubordinates );
497
	}
498

499
	slapi_pblock_destroy( pb );
500

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
501
	return ( rc == LDAP_SUCCESS && hasSubordinates == LDAP_COMPARE_TRUE );
502
503
}

Luke Howard's avatar
Luke Howard committed
504
505
506
507
508
509
510
511
512
513
514
515
516
/*
 * Return approximate size of the entry rounded to the nearest
 * 1K. Only the size of the attribute values are counted in the
 * Sun implementation.
 *
 * http://docs.sun.com/source/816-6701-10/funcref.html#1017388
 */
size_t slapi_entry_size(Slapi_Entry *e)
{
	size_t size;
	Attribute *a;
	int i;

Pierangelo Masarati's avatar
typo?    
Pierangelo Masarati committed
517
	for ( size = 0, a = e->e_attrs; a != NULL; a = a->a_next ) {
Luke Howard's avatar
Luke Howard committed
518
519
520
521
522
523
524
525
526
527
528
		for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
			size += a->a_vals[i].bv_len + 1;
		}
	}

	size += 1023;
	size -= (size % 1024);

	return size;
}

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
/*
 * Add values to entry.
 *
 * Returns:
 *	LDAP_SUCCESS			Values added to entry
 *	LDAP_TYPE_OR_VALUE_EXISTS	One or more values exist in entry already
 *	LDAP_CONSTRAINT_VIOLATION	Any other error (odd, but it's the spec)
 */
int
slapi_entry_add_values( Slapi_Entry *e, const char *type, struct berval **vals )
{
	Modification		mod;
	const char		*text;
	int			rc;
	char			textbuf[SLAP_TEXT_BUFLEN];

	mod.sm_op = LDAP_MOD_ADD;
546
	mod.sm_flags = 0;
547
548
549
550
551
552
553
554
555
556
	mod.sm_desc = NULL;
	mod.sm_type.bv_val = (char *)type;
	mod.sm_type.bv_len = strlen( type );

	rc = slap_str2ad( type, &mod.sm_desc, &text );
	if ( rc != LDAP_SUCCESS ) {
		return rc;
	}

	if ( vals == NULL ) {
557
		/* Apparently vals can be NULL
Kurt Zeilenga's avatar
Kurt Zeilenga committed
558
559
560
		 * FIXME: sm_values = NULL ? */
		mod.sm_values = (BerVarray)ch_malloc( sizeof(struct berval) );
		mod.sm_values->bv_val = NULL;
561
		mod.sm_numvals = 0;
562

563
	} else {
564
		rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
565
566
567
568
		if ( rc != LDAP_SUCCESS ) {
			return LDAP_CONSTRAINT_VIOLATION;
		}
	}
569
	mod.sm_nvalues = NULL;
570
571
572

	rc = modify_add_values( e, &mod, 0, &text, textbuf, sizeof(textbuf) );

573
	slapi_ch_free( (void **)&mod.sm_values );
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

	return (rc == LDAP_SUCCESS) ? LDAP_SUCCESS : LDAP_CONSTRAINT_VIOLATION;
}

int
slapi_entry_add_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
{
	return slapi_entry_add_values( e, type, vals );
}

int
slapi_entry_add_valueset(Slapi_Entry *e, const char *type, Slapi_ValueSet *vs)
{
	AttributeDescription	*ad = NULL;
	const char		*text;
	int			rc;
	
	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return -1;
	}

596
	return attr_merge_normalize( e, ad, *vs, NULL );
597
598
599
600
601
602
603
604
605
606
607
}

int
slapi_entry_delete_values( Slapi_Entry *e, const char *type, struct berval **vals )
{
	Modification		mod;
	const char		*text;
	int			rc;
	char			textbuf[SLAP_TEXT_BUFLEN];

	mod.sm_op = LDAP_MOD_DELETE;
608
	mod.sm_flags = 0;
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
	mod.sm_desc = NULL;
	mod.sm_type.bv_val = (char *)type;
	mod.sm_type.bv_len = strlen( type );

	if ( vals == NULL ) {
		/* If vals is NULL, this is a NOOP. */
		return LDAP_SUCCESS;
	}
	
	rc = slap_str2ad( type, &mod.sm_desc, &text );
	if ( rc != LDAP_SUCCESS ) {
		return rc;
	}

	if ( vals[0] == NULL ) {
624
		/* SLAPI doco says LDApb_opERATIONS_ERROR but LDAP_OTHER is better */
625
		return attr_delete( &e->e_attrs, mod.sm_desc ) ? LDAP_OTHER : LDAP_SUCCESS;
626
627
	}

628
	rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
629
630
631
	if ( rc != LDAP_SUCCESS ) {
		return LDAP_CONSTRAINT_VIOLATION;
	}
632
	mod.sm_nvalues = NULL;
633
634
635

	rc = modify_delete_values( e, &mod, 0, &text, textbuf, sizeof(textbuf) );

636
	slapi_ch_free( (void **)&mod.sm_values );
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

	return rc;
}

int
slapi_entry_delete_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
{
	return slapi_entry_delete_values( e, type, vals );
}

int
slapi_entry_merge_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
{
	return slapi_entry_attr_merge( e, (char *)type, vals );
}

int
slapi_entry_add_value(Slapi_Entry *e, const char *type, const Slapi_Value *value)
{
	AttributeDescription	*ad = NULL;
	int 			rc;
	const char		*text;

	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return -1;
	}

665
	rc = attr_merge_normalize_one( e, ad, (Slapi_Value *)value, NULL );
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
	if ( rc != LDAP_SUCCESS ) {
		return -1;
	}

	return 0;
}

int
slapi_entry_add_string(Slapi_Entry *e, const char *type, const char *value)
{
	Slapi_Value val;

	val.bv_val = (char *)value;
	val.bv_len = strlen( value );

	return slapi_entry_add_value( e, type, &val );
}

int
slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *value)
{
	Slapi_Value *vals[2];
	Slapi_Value val;

	val.bv_val = (char *)value;
	val.bv_len = strlen( value );
	vals[0] = &val;
	vals[1] = NULL;

	return slapi_entry_delete_values_sv( e, type, vals );	
}

Luke Howard's avatar
Luke Howard committed
698
699
700
701
702
703
int
slapi_entry_attr_merge_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
{
	return slapi_entry_attr_merge( e, (char *)type, vals );
}

704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
int
slapi_entry_first_attr( const Slapi_Entry *e, Slapi_Attr **attr )
{
	if ( e == NULL ) {
		return -1;
	}

	*attr = e->e_attrs;

	return ( *attr != NULL ) ? 0 : -1;
}

int
slapi_entry_next_attr( const Slapi_Entry *e, Slapi_Attr *prevattr, Slapi_Attr **attr )
{
	if ( e == NULL ) {
		return -1;
	}

	if ( prevattr == NULL ) {
		return -1;
	}

	*attr = prevattr->a_next;

	return ( *attr != NULL ) ? 0 : -1;
}

Luke Howard's avatar
Luke Howard committed
732
733
734
int
slapi_entry_attr_replace_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
{
735
	AttributeDescription *ad = NULL;
Luke Howard's avatar
Luke Howard committed
736
737
738
739
740
741
742
743
744
745
746
	const char *text;
	int rc;
	BerVarray bv;
	
	rc = slap_str2ad( type, &ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		return 0;
	}

	attr_delete( &e->e_attrs, ad );

747
	rc = bvptr2obj( vals, &bv, NULL );
Luke Howard's avatar
Luke Howard committed
748
749
750
751
	if ( rc != LDAP_SUCCESS ) {
		return -1;
	}
	
752
	rc = attr_merge_normalize( e, ad, bv, NULL );
Luke Howard's avatar
Luke Howard committed
753
754
755
756
757
758
759
760
	slapi_ch_free( (void **)&bv );
	if ( rc != LDAP_SUCCESS ) {
		return -1;
	}
	
	return 0;
}

761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
/* 
 * FIXME -- The caller must free the allocated memory. 
 * In Netscape they do not have to.
 */
int 
slapi_attr_get_values(
	Slapi_Attr	*attr, 
	struct berval	***vals ) 
{
	int		i, j;
	struct berval	**bv;

	if ( attr == NULL ) {
		return 1;
	}

	for ( i = 0; attr->a_vals[i].bv_val != NULL; i++ ) {
		; /* EMPTY */
	}

	bv = (struct berval **)ch_malloc( (i + 1) * sizeof(struct berval *) );
	for ( j = 0; j < i; j++ ) {
783
		bv[j] = ber_dupbv( NULL, &attr->a_vals[j] );
784
785
786
787
788
789
790
791
792
793
794
795
	}
	bv[j] = NULL;
	
	*vals = (struct berval **)bv;

	return 0;
}

char *
slapi_dn_normalize( char *dn ) 
{
	struct berval	bdn;
796
	struct berval	pdn;
797
798
799
800
801
802

	assert( dn != NULL );
	
	bdn.bv_val = dn;
	bdn.bv_len = strlen( dn );

803
	if ( slapi_int_dn_pretty( &bdn, &pdn ) != LDAP_SUCCESS ) {
Luke Howard's avatar
Luke Howard committed
804
805
		return NULL;
	}
806

807
	return pdn.bv_val;
808
809
810
811
812
}

char *
slapi_dn_normalize_case( char *dn ) 
{
813
814
815
816
817
818
819
820
	struct berval	bdn;
	struct berval	ndn;

	assert( dn != NULL );
	
	bdn.bv_val = dn;
	bdn.bv_len = strlen( dn );

821
	if ( slapi_int_dn_normalize( &bdn, &ndn ) != LDAP_SUCCESS ) {
822
823
824
825
		return NULL;
	}

	return ndn.bv_val;
826
827
828
829
830
831
832
833
834
}

int 
slapi_dn_issuffix(
	char		*dn, 
	char		*suffix )
{
	struct berval	bdn, ndn;
	struct berval	bsuffix, nsuffix;
835
	int rc;
836
837
838
839
840
841
842
843
844
845

	assert( dn != NULL );
	assert( suffix != NULL );

	bdn.bv_val = dn;
	bdn.bv_len = strlen( dn );

	bsuffix.bv_val = suffix;
	bsuffix.bv_len = strlen( suffix );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
846
	if ( dnNormalize( 0, NULL, NULL, &bdn, &ndn, NULL ) != LDAP_SUCCESS ) {
847
848
849
		return 0;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
850
851
852
	if ( dnNormalize( 0, NULL, NULL, &bsuffix, &nsuffix, NULL )
		!= LDAP_SUCCESS )
	{
853
854
855
856
857
		slapi_ch_free( (void **)&ndn.bv_val );
		return 0;
	}

	rc = dnIsSuffix( &ndn, &nsuffix );
858

859
860
861
862
	slapi_ch_free( (void **)&ndn.bv_val );
	slapi_ch_free( (void **)&nsuffix.bv_val );

	return rc;
863
864
}

865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
int
slapi_dn_isparent(
	const char	*parentdn,
	const char	*childdn )
{
	struct berval	assertedParentDN, normalizedAssertedParentDN;
	struct berval	childDN, normalizedChildDN;
	struct berval	normalizedParentDN;
	int		match;

	assert( parentdn != NULL );
	assert( childdn != NULL );

	assertedParentDN.bv_val = (char *)parentdn;
	assertedParentDN.bv_len = strlen( parentdn );

	if ( dnNormalize( 0, NULL, NULL, &assertedParentDN,
		&normalizedAssertedParentDN, NULL ) != LDAP_SUCCESS )
	{
		return 0;
	}

	childDN.bv_val = (char *)childdn;
	childDN.bv_len = strlen( childdn );

	if ( dnNormalize( 0, NULL, NULL, &childDN,
		&normalizedChildDN, NULL ) != LDAP_SUCCESS )
	{
		slapi_ch_free( (void **)&normalizedAssertedParentDN.bv_val );
		return 0;
	}

	dnParent( &normalizedChildDN, &normalizedParentDN );

	if ( dnMatch( &match, 0, slap_schema.si_syn_distinguishedName, NULL,
		&normalizedParentDN, (void *)&normalizedAssertedParentDN ) != LDAP_SUCCESS )
	{
		match = -1;
	}

	slapi_ch_free( (void **)&normalizedAssertedParentDN.bv_val );
	slapi_ch_free( (void **)&normalizedChildDN.bv_val );

	return ( match == 0 );
}

/*
 * Returns DN of the parent entry, or NULL if the DN is
 * an empty string or NULL, or has no parent.
 */
char *
slapi_dn_parent( const char *_dn )
{
	struct berval	dn, prettyDN;
	struct berval	parentDN;
Luke Howard's avatar
Luke Howard committed
920
	char		*ret;
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939

	if ( _dn == NULL ) {
		return NULL;
	}

	dn.bv_val = (char *)_dn;
	dn.bv_len = strlen( _dn );

	if ( dn.bv_len == 0 ) {
		return NULL;
	}

	if ( dnPretty( NULL, &dn, &prettyDN, NULL ) != LDAP_SUCCESS ) {
		return NULL;
	}

	dnParent( &prettyDN, &parentDN ); /* in-place */

	if ( parentDN.bv_len == 0 ) {
Luke Howard's avatar
Luke Howard committed
940
		slapi_ch_free_string( &prettyDN.bv_val );
941
942
943
		return NULL;
	}

Luke Howard's avatar
Luke Howard committed
944
945
946
947
	ret = slapi_ch_strdup( parentDN.bv_val );
	slapi_ch_free_string( &prettyDN.bv_val );

	return ret;
948
949
}

Luke Howard's avatar
Luke Howard committed
950
951
952
953
954
955
956
957
958
959
960
961
962
int slapi_dn_isbesuffix( Slapi_PBlock *pb, char *ldn )
{
	struct berval	ndn;
	Backend		*be;

	if ( slapi_is_rootdse( ldn ) ) {
		return 0;
	}

	/* according to spec should already be normalized */
	ndn.bv_len = strlen( ldn );
	ndn.bv_val = ldn;

963
	be = select_backend( &pb->pb_op->o_req_ndn, 0 );
Luke Howard's avatar
Luke Howard committed
964
965
966
967
968
969
970
	if ( be == NULL ) {
		return 0;
	}

	return be_issuffix( be, &ndn );
}

971
972
973
974
975
/*
 * Returns DN of the parent entry; or NULL if the DN is
 * an empty string, if the DN has no parent, or if the
 * DN is the suffix of the backend database
 */
Luke Howard's avatar
Luke Howard committed
976
char *slapi_dn_beparent( Slapi_PBlock *pb, const char *ldn )
977
978
979
980
{
	Backend 	*be;
	struct berval	dn, prettyDN;
	struct berval	normalizedDN, parentDN;
Luke Howard's avatar
Luke Howard committed
981
	char		*parent = NULL;
982

Luke Howard's avatar
Luke Howard committed
983
	if ( pb == NULL ) {
Luke Howard's avatar
Luke Howard committed
984
		return NULL;
Luke Howard's avatar
Luke Howard committed
985
	}
Luke Howard's avatar
Luke Howard committed
986

987
988
	PBLOCK_ASSERT_OP( pb, 0 );

Luke Howard's avatar
Luke Howard committed
989
	if ( slapi_is_rootdse( ldn ) ) {
Luke Howard's avatar
Luke Howard committed
990
991
		return NULL;
	}
992

Luke Howard's avatar
Luke Howard committed
993
994
	dn.bv_val = (char *)ldn;
	dn.bv_len = strlen( ldn );
995
996
997
998
999

	if ( dnPrettyNormal( NULL, &dn, &prettyDN, &normalizedDN, NULL ) != LDAP_SUCCESS ) {
		return NULL;
	}

1000
	be = select_backend( &pb->pb_op->o_req_ndn, 0 );
For faster browsing, not all history is shown. View entire blame