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