]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
Const'ification
[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         if ( err != LDAP_SUCCESS ) {
316                 free( (char *) f );
317                 if ( *fstr != NULL ) {
318                         free( *fstr );
319                 }
320         } else {
321                 *filt = f;
322         }
323
324         free( ftmp );
325
326         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
327         return( err );
328 }
329
330 static int
331 get_filter_list( Connection *conn, BerElement *ber,
332         Filter **f, char **fstr,
333         const char **text )
334 {
335         Filter          **new;
336         int             err;
337         ber_tag_t       tag;
338         ber_len_t       len;
339         char            *last, *ftmp;
340
341         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
342
343         *fstr = NULL;
344         new = f;
345         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
346             tag = ber_next_element( ber, &len, last ) )
347         {
348                 err = get_filter( conn, ber, new, &ftmp, text );
349                 if ( err != LDAP_SUCCESS )
350                         return( err );
351
352                 if ( *fstr == NULL ) {
353                         *fstr = ftmp;
354                 } else {
355                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
356                             strlen( ftmp ) + 1 );
357                         strcat( *fstr, ftmp );
358                         free( ftmp );
359                 }
360                 new = &(*new)->f_next;
361         }
362         *new = NULL;
363
364         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
365         return( LDAP_SUCCESS );
366 }
367
368 static int
369 get_substring_filter(
370     Connection  *conn,
371     BerElement  *ber,
372     Filter      *f,
373     char        **fstr,
374         const char      **text
375 )
376 {
377         ber_tag_t       tag;
378         ber_len_t       len;
379         ber_tag_t       rc;
380         struct berval *value;
381         char            *last;
382         struct berval type;
383 #ifdef SLAPD_SCHEMA_NOT_COMPAT
384         struct berval *nvalue;
385 #else
386         int             syntax;
387 #endif
388         *text = "error decoding filter";
389
390         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
391
392         if ( ber_scanf( ber, "{o" /*}*/, &type ) == LBER_ERROR ) {
393                 return SLAPD_DISCONNECT;
394         }
395
396 #ifdef SLAPD_SCHEMA_NOT_COMPAT
397         f->f_sub_desc = NULL;
398         rc = slap_bv2ad( &type, &f->f_sub_desc, text );
399
400         ch_free( type.bv_val );
401
402         if( rc != LDAP_SUCCESS ) {
403                 text = NULL;
404                 f->f_choice = SLAPD_FILTER_COMPUTED;
405                 f->f_result = SLAPD_COMPARE_UNDEFINED;
406                 *fstr = ch_strdup( "(undefined)" );
407                 return LDAP_SUCCESS;
408         }
409 #else
410         f->f_sub_type = type.bv_val;
411         attr_normalize( f->f_sub_type );
412
413         /* should get real syntax and see if we have a substring matching rule */
414         syntax = attr_syntax( f->f_sub_type );
415 #endif
416
417         f->f_sub_initial = NULL;
418         f->f_sub_any = NULL;
419         f->f_sub_final = NULL;
420
421 #ifdef SLAPD_SCHEMA_NOT_COMPAT
422         if( fstr ) {
423                 *fstr = ch_malloc( sizeof("(=" /*)*/) +
424                         f->f_sub_desc->ad_cname->bv_len );
425                 sprintf( *fstr, "(%s=" /*)*/, f->f_sub_desc->ad_cname->bv_val );
426         }
427 #else
428         if( fstr ) {
429                 *fstr = ch_malloc( strlen( f->f_sub_type ) + 3 );
430                 sprintf( *fstr, "(%s=" /*)*/, f->f_sub_type );
431         }
432 #endif
433
434         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
435             tag = ber_next_element( ber, &len, last ) )
436         {
437 #ifdef SLAPD_SCHEMA_NOT_COMPAT
438                 unsigned usage;
439 #endif
440
441                 rc = ber_scanf( ber, "O", &value );
442                 if ( rc == LBER_ERROR ) {
443                         rc = SLAPD_DISCONNECT;
444                         goto return_error;
445                 }
446
447                 if ( value == NULL || value->bv_len == 0 ) {
448                         ber_bvfree( value );
449                         rc = LDAP_INVALID_SYNTAX;
450                         goto return_error;
451                 } 
452
453 #ifdef SLAPD_SCHEMA_NOT_COMPAT
454                 switch ( tag ) {
455                 case LDAP_SUBSTRING_INITIAL:
456                         usage = SLAP_MR_SUBSTR_INITIAL;
457                         break;
458
459                 case LDAP_SUBSTRING_ANY:
460                         usage = SLAP_MR_SUBSTR_ANY;
461                         break;
462
463                 case LDAP_SUBSTRING_FINAL:
464                         usage = SLAP_MR_SUBSTR_FINAL;
465                         break;
466
467                 default:
468                         rc = LDAP_PROTOCOL_ERROR;
469
470                         Debug( LDAP_DEBUG_FILTER,
471                                 "  unknown substring choice=%ld\n",
472                                 (long) tag, 0, 0 );
473
474                         ber_bvfree( value );
475                         goto return_error;
476                 }
477
478                 rc = value_normalize( f->f_sub_desc, usage, value, &nvalue, text );
479                 ber_bvfree( value );
480
481                 if( rc != LDAP_SUCCESS ) {
482                         goto return_error;
483                 }
484
485                 value = nvalue;
486 #else
487
488                 /* we should call a substring syntax normalization routine */
489                 value_normalize( value->bv_val, syntax );
490                 /* this is bogus, value_normalize should take a berval */
491                 value->bv_len = strlen( value->bv_val );
492 #endif
493
494                 rc = LDAP_PROTOCOL_ERROR;
495
496                 switch ( tag ) {
497                 case LDAP_SUBSTRING_INITIAL:
498                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
499                         if ( f->f_sub_initial != NULL ) {
500                                 ber_bvfree( value );
501                                 goto return_error;
502                         }
503
504                         f->f_sub_initial = value;
505
506                         if( fstr ) {
507                                 *fstr = ch_realloc( *fstr,
508                                         strlen( *fstr ) + value->bv_len + 1 );
509                                 strcat( *fstr, value->bv_val );
510                         }
511                         break;
512
513                 case LDAP_SUBSTRING_ANY:
514                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
515                         if( ber_bvecadd( &f->f_sub_any, value ) < 0 ) {
516                                 ber_bvfree( value );
517                                 goto return_error;
518                         }
519
520                         if( fstr ) {
521                                 *fstr = ch_realloc( *fstr,
522                                         strlen( *fstr ) + value->bv_len + 2 );
523                                 strcat( *fstr, "*" );
524                                 strcat( *fstr, value->bv_val );
525                         }
526                         break;
527
528                 case LDAP_SUBSTRING_FINAL:
529                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
530                         if ( f->f_sub_final != NULL ) {
531                                 ber_bvfree( value );
532                                 goto return_error;
533                         }
534                         f->f_sub_final = value;
535
536                         if( fstr ) {
537                                 *fstr = ch_realloc( *fstr,
538                                         strlen( *fstr ) + value->bv_len + 2 );
539                                 strcat( *fstr, "*" );
540                                 strcat( *fstr, value->bv_val );
541                         }
542                         break;
543
544                 default:
545                         Debug( LDAP_DEBUG_FILTER,
546                                 "  unknown substring type=%ld\n",
547                                 (long) tag, 0, 0 );
548
549                         ber_bvfree( value );
550
551 return_error:
552                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
553                                 (long) rc, 0, 0 );
554
555                         if( fstr ) {
556                                 free( *fstr );
557                                 *fstr = NULL;
558                         }
559
560 #ifdef SLAPD_SCHEMA_NOT_COMPAT
561                         ad_free( f->f_sub_desc, 1 );
562 #else
563                         ch_free( f->f_sub_type );
564 #endif
565                         ber_bvfree( f->f_sub_initial );
566                         ber_bvecfree( f->f_sub_any );
567                         ber_bvfree( f->f_sub_final );
568                         return rc;
569                 }
570         }
571
572         if( fstr ) {
573                 *fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
574                 if ( f->f_sub_final == NULL ) {
575                         strcat( *fstr, "*" );
576                 }
577                 strcat( *fstr, /*(*/ ")" );
578         }
579
580         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
581         return( LDAP_SUCCESS );
582 }
583
584 void
585 filter_free( Filter *f )
586 {
587         Filter  *p, *next;
588
589         if ( f == NULL ) {
590                 return;
591         }
592
593         switch ( f->f_choice ) {
594         case LDAP_FILTER_PRESENT:
595 #ifdef SLAPD_SCHEMA_NOT_COMPAT
596                 ad_free( f->f_desc, 1 );
597 #else
598                 if ( f->f_type != NULL ) {
599                         free( f->f_type );
600                 }
601 #endif
602                 break;
603
604         case LDAP_FILTER_EQUALITY:
605         case LDAP_FILTER_GE:
606         case LDAP_FILTER_LE:
607         case LDAP_FILTER_APPROX:
608 #ifdef SLAPD_SCHEMA_NOT_COMPAT
609                 ava_free( f->f_ava, 1 );
610 #else
611                 ava_free( &f->f_ava, 0 );
612 #endif
613                 break;
614
615         case LDAP_FILTER_SUBSTRINGS:
616 #ifdef SLAPD_SCHEMA_NOT_COMPAT
617                 ad_free( f->f_sub_desc, 1 );
618                 if ( f->f_sub_initial != NULL ) {
619                         ber_bvfree( f->f_sub_initial );
620                 }
621                 ber_bvecfree( f->f_sub_any );
622                 if ( f->f_sub_final != NULL ) {
623                         ber_bvfree( f->f_sub_final );
624                 }
625 #else
626                 if ( f->f_sub_type != NULL ) {
627                         free( f->f_sub_type );
628                 }
629                 if ( f->f_sub_initial != NULL ) {
630                         ber_bvfree( f->f_sub_initial );
631                 }
632                 ber_bvecfree( f->f_sub_any );
633                 if ( f->f_sub_final != NULL ) {
634                         ber_bvfree( f->f_sub_final );
635                 }
636 #endif
637                 break;
638
639         case LDAP_FILTER_AND:
640         case LDAP_FILTER_OR:
641         case LDAP_FILTER_NOT:
642                 for ( p = f->f_list; p != NULL; p = next ) {
643                         next = p->f_next;
644                         filter_free( p );
645                 }
646                 break;
647
648         case SLAPD_FILTER_COMPUTED:
649                 break;
650
651         default:
652                 Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
653                        f->f_choice, 0, 0 );
654                 break;
655         }
656
657         free( f );
658 }
659
660 #ifdef LDAP_DEBUG
661
662 void
663 filter_print( Filter *f )
664 {
665         int     i;
666         Filter  *p;
667
668         if ( f == NULL ) {
669                 fprintf( stderr, "No filter!" );
670         }
671
672         switch ( f->f_choice ) {
673         case LDAP_FILTER_EQUALITY:
674 #ifdef SLAPD_SCHEMA_NOT_COMPAT
675                 fprintf( stderr, "(%s=%s)",
676                         f->f_av_desc->ad_cname->bv_val,
677                     f->f_av_value->bv_val );
678 #else
679                 fprintf( stderr, "(%s=%s)",
680                         f->f_ava.ava_type,
681                     f->f_ava.ava_value.bv_val );
682 #endif
683                 break;
684
685         case LDAP_FILTER_GE:
686 #ifdef SLAPD_SCHEMA_NOT_COMPAT
687                 fprintf( stderr, "(%s>=%s)",
688                         f->f_av_desc->ad_cname->bv_val,
689                     f->f_av_value->bv_val );
690 #else
691                 fprintf( stderr, "(%s>=%s)",
692                         f->f_ava.ava_type,
693                     f->f_ava.ava_value.bv_val );
694 #endif
695                 break;
696
697         case LDAP_FILTER_LE:
698 #ifdef SLAPD_SCHEMA_NOT_COMPAT
699                 fprintf( stderr, "(%s<=%s)",
700                         f->f_ava->aa_desc->ad_cname->bv_val,
701                     f->f_ava->aa_value->bv_val );
702 #else
703                 fprintf( stderr, "(%s<=%s)",
704                         f->f_ava.ava_type,
705                     f->f_ava.ava_value.bv_val );
706 #endif
707                 break;
708
709         case LDAP_FILTER_APPROX:
710 #ifdef SLAPD_SCHEMA_NOT_COMPAT
711                 fprintf( stderr, "(%s~=%s)",
712                         f->f_ava->aa_desc->ad_cname->bv_val,
713                     f->f_ava->aa_value->bv_val );
714 #else
715                 fprintf( stderr, "(%s~=%s)",
716                         f->f_ava.ava_type,
717                     f->f_ava.ava_value.bv_val );
718 #endif
719                 break;
720
721         case LDAP_FILTER_SUBSTRINGS:
722 #ifdef SLAPD_SCHEMA_NOT_COMPAT
723                 fprintf( stderr, "(%s=" /*)*/,
724                         f->f_sub_desc->ad_cname->bv_val );
725 #else
726                 fprintf( stderr, "(%s=" /*)*/,
727                         f->f_sub_type );
728 #endif
729                 if ( f->f_sub_initial != NULL ) {
730                         fprintf( stderr, "%s",
731                                 f->f_sub_initial->bv_val );
732                 }
733                 if ( f->f_sub_any != NULL ) {
734                         for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
735                                 fprintf( stderr, "*%s",
736                                         f->f_sub_any[i]->bv_val );
737                         }
738                 }
739                 if ( f->f_sub_final != NULL ) {
740                         fprintf( stderr,
741                                 "*%s", f->f_sub_final->bv_val );
742                 }
743                 fprintf( stderr, /*(*/ ")" );
744                 break;
745
746         case LDAP_FILTER_PRESENT:
747 #ifdef SLAPD_SCHEMA_NOT_COMPAT
748                 fprintf( stderr, "(%s=*)",
749                         f->f_desc->ad_cname->bv_val );
750 #else
751                 fprintf( stderr, "(%s=*)",
752                         f->f_type );
753 #endif
754                 break;
755
756         case LDAP_FILTER_AND:
757         case LDAP_FILTER_OR:
758         case LDAP_FILTER_NOT:
759                 fprintf( stderr, "(%c" /*)*/,
760                         f->f_choice == LDAP_FILTER_AND ? '&' :
761                     f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
762                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
763                         filter_print( p );
764                 }
765                 fprintf( stderr, /*(*/ ")" );
766                 break;
767
768         case SLAPD_FILTER_COMPUTED:
769                 fprintf( stderr, "(?=%s)",
770                         f->f_result == LDAP_COMPARE_FALSE ? "false" :
771                         f->f_result == LDAP_COMPARE_TRUE ? "true" :
772                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
773                         "error" );
774                 break;
775
776         default:
777                 fprintf( stderr, "(unknown-filter=%lu)", f->f_choice );
778                 break;
779         }
780 }
781
782 #endif /* ldap_debug */