int opattrs;
AccessControlState acl_state = ACL_STATE_INIT;
#ifdef LDAP_SLAPI
- /* Support virtual attribute plugins. */
- Slapi_PBlock *pb = op->o_pb;
- Slapi_AttrSet *vattrs = NULL;
+ /* Support for computed attribute plugins */
+ computed_attr_context ctx;
+ AttributeName *anp;
#endif
AttributeDescription *ad_entry = slap_schema.si_ad_entry;
}
}
-#if defined( LDAP_SLAPI )
- /* Add virtual attributes */
- vattrs = slapi_x_attrset_new();
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, (void *)e );
- slapi_pblock_set( pb, SLAPI_PLUGIN_OPATTR_COALESCE_DATA, (void *)vattrs );
- rc = doPluginFNs( be, SLAPI_PLUGIN_OPATTR_COALESCE_FN, pb );
- if ( rc == 0 ) {
- /*
- * Re-fetch this to be safe; plugin could have freed and
- * changed it, although it shouldn't.
- */
- rc = slapi_pblock_get( pb, SLAPI_PLUGIN_OPATTR_COALESCE_DATA, (void **)&vattrs );
- if ( rc != 0 ) {
- /* Something bad happened. */
- vattrs = NULL;
- }
- }
-
- /* Now, send the virtual attributes. */
- if ( vattrs != NULL ) {
- for (a = *vattrs, j = 0; a != NULL; a = a->a_next, j++ ) {
- AttributeDescription *desc = a->a_desc;
-
- if ( attrs == NULL ) {
- /* all attrs request, skip operational attributes */
- if( is_at_operational( desc->ad_type ) ) {
- continue;
- }
-
- } else {
- /* specific attrs requested */
- if( is_at_operational( desc->ad_type ) ) {
- if( !opattrs && !ad_inlist( desc, attrs ) ) {
- continue;
- }
- } else {
- if (!userattrs && !ad_inlist( desc, attrs ) )
- {
- continue;
- }
- }
- }
-
- if ( ! access_allowed( be, conn, op, e, desc, NULL,
- ACL_READ, &acl_state ) )
- {
-#ifdef NEW_LOGGING
- LDAP_LOG( ACL, INFO,
- "send_search_entry: conn %lu "
- "access to attribute %s not allowed\n",
- op->o_connid, desc->ad_cname.bv_val, 0 );
-#else
- Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s "
- "not allowed\n",
- desc->ad_cname.bv_val, 0, 0 );
-#endif
-
- continue;
- }
-
- rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
- if ( rc == -1 ) {
-#ifdef NEW_LOGGING
- LDAP_LOG( OPERATION, ERR,
- "send_search_entry: conn %lu "
- "ber_printf failed\n", op->o_connid, 0, 0 );
-#else
- Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
-#endif
-
- ber_free_buf( ber );
- send_ldap_result( conn, op, LDAP_OTHER,
- NULL, "encoding description error", NULL, NULL );
-
- attrs_free( aa );
- goto error_return;
- }
-
- if ( ! attrsonly ) {
- for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
- if ( ! access_allowed( be, conn, op, e,
- desc, &a->a_vals[i], ACL_READ, &acl_state ) )
- {
-#ifdef NEW_LOGGING
- LDAP_LOG( ACL, INFO,
- "send_search_entry: conn %lu "
- "access to %s, value %d not allowed\n",
- op->o_connid, desc->ad_cname.bv_val, i );
-#else
- Debug( LDAP_DEBUG_ACL,
- "acl: access to attribute %s, "
- "value %d not allowed\n",
- desc->ad_cname.bv_val, i, 0 );
-#endif
-
- continue;
- }
-
- if ( op->vrFilter && e_flags[j][i] == 0 ){
- continue;
- }
-
- if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
-#ifdef NEW_LOGGING
- LDAP_LOG( OPERATION, ERR,
- "send_search_entry: conn %lu ber_printf failed\n",
- op->o_connid, 0, 0 );
-#else
- Debug( LDAP_DEBUG_ANY,
- "ber_printf failed\n", 0, 0, 0 );
-#endif
-
- ber_free_buf( ber );
- send_ldap_result( conn, op, LDAP_OTHER,
- NULL, "encoding values error",
- NULL, NULL );
-
- attrs_free( aa );
- goto error_return;
- }
- }
- }
-
- if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
-#ifdef NEW_LOGGING
- LDAP_LOG( OPERATION, ERR,
- "send_search_entry: conn %lu ber_printf failed\n",
- op->o_connid, 0, 0 );
-#else
- Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
-#endif
-
- ber_free_buf( ber );
- send_ldap_result( conn, op, LDAP_OTHER,
- NULL, "encode end error", NULL, NULL );
+#ifdef LDAP_SLAPI
+ /* Support Sun ONE DS 5.x computed attributes */
- attrs_free( aa );
- goto error_return;
+ /*
+ * First, setup the computed attribute context that is
+ * passed to all plugins.
+ */
+ ctx.cac_pb = op->o_pb;
+ ctx.cac_attrs = attrs;
+ ctx.cac_attrsonly = attrsonly;
+ ctx.cac_userattrs = userattrs;
+ ctx.cac_opattrs = opattrs;
+ ctx.cac_acl_state = acl_state;
+ ctx.cac_private = (void *)ber;
+
+ /*
+ * For each client requested attribute, call the plugins.
+ */
+ if ( attrs != NULL ) {
+ for ( anp = attrs; anp->an_name.bv_val != NULL; anp++ ) {
+ rc = compute_evaluator( &ctx, anp->an_name.bv_val, e, slapi_x_compute_output_ber );
+ if ( rc == 1 ) {
+ break;
}
}
- slapi_x_attrset_free( &vattrs );
- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
- slapi_pblock_set( pb, SLAPI_PLUGIN_OPATTR_COALESCE_DATA, NULL );
+ } else {
+ rc = compute_evaluator( &ctx, "*", e, slapi_x_compute_output_ber );
+ }
+ if ( rc == 1 ) {
+ ber_free_buf( ber );
+ send_ldap_result( conn, op, LDAP_OTHER,
+ NULL, "computed attribute error", NULL, NULL );
+ goto error_return;
}
#endif /* LDAP_SLAPI */
}
rc = loadPlugin( pPlugin, path, initfunc, TRUE, NULL, &hdLoadHandle );
+ if ( rc != 0 ) {
+ rc = LDAP_OTHER;
+ goto done;
+ }
done:
if ( rc != LDAP_SUCCESS && pPlugin != NULL ) {
return rc;
}
-
+/*
+ * Special support for computed attribute plugins
+ */
int
doPluginFNs(
Backend *be,
* backend); same logic as above.
*/
if ( be != NULL ) {
- rc = getAllPluginFuncs( be, funcType, &tmpPlugin );
+ rc = getAllPluginFuncs( NULL, funcType, &tmpPlugin );
if ( rc != LDAP_SUCCESS || tmpPlugin == NULL )
return 0;
for ( pGetPlugin = tmpPlugin; *pGetPlugin != NULL; pGetPlugin++ ) {
iType = SLAPI_PLUGIN_POSTOPERATION;
} else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
iType = SLAPI_PLUGIN_EXTENDEDOP;
- } else if ( strcasecmp( argv[1], "opattrsp" ) == 0 ) {
- iType = SLAPI_PLUGIN_OPATTR_SP;
+ } else if ( strcasecmp( argv[1], "object" ) == 0 ) {
+ iType = SLAPI_PLUGIN_OBJECT;
} else {
fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
fname, lineno, argv[1] );
if ( iType == SLAPI_PLUGIN_PREOPERATION ||
iType == SLAPI_PLUGIN_EXTENDEDOP ||
- iType == SLAPI_PLUGIN_POSTOPERATION ||
- iType == SLAPI_PLUGIN_OPATTR_SP ) {
+ iType == SLAPI_PLUGIN_POSTOPERATION ) {
int rc;
Slapi_PBlock *pPlugin;
typedef struct slapi_pblock Slapi_PBlock;
typedef struct slap_entry Slapi_Entry;
typedef struct slap_attr Slapi_Attr;
-typedef struct slap_attr * Slapi_AttrSet;
typedef struct berval Slapi_Value;
typedef BerVarray Slapi_ValueSet;
typedef Filter Slapi_Filter;
#define SLAPI_PLUGIN_PWD_STORAGE_SCHEME 14
#define SLAPI_PLUGIN_VATTR_SP 15
#define SLAPI_PLUGIN_REVER_PWD_STORAGE_SCHEME 16
-/*
- * Because the Sun ONE DS virtual attribute service
- * is quite complicated, we've added a "lightweight"
- * virtual attribute service. Virtual attribute
- * plugins are called for each search result;
- * they should examine the list of attributes
- * requested to minimise the performance impact.
- */
-#define SLAPI_PLUGIN_OPATTR_SP 17
#define SLAPI_PLUGIN_EXTENDED_SENT_RESULT -1
#define SLAPI_PLUGIN_EXTENDED_NOT_HANDLED -2
#define SLAPI_RESULT_TEXT 882
#define SLAPI_RESULT_MATCHED 883
-/* Virtual attribute service provider */
-#define SLAPI_PLUGIN_OPATTR_COALESCE_DATA 900
-/* Pointer to a Slapi_AttrSet */
-#define SLAPI_PLUGIN_OPATTR_COALESCE_FN 901
-
#define SLAPI_PLUGIN_SYNTAX_FLAG_ORKEYS 1
#define SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING 2
#define SLAPI_PLUGIN_AUDIT_DATA 1100
#define SLAPI_PLUGIN_AUDIT_FN 1101
+/* DS 5.x Computed Attribute Callbacks (not exposed) */
+#define SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN 1200
+#define SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN 1201
+
#define SLAPI_MANAGEDSAIT 1000
#define SLAPI_CONFIG_FILENAME 40
case SLAPI_RESULT_CODE:
case SLAPI_RESULT_TEXT:
case SLAPI_RESULT_MATCHED:
- case SLAPI_PLUGIN_OPATTR_COALESCE_FN:
- case SLAPI_PLUGIN_OPATTR_COALESCE_DATA:
+ case SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN:
+ case SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN:
return LDAP_SUCCESS;
default:
return INVALID_PARAM;
#endif
}
-/*
- * Attribute sets are an OpenLDAP extension for the
- * virtual operational attribute coalescing plugin
- *
- * Subject to going away very soon; do not use
- */
-Slapi_AttrSet *slapi_x_attrset_new( void )
-{
-#ifdef LDAP_SLAPI
- Slapi_AttrSet *a;
-
- /*
- * Like a Slapi_ValueSet, a Slapi_AttrSet is a container
- * for objects: we need this because it may be initially
- * empty.
- */
- a = (Slapi_AttrSet *)slapi_ch_malloc( sizeof( *a ) );
- *a = NULL;
-
- return a;
-#else
- return NULL;
-#endif
-}
-
-Slapi_AttrSet *slapi_x_attrset_init( Slapi_AttrSet *as, Slapi_Attr *a )
-{
-#ifdef LDAP_SLAPI
- *as = a;
- a->a_next = NULL;
-
- return as;
-#else
- return NULL;
-#endif
-}
-
-void slapi_x_attrset_free( Slapi_AttrSet **pAs )
-{
-#ifdef LDAP_SLAPI
- Slapi_AttrSet *as = *pAs;
-
- if ( as != NULL ) {
- attrs_free( *as );
- slapi_ch_free( (void **)pAs );
- }
-#endif
-}
-
-Slapi_AttrSet *slapi_x_attrset_dup( Slapi_AttrSet *as )
-{
-#ifdef LDAP_SLAPI
- Slapi_AttrSet *newAs = slapi_x_attrset_new();
-
- if ( *as != NULL )
- *newAs = attrs_dup( *as );
-
- return newAs;
-#else
- return NULL;
-#endif
-}
-
-int slapi_x_attrset_add_attr( Slapi_AttrSet *as, Slapi_Attr *a )
-{
-#ifdef LDAP_SLAPI
- Slapi_Attr *nextAttr;
-
- if ( as == NULL || a == NULL )
- return -1;
-
- if ( *as == NULL ) {
- /* First attribute */
- nextAttr = NULL;
- (*as) = a;
- } else {
- /* Non-first attribute */
- nextAttr = (*as)->a_next;
- (*as)->a_next = a;
- }
-
- a->a_next = nextAttr;
-
- return 0;
-#else
- return -1;
-#endif
-}
-
-int slapi_x_attrset_add_attr_copy( Slapi_AttrSet *as, Slapi_Attr *a )
-{
-#ifdef LDAP_SLAPI
- Slapi_Attr *adup;
-
- adup = slapi_attr_dup( a );
- return slapi_x_attrset_add_attr( as, adup );
-#else
- return -1;
-#endif
-}
-
-int slapi_x_attrset_find( Slapi_AttrSet *as, const char *type, Slapi_Attr **attr )
-{
-#ifdef LDAP_SLAPI
- AttributeDescription *ad = NULL;
- const char *text;
-
- if ( as == NULL || *as == NULL ) {
- return -1;
- }
-
- if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
- return -1;
- }
- *attr = attrs_find( *as, ad );
- return ( *attr == NULL ) ? -1 : 0;
-#else
- return -1;
-#endif
-}
-
-int slapi_x_attrset_merge( Slapi_AttrSet *as, const char *type, Slapi_ValueSet *vals )
-{
-#ifdef LDAP_SLAPI
- AttributeDescription *ad = NULL;
- Slapi_AttrSet *a;
- const char *text;
-
- if ( vals == NULL || *vals == NULL ) {
- /* Must have something to add. */
- return -1;
- }
-
- if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
- return -1;
- }
-
- for ( a = as; *a != NULL; a = &(*a)->a_next ) {
- if ( ad_cmp( (*a)->a_desc, ad ) == 0 ) {
- break;
- }
- }
-
- if ( *a == NULL ) {
- *a = (Slapi_Attr *) slapi_ch_malloc( sizeof(Attribute) );
- (*a)->a_desc = ad;
- (*a)->a_vals = NULL;
- (*a)->a_next = NULL;
- (*a)->a_flags = 0;
- }
-
- return value_add ( &(*a)->a_vals, *vals );
-#else
- return -1;
-#endif
-}
-
-int slapi_x_attrset_merge_bervals( Slapi_AttrSet *as, const char *type, struct berval **vals )
-{
-#ifdef LDAP_SLAPI
- BerVarray vp;
- int rc;
-
- if ( bvptr2obj( vals, &vp ) != LDAP_SUCCESS ) {
- return -1;
- }
- rc = slapi_x_attrset_merge( as, type, &vp );
- slapi_ch_free( (void **)&vp );
-
- return rc;
-#else
- return -1;
-#endif
-}
-
-int slapi_x_attrset_delete( Slapi_AttrSet *as, const char *type )
-{
-#ifdef LDAP_SLAPI
- AttributeDescription *ad = NULL;
- const char *text;
-
- if ( as == NULL ) {
- return -1;
- }
-
- if ( *as == NULL ) {
- return -1;
- }
-
- if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
- return -1;
- }
-
- if ( attr_delete( as, ad ) != LDAP_SUCCESS ) {
- return -1;
- }
-
- return 0;
-#else
- return -1;
-#endif
-}
-
/*
* Synthesise an LDAPMod array from a Modifications list to pass
* to SLAPI. This synthesis is destructive and as such the
#endif /* LDAP_SLAPI */
}
+/*
+ * Sun ONE DS 5.x computed attribute support
+ */
+
+/*
+ * Write the computed attribute to a BerElement.
+ */
+int slapi_x_compute_output_ber(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e)
+{
+#ifdef LDAP_SLAPI
+ Backend *be = NULL;
+ Connection *conn = NULL;
+ Operation *op = NULL;
+ BerElement *ber;
+ AttributeDescription *desc;
+ int rc;
+ int i;
+
+ if ( c == NULL ) {
+ return 1;
+ }
+
+ if ( a == NULL ) {
+ return 1;
+ }
+
+ if ( e == NULL ) {
+ return 1;
+ }
+
+ rc = slapi_pblock_get( c->cac_pb, SLAPI_BACKEND, (void *)&be );
+ if ( rc != 0 ) {
+ be = NULL; /* no backend for root DSE */
+ }
+
+ rc = slapi_pblock_get( c->cac_pb, SLAPI_CONNECTION, (void *)&conn );
+ if ( rc != 0 || conn == NULL ) {
+ return rc;
+ }
+
+ rc = slapi_pblock_get( c->cac_pb, SLAPI_OPERATION, (void *)&op );
+ if ( rc != 0 || op == NULL ) {
+ return rc;
+ }
+
+ ber = (BerElement *)c->cac_private;
+ desc = a->a_desc;
+
+ if ( c->cac_attrs == NULL ) {
+ /* All attrs request, skip operational attributes */
+ if ( is_at_operational( desc->ad_type ) ) {
+ return 0;
+ }
+ } else {
+ /* Specific attrs requested */
+ if ( is_at_operational( desc->ad_type ) ) {
+ if ( !c->cac_opattrs && !ad_inlist( desc, c->cac_attrs ) ) {
+ return 0;
+ }
+ } else {
+ if ( !c->cac_userattrs && !ad_inlist( desc, c->cac_attrs ) ) {
+ return 0;
+ }
+ }
+ }
+
+ if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_READ, &c->cac_acl_state) ) {
+ slapi_log_error( SLAPI_LOG_ACL, "SLAPI_COMPUTE",
+ "acl: access to attribute %s not allowed\n",
+ desc->ad_cname.bv_val );
+ return 0;
+ }
+
+ rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
+ if (rc == -1 ) {
+ slapi_log_error( SLAPI_LOG_BER, "SLAPI_COMPUTE",
+ "ber_printf failed\n");
+ return 1;
+ }
+
+ if ( !c->cac_attrsonly ) {
+ for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
+ if ( !access_allowed( be, conn, op, e,
+ desc, &a->a_vals[i], ACL_READ, &c->cac_acl_state)) {
+ slapi_log_error( SLAPI_LOG_ACL, "SLAPI_COMPUTE",
+ "slapi_x_compute_output_ber: conn %lu "
+ "acl: access to %s, value %d not allowed\n",
+ op->o_connid, desc->ad_cname.bv_val, i );
+ continue;
+ }
+
+ if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
+ slapi_log_error( SLAPI_LOG_BER, "SLAPI_COMPUTE",
+ "ber_printf failed\n");
+ return 1;
+ }
+ }
+ }
+
+ if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
+ slapi_log_error( SLAPI_LOG_BER, "SLAPI_COMPUTE",
+ "ber_printf failed\n" );
+ return 1;
+ }
+
+ return 0;
+#else
+ return 1;
+#endif
+}
+
+int slapi_compute_add_evaluator(slapi_compute_callback_t function)
+{
+#ifdef LDAP_SLAPI
+ Slapi_PBlock *pPlugin = NULL;
+ int rc;
+
+ pPlugin = slapi_pblock_new();
+ if ( pPlugin == NULL ) {
+ rc = LDAP_NO_MEMORY;
+ goto done;
+ }
+
+ rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)SLAPI_PLUGIN_OBJECT );
+ if ( rc != LDAP_SUCCESS ) {
+ goto done;
+ }
+
+ rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN, (void *)function );
+ if ( rc != LDAP_SUCCESS ) {
+ goto done;
+ }
+
+ rc = insertPlugin( NULL, pPlugin );
+ if ( rc != 0 ) {
+ rc = LDAP_OTHER;
+ goto done;
+ }
+
+done:
+ if ( rc != LDAP_SUCCESS ) {
+ if ( pPlugin != NULL ) {
+ slapi_pblock_destroy( pPlugin );
+ }
+ return -1;
+ }
+
+ return 0;
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+int slapi_compute_add_search_rewriter(slapi_search_rewrite_callback_t function)
+{
+#ifdef LDAP_SLAPI
+ return -1;
+#else
+ return -1;
+#endif
+}
+
+/*
+ * Call compute evaluators
+ */
+int compute_evaluator(computed_attr_context *c, char *type, Slapi_Entry *e, slapi_compute_output_t outputfn)
+{
+#ifdef LDAP_SLAPI
+ int rc = 0;
+ slapi_compute_callback_t *pGetPlugin, *tmpPlugin;
+
+ rc = getAllPluginFuncs( NULL, SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN, (SLAPI_FUNC **)&tmpPlugin );
+ if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
+ /* Nothing to do; front-end should ignore. */
+ return 0;
+ }
+
+ for ( pGetPlugin = tmpPlugin; *pGetPlugin != NULL; pGetPlugin++ ) {
+ /*
+ * -1: no attribute matched requested type
+ * 0: one attribute matched
+ * >0: error happened
+ */
+ rc = (*pGetPlugin)( c, type, e, outputfn );
+ if ( rc > 0 ) {
+ break;
+ }
+ }
+
+ slapi_ch_free( (void **)&tmpPlugin );
+
+ return rc;
+#else
+ return 1;
+#endif /* LDAP_SLAPI */
+}
+
+int compute_rewrite_search_filter(Slapi_PBlock *pb)
+{
+#ifdef LDAP_SLAPI
+ Backend *be;
+ int rc;
+
+ rc = slapi_pblock_get( pb, SLAPI_BACKEND, (void *)&be );
+ if ( rc != 0 ) {
+ return rc;
+ }
+
+ return doPluginFNs( be, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, pb );
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
+/*
+ * New API to provide the plugin with access to the search
+ * pblock. Have informed Sun DS team.
+ */
+int slapi_x_compute_get_pblock(computed_attr_context *c, Slapi_PBlock **pb)
+{
+#ifdef LDAP_SLAPI
+ if ( c == NULL )
+ return -1;
+
+ if ( c->cac_pb == NULL )
+ return -1;
+
+ *pb = c->cac_pb;
+
+ return 0;
+#else
+ return -1;
+#endif /* LDAP_SLAPI */
+}
+
void slapi_entry_free( Slapi_Entry *e );
int slapi_attr_get_values( Slapi_Attr *attr, struct berval ***vals );
-/* OpenLDAP AttrSet extensions for virtual attribute service */
-Slapi_AttrSet *slapi_x_attrset_new( void );
-Slapi_AttrSet *slapi_x_attrset_init( Slapi_AttrSet *as, Slapi_Attr *a );
-void slapi_x_attrset_free( Slapi_AttrSet **as );
-Slapi_AttrSet *slapi_x_attrset_dup( Slapi_AttrSet *as );
-int slapi_x_attrset_add_attr( Slapi_AttrSet *as, Slapi_Attr *a );
-int slapi_x_attrset_add_attr_copy( Slapi_AttrSet *as, Slapi_Attr *a );
-int slapi_x_attrset_find( Slapi_AttrSet *as, const char *type, Slapi_Attr **attr );
-int slapi_x_attrset_merge( Slapi_AttrSet *as, const char *type, Slapi_ValueSet *vals );
-int slapi_x_attrset_merge_bervals( Slapi_AttrSet *as, const char *type, struct berval **vals );
-int slapi_x_attrset_delete( Slapi_AttrSet *as, const char *type );
-
/* DS 5.x SLAPI */
int slapi_access_allowed( Slapi_PBlock *pb, Slapi_Entry *e, char *attr, struct berval *val, int access );
int slapi_acl_check_mods( Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char **errbuf );
Modifications *slapi_x_ldapmods2modifications(LDAPMod **);
void slapi_x_free_ldapmods(LDAPMod **);
+/* Computed attribute support */
+struct _computed_attr_context {
+ /* slap_send_search_entry() argblock */
+ Slapi_PBlock *cac_pb;
+ AttributeName *cac_attrs;
+ int cac_attrsonly : 1;
+ int cac_userattrs : 1;
+ int cac_opattrs : 1;
+ AccessControlState cac_acl_state;
+ /* private data */
+ void *cac_private;
+};
+typedef struct _computed_attr_context computed_attr_context;
+typedef int (*slapi_compute_output_t)(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e);
+typedef int (*slapi_compute_callback_t)(computed_attr_context *c, char *type,
+ Slapi_Entry *e, slapi_compute_output_t outputfn);
+typedef int (*slapi_search_rewrite_callback_t)(Slapi_PBlock *pb);
+int slapi_compute_add_evaluator(slapi_compute_callback_t function);
+int slapi_compute_add_search_rewriter(slapi_search_rewrite_callback_t function);
+int compute_rewrite_search_filter(Slapi_PBlock *pb);
+int compute_evaluator(computed_attr_context *c, char *type, Slapi_Entry *e, slapi_compute_output_t outputfn);
+int slapi_x_compute_output_ber(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e);
+int slapi_x_compute_get_pblock(computed_attr_context *c, Slapi_PBlock **pb);
+
extern ldap_pvt_thread_mutex_t slapi_hn_mutex;
extern ldap_pvt_thread_mutex_t slapi_time_mutex;
extern ldap_pvt_thread_mutex_t slapi_printmessage_mutex;