+ return rc;
+}
+
+/* Dup the filter, excluding invalid elements */
+static Filter *
+trans_filter_dup(Operation *op, Filter *f, AttributeName *an)
+{
+ Filter *n = NULL;
+
+ if ( !f )
+ return NULL;
+
+ switch( f->f_choice & SLAPD_FILTER_MASK ) {
+ case SLAPD_FILTER_COMPUTED:
+ n = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
+ n->f_choice = f->f_choice;
+ n->f_result = f->f_result;
+ n->f_next = NULL;
+ break;
+
+ case LDAP_FILTER_PRESENT:
+ if ( ad_inlist( f->f_desc, an )) {
+ n = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
+ n->f_choice = f->f_choice;
+ n->f_desc = f->f_desc;
+ n->f_next = NULL;
+ }
+ break;
+
+ case LDAP_FILTER_EQUALITY:
+ case LDAP_FILTER_GE:
+ case LDAP_FILTER_LE:
+ case LDAP_FILTER_APPROX:
+ case LDAP_FILTER_SUBSTRINGS:
+ case LDAP_FILTER_EXT:
+ if ( !f->f_av_desc || ad_inlist( f->f_av_desc, an )) {
+ n = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
+ n->f_choice = f->f_choice;
+ n->f_ava = f->f_ava;
+ n->f_next = NULL;
+ }
+ break;
+
+ case LDAP_FILTER_AND:
+ case LDAP_FILTER_OR:
+ case LDAP_FILTER_NOT: {
+ Filter **p;
+
+ n = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
+ n->f_choice = f->f_choice;
+ n->f_next = NULL;
+
+ for ( p = &n->f_list, f = f->f_list; f; f = f->f_next ) {
+ *p = trans_filter_dup( op, f, an );
+ if ( !*p )
+ continue;
+ p = &(*p)->f_next;
+ }
+ /* nothing valid in this list */
+ if ( !n->f_list ) {
+ op->o_tmpfree( n, op->o_tmpmemctx );
+ return NULL;
+ }
+ /* Only 1 element in this list */
+ if ((n->f_choice & SLAPD_FILTER_MASK) != LDAP_FILTER_NOT &&
+ !n->f_list->f_next ) {
+ f = n->f_list;
+ *n = *f;
+ op->o_tmpfree( f, op->o_tmpmemctx );
+ }
+ break;
+ }
+ }
+ return n;
+}
+
+static void
+trans_filter_free( Operation *op, Filter *f )
+{
+ Filter *n, *p, *next;
+
+ f->f_choice &= SLAPD_FILTER_MASK;
+
+ switch( f->f_choice ) {
+ case LDAP_FILTER_AND:
+ case LDAP_FILTER_OR:
+ case LDAP_FILTER_NOT:
+ /* Free in reverse order */
+ n = NULL;
+ for ( p = f->f_list; p; p = next ) {
+ next = p->f_next;
+ p->f_next = n;
+ n = p;
+ }
+ for ( p = n; p; p = next ) {
+ next = p->f_next;
+ trans_filter_free( op, p );
+ }
+ break;
+ default:
+ break;
+ }
+ op->o_tmpfree( f, op->o_tmpmemctx );