]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
Berkeley DB 4.2 support (DB 4.2 required by default)
[openldap] / servers / slapd / filter.c
1 /* filter.c - routines for parsing and dealing with filters */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/socket.h>
13 #include <ac/string.h>
14
15 #include "slap.h"
16
17 static int      get_filter_list(
18         Operation *op,
19         BerElement *ber,
20         Filter **f,
21         const char **text );
22
23 static int      get_ssa(
24         Operation *op,
25         BerElement *ber,
26         SubstringsAssertion **s,
27         const char **text );
28
29 static int filter_escape_value_x(
30         struct berval *in,
31         struct berval *out,
32         void *ctx );
33
34 static void simple_vrFilter2bv(
35         Operation *op,
36         ValuesReturnFilter *f,
37         struct berval *fstr );
38
39 static int      get_simple_vrFilter(
40         Operation *op,
41         BerElement *ber,
42         ValuesReturnFilter **f,
43         const char **text );
44
45 int
46 get_filter(
47         Operation *op,
48         BerElement *ber,
49         Filter **filt,
50         const char **text )
51 {
52         ber_tag_t       tag;
53         ber_len_t       len;
54         int             err;
55         Filter          f;
56
57 #ifdef NEW_LOGGING
58         LDAP_LOG( FILTER, ENTRY, "get_filter: conn %d\n", op->o_connid, 0, 0 );
59 #else
60         Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
61 #endif
62         /*
63          * A filter looks like this coming in:
64          *      Filter ::= CHOICE {
65          *              and             [0]     SET OF Filter,
66          *              or              [1]     SET OF Filter,
67          *              not             [2]     Filter,
68          *              equalityMatch   [3]     AttributeValueAssertion,
69          *              substrings      [4]     SubstringFilter,
70          *              greaterOrEqual  [5]     AttributeValueAssertion,
71          *              lessOrEqual     [6]     AttributeValueAssertion,
72          *              present         [7]     AttributeType,,
73          *              approxMatch     [8]     AttributeValueAssertion
74          *              extensibleMatch [9]     MatchingRuleAssertion
75          *      }
76          *
77          *      SubstringFilter ::= SEQUENCE {
78          *              type               AttributeType,
79          *              SEQUENCE OF CHOICE {
80          *                      initial          [0] IA5String,
81          *                      any              [1] IA5String,
82          *                      final            [2] IA5String
83          *              }
84          *      }
85          *
86          *      MatchingRuleAssertion ::= SEQUENCE {
87          *              matchingRule    [1] MatchingRuleId OPTIONAL,
88          *              type            [2] AttributeDescription OPTIONAL,
89          *              matchValue      [3] AssertionValue,
90          *              dnAttributes    [4] BOOLEAN DEFAULT FALSE
91          *      }
92          *
93          */
94
95         tag = ber_peek_tag( ber, &len );
96
97         if( tag == LBER_ERROR ) {
98                 *text = "error decoding filter";
99                 return SLAPD_DISCONNECT;
100         }
101
102         err = LDAP_SUCCESS;
103
104         f.f_next = NULL;
105         f.f_choice = tag; 
106
107         switch ( f.f_choice ) {
108         case LDAP_FILTER_EQUALITY:
109 #ifdef NEW_LOGGING
110                 LDAP_LOG( FILTER, DETAIL2, 
111                         "get_filter: conn %d  EQUALITY\n", op->o_connid, 0, 0 );
112 #else
113                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
114 #endif
115                 err = get_ava( op, ber, &f.f_ava, SLAP_MR_EQUALITY, text );
116                 if ( err != LDAP_SUCCESS ) {
117                         break;
118                 }
119
120                 assert( f.f_ava != NULL );
121                 break;
122
123         case LDAP_FILTER_SUBSTRINGS:
124 #ifdef NEW_LOGGING
125                 LDAP_LOG( FILTER, DETAIL1, 
126                         "get_filter: conn %d  SUBSTRINGS\n", op->o_connid, 0, 0 );
127 #else
128                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
129 #endif
130                 err = get_ssa( op, ber, &f.f_sub, text );
131                 if( err != LDAP_SUCCESS ) {
132                         break;
133                 }
134                 assert( f.f_sub != NULL );
135                 break;
136
137         case LDAP_FILTER_GE:
138 #ifdef NEW_LOGGING
139                 LDAP_LOG( FILTER, DETAIL1, 
140                         "get_filter: conn %d  GE\n", op->o_connid, 0, 0 );
141 #else
142                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
143 #endif
144                 err = get_ava( op, ber, &f.f_ava, SLAP_MR_ORDERING, text );
145                 if ( err != LDAP_SUCCESS ) {
146                         break;
147                 }
148                 assert( f.f_ava != NULL );
149                 break;
150
151         case LDAP_FILTER_LE:
152 #ifdef NEW_LOGGING
153                 LDAP_LOG( FILTER, DETAIL1, 
154                         "get_filter: conn %d  LE\n", op->o_connid, 0, 0 );
155 #else
156                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
157 #endif
158                 err = get_ava( op, ber, &f.f_ava, SLAP_MR_ORDERING, text );
159                 if ( err != LDAP_SUCCESS ) {
160                         break;
161                 }
162                 assert( f.f_ava != NULL );
163                 break;
164
165         case LDAP_FILTER_PRESENT: {
166                 struct berval type;
167
168 #ifdef NEW_LOGGING
169                 LDAP_LOG( FILTER, DETAIL1, 
170                         "get_filter: conn %d PRESENT\n", op->o_connid, 0, 0 );
171 #else
172                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
173 #endif
174                 if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) {
175                         err = SLAPD_DISCONNECT;
176                         *text = "error decoding filter";
177                         break;
178                 }
179
180                 f.f_desc = NULL;
181                 err = slap_bv2ad( &type, &f.f_desc, text );
182
183                 if( err != LDAP_SUCCESS ) {
184                         /* unrecognized attribute description or other error */
185                         f.f_choice = SLAPD_FILTER_COMPUTED;
186                         f.f_result = LDAP_COMPARE_FALSE;
187                         err = LDAP_SUCCESS;
188                         *text = NULL;
189                         break;
190                 }
191
192                 assert( f.f_desc != NULL );
193                 } break;
194
195         case LDAP_FILTER_APPROX:
196 #ifdef NEW_LOGGING
197                 LDAP_LOG( FILTER, DETAIL1, 
198                         "get_filter: conn %d  APPROX\n", op->o_connid, 0, 0 );
199 #else
200                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
201 #endif
202                 err = get_ava( op, ber, &f.f_ava, SLAP_MR_EQUALITY_APPROX, text );
203                 if ( err != LDAP_SUCCESS ) {
204                         break;
205                 }
206                 assert( f.f_ava != NULL );
207                 break;
208
209         case LDAP_FILTER_AND:
210 #ifdef NEW_LOGGING
211                 LDAP_LOG( FILTER, DETAIL1, 
212                         "get_filter: conn %d  AND\n", op->o_connid, 0, 0 );
213 #else
214                 Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
215 #endif
216                 err = get_filter_list( op, ber, &f.f_and, text );
217                 if ( err != LDAP_SUCCESS ) {
218                         break;
219                 }
220                 if ( f.f_and == NULL ) {
221                         f.f_choice = SLAPD_FILTER_COMPUTED;
222                         f.f_result = LDAP_COMPARE_TRUE;
223                 }
224                 /* no assert - list could be empty */
225                 break;
226
227         case LDAP_FILTER_OR:
228 #ifdef NEW_LOGGING
229                 LDAP_LOG( FILTER, DETAIL1, 
230                         "get_filter: conn %d  OR\n", op->o_connid, 0, 0  );
231 #else
232                 Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
233 #endif
234                 err = get_filter_list( op, ber, &f.f_or, text );
235                 if ( err != LDAP_SUCCESS ) {
236                         break;
237                 }
238                 if ( f.f_or == NULL ) {
239                         f.f_choice = SLAPD_FILTER_COMPUTED;
240                         f.f_result = LDAP_COMPARE_FALSE;
241                 }
242                 /* no assert - list could be empty */
243                 break;
244
245         case LDAP_FILTER_NOT:
246 #ifdef NEW_LOGGING
247                 LDAP_LOG( FILTER, DETAIL1, 
248                         "get_filter: conn %d  NOT\n", op->o_connid, 0, 0 );
249 #else
250                 Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
251 #endif
252                 (void) ber_skip_tag( ber, &len );
253                 err = get_filter( op, ber, &f.f_not, text );
254                 if ( err != LDAP_SUCCESS ) {
255                         break;
256                 }
257
258                 assert( f.f_not != NULL );
259                 if ( f.f_not->f_choice == SLAPD_FILTER_COMPUTED ) {
260                         int fresult = f.f_not->f_result;
261                         f.f_choice = SLAPD_FILTER_COMPUTED;
262                         op->o_tmpfree( f.f_not, op->o_tmpmemctx );
263                         f.f_not = NULL;
264
265                         switch( fresult ) {
266                         case LDAP_COMPARE_TRUE:
267                                 f.f_result = LDAP_COMPARE_FALSE;
268                                 break;
269                         case LDAP_COMPARE_FALSE:
270                                 f.f_result = LDAP_COMPARE_TRUE;
271                                 break;
272                         default: ;
273                                 /* (!Undefined) is Undefined */
274                         }
275                 }
276                 break;
277
278         case LDAP_FILTER_EXT:
279 #ifdef NEW_LOGGING
280                 LDAP_LOG( FILTER, DETAIL1, 
281                         "get_filter: conn %d  EXTENSIBLE\n", op->o_connid, 0, 0 );
282 #else
283                 Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
284 #endif
285
286                 err = get_mra( op, ber, &f.f_mra, text );
287                 if ( err != LDAP_SUCCESS ) {
288                         break;
289                 }
290
291                 assert( f.f_mra != NULL );
292                 break;
293
294         default:
295                 (void) ber_scanf( ber, "x" ); /* skip the element */
296 #ifdef NEW_LOGGING
297                 LDAP_LOG( FILTER, ERR, 
298                         "get_filter: conn %d unknown filter type=%lu\n",
299                         op->o_connid, f.f_choice, 0 );
300 #else
301                 Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n",
302                         f.f_choice, 0, 0 );
303 #endif
304                 f.f_choice = SLAPD_FILTER_COMPUTED;
305                 f.f_result = SLAPD_COMPARE_UNDEFINED;
306                 break;
307         }
308
309         if( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
310                 /* ignore error */
311                 *text = NULL;
312                 f.f_choice = SLAPD_FILTER_COMPUTED;
313                 f.f_result = SLAPD_COMPARE_UNDEFINED;
314                 err = LDAP_SUCCESS;
315         }
316
317         if ( err == LDAP_SUCCESS ) {
318                 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
319                 **filt = f;
320         }
321
322 #ifdef NEW_LOGGING
323         LDAP_LOG( FILTER, DETAIL2, 
324                 "get_filter: conn %d exit\n", op->o_connid, 0, 0 );
325 #else
326         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
327 #endif
328
329         return( err );
330 }
331
332 static int
333 get_filter_list( Operation *op, BerElement *ber,
334         Filter **f,
335         const char **text )
336 {
337         Filter          **new;
338         int             err;
339         ber_tag_t       tag;
340         ber_len_t       len;
341         char            *last;
342
343 #ifdef NEW_LOGGING
344         LDAP_LOG( FILTER, ENTRY, 
345                 "get_filter_list: conn %d start\n", op->o_connid, 0, 0 );
346 #else
347         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
348 #endif
349         new = f;
350         for ( tag = ber_first_element( ber, &len, &last );
351                 tag != LBER_DEFAULT;
352                 tag = ber_next_element( ber, &len, last ) )
353         {
354                 err = get_filter( op, ber, new, text );
355                 if ( err != LDAP_SUCCESS )
356                         return( err );
357                 new = &(*new)->f_next;
358         }
359         *new = NULL;
360
361 #ifdef NEW_LOGGING
362         LDAP_LOG( FILTER, ENTRY, 
363                 "get_filter_list: conn %d exit\n", op->o_connid, 0, 0 );
364 #else
365         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
366 #endif
367         return( LDAP_SUCCESS );
368 }
369
370 static int
371 get_ssa(
372         Operation *op,
373         BerElement      *ber,
374         SubstringsAssertion     **out,
375         const char      **text )
376 {
377         ber_tag_t       tag;
378         ber_len_t       len;
379         ber_tag_t       rc;
380         struct berval desc, value, nvalue;
381         char            *last;
382         SubstringsAssertion ssa;
383
384         *text = "error decoding filter";
385
386 #ifdef NEW_LOGGING
387         LDAP_LOG( FILTER, ENTRY, 
388                 "get_ssa: conn %d  begin\n", op->o_connid, 0, 0 );
389 #else
390         Debug( LDAP_DEBUG_FILTER, "begin get_ssa\n", 0, 0, 0 );
391 #endif
392         if ( ber_scanf( ber, "{m" /*}*/, &desc ) == LBER_ERROR ) {
393                 return SLAPD_DISCONNECT;
394         }
395
396         *text = NULL;
397
398         ssa.sa_desc = NULL;
399         ssa.sa_initial.bv_val = NULL;
400         ssa.sa_any = NULL;
401         ssa.sa_final.bv_val = NULL;
402
403         rc = slap_bv2ad( &desc, &ssa.sa_desc, text );
404
405         if( rc != LDAP_SUCCESS ) {
406                 /* skip over the rest of this filter */
407                 for ( tag = ber_first_element( ber, &len, &last );
408                         tag != LBER_DEFAULT;
409                         tag = ber_next_element( ber, &len, last ) ) {
410                         ber_scanf( ber, "x" );
411                 }
412                 return rc;
413         }
414
415         rc = LDAP_PROTOCOL_ERROR;
416
417         for ( tag = ber_first_element( ber, &len, &last );
418                 tag != LBER_DEFAULT;
419                 tag = ber_next_element( ber, &len, last ) )
420         {
421                 unsigned usage;
422
423                 rc = ber_scanf( ber, "m", &value );
424                 if ( rc == LBER_ERROR ) {
425                         rc = SLAPD_DISCONNECT;
426                         goto return_error;
427                 }
428
429                 if ( value.bv_val == NULL || value.bv_len == 0 ) {
430                         rc = LDAP_INVALID_SYNTAX;
431                         goto return_error;
432                 } 
433
434                 switch ( tag ) {
435                 case LDAP_SUBSTRING_INITIAL:
436                         usage = SLAP_MR_SUBSTR_INITIAL;
437                         break;
438
439                 case LDAP_SUBSTRING_ANY:
440                         usage = SLAP_MR_SUBSTR_ANY;
441                         break;
442
443                 case LDAP_SUBSTRING_FINAL:
444                         usage = SLAP_MR_SUBSTR_FINAL;
445                         break;
446
447                 default:
448                         rc = LDAP_PROTOCOL_ERROR;
449
450 #ifdef NEW_LOGGING
451                         LDAP_LOG( FILTER, ERR,
452                                 "get_filter_substring: conn %d  unknown substring choice=%ld\n",
453                                 op->o_connid, (long)tag, 0 );
454 #else
455                         Debug( LDAP_DEBUG_FILTER,
456                                 "  unknown substring choice=%ld\n",
457                                 (long) tag, 0, 0 );
458 #endif
459
460                         goto return_error;
461                 }
462
463                 /* validate/normalize using equality matching rule validator! */
464                 rc = asserted_value_validate_normalize(
465                         ssa.sa_desc, ssa.sa_desc->ad_type->sat_equality,
466                         usage, &value, &nvalue, text, op->o_tmpmemctx );
467
468                 if( rc != LDAP_SUCCESS ) {
469                         goto return_error;
470                 }
471
472                 rc = LDAP_PROTOCOL_ERROR;
473
474                 switch ( tag ) {
475                 case LDAP_SUBSTRING_INITIAL:
476 #ifdef NEW_LOGGING
477                         LDAP_LOG( FILTER, DETAIL1,
478                                 "get_ssa: conn %d  INITIAL\n",
479                                 op->o_connid, 0, 0 );
480 #else
481                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
482 #endif
483
484                         if ( ssa.sa_initial.bv_val != NULL
485                                 || ssa.sa_any != NULL 
486                                 || ssa.sa_final.bv_val != NULL )
487                         {
488                                 sl_free( nvalue.bv_val, op->o_tmpmemctx );
489                                 goto return_error;
490                         }
491
492                         ssa.sa_initial = nvalue;
493                         break;
494
495                 case LDAP_SUBSTRING_ANY:
496 #ifdef NEW_LOGGING
497                         LDAP_LOG( FILTER, DETAIL1,
498                                 "get_ssa: conn %d  ANY\n",
499                                 op->o_connid, 0, 0 );
500 #else
501                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
502 #endif
503
504                         if ( ssa.sa_final.bv_val != NULL ) {
505                                 sl_free( nvalue.bv_val, op->o_tmpmemctx );
506                                 goto return_error;
507                         }
508
509                         ber_bvarray_add_x( &ssa.sa_any, &nvalue, op->o_tmpmemctx );
510                         break;
511
512                 case LDAP_SUBSTRING_FINAL:
513 #ifdef NEW_LOGGING
514                         LDAP_LOG( FILTER, DETAIL1, 
515                                 "get_ssa: conn %d  FINAL\n",
516                                 op->o_connid, 0, 0 );
517 #else
518                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
519 #endif
520
521                         if ( ssa.sa_final.bv_val != NULL ) {
522                                 sl_free( nvalue.bv_val, op->o_tmpmemctx );
523                                 goto return_error;
524                         }
525
526                         ssa.sa_final = nvalue;
527                         break;
528
529                 default:
530 #ifdef NEW_LOGGING
531                         LDAP_LOG( FILTER, INFO, 
532                                 "get_ssa: conn %d  unknown substring type %ld\n",
533                                 op->o_connid, (long)tag, 0 );
534 #else
535                         Debug( LDAP_DEBUG_FILTER,
536                                 "  unknown substring type=%ld\n",
537                                 (long) tag, 0, 0 );
538 #endif
539
540                         assert( 0 );
541                         sl_free( nvalue.bv_val, op->o_tmpmemctx );
542
543 return_error:
544 #ifdef NEW_LOGGING
545                         LDAP_LOG( FILTER, INFO, 
546                                 "get_ssa: conn %d  error %ld\n",
547                                 op->o_connid, (long)rc, 0 );
548 #else
549                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
550                                 (long) rc, 0, 0 );
551 #endif
552                         sl_free( ssa.sa_initial.bv_val, op->o_tmpmemctx );
553                         ber_bvarray_free_x( ssa.sa_any, op->o_tmpmemctx );
554                         sl_free( ssa.sa_final.bv_val, op->o_tmpmemctx );
555                         return rc;
556                 }
557
558                 rc = LDAP_SUCCESS;
559         }
560
561         if( rc == LDAP_SUCCESS ) {
562                 *out = op->o_tmpalloc( sizeof( ssa ), op->o_tmpmemctx );
563                 **out = ssa;
564         }
565
566 #ifdef NEW_LOGGING
567         LDAP_LOG( FILTER, ENTRY, 
568                 "get_ssa: conn %d exit\n", op->o_connid, 0, 0 );
569 #else
570         Debug( LDAP_DEBUG_FILTER, "end get_ssa\n", 0, 0, 0 );
571 #endif
572
573         return LDAP_SUCCESS;
574 }
575
576 void
577 filter_free_x( Operation *op, Filter *f )
578 {
579         Filter  *p, *next;
580
581         if ( f == NULL ) {
582                 return;
583         }
584
585         switch ( f->f_choice ) {
586         case LDAP_FILTER_PRESENT:
587                 break;
588
589         case LDAP_FILTER_EQUALITY:
590         case LDAP_FILTER_GE:
591         case LDAP_FILTER_LE:
592         case LDAP_FILTER_APPROX:
593                 ava_free( op, f->f_ava, 1 );
594                 break;
595
596         case LDAP_FILTER_SUBSTRINGS:
597                 if ( f->f_sub_initial.bv_val != NULL ) {
598                         op->o_tmpfree( f->f_sub_initial.bv_val, op->o_tmpmemctx );
599                 }
600                 ber_bvarray_free_x( f->f_sub_any, op->o_tmpmemctx );
601                 if ( f->f_sub_final.bv_val != NULL ) {
602                         op->o_tmpfree( f->f_sub_final.bv_val, op->o_tmpmemctx );
603                 }
604                 op->o_tmpfree( f->f_sub, op->o_tmpmemctx );
605                 break;
606
607         case LDAP_FILTER_AND:
608         case LDAP_FILTER_OR:
609         case LDAP_FILTER_NOT:
610                 for ( p = f->f_list; p != NULL; p = next ) {
611                         next = p->f_next;
612                         filter_free_x( op, p );
613                 }
614                 break;
615
616         case LDAP_FILTER_EXT:
617                 mra_free( op, f->f_mra, 1 );
618                 break;
619
620         case SLAPD_FILTER_COMPUTED:
621                 break;
622
623         default:
624 #ifdef NEW_LOGGING
625                 LDAP_LOG( FILTER, ERR, 
626                         "filter_free: unknown filter type %lu\n", f->f_choice, 0, 0 );
627 #else
628                 Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
629                         f->f_choice, 0, 0 );
630 #endif
631                 break;
632         }
633
634         op->o_tmpfree( f, op->o_tmpmemctx );
635 }
636
637 void
638 filter_free( Filter *f )
639 {
640         Operation op;
641
642         op.o_tmpmemctx = sl_context( f );
643         op.o_tmpmfuncs = &sl_mfuncs;
644         filter_free_x( &op, f );
645 }
646
647 void
648 filter2bv_x( Operation *op, Filter *f, struct berval *fstr )
649 {
650         int     i;
651         Filter  *p;
652         struct berval tmp;
653         ber_len_t len;
654
655         if ( f == NULL ) {
656                 ber_str2bv_x( "No filter!", sizeof("No filter!")-1, 1, fstr, op->o_tmpmemctx );
657                 return;
658         }
659
660         switch ( f->f_choice ) {
661         case LDAP_FILTER_EQUALITY:
662                 filter_escape_value_x( &f->f_av_value, &tmp, op->o_tmpmemctx );
663
664                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
665                         tmp.bv_len + ( sizeof("(=)") - 1 );
666                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
667
668                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
669                         f->f_av_desc->ad_cname.bv_val,
670                         tmp.bv_val );
671
672                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
673                 break;
674
675         case LDAP_FILTER_GE:
676                 filter_escape_value_x( &f->f_av_value, &tmp, op->o_tmpmemctx );
677
678                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
679                         tmp.bv_len + ( sizeof("(>=)") - 1 );
680                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
681
682                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
683                         f->f_av_desc->ad_cname.bv_val,
684                         tmp.bv_val );
685
686                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
687                 break;
688
689         case LDAP_FILTER_LE:
690                 filter_escape_value_x( &f->f_av_value, &tmp, op->o_tmpmemctx );
691
692                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
693                         tmp.bv_len + ( sizeof("(<=)") - 1 );
694                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
695
696                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
697                         f->f_av_desc->ad_cname.bv_val,
698                         tmp.bv_val );
699
700                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
701                 break;
702
703         case LDAP_FILTER_APPROX:
704                 filter_escape_value_x( &f->f_av_value, &tmp, op->o_tmpmemctx );
705
706                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
707                         tmp.bv_len + ( sizeof("(~=)") - 1 );
708                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
709
710                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
711                         f->f_av_desc->ad_cname.bv_val,
712                         tmp.bv_val );
713                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
714                 break;
715
716         case LDAP_FILTER_SUBSTRINGS:
717                 fstr->bv_len = f->f_sub_desc->ad_cname.bv_len +
718                         ( sizeof("(=*)") - 1 );
719                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
720
721                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
722                         f->f_sub_desc->ad_cname.bv_val );
723
724                 if ( f->f_sub_initial.bv_val != NULL ) {
725                         len = fstr->bv_len;
726
727                         filter_escape_value_x( &f->f_sub_initial, &tmp, op->o_tmpmemctx );
728
729                         fstr->bv_len += tmp.bv_len;
730                         fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
731
732                         snprintf( &fstr->bv_val[len-2], tmp.bv_len+3,
733                                 /* "(attr=" */ "%s*)",
734                                 tmp.bv_val );
735
736                         ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
737                 }
738
739                 if ( f->f_sub_any != NULL ) {
740                         for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
741                                 len = fstr->bv_len;
742                                 filter_escape_value_x( &f->f_sub_any[i], &tmp, op->o_tmpmemctx );
743
744                                 fstr->bv_len += tmp.bv_len + 1;
745                                 fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
746
747                                 snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
748                                         /* "(attr=[init]*[any*]" */ "%s*)",
749                                         tmp.bv_val );
750                                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
751                         }
752                 }
753
754                 if ( f->f_sub_final.bv_val != NULL ) {
755                         len = fstr->bv_len;
756
757                         filter_escape_value_x( &f->f_sub_final, &tmp, op->o_tmpmemctx );
758
759                         fstr->bv_len += tmp.bv_len;
760                         fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
761
762                         snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
763                                 /* "(attr=[init*][any*]" */ "%s)",
764                                 tmp.bv_val );
765
766                         ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
767                 }
768
769                 break;
770
771         case LDAP_FILTER_PRESENT:
772                 fstr->bv_len = f->f_desc->ad_cname.bv_len +
773                         ( sizeof("(=*)") - 1 );
774                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
775
776                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
777                         f->f_desc->ad_cname.bv_val );
778                 break;
779
780         case LDAP_FILTER_AND:
781         case LDAP_FILTER_OR:
782         case LDAP_FILTER_NOT:
783                 fstr->bv_len = sizeof("(%)") - 1;
784                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
785
786                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
787                         f->f_choice == LDAP_FILTER_AND ? '&' :
788                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
789
790                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
791                         len = fstr->bv_len;
792
793                         filter2bv_x( op, p, &tmp );
794                         
795                         fstr->bv_len += tmp.bv_len;
796                         fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
797
798                         snprintf( &fstr->bv_val[len-1], tmp.bv_len + 2, 
799                                 /*"("*/ "%s)", tmp.bv_val );
800
801                         op->o_tmpfree( tmp.bv_val, op->o_tmpmemctx );
802                 }
803
804                 break;
805
806         case LDAP_FILTER_EXT: {
807                 struct berval ad;
808                 filter_escape_value_x( &f->f_mr_value, &tmp, op->o_tmpmemctx );
809
810                 if ( f->f_mr_desc ) {
811                         ad = f->f_mr_desc->ad_cname;
812                 } else {
813                         ad.bv_len = 0;
814                         ad.bv_val = "";
815                 }
816                         
817                 fstr->bv_len = ad.bv_len +
818                         ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
819                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
820                         tmp.bv_len + ( sizeof("(:=)") - 1 );
821                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
822
823                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
824                         ad.bv_val,
825                         f->f_mr_dnattrs ? ":dn" : "",
826                         f->f_mr_rule_text.bv_len ? ":" : "",
827                         f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
828                         tmp.bv_val );
829                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
830                 } break;
831
832         case SLAPD_FILTER_COMPUTED:
833                 ber_str2bv_x(
834                         f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
835                         f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
836                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
837                         "(?=error)",
838                         f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
839                         f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
840                         f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
841                         sizeof("(?=error)")-1,
842                         1, fstr, op->o_tmpmemctx );
843                 break;
844
845         default:
846                 ber_str2bv_x( "(?=unknown)", sizeof("(?=unknown)")-1,
847                         1, fstr, op->o_tmpmemctx );
848                 break;
849         }
850 }
851
852 void
853 filter2bv( Filter *f, struct berval *fstr )
854 {
855         Operation op;
856         op.o_tmpmemctx = NULL;
857         op.o_tmpmfuncs = &ch_mfuncs;
858
859         filter2bv_x( &op, f, fstr );
860 }
861
862 static int
863 filter_escape_value_x(
864         struct berval *in,
865         struct berval *out,
866         void *ctx )
867 {
868         ber_len_t i;
869         assert( in );
870         assert( out );
871
872         i = in->bv_len * 3 + 1;
873         out->bv_val = ctx ? sl_malloc( i, ctx ) : ch_malloc( i );
874         out->bv_len = 0;
875
876         for( i=0; i < in->bv_len ; i++ ) {
877                 if( FILTER_ESCAPE(in->bv_val[i]) ) {
878                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_CHAR;
879                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_HI( in->bv_val[i] );
880                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_LO( in->bv_val[i] );
881                 } else {
882                         out->bv_val[out->bv_len++] = in->bv_val[i];
883                 }
884         }
885
886         out->bv_val[out->bv_len] = '\0';
887         return LDAP_SUCCESS;
888 }
889
890 int
891 filter_escape_value(
892         struct berval *in,
893         struct berval *out )
894 {
895         return filter_escape_value_x( in, out, NULL );
896 }
897
898 static int
899 get_simple_vrFilter(
900         Operation *op,
901         BerElement *ber,
902         ValuesReturnFilter **filt,
903         const char **text )
904 {
905         ber_tag_t       tag;
906         ber_len_t       len;
907         int             err;
908         ValuesReturnFilter vrf;
909
910 #ifdef NEW_LOGGING
911         LDAP_LOG( FILTER, ENTRY, 
912                 "get_simple_vrFilter: conn %d\n", op->o_connid, 0, 0 );
913 #else
914         Debug( LDAP_DEBUG_FILTER, "begin get_simple_vrFilter\n", 0, 0, 0 );
915 #endif
916
917         tag = ber_peek_tag( ber, &len );
918
919         if( tag == LBER_ERROR ) {
920                 *text = "error decoding filter";
921                 return SLAPD_DISCONNECT;
922         }
923
924         vrf.vrf_next = NULL;
925
926         err = LDAP_SUCCESS;
927         vrf.vrf_choice = tag; 
928
929         switch ( vrf.vrf_choice ) {
930         case LDAP_FILTER_EQUALITY:
931 #ifdef NEW_LOGGING
932                 LDAP_LOG( FILTER, DETAIL2, 
933                         "get_simple_vrFilter: conn %d  EQUALITY\n", op->o_connid, 0, 0 );
934 #else
935                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
936 #endif
937                 err = get_ava( op, ber, &vrf.vrf_ava, SLAP_MR_EQUALITY, text );
938                 if ( err != LDAP_SUCCESS ) {
939                         break;
940                 }
941
942                 assert( vrf.vrf_ava != NULL );
943                 break;
944
945         case LDAP_FILTER_SUBSTRINGS:
946 #ifdef NEW_LOGGING
947                 LDAP_LOG( FILTER, DETAIL1, 
948                         "get_simple_vrFilter: conn %d  SUBSTRINGS\n", op->o_connid, 0, 0 );
949 #else
950                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
951 #endif
952                 err = get_ssa( op, ber, &vrf.vrf_sub, text );
953                 break;
954
955         case LDAP_FILTER_GE:
956 #ifdef NEW_LOGGING
957                 LDAP_LOG( FILTER, DETAIL1, 
958                         "get_simple_vrFilter: conn %d  GE\n", op->o_connid, 0, 0 );
959 #else
960                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
961 #endif
962                 err = get_ava( op, ber, &vrf.vrf_ava, SLAP_MR_ORDERING, text );
963                 if ( err != LDAP_SUCCESS ) {
964                         break;
965                 }
966                 break;
967
968         case LDAP_FILTER_LE:
969 #ifdef NEW_LOGGING
970                 LDAP_LOG( FILTER, DETAIL1, 
971                         "get_simple_vrFilter: conn %d  LE\n", op->o_connid, 0, 0 );
972 #else
973                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
974 #endif
975                 err = get_ava( op, ber, &vrf.vrf_ava, SLAP_MR_ORDERING, text );
976                 if ( err != LDAP_SUCCESS ) {
977                         break;
978                 }
979                 break;
980
981         case LDAP_FILTER_PRESENT: {
982                 struct berval type;
983
984 #ifdef NEW_LOGGING
985                 LDAP_LOG( FILTER, DETAIL1, 
986                         "get_simple_vrFilter: conn %d PRESENT\n", op->o_connid, 0, 0 );
987 #else
988                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
989 #endif
990                 if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) {
991                         err = SLAPD_DISCONNECT;
992                         *text = "error decoding filter";
993                         break;
994                 }
995
996                 vrf.vrf_desc = NULL;
997                 err = slap_bv2ad( &type, &vrf.vrf_desc, text );
998
999                 if( err != LDAP_SUCCESS ) {
1000                         /* unrecognized attribute description or other error */
1001                         vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
1002                         vrf.vrf_result = LDAP_COMPARE_FALSE;
1003                         err = LDAP_SUCCESS;
1004                         break;
1005                 }
1006                 } break;
1007
1008         case LDAP_FILTER_APPROX:
1009 #ifdef NEW_LOGGING
1010                 LDAP_LOG( FILTER, DETAIL1, 
1011                         "get_simple_vrFilter: conn %d  APPROX\n", op->o_connid, 0, 0 );
1012 #else
1013                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
1014 #endif
1015                 err = get_ava( op, ber, &vrf.vrf_ava, SLAP_MR_EQUALITY_APPROX, text );
1016                 if ( err != LDAP_SUCCESS ) {
1017                         break;
1018                 }
1019                 break;
1020
1021         case LDAP_FILTER_EXT:
1022 #ifdef NEW_LOGGING
1023                 LDAP_LOG( FILTER, DETAIL1, 
1024                         "get_simple_vrFilter: conn %d  EXTENSIBLE\n", op->o_connid, 0, 0 );
1025 #else
1026                 Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
1027 #endif
1028
1029                 err = get_mra( op, ber, &vrf.vrf_mra, text );
1030                 if ( err != LDAP_SUCCESS ) {
1031                         break;
1032                 }
1033
1034                 assert( vrf.vrf_mra != NULL );
1035                 break;
1036
1037         default:
1038                 (void) ber_scanf( ber, "x" ); /* skip the element */
1039 #ifdef NEW_LOGGING
1040                 LDAP_LOG( FILTER, ERR, 
1041                         "get_simple_vrFilter: conn %d unknown filter type=%lu\n",
1042                         op->o_connid, vrf.vrf_choice, 0 );
1043 #else
1044                 Debug( LDAP_DEBUG_ANY, "get_simple_vrFilter: unknown filter type=%lu\n",
1045                         vrf.vrf_choice, 0, 0 );
1046 #endif
1047                 vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
1048                 vrf.vrf_result = SLAPD_COMPARE_UNDEFINED;
1049                 break;
1050         }
1051
1052         if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1053                 /* ignore error */
1054                 vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
1055                 vrf.vrf_result = SLAPD_COMPARE_UNDEFINED;
1056                 err = LDAP_SUCCESS;
1057         }
1058
1059         if ( err == LDAP_SUCCESS ) {
1060                 *filt = ch_malloc( sizeof vrf );
1061                 **filt = vrf;
1062         }
1063
1064 #ifdef NEW_LOGGING
1065         LDAP_LOG( FILTER, DETAIL2, 
1066                 "get_simple_vrFilter: conn %d exit\n", op->o_connid, 0, 0 );
1067 #else
1068         Debug( LDAP_DEBUG_FILTER, "end get_simple_vrFilter %d\n", err, 0, 0 );
1069 #endif
1070
1071         return err;
1072 }
1073
1074 int
1075 get_vrFilter( Operation *op, BerElement *ber,
1076         ValuesReturnFilter **vrf,
1077         const char **text )
1078 {
1079         /*
1080          * A ValuesReturnFilter looks like this:
1081          *
1082          *      ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem
1083          *      SimpleFilterItem ::= CHOICE {
1084          *              equalityMatch   [3]     AttributeValueAssertion,
1085          *              substrings      [4]     SubstringFilter,
1086          *              greaterOrEqual  [5]     AttributeValueAssertion,
1087          *              lessOrEqual     [6]     AttributeValueAssertion,
1088          *              present         [7]     AttributeType,
1089          *              approxMatch     [8]     AttributeValueAssertion,
1090          *              extensibleMatch [9]     SimpleMatchingAssertion -- LDAPv3
1091          *      }
1092          *
1093          *      SubstringFilter ::= SEQUENCE {
1094          *              type               AttributeType,
1095          *              SEQUENCE OF CHOICE {
1096          *                      initial          [0] IA5String,
1097          *                      any              [1] IA5String,
1098          *                      final            [2] IA5String
1099          *              }
1100          *      }
1101          *
1102          *      SimpleMatchingAssertion ::= SEQUENCE {  -- LDAPv3
1103          *              matchingRule    [1] MatchingRuleId OPTIONAL,
1104          *              type            [2] AttributeDescription OPTIONAL,
1105          *              matchValue      [3] AssertionValue }
1106          */
1107
1108         ValuesReturnFilter **n;
1109         ber_tag_t       tag;
1110         ber_len_t       len;
1111         char            *last;
1112
1113 #ifdef NEW_LOGGING
1114         LDAP_LOG( FILTER, ENTRY, 
1115                 "get_vrFilter: conn %d start\n", op->o_connid, 0, 0 );
1116 #else
1117         Debug( LDAP_DEBUG_FILTER, "begin get_vrFilter\n", 0, 0, 0 );
1118 #endif
1119
1120         tag = ber_peek_tag( ber, &len );
1121
1122         if( tag == LBER_ERROR ) {
1123                 *text = "error decoding vrFilter";
1124                 return SLAPD_DISCONNECT;
1125         }
1126
1127         if( tag != LBER_SEQUENCE ) {
1128                 *text = "error decoding vrFilter, expect SEQUENCE tag";
1129                 return SLAPD_DISCONNECT;
1130         }
1131
1132         n = vrf;
1133         for ( tag = ber_first_element( ber, &len, &last );
1134                 tag != LBER_DEFAULT;
1135                 tag = ber_next_element( ber, &len, last ) )
1136         {
1137                 int err = get_simple_vrFilter( op, ber, n, text );
1138
1139                 if ( err != LDAP_SUCCESS ) return( err );
1140
1141                 n = &(*n)->vrf_next;
1142         }
1143         *n = NULL;
1144
1145 #ifdef NEW_LOGGING
1146         LDAP_LOG( FILTER, ENTRY, 
1147                 "get_vrFilter: conn %d exit\n", op->o_connid, 0, 0 );
1148 #else
1149         Debug( LDAP_DEBUG_FILTER, "end get_vrFilter\n", 0, 0, 0 );
1150 #endif
1151         return( LDAP_SUCCESS );
1152 }
1153
1154 void
1155 vrFilter_free( Operation *op, ValuesReturnFilter *vrf )
1156 {
1157         ValuesReturnFilter      *p, *next;
1158
1159         if ( vrf == NULL ) {
1160                 return;
1161         }
1162
1163         for ( p = vrf; p != NULL; p = next ) {
1164                 next = p->vrf_next;
1165
1166                 switch ( vrf->vrf_choice ) {
1167                 case LDAP_FILTER_PRESENT:
1168                         break;
1169
1170                 case LDAP_FILTER_EQUALITY:
1171                 case LDAP_FILTER_GE:
1172                 case LDAP_FILTER_LE:
1173                 case LDAP_FILTER_APPROX:
1174                         ava_free( op, vrf->vrf_ava, 1 );
1175                         break;
1176
1177                 case LDAP_FILTER_SUBSTRINGS:
1178                         if ( vrf->vrf_sub_initial.bv_val != NULL ) {
1179                                 op->o_tmpfree( vrf->vrf_sub_initial.bv_val, op->o_tmpmemctx );
1180                         }
1181                         ber_bvarray_free_x( vrf->vrf_sub_any, op->o_tmpmemctx );
1182                         if ( vrf->vrf_sub_final.bv_val != NULL ) {
1183                                 op->o_tmpfree( vrf->vrf_sub_final.bv_val, op->o_tmpmemctx );
1184                         }
1185                         op->o_tmpfree( vrf->vrf_sub, op->o_tmpmemctx );
1186                         break;
1187
1188                 case LDAP_FILTER_EXT:
1189                         mra_free( op, vrf->vrf_mra, 1 );
1190                         break;
1191
1192                 case SLAPD_FILTER_COMPUTED:
1193                         break;
1194
1195                 default:
1196 #ifdef NEW_LOGGING
1197                         LDAP_LOG( FILTER, ERR, 
1198                                 "filter_free: unknown filter type %lu\n", vrf->vrf_choice, 0, 0 );
1199 #else
1200                         Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
1201                                 vrf->vrf_choice, 0, 0 );
1202 #endif
1203                         break;
1204                 }
1205
1206                 op->o_tmpfree( vrf, op->o_tmpmemctx );
1207         }
1208 }
1209
1210 void
1211 vrFilter2bv( Operation *op, ValuesReturnFilter *vrf, struct berval *fstr )
1212 {
1213         ValuesReturnFilter      *p;
1214         struct berval tmp;
1215         ber_len_t len;
1216
1217         if ( vrf == NULL ) {
1218                 ber_str2bv_x( "No filter!", sizeof("No filter!")-1,
1219                         1, fstr, op->o_tmpmemctx );
1220                 return;
1221         }
1222
1223         fstr->bv_len = sizeof("()") - 1;
1224         fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
1225
1226         snprintf( fstr->bv_val, fstr->bv_len + 1, "()");
1227
1228         for ( p = vrf; p != NULL; p = p->vrf_next ) {
1229                 len = fstr->bv_len;
1230
1231                 simple_vrFilter2bv( op, p, &tmp );
1232                         
1233                 fstr->bv_len += tmp.bv_len;
1234                 fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
1235
1236                 snprintf( &fstr->bv_val[len-1], tmp.bv_len + 2, 
1237                         /*"("*/ "%s)", tmp.bv_val );
1238
1239                 op->o_tmpfree( tmp.bv_val, op->o_tmpmemctx );
1240         }
1241 }
1242
1243 static void
1244 simple_vrFilter2bv( Operation *op, ValuesReturnFilter *vrf, struct berval *fstr )
1245 {
1246         struct berval tmp;
1247         ber_len_t len;
1248
1249         if ( vrf == NULL ) {
1250                 ber_str2bv_x( "No filter!", sizeof("No filter!")-1, 1, fstr, op->o_tmpmemctx );
1251                 return;
1252         }
1253
1254         switch ( vrf->vrf_choice ) {
1255         case LDAP_FILTER_EQUALITY:
1256                 filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
1257
1258                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1259                         tmp.bv_len + ( sizeof("(=)") - 1 );
1260                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1261
1262                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
1263                         vrf->vrf_av_desc->ad_cname.bv_val,
1264                         tmp.bv_val );
1265
1266                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1267                 break;
1268
1269         case LDAP_FILTER_GE:
1270                 filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
1271
1272                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1273                         tmp.bv_len + ( sizeof("(>=)") - 1 );
1274                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1275
1276                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
1277                         vrf->vrf_av_desc->ad_cname.bv_val,
1278                         tmp.bv_val );
1279
1280                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1281                 break;
1282
1283         case LDAP_FILTER_LE:
1284                 filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
1285
1286                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1287                         tmp.bv_len + ( sizeof("(<=)") - 1 );
1288                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1289
1290                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
1291                         vrf->vrf_av_desc->ad_cname.bv_val,
1292                         tmp.bv_val );
1293
1294                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1295                 break;
1296
1297         case LDAP_FILTER_APPROX:
1298                 filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
1299
1300                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1301                         tmp.bv_len + ( sizeof("(~=)") - 1 );
1302                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1303
1304                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
1305                         vrf->vrf_av_desc->ad_cname.bv_val,
1306                         tmp.bv_val );
1307                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1308                 break;
1309
1310         case LDAP_FILTER_SUBSTRINGS:
1311                 fstr->bv_len = vrf->vrf_sub_desc->ad_cname.bv_len +
1312                         ( sizeof("(=*)") - 1 );
1313                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
1314
1315                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
1316                         vrf->vrf_sub_desc->ad_cname.bv_val );
1317
1318                 if ( vrf->vrf_sub_initial.bv_val != NULL ) {
1319                         len = fstr->bv_len;
1320
1321                         filter_escape_value_x( &vrf->vrf_sub_initial, &tmp, op->o_tmpmemctx );
1322
1323                         fstr->bv_len += tmp.bv_len;
1324                         fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
1325
1326                         snprintf( &fstr->bv_val[len-2], tmp.bv_len+3,
1327                                 /* "(attr=" */ "%s*)",
1328                                 tmp.bv_val );
1329
1330                         ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1331                 }
1332
1333                 if ( vrf->vrf_sub_any != NULL ) {
1334                         int i;
1335                         for ( i = 0; vrf->vrf_sub_any[i].bv_val != NULL; i++ ) {
1336                                 len = fstr->bv_len;
1337                                 filter_escape_value_x( &vrf->vrf_sub_any[i], &tmp, op->o_tmpmemctx );
1338
1339                                 fstr->bv_len += tmp.bv_len + 1;
1340                                 fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
1341
1342                                 snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
1343                                         /* "(attr=[init]*[any*]" */ "%s*)",
1344                                         tmp.bv_val );
1345                                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1346                         }
1347                 }
1348
1349                 if ( vrf->vrf_sub_final.bv_val != NULL ) {
1350                         len = fstr->bv_len;
1351
1352                         filter_escape_value_x( &vrf->vrf_sub_final, &tmp, op->o_tmpmemctx );
1353
1354                         fstr->bv_len += tmp.bv_len;
1355                         fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
1356
1357                         snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
1358                                 /* "(attr=[init*][any*]" */ "%s)",
1359                                 tmp.bv_val );
1360
1361                         ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1362                 }
1363
1364                 break;
1365
1366         case LDAP_FILTER_PRESENT:
1367                 fstr->bv_len = vrf->vrf_desc->ad_cname.bv_len +
1368                         ( sizeof("(=*)") - 1 );
1369                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1370
1371                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
1372                         vrf->vrf_desc->ad_cname.bv_val );
1373                 break;
1374
1375         case LDAP_FILTER_EXT: {
1376                 struct berval ad;
1377                 filter_escape_value_x( &vrf->vrf_mr_value, &tmp, op->o_tmpmemctx );
1378
1379                 if ( vrf->vrf_mr_desc ) {
1380                         ad = vrf->vrf_mr_desc->ad_cname;
1381                 } else {
1382                         ad.bv_len = 0;
1383                         ad.bv_val = "";
1384                 }
1385                         
1386                 fstr->bv_len = ad.bv_len +
1387                         ( vrf->vrf_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
1388                         ( vrf->vrf_mr_rule_text.bv_len ? vrf->vrf_mr_rule_text.bv_len+1 : 0 ) +
1389                         tmp.bv_len + ( sizeof("(:=)") - 1 );
1390                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1391
1392                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
1393                         ad.bv_val,
1394                         vrf->vrf_mr_dnattrs ? ":dn" : "",
1395                         vrf->vrf_mr_rule_text.bv_len ? ":" : "",
1396                         vrf->vrf_mr_rule_text.bv_len ? vrf->vrf_mr_rule_text.bv_val : "",
1397                         tmp.bv_val );
1398
1399                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1400                 } break;
1401
1402         case SLAPD_FILTER_COMPUTED:
1403                 ber_str2bv_x(
1404                         vrf->vrf_result == LDAP_COMPARE_FALSE ? "(?=false)" :
1405                         vrf->vrf_result == LDAP_COMPARE_TRUE ? "(?=true)" :
1406                         vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
1407                         "(?=error)",
1408                         vrf->vrf_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
1409                         vrf->vrf_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
1410                         vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
1411                         sizeof("(?=error)")-1,
1412                         1, fstr, op->o_tmpmemctx );
1413                 break;
1414
1415         default:
1416                 ber_str2bv_x( "(?=unknown)", sizeof("(?=unknown)")-1,
1417                         1, fstr, op->o_tmpmemctx );
1418                 break;
1419         }
1420 }