+int
+slapi_entry_delete_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
+{
+#ifdef LDAP_SLAPI
+ return slapi_entry_delete_values( e, type, vals );
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+int
+slapi_entry_merge_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
+{
+#ifdef LDAP_SLAPI
+ return slapi_entry_attr_merge( e, (char *)type, vals );
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+int
+slapi_entry_add_value(Slapi_Entry *e, const char *type, const Slapi_Value *value)
+{
+#ifdef LDAP_SLAPI
+ AttributeDescription *ad = NULL;
+ int rc;
+ const char *text;
+
+ rc = slap_str2ad( type, &ad, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ return -1;
+ }
+
+ rc = attr_merge_normalize_one( e, ad, (Slapi_Value *)value, NULL );
+ if ( rc != LDAP_SUCCESS ) {
+ return -1;
+ }
+
+ return 0;
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+int
+slapi_entry_add_string(Slapi_Entry *e, const char *type, const char *value)
+{
+#ifdef LDAP_SLAPI
+ Slapi_Value val;
+
+ val.bv_val = (char *)value;
+ val.bv_len = strlen( value );
+
+ return slapi_entry_add_value( e, type, &val );
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+int
+slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *value)
+{
+#ifdef LDAP_SLAPI
+ 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 );
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+
+int
+slapi_entry_attr_merge_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
+{
+#ifdef LDAP_SLAPI
+ return slapi_entry_attr_merge( e, (char *)type, vals );
+#else
+ return -1;
+#endif
+}
+
+int
+slapi_entry_first_attr( const Slapi_Entry *e, Slapi_Attr **attr )
+{
+#ifdef LDAP_SLAPI
+ if ( e == NULL ) {
+ return -1;
+ }
+
+ *attr = e->e_attrs;
+
+ return ( *attr != NULL ) ? 0 : -1;
+#else
+ return -1;
+#endif
+}
+
+int
+slapi_entry_next_attr( const Slapi_Entry *e, Slapi_Attr *prevattr, Slapi_Attr **attr )
+{
+#ifdef LDAP_SLAPI
+ if ( e == NULL ) {
+ return -1;
+ }
+
+ if ( prevattr == NULL ) {
+ return -1;
+ }
+
+ *attr = prevattr->a_next;
+
+ return ( *attr != NULL ) ? 0 : -1;
+#else
+ return -1;
+#endif
+}
+
+int
+slapi_entry_attr_replace_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
+{
+#ifdef LDAP_SLAPI
+ AttributeDescription *ad = NULL;
+ 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 );
+
+ rc = bvptr2obj( vals, &bv );
+ if ( rc != LDAP_SUCCESS ) {
+ return -1;
+ }
+
+ rc = attr_merge_normalize( e, ad, bv, NULL );
+ slapi_ch_free( (void **)&bv );
+ if ( rc != LDAP_SUCCESS ) {
+ return -1;
+ }
+
+ return 0;
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+/*
+ * 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 )
+{
+#ifdef LDAP_SLAPI
+ 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++ ) {
+ bv[j] = ber_dupbv( NULL, &attr->a_vals[j] );
+ }
+ bv[j] = NULL;
+
+ *vals = (struct berval **)bv;
+
+ return 0;
+#else /* LDAP_SLAPI */
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+char *
+slapi_dn_normalize( char *dn )
+{
+#ifdef LDAP_SLAPI
+ struct berval bdn;
+ struct berval pdn;
+
+ assert( dn != NULL );
+
+ bdn.bv_val = dn;
+ bdn.bv_len = strlen( dn );
+
+ if ( dnPretty( NULL, &bdn, &pdn, NULL ) != LDAP_SUCCESS ) {
+ return NULL;
+ }
+
+ return pdn.bv_val;
+#else /* LDAP_SLAPI */
+ return NULL;
+#endif /* LDAP_SLAPI */
+}
+
+char *
+slapi_dn_normalize_case( char *dn )
+{
+#ifdef LDAP_SLAPI
+ struct berval bdn;
+ struct berval ndn;
+
+ assert( dn != NULL );
+
+ bdn.bv_val = dn;
+ bdn.bv_len = strlen( dn );
+
+ if ( dnNormalize( 0, NULL, NULL, &bdn, &ndn, NULL ) != LDAP_SUCCESS ) {
+ return NULL;
+ }
+
+ return ndn.bv_val;
+#else /* LDAP_SLAPI */
+ return NULL;
+#endif /* LDAP_SLAPI */
+}
+
+int
+slapi_dn_issuffix(
+ char *dn,
+ char *suffix )
+{
+#ifdef LDAP_SLAPI
+ struct berval bdn, ndn;
+ struct berval bsuffix, nsuffix;
+ int rc;
+
+ assert( dn != NULL );
+ assert( suffix != NULL );
+
+ bdn.bv_val = dn;
+ bdn.bv_len = strlen( dn );
+
+ bsuffix.bv_val = suffix;
+ bsuffix.bv_len = strlen( suffix );
+
+ if ( dnNormalize( 0, NULL, NULL, &bdn, &ndn, NULL ) != LDAP_SUCCESS ) {
+ return 0;
+ }
+
+ if ( dnNormalize( 0, NULL, NULL, &bsuffix, &nsuffix, NULL )
+ != LDAP_SUCCESS )
+ {
+ slapi_ch_free( (void **)&ndn.bv_val );
+ return 0;
+ }
+
+ rc = dnIsSuffix( &ndn, &nsuffix );
+
+ slapi_ch_free( (void **)&ndn.bv_val );
+ slapi_ch_free( (void **)&nsuffix.bv_val );
+
+ return rc;
+#else /* LDAP_SLAPI */
+ return 0;
+#endif /* LDAP_SLAPI */
+}
+
+int
+slapi_dn_isparent(
+ const char *parentdn,
+ const char *childdn )
+{
+#ifdef LDAP_SLAPI
+ 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 );
+#else
+ return 0;
+#endif /* LDAP_SLAPI */
+}
+
+/*
+ * 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 )
+{
+#ifdef LDAP_SLAPI
+ struct berval dn, prettyDN;
+ struct berval parentDN;
+
+ 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 */
+
+ slapi_ch_free( (void **)&prettyDN.bv_val );
+
+ if ( parentDN.bv_len == 0 ) {
+ return NULL;
+ }
+
+ return slapi_ch_strdup( parentDN.bv_val );
+#else
+ return NULL;
+#endif /* LDAP_SLAPI */
+}
+
+/*
+ * 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
+ */
+char *slapi_dn_beparent( Slapi_PBlock *pb, const char *_dn )
+{
+#ifdef LDAP_SLAPI
+ Backend *be;
+ struct berval dn, prettyDN;
+ struct berval normalizedDN, parentDN;
+
+ if ( slapi_pblock_get( pb, SLAPI_BACKEND, (void **)&be ) != 0 )
+ be = NULL;
+
+ dn.bv_val = (char *)_dn;
+ dn.bv_len = strlen( _dn );
+
+ if ( dnPrettyNormal( NULL, &dn, &prettyDN, &normalizedDN, NULL ) != LDAP_SUCCESS ) {
+ return NULL;
+ }
+
+ if ( be != NULL && be_issuffix( be, &normalizedDN ) ) {
+ slapi_ch_free( (void **)&prettyDN.bv_val );
+ slapi_ch_free( (void **)&normalizedDN.bv_val );
+ return NULL;
+ }
+
+ dnParent( &prettyDN, &parentDN );
+
+ slapi_ch_free( (void **)&prettyDN.bv_val );
+ slapi_ch_free( (void **)&normalizedDN.bv_val );
+
+ if ( parentDN.bv_len == 0 ) {
+ return NULL;
+ }
+
+ return slapi_ch_strdup( parentDN.bv_val );
+#else
+ return NULL;
+#endif /* LDAP_SLAPI */
+}
+
+char *
+slapi_dn_ignore_case( char *dn )
+{
+#ifdef LDAP_SLAPI
+ return slapi_dn_normalize_case( dn );
+#else /* LDAP_SLAPI */
+ return NULL;
+#endif /* LDAP_SLAPI */
+}
+
+char *
+slapi_ch_malloc( unsigned long size )
+{
+#ifdef LDAP_SLAPI
+ return ch_malloc( size );
+#else /* LDAP_SLAPI */
+ return NULL;
+#endif /* LDAP_SLAPI */
+}
+
+void
+slapi_ch_free( void **ptr )
+{
+#ifdef LDAP_SLAPI
+ ch_free( *ptr );
+ *ptr = NULL;
+#endif /* LDAP_SLAPI */
+}
+
+void
+slapi_ch_free_string( char **ptr )
+{
+#ifdef LDAP_SLAPI
+ slapi_ch_free( (void **)ptr );
+#endif /* LDAP_SLAPI */
+}
+
+void
+slapi_ch_array_free( char **arrayp )
+{
+#ifdef LDAP_SLAPI
+ char **p;
+
+ if ( arrayp != NULL ) {
+ for ( p = arrayp; *p != NULL; p++ ) {
+ slapi_ch_free( (void **)p );
+ }
+ slapi_ch_free( (void **)&arrayp );
+ }
+#endif
+}
+
+struct berval *
+slapi_ch_bvdup(const struct berval *v)
+{
+#ifdef LDAP_SLAPI
+ struct berval *bv;
+
+ bv = (struct berval *) slapi_ch_malloc( sizeof(struct berval) );
+ bv->bv_len = v->bv_len;
+ bv->bv_val = slapi_ch_malloc( bv->bv_len );
+ AC_MEMCPY( bv->bv_val, v->bv_val, bv->bv_len );
+
+ return bv;
+#else
+ return NULL;
+#endif
+}
+
+struct berval **
+slapi_ch_bvecdup(const struct berval **v)