]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
Updated for schemas.
[openldap] / servers / slapd / filter.c
1 /* filter.c - routines for parsing and dealing with filters */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 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         Connection *conn,
19         BerElement *ber,
20         Filter **f,
21         char **fstr,
22         const char **text );
23
24 static int      get_substring_filter(
25         Connection *conn,
26         BerElement *ber,
27         Filter *f,
28         char **fstr,
29         const char **text );
30
31 int
32 get_filter(
33         Connection *conn,
34         BerElement *ber,
35         Filter **filt,
36         char **fstr,
37         const char **text )
38 {
39         ber_tag_t       tag;
40         ber_len_t       len;
41         int             err;
42         Filter          *f;
43         char            *ftmp = NULL;
44
45         Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
46
47         /*
48          * A filter looks like this coming in:
49          *      Filter ::= CHOICE {
50          *              and             [0]     SET OF Filter,
51          *              or              [1]     SET OF Filter,
52          *              not             [2]     Filter,
53          *              equalityMatch   [3]     AttributeValueAssertion,
54          *              substrings      [4]     SubstringFilter,
55          *              greaterOrEqual  [5]     AttributeValueAssertion,
56          *              lessOrEqual     [6]     AttributeValueAssertion,
57          *              present         [7]     AttributeType,,
58          *              approxMatch     [8]     AttributeValueAssertion
59          *              extensibleMatch [9] MatchingRuleAssertion
60          *      }
61          *
62          *      SubstringFilter ::= SEQUENCE {
63          *              type               AttributeType,
64          *              SEQUENCE OF CHOICE {
65          *                      initial          [0] IA5String,
66          *                      any              [1] IA5String,
67          *                      final            [2] IA5String
68          *              }
69          *      }
70          *
71      *  MatchingRuleAssertion ::= SEQUENCE {
72      *          matchingRule    [1] MatchingRuleId OPTIONAL,
73      *          type            [2] AttributeDescription OPTIONAL,
74      *          matchValue      [3] AssertionValue,
75      *          dnAttributes    [4] BOOLEAN DEFAULT FALSE
76          *      }
77          *
78          */
79
80         tag = ber_peek_tag( ber, &len );
81
82         if( tag == LBER_ERROR ) {
83                 *text = "error decoding filter";
84                 return SLAPD_DISCONNECT;
85         }
86
87         f = (Filter *) ch_malloc( sizeof(Filter) );
88         f->f_next = NULL;
89
90         err = LDAP_SUCCESS;
91         *fstr = NULL;
92         f->f_choice = tag; 
93
94         switch ( f->f_choice ) {
95         case LDAP_FILTER_EQUALITY:
96                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
97
98 #ifdef SLAPD_SCHEMA_NOT_COMPAT
99                 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY, text );
100 #else
101                 err = get_ava( ber, &f->f_ava, text );
102 #endif
103                 if ( err != LDAP_SUCCESS ) {
104                         break;
105                 }
106
107 #ifdef SLAPD_SCHEMA_NOT_COMPAT
108                 assert( f->f_ava != NULL );
109
110                 *fstr = ch_malloc( sizeof("(=)")
111                         + f->f_av_desc->ad_cname->bv_len
112                         + f->f_av_value->bv_len );
113
114                 sprintf( *fstr, "(%s=%s)",
115                         f->f_av_desc->ad_cname->bv_val,
116                     f->f_av_value->bv_val );
117
118 #else
119                 *fstr = ch_malloc( sizeof("(=)")
120                         + strlen( f->f_avtype )
121                         + f->f_avvalue.bv_len);
122                 sprintf( *fstr, "(%s=%s)", f->f_avtype,
123                     f->f_avvalue.bv_val );
124 #endif
125                 break;
126
127         case LDAP_FILTER_SUBSTRINGS:
128                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
129                 err = get_substring_filter( conn, ber, f, fstr, text );
130                 break;
131
132         case LDAP_FILTER_GE:
133                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
134
135 #ifdef SLAPD_SCHEMA_NOT_COMPAT
136                 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
137 #else
138                 err = get_ava( ber, &f->f_ava, text );
139 #endif
140                 if ( err != LDAP_SUCCESS ) {
141                         break;
142                 }
143
144 #ifdef SLAPD_SCHEMA_NOT_COMPAT
145                 *fstr = ch_malloc( sizeof("(>=)")
146                         + f->f_av_desc->ad_cname->bv_len
147                         + f->f_av_value->bv_len );
148
149                 sprintf( *fstr, "(%s>=%s)",
150                         f->f_av_desc->ad_cname->bv_val,
151                     f->f_av_value->bv_val );
152
153 #else
154                 *fstr = ch_malloc( sizeof("(>=)")
155                         + strlen( f->f_avtype )
156                         + f->f_avvalue.bv_len);
157                 sprintf( *fstr, "(%s>=%s)", f->f_avtype,
158                     f->f_avvalue.bv_val );
159 #endif
160                 break;
161
162         case LDAP_FILTER_LE:
163                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
164
165 #ifdef SLAPD_SCHEMA_NOT_COMPAT
166                 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
167 #else
168                 err = get_ava( ber, &f->f_ava, text );
169 #endif
170                 if ( err != LDAP_SUCCESS ) {
171                         break;
172                 }
173
174
175 #ifdef SLAPD_SCHEMA_NOT_COMPAT
176                 *fstr = ch_malloc( sizeof("(<=)")
177                         + f->f_av_desc->ad_cname->bv_len
178                         + f->f_av_value->bv_len );
179
180                 sprintf( *fstr, "(%s<=%s)",
181                         f->f_av_desc->ad_cname->bv_val,
182                     f->f_av_value->bv_val );
183
184 #else
185                 *fstr = ch_malloc( sizeof("(<=)")
186                         + strlen( f->f_avtype )
187                         + f->f_avvalue.bv_len);
188                 sprintf( *fstr, "(%s<=%s)", f->f_avtype,
189                     f->f_avvalue.bv_val );
190 #endif
191                 break;
192
193         case LDAP_FILTER_PRESENT: {
194                 struct berval type;
195
196                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
197
198                 if ( ber_scanf( ber, "o", &type ) == LBER_ERROR ) {
199                         err = SLAPD_DISCONNECT;
200                         *text = "error decoding filter";
201                         break;
202                 }
203
204 #ifdef SLAPD_SCHEMA_NOT_COMPAT
205                 f->f_desc = NULL;
206                 err = slap_bv2ad( &type, &f->f_desc, text );
207
208                 if( err != LDAP_SUCCESS ) {
209                         ch_free( type.bv_val );
210                         break;
211                 }
212
213                 ch_free( type.bv_val );
214
215                 *fstr = ch_malloc( sizeof("(=*)")
216                         + f->f_desc->ad_cname->bv_len );
217                 sprintf( *fstr, "(%s=*)",
218                         f->f_desc->ad_cname->bv_val );
219
220 #else
221                 f->f_type = type.bv_val;
222                 err = LDAP_SUCCESS;
223                 attr_normalize( f->f_type );
224                 *fstr = ch_malloc( sizeof("(=*)")
225                         + strlen( f->f_type ) );
226                 sprintf( *fstr, "(%s=*)", f->f_type );
227 #endif
228                 } break;
229
230         case LDAP_FILTER_APPROX:
231                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
232
233 #ifdef SLAPD_SCHEMA_NOT_COMPAT
234                 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY_APPROX, text );
235 #else
236                 err = get_ava( ber, &f->f_ava, text );
237 #endif
238                 if ( err != LDAP_SUCCESS ) {
239                         break;
240                 }
241
242 #ifdef SLAPD_SCHEMA_NOT_COMPAT
243                 *fstr = ch_malloc( sizeof("(~=)")
244                         + f->f_av_desc->ad_cname->bv_len
245                         + f->f_av_value->bv_len );
246
247                 sprintf( *fstr, "(%s~=%s)",
248                         f->f_av_desc->ad_cname->bv_val,
249                     f->f_av_value->bv_val );
250
251 #else
252                 *fstr = ch_malloc( sizeof("(~=)")
253                         + strlen( f->f_avtype )
254                         + f->f_avvalue.bv_len);
255                 sprintf( *fstr, "(%s~=%s)", f->f_avtype,
256                     f->f_avvalue.bv_val );
257 #endif
258                 break;
259
260         case LDAP_FILTER_AND:
261                 Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
262                 err = get_filter_list( conn, ber, &f->f_and, &ftmp, text );
263                 if ( err != LDAP_SUCCESS ) {
264                         break;
265                 }
266                 *fstr = ch_malloc( sizeof("(&)")
267                         + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
268                 sprintf( *fstr, "(&%s)",
269                         ftmp == NULL ? "" : ftmp );
270                 break;
271
272         case LDAP_FILTER_OR:
273                 Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
274                 err = get_filter_list( conn, ber, &f->f_and, &ftmp, text );
275                 if ( err != LDAP_SUCCESS ) {
276                         break;
277                 }
278                 *fstr = ch_malloc( sizeof("(!)")
279                         + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
280                 sprintf( *fstr, "(|%s)",
281                         ftmp == NULL ? "" : ftmp );
282                 break;
283
284         case LDAP_FILTER_NOT:
285                 Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
286                 (void) ber_skip_tag( ber, &len );
287                 err = get_filter( conn, ber, &f->f_not, &ftmp, text );
288                 if ( err != LDAP_SUCCESS ) {
289                         break;
290                 }
291                 *fstr = ch_malloc( sizeof("(!)")
292                         + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
293                 sprintf( *fstr, "(!%s)",
294                         ftmp == NULL ? "" : ftmp );
295                 break;
296
297         case LDAP_FILTER_EXT:
298                 /* not yet implemented */
299                 Debug( LDAP_DEBUG_ANY, "extensible match not yet implemented.\n",
300                        f->f_choice, 0, 0 );
301                 f->f_choice = SLAPD_FILTER_COMPUTED;
302                 f->f_result = SLAPD_COMPARE_UNDEFINED;
303                 *fstr = ch_strdup( "(extended)" );
304                 break;
305
306         default:
307                 Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n",
308                        f->f_choice, 0, 0 );
309                 f->f_choice = SLAPD_FILTER_COMPUTED;
310                 f->f_result = SLAPD_COMPARE_UNDEFINED;
311                 *fstr = ch_strdup( "(undefined)" );
312                 break;
313         }
314
315         free( ftmp );
316
317         if ( err != LDAP_SUCCESS ) {
318                 if ( *fstr != NULL ) {
319                         free( *fstr );
320                 }
321
322                 if( err != SLAPD_DISCONNECT ) {
323                         /* ignore error */
324                         f->f_choice = SLAPD_FILTER_COMPUTED;
325                         f->f_result = SLAPD_COMPARE_UNDEFINED;
326                         *fstr = ch_strdup( "(badfilter)" );
327                         err = LDAP_SUCCESS;
328                         *filt = f;
329
330                 } else {
331                         free(f);
332                 }
333         } else {
334                 *filt = f;
335         }
336
337         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
338         return( err );
339 }
340
341 static int
342 get_filter_list( Connection *conn, BerElement *ber,
343         Filter **f, char **fstr,
344         const char **text )
345 {
346         Filter          **new;
347         int             err;
348         ber_tag_t       tag;
349         ber_len_t       len;
350         char            *last, *ftmp;
351
352         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
353
354         *fstr = NULL;
355         new = f;
356         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
357             tag = ber_next_element( ber, &len, last ) )
358         {
359                 err = get_filter( conn, ber, new, &ftmp, text );
360                 if ( err != LDAP_SUCCESS )
361                         return( err );
362
363                 if ( *fstr == NULL ) {
364                         *fstr = ftmp;
365                 } else {
366                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
367                             strlen( ftmp ) + 1 );
368                         strcat( *fstr, ftmp );
369                         free( ftmp );
370                 }
371                 new = &(*new)->f_next;
372         }
373         *new = NULL;
374
375         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
376         return( LDAP_SUCCESS );
377 }
378
379 static int
380 get_substring_filter(
381     Connection  *conn,
382     BerElement  *ber,
383     Filter      *f,
384     char        **fstr,
385         const char      **text
386 )
387 {
388         ber_tag_t       tag;
389         ber_len_t       len;
390         ber_tag_t       rc;
391         struct berval *value;
392         char            *last;
393         struct berval type;
394 #ifdef SLAPD_SCHEMA_NOT_COMPAT
395         struct berval *nvalue;
396 #else
397         int             syntax;
398 #endif
399         *text = "error decoding filter";
400
401         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
402
403         if ( ber_scanf( ber, "{o" /*}*/, &type ) == LBER_ERROR ) {
404                 return SLAPD_DISCONNECT;
405         }
406
407 #ifdef SLAPD_SCHEMA_NOT_COMPAT
408         f->f_sub = ch_calloc( 1, sizeof(SubstringsAssertion) );
409         f->f_sub_desc = NULL;
410         rc = slap_bv2ad( &type, &f->f_sub_desc, text );
411
412         ch_free( type.bv_val );
413
414         if( rc != LDAP_SUCCESS ) {
415                 text = NULL;
416                 ch_free( f->f_sub );
417                 f->f_choice = SLAPD_FILTER_COMPUTED;
418                 f->f_result = SLAPD_COMPARE_UNDEFINED;
419                 *fstr = ch_strdup( "(undefined)" );
420                 return LDAP_SUCCESS;
421         }
422 #else
423         f->f_sub_type = type.bv_val;
424         attr_normalize( f->f_sub_type );
425
426         /* should get real syntax and see if we have a substring matching rule */
427         syntax = attr_syntax( f->f_sub_type );
428 #endif
429
430         f->f_sub_initial = NULL;
431         f->f_sub_any = NULL;
432         f->f_sub_final = NULL;
433
434 #ifdef SLAPD_SCHEMA_NOT_COMPAT
435         if( fstr ) {
436                 *fstr = ch_malloc( sizeof("(=" /*)*/) +
437                         f->f_sub_desc->ad_cname->bv_len );
438                 sprintf( *fstr, "(%s=" /*)*/, f->f_sub_desc->ad_cname->bv_val );
439         }
440 #else
441         if( fstr ) {
442                 *fstr = ch_malloc( strlen( f->f_sub_type ) + 3 );
443                 sprintf( *fstr, "(%s=" /*)*/, f->f_sub_type );
444         }
445 #endif
446
447         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
448             tag = ber_next_element( ber, &len, last ) )
449         {
450 #ifdef SLAPD_SCHEMA_NOT_COMPAT
451                 unsigned usage;
452 #endif
453
454                 rc = ber_scanf( ber, "O", &value );
455                 if ( rc == LBER_ERROR ) {
456                         rc = SLAPD_DISCONNECT;
457                         goto return_error;
458                 }
459
460                 if ( value == NULL || value->bv_len == 0 ) {
461                         ber_bvfree( value );
462                         rc = LDAP_INVALID_SYNTAX;
463                         goto return_error;
464                 } 
465
466 #ifdef SLAPD_SCHEMA_NOT_COMPAT
467                 switch ( tag ) {
468                 case LDAP_SUBSTRING_INITIAL:
469                         usage = SLAP_MR_SUBSTR_INITIAL;
470                         break;
471
472                 case LDAP_SUBSTRING_ANY:
473                         usage = SLAP_MR_SUBSTR_ANY;
474                         break;
475
476                 case LDAP_SUBSTRING_FINAL:
477                         usage = SLAP_MR_SUBSTR_FINAL;
478                         break;
479
480                 default:
481                         rc = LDAP_PROTOCOL_ERROR;
482
483                         Debug( LDAP_DEBUG_FILTER,
484                                 "  unknown substring choice=%ld\n",
485                                 (long) tag, 0, 0 );
486
487                         ber_bvfree( value );
488                         goto return_error;
489                 }
490
491                 rc = value_normalize( f->f_sub_desc, usage, value, &nvalue, text );
492                 ber_bvfree( value );
493
494                 if( rc != LDAP_SUCCESS ) {
495                         goto return_error;
496                 }
497
498                 value = nvalue;
499 #else
500
501                 /* we should call a substring syntax normalization routine */
502                 value_normalize( value->bv_val, syntax );
503                 /* this is bogus, value_normalize should take a berval */
504                 value->bv_len = strlen( value->bv_val );
505 #endif
506
507                 rc = LDAP_PROTOCOL_ERROR;
508
509                 switch ( tag ) {
510                 case LDAP_SUBSTRING_INITIAL:
511                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
512                         if ( f->f_sub_initial != NULL ) {
513                                 ber_bvfree( value );
514                                 goto return_error;
515                         }
516
517                         f->f_sub_initial = value;
518
519                         if( fstr ) {
520                                 *fstr = ch_realloc( *fstr,
521                                         strlen( *fstr ) + value->bv_len + 1 );
522                                 strcat( *fstr, value->bv_val );
523                         }
524                         break;
525
526                 case LDAP_SUBSTRING_ANY:
527                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
528                         if( ber_bvecadd( &f->f_sub_any, value ) < 0 ) {
529                                 ber_bvfree( value );
530                                 goto return_error;
531                         }
532
533                         if( fstr ) {
534                                 *fstr = ch_realloc( *fstr,
535                                         strlen( *fstr ) + value->bv_len + 2 );
536                                 strcat( *fstr, "*" );
537                                 strcat( *fstr, value->bv_val );
538                         }
539                         break;
540
541                 case LDAP_SUBSTRING_FINAL:
542                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
543                         if ( f->f_sub_final != NULL ) {
544                                 ber_bvfree( value );
545                                 goto return_error;
546                         }
547                         f->f_sub_final = value;
548
549                         if( fstr ) {
550                                 *fstr = ch_realloc( *fstr,
551                                         strlen( *fstr ) + value->bv_len + 2 );
552                                 strcat( *fstr, "*" );
553                                 strcat( *fstr, value->bv_val );
554                         }
555                         break;
556
557                 default:
558                         Debug( LDAP_DEBUG_FILTER,
559                                 "  unknown substring type=%ld\n",
560                                 (long) tag, 0, 0 );
561
562                         ber_bvfree( value );
563
564 return_error:
565                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
566                                 (long) rc, 0, 0 );
567
568                         if( fstr ) {
569                                 free( *fstr );
570                                 *fstr = NULL;
571                         }
572
573 #ifdef SLAPD_SCHEMA_NOT_COMPAT
574                         ad_free( f->f_sub_desc, 1 );
575 #else
576                         ch_free( f->f_sub_type );
577 #endif
578                         ber_bvfree( f->f_sub_initial );
579                         ber_bvecfree( f->f_sub_any );
580                         ber_bvfree( f->f_sub_final );
581 #ifdef SLAPD_SCHEMA_NOT_COMPAT
582                         ch_free( f->f_sub );
583 #endif
584                         return rc;
585                 }
586         }
587
588         if( fstr ) {
589                 *fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
590                 if ( f->f_sub_final == NULL ) {
591                         strcat( *fstr, "*" );
592                 }
593                 strcat( *fstr, /*(*/ ")" );
594         }
595
596         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
597         return( LDAP_SUCCESS );
598 }
599
600 void
601 filter_free( Filter *f )
602 {
603         Filter  *p, *next;
604
605         if ( f == NULL ) {
606                 return;
607         }
608
609         switch ( f->f_choice ) {
610         case LDAP_FILTER_PRESENT:
611 #ifdef SLAPD_SCHEMA_NOT_COMPAT
612                 ad_free( f->f_desc, 1 );
613 #else
614                 if ( f->f_type != NULL ) {
615                         free( f->f_type );
616                 }
617 #endif
618                 break;
619
620         case LDAP_FILTER_EQUALITY:
621         case LDAP_FILTER_GE:
622         case LDAP_FILTER_LE:
623         case LDAP_FILTER_APPROX:
624 #ifdef SLAPD_SCHEMA_NOT_COMPAT
625                 ava_free( f->f_ava, 1 );
626 #else
627                 ava_free( &f->f_ava, 0 );
628 #endif
629                 break;
630
631         case LDAP_FILTER_SUBSTRINGS:
632 #ifdef SLAPD_SCHEMA_NOT_COMPAT
633                 ad_free( f->f_sub_desc, 1 );
634                 if ( f->f_sub_initial != NULL ) {
635                         ber_bvfree( f->f_sub_initial );
636                 }
637                 ber_bvecfree( f->f_sub_any );
638                 if ( f->f_sub_final != NULL ) {
639                         ber_bvfree( f->f_sub_final );
640                 }
641 #else
642                 if ( f->f_sub_type != NULL ) {
643                         free( f->f_sub_type );
644                 }
645                 if ( f->f_sub_initial != NULL ) {
646                         ber_bvfree( f->f_sub_initial );
647                 }
648                 ber_bvecfree( f->f_sub_any );
649                 if ( f->f_sub_final != NULL ) {
650                         ber_bvfree( f->f_sub_final );
651                 }
652 #endif
653                 break;
654
655         case LDAP_FILTER_AND:
656         case LDAP_FILTER_OR:
657         case LDAP_FILTER_NOT:
658                 for ( p = f->f_list; p != NULL; p = next ) {
659                         next = p->f_next;
660                         filter_free( p );
661                 }
662                 break;
663
664         case SLAPD_FILTER_COMPUTED:
665                 break;
666
667         default:
668                 Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
669                        f->f_choice, 0, 0 );
670                 break;
671         }
672
673         free( f );
674 }
675
676 #ifdef LDAP_DEBUG
677
678 void
679 filter_print( Filter *f )
680 {
681         int     i;
682         Filter  *p;
683
684         if ( f == NULL ) {
685                 fprintf( stderr, "No filter!" );
686         }
687
688         switch ( f->f_choice ) {
689         case LDAP_FILTER_EQUALITY:
690 #ifdef SLAPD_SCHEMA_NOT_COMPAT
691                 fprintf( stderr, "(%s=%s)",
692                         f->f_av_desc->ad_cname->bv_val,
693                     f->f_av_value->bv_val );
694 #else
695                 fprintf( stderr, "(%s=%s)",
696                         f->f_ava.ava_type,
697                     f->f_ava.ava_value.bv_val );
698 #endif
699                 break;
700
701         case LDAP_FILTER_GE:
702 #ifdef SLAPD_SCHEMA_NOT_COMPAT
703                 fprintf( stderr, "(%s>=%s)",
704                         f->f_av_desc->ad_cname->bv_val,
705                     f->f_av_value->bv_val );
706 #else
707                 fprintf( stderr, "(%s>=%s)",
708                         f->f_ava.ava_type,
709                     f->f_ava.ava_value.bv_val );
710 #endif
711                 break;
712
713         case LDAP_FILTER_LE:
714 #ifdef SLAPD_SCHEMA_NOT_COMPAT
715                 fprintf( stderr, "(%s<=%s)",
716                         f->f_ava->aa_desc->ad_cname->bv_val,
717                     f->f_ava->aa_value->bv_val );
718 #else
719                 fprintf( stderr, "(%s<=%s)",
720                         f->f_ava.ava_type,
721                     f->f_ava.ava_value.bv_val );
722 #endif
723                 break;
724
725         case LDAP_FILTER_APPROX:
726 #ifdef SLAPD_SCHEMA_NOT_COMPAT
727                 fprintf( stderr, "(%s~=%s)",
728                         f->f_ava->aa_desc->ad_cname->bv_val,
729                     f->f_ava->aa_value->bv_val );
730 #else
731                 fprintf( stderr, "(%s~=%s)",
732                         f->f_ava.ava_type,
733                     f->f_ava.ava_value.bv_val );
734 #endif
735                 break;
736
737         case LDAP_FILTER_SUBSTRINGS:
738 #ifdef SLAPD_SCHEMA_NOT_COMPAT
739                 fprintf( stderr, "(%s=" /*)*/,
740                         f->f_sub_desc->ad_cname->bv_val );
741 #else
742                 fprintf( stderr, "(%s=" /*)*/,
743                         f->f_sub_type );
744 #endif
745                 if ( f->f_sub_initial != NULL ) {
746                         fprintf( stderr, "%s",
747                                 f->f_sub_initial->bv_val );
748                 }
749                 if ( f->f_sub_any != NULL ) {
750                         for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
751                                 fprintf( stderr, "*%s",
752                                         f->f_sub_any[i]->bv_val );
753                         }
754                 }
755                 if ( f->f_sub_final != NULL ) {
756                         fprintf( stderr,
757                                 "*%s", f->f_sub_final->bv_val );
758                 }
759                 fprintf( stderr, /*(*/ ")" );
760                 break;
761
762         case LDAP_FILTER_PRESENT:
763 #ifdef SLAPD_SCHEMA_NOT_COMPAT
764                 fprintf( stderr, "(%s=*)",
765                         f->f_desc->ad_cname->bv_val );
766 #else
767                 fprintf( stderr, "(%s=*)",
768                         f->f_type );
769 #endif
770                 break;
771
772         case LDAP_FILTER_AND:
773         case LDAP_FILTER_OR:
774         case LDAP_FILTER_NOT:
775                 fprintf( stderr, "(%c" /*)*/,
776                         f->f_choice == LDAP_FILTER_AND ? '&' :
777                     f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
778                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
779                         filter_print( p );
780                 }
781                 fprintf( stderr, /*(*/ ")" );
782                 break;
783
784         case SLAPD_FILTER_COMPUTED:
785                 fprintf( stderr, "(?=%s)",
786                         f->f_result == LDAP_COMPARE_FALSE ? "false" :
787                         f->f_result == LDAP_COMPARE_TRUE ? "true" :
788                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
789                         "error" );
790                 break;
791
792         default:
793                 fprintf( stderr, "(unknown-filter=%lu)", f->f_choice );
794                 break;
795         }
796 }
797
798 #endif /* ldap_debug */