+static int psearch_candidates(
+ BackendDB *be,
+ Operation *op,
+ Entry *e,
+ Filter *filter,
+ int scope,
+ int deref,
+ ID *ids )
+{
+ int rc, depth = 1;
+ Filter f, scopef, rf, xf;
+ ID *stack;
+ AttributeAssertion aa_ref;
+#ifdef BDB_SUBENTRIES
+ Filter sf;
+ AttributeAssertion aa_subentry;
+#endif
+#ifdef BDB_ALIASES
+ Filter af;
+ AttributeAssertion aa_alias;
+#endif
+
+ /*
+ * This routine takes as input a filter (user-filter)
+ * and rewrites it as follows:
+ * (&(scope=DN)[(objectClass=subentry)]
+ * (|[(objectClass=referral)(objectClass=alias)](user-filter))
+ */
+
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, ENTRY,
+ "psearch_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
+ e->e_dn, (long) e->e_id, scope);
+#else
+ Debug(LDAP_DEBUG_TRACE,
+ "psearch_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
+ e->e_dn, (long) e->e_id, scope );
+#endif
+
+ xf.f_or = filter;
+ xf.f_choice = LDAP_FILTER_OR;
+ xf.f_next = NULL;
+
+ /* If the user's filter uses objectClass=*,
+ * these clauses are redundant.
+ */
+ if (!psearch_oc_filter(filter, 1, &depth) && !get_subentries_visibility(op) ) {
+ if( !get_manageDSAit(op) ) { /* match referrals */
+ struct berval bv_ref = { sizeof("REFERRAL")-1, "REFERRAL" };
+ rf.f_choice = LDAP_FILTER_EQUALITY;
+ rf.f_ava = &aa_ref;
+ rf.f_av_desc = slap_schema.si_ad_objectClass;
+ rf.f_av_value = bv_ref;
+ rf.f_next = xf.f_or;
+ xf.f_or = &rf;
+ }
+
+#ifdef BDB_ALIASES
+ if( deref & LDAP_DEREF_SEARCHING ) { /* match aliases */
+ struct berval bv_alias = { sizeof("ALIAS")-1, "ALIAS" };
+ af.f_choice = LDAP_FILTER_EQUALITY;
+ af.f_ava = &aa_alias;
+ af.f_av_desc = slap_schema.si_ad_objectClass;
+ af.f_av_value = bv_alias;
+ af.f_next = xf.f_or;
+ xf.f_or = ⁡
+ }
+#endif
+ /* We added one of these clauses, filter depth increased */
+ if( xf.f_or != filter ) depth++;
+ }
+
+ f.f_next = NULL;
+ f.f_choice = LDAP_FILTER_AND;
+ f.f_and = &scopef;
+ scopef.f_choice = scope == LDAP_SCOPE_SUBTREE
+ ? SLAPD_FILTER_DN_SUBTREE
+ : SLAPD_FILTER_DN_ONE;
+ scopef.f_dn = &e->e_nname;
+ scopef.f_next = xf.f_or == filter ? filter : &xf ;
+ /* Filter depth increased again, adding scope clause */
+ depth++;
+
+#ifdef BDB_SUBENTRIES
+ if( get_subentries_visibility( op ) ) {
+ struct berval bv_subentry = { sizeof("SUBENTRY")-1, "SUBENTRY" };
+ sf.f_choice = LDAP_FILTER_EQUALITY;
+ sf.f_ava = &aa_subentry;
+ sf.f_av_desc = slap_schema.si_ad_objectClass;
+ sf.f_av_value = bv_subentry;
+ sf.f_next = scopef.f_next;
+ scopef.f_next = &sf;
+ }
+#endif
+
+ /* Allocate IDL stack, plus 1 more for former tmp */
+ stack = ch_malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) );
+
+ rc = bdb_filter_candidates( be, &f, ids, stack, stack+BDB_IDL_UM_SIZE );
+
+ ch_free( stack );
+
+ if( rc ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, DETAIL1,
+ "bdb_psearch_candidates: failed (rc=%d)\n", rc, 0, 0 );
+#else
+ Debug(LDAP_DEBUG_TRACE,
+ "bdb_psearch_candidates: failed (rc=%d)\n",
+ rc, NULL, NULL );
+#endif
+
+ } else {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, DETAIL1,
+ "bdb_psearch_candidates: id=%ld first=%ld last=%ld\n",
+ (long) ids[0], (long) BDB_IDL_FIRST(ids),
+ (long) BDB_IDL_LAST(ids));
+#else
+ Debug(LDAP_DEBUG_TRACE,
+ "bdb_psearch_candidates: id=%ld first=%ld last=%ld\n",
+ (long) ids[0],
+ (long) BDB_IDL_FIRST(ids),
+ (long) BDB_IDL_LAST(ids) );
+#endif
+ }