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