extern BI_operational bdb_operational;
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+extern BI_has_subordinates bdb_hasSubordinates;
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
/* tools.c */
extern BI_tool_entry_open bdb_tool_entry_open;
extern BI_tool_entry_close bdb_tool_entry_close;
bi->bi_chk_referrals = bdb_referrals;
bi->bi_operational = bdb_operational;
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ bi->bi_has_subordinates = bdb_hasSubordinates;
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
bi->bi_entry_release_rw = bdb_entry_release;
/*
int isroot = 0;
int scopeok = 0;
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- int filter_hasSubordinates = 0;
- Attribute *hasSubordinates = NULL;
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
u_int32_t locker;
DB_LOCK lock;
}
}
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- /*
- * is hasSubordinates used in the filter ?
- * FIXME: we may compute this directly when parsing the filter
- */
- filter_hasSubordinates = filter_has_subordinates( filter );
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
lcupf.f_choice = LDAP_FILTER_AND;
lcupf.f_and = &csnfnot;
lcupf.f_next = NULL;
goto test_done;
}
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- /*
- * if hasSubordinates is used in the filter,
- * append it to the entry's attributes
- */
- if ( filter_hasSubordinates ) {
- int hs;
-
- rc = bdb_hasSubordinates( be, ps_conn, ps_op, e, &hs);
- if ( rc != LDAP_SUCCESS ) {
- goto test_done;
- }
-
- hasSubordinates = slap_operational_hasSubordinate(
- hs == LDAP_COMPARE_TRUE );
-
- if ( hasSubordinates == NULL ) {
- goto test_done;
- }
-
- hasSubordinates->a_next = e->e_attrs;
- e->e_attrs = hasSubordinates;
- }
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
if ( psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
rc = test_filter( be, ps_conn, ps_op, e, &lcupf );
} else {
rc = LDAP_COMPARE_TRUE;
}
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- if ( hasSubordinates ) {
- /*
- * FIXME: this is fairly inefficient, because
- * if hasSubordinates is among the required
- * attrs, it will be added again later;
- * maybe we should leave it and check
- * check later if it's already present,
- * if required
- */
- e->e_attrs = e->e_attrs->a_next;
- attr_free( hasSubordinates );
- }
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
if ( rc == LDAP_COMPARE_TRUE ) {
struct berval dn;
#include "proto-bdb.h"
/*
- * sets the supported operational attributes (if required)
+ * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
+ * if the entry has children or not.
*/
-
int
bdb_hasSubordinates(
BackendDB *be,
return rc;
}
+/*
+ * sets the supported operational attributes (if required)
+ */
int
bdb_operational(
BackendDB *be,
struct slap_limits_set *limit = NULL;
int isroot = 0;
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- int filter_hasSubordinates = 0;
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
u_int32_t locker;
DB_LOCK lock;
}
}
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- /*
- * is hasSubordinates used in the filter ?
- * FIXME: we may compute this directly when parsing the filter
- */
- filter_hasSubordinates = filter_has_subordinates( filter );
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
lcupf.f_choice = LDAP_FILTER_AND;
id = bdb_idl_next( candidates, &cursor ) )
{
int scopeok = 0;
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- Attribute *hasSubordinates = NULL;
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/* check for abandon */
if ( op->o_abandon ) {
goto loop_continue;
}
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- /*
- * if hasSubordinates is used in the filter,
- * append it to the entry's attributes
- */
- if ( filter_hasSubordinates ) {
- int hs;
-
- rc = bdb_hasSubordinates( be, conn, op, e, &hs);
- if ( rc != LDAP_SUCCESS ) {
- goto loop_continue;
- }
-
- hasSubordinates = slap_operational_hasSubordinate(
- hs == LDAP_COMPARE_TRUE );
-
- if ( hasSubordinates == NULL ) {
- goto loop_continue;
- }
-
- hasSubordinates->a_next = e->e_attrs;
- e->e_attrs = hasSubordinates;
- }
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
/* if it matches the filter and scope, send it */
#ifdef LDAP_CLIENT_UPDATE
if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
rc = test_filter( be, conn, op, e, filter );
}
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- if ( hasSubordinates ) {
- /*
- * FIXME: this is fairly inefficient, because
- * if hasSubordinates is among the required
- * attrs, it will be added again later;
- * maybe we should leave it and check
- * check later if it's already present,
- * if required
- */
- e->e_attrs = e->e_attrs->a_next;
- attr_free( hasSubordinates );
- }
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
if ( rc == LDAP_COMPARE_TRUE ) {
struct berval dn;
extern BI_operational ldbm_back_operational;
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+extern BI_has_subordinates ldbm_back_hasSubordinates;
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
/* hooks for slap tools */
extern BI_tool_entry_open ldbm_tool_entry_open;
extern BI_tool_entry_close ldbm_tool_entry_close;
bi->bi_acl_attribute = ldbm_back_attribute;
bi->bi_chk_referrals = ldbm_back_referrals;
bi->bi_operational = ldbm_back_operational;
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ bi->bi_has_subordinates = ldbm_back_hasSubordinates;
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/*
* hooks for slap tools
#include "proto-back-ldbm.h"
/*
- * sets the supported operational attributes (if required)
+ * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
+ * if the entry has children or not.
*/
+int
+ldbm_back_hasSubordinates(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ int *hasSubordinates )
+{
+ if ( has_children( be, e ) ) {
+ *hasSubordinates = LDAP_COMPARE_TRUE;
+ } else {
+ *hasSubordinates = LDAP_COMPARE_FALSE;
+ }
+
+ return 0;
+}
+
+/*
+ * sets the supported operational attributes (if required)
+ */
int
ldbm_back_operational(
BackendDB *be,
struct slap_limits_set *limit = NULL;
int isroot = 0;
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- int filter_hasSubordinates = 0;
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
#ifdef NEW_LOGGING
LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_search: enter\n", 0, 0, 0 );
#else
/* compute it anyway; root does not use it */
stoptime = op->o_time + tlimit;
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- /*
- * is hasSubordinates used in the filter ?
- * FIXME: we may compute this directly when parsing the filter
- */
- filter_hasSubordinates = filter_has_subordinates( filter );
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
for ( id = idl_firstid( candidates, &cursor ); id != NOID;
id = idl_nextid( candidates, &cursor ) )
{
int scopeok = 0;
int result = 0;
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- Attribute *hasSubordinates = NULL;
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/* check for abandon */
if ( op->o_abandon ) {
goto loop_continue;
}
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- /*
- * if hasSubordinates is used in the filter,
- * append it to the entry's attributes
- */
- if ( filter_hasSubordinates ) {
- int hs;
-
- hs = has_children( be, e );
- hasSubordinates = slap_operational_hasSubordinate( hs );
- if ( hasSubordinates == NULL ) {
- goto loop_continue;
- }
-
- hasSubordinates->a_next = e->e_attrs;
- e->e_attrs = hasSubordinates;
- }
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
/* if it matches the filter and scope, send it */
result = test_filter( be, conn, op, e, filter );
-#ifdef SLAP_X_FILTER_HASSUBORDINATES
- if ( hasSubordinates ) {
- /*
- * FIXME: this is fairly inefficient, because
- * if hasSubordinates is among the required
- * attrs, it will be added again later;
- * maybe we should leave it and check
- * check later if it's already present,
- * if required
- */
- e->e_attrs = e->e_attrs->a_next;
- attr_free( hasSubordinates );
- }
-#endif /* SLAP_X_FILTER_HASSUBORDINATES */
-
if ( result == LDAP_COMPARE_TRUE ) {
struct berval dn;
*/
backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l",
(ber_len_t)sizeof( "1=1" ) - 1, "1=1" );
- if ( ad != NULL ) {
+ if ( ad == slap_schema.si_ad_hasSubordinates ) {
/*
* We use this flag since we need to parse
* the filter anyway; we should have used
* filter_has_subordinates()
*/
bsi->bsi_flags |= BSQL_SF_FILTER_HASSUBORDINATE;
+
} else {
/*
* clear attributes to fetch, to require ALL
}
}
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
+ && be && be->be_has_subordinates ) {
+ int hasSubordinates;
+ struct berval hs;
+
+ /*
+ * No other match should be allowed ...
+ */
+ assert( type == LDAP_FILTER_EQUALITY );
+
+ if ( (*be->be_has_subordinates)( be, conn, op, e, &hasSubordinates ) ) {
+ return LDAP_OTHER;
+ }
+
+ if ( hasSubordinates == LDAP_COMPARE_TRUE ) {
+ hs.bv_val = "TRUE";
+ hs.bv_len = sizeof( "TRUE" ) - 1;
+
+ } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) {
+ hs.bv_val = "FALSE";
+ hs.bv_len = sizeof( "FALSE" ) - 1;
+
+ } else {
+ return LDAP_OTHER;
+ }
+
+ if ( bvmatch( &ava->aa_value, &hs ) ) {
+ return LDAP_COMPARE_TRUE;
+ }
+
+ return LDAP_COMPARE_FALSE;
+ }
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
return( LDAP_COMPARE_FALSE );
}
AttributeDescription *desc
)
{
+ Attribute *a;
+
if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
- return attrs_find( e->e_attrs, desc ) != NULL
- ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
+ a = attrs_find( e->e_attrs, desc );
+
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ if ( a == NULL && desc == slap_schema.si_ad_hasSubordinates ) {
+
+ /*
+ * XXX: fairly optimistic: if the function is defined,
+ * then PRESENCE must succeed, because hasSubordinate
+ * is boolean-valued; I think we may live with this
+ * simplification by now
+ */
+ if ( be && be->be_has_subordinates ) {
+ return LDAP_COMPARE_TRUE;
+ }
+
+ return LDAP_COMPARE_FALSE;
+ }
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
+ return a != NULL ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
}
/*
* define to honor hasSubordinates operational attribute in search filters
+ * (in previous use there was a flaw with back-bdb and back-ldbm; now it
+ * is fixed).
*/
#undef SLAP_X_FILTER_HASSUBORDINATES
#define be_group bd_info->bi_acl_group
#define be_attribute bd_info->bi_acl_attribute
#define be_operational bd_info->bi_operational
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+#define be_has_subordinates bd_info->bi_has_subordinates
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
#define be_controls bd_info->bi_controls
struct slap_conn *c, struct slap_op *o,
Entry *e, AttributeName *attrs, int opattrs, Attribute **a ));
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+typedef int (BI_has_subordinates) LDAP_P((Backend *bd,
+ struct slap_conn *c, struct slap_op *o,
+ Entry *e, int *has_subordinates ));
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
+
typedef int (BI_connection_init) LDAP_P((BackendDB *bd,
struct slap_conn *c));
typedef int (BI_connection_destroy) LDAP_P((BackendDB *bd,
BI_acl_attribute *bi_acl_attribute;
BI_operational *bi_operational;
+#ifdef SLAP_X_FILTER_HASSUBORDINATES
+ BI_has_subordinates *bi_has_subordinates;
+#endif /* SLAP_X_FILTER_HASSUBORDINATES */
BI_connection_init *bi_connection_init;
BI_connection_destroy *bi_connection_destroy;