First pass at replacing proprietary OpenLDAP virtual attribute API

(which existed briefly for a day!) with Sun ONE DS 5.x computed
attribute API
This commit is contained in:
Luke Howard 2003-01-22 13:06:46 +00:00
parent c76d37313b
commit faf8d43a6f
6 changed files with 310 additions and 382 deletions

View file

@ -687,9 +687,9 @@ slap_send_search_entry(
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;
@ -1148,149 +1148,39 @@ slap_send_search_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;
#ifdef LDAP_SLAPI
/* Support Sun ONE DS 5.x computed attributes */
/*
* 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;
}
}
} else {
rc = compute_evaluator( &ctx, "*", e, slapi_x_compute_output_ber );
}
/* 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 );
attrs_free( aa );
goto error_return;
}
}
slapi_x_attrset_free( &vattrs );
slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
slapi_pblock_set( pb, SLAPI_PLUGIN_OPATTR_COALESCE_DATA, NULL );
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 */

View file

@ -86,6 +86,10 @@ newPlugin(
}
rc = loadPlugin( pPlugin, path, initfunc, TRUE, NULL, &hdLoadHandle );
if ( rc != 0 ) {
rc = LDAP_OTHER;
goto done;
}
done:
if ( rc != LDAP_SUCCESS && pPlugin != NULL ) {
@ -557,7 +561,9 @@ loadPlugin(
return rc;
}
/*
* Special support for computed attribute plugins
*/
int
doPluginFNs(
Backend *be,
@ -607,7 +613,7 @@ doPluginFNs(
* 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++ ) {
@ -650,8 +656,8 @@ netscape_plugin(
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] );
@ -667,8 +673,7 @@ netscape_plugin(
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;

View file

@ -20,7 +20,6 @@ LDAP_BEGIN_DECL
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;
@ -88,15 +87,6 @@ LDAP_BEGIN_DECL
#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
@ -250,17 +240,16 @@ LDAP_BEGIN_DECL
#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

View file

@ -196,8 +196,8 @@ isOkNetscapeParam( int param )
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;

View file

@ -2438,209 +2438,6 @@ int slapi_acl_check_mods(Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char
#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
@ -2799,3 +2596,238 @@ void slapi_x_free_ldapmods (LDAPMod **mods)
#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 */
}

View file

@ -63,18 +63,6 @@ Slapi_Entry *slapi_entry_alloc();
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 );
@ -204,6 +192,30 @@ LDAPMod **slapi_x_modifications2ldapmods(Modifications **);
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;