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