]> git.sur5r.net Git - openldap/blob - servers/slapd/component.c
fix messages
[openldap] / servers / slapd / component.c
1 /* component.c -- Component Filter Match Routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2005 The OpenLDAP Foundation.
6  * Portions Copyright 2004 by IBM Corporation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17
18 #include "portable.h"
19
20 #include <ac/string.h>
21 #include <ac/socket.h>
22
23 #include "lutil.h"
24 #include <ldap.h>
25 #include "slap.h"
26
27 #ifdef LDAP_COMP_MATCH
28
29 #include "component.h"
30
31 /*
32  * Following function pointers are initialized
33  * when a component module is loaded
34  */
35 alloc_nibble_func* nibble_mem_allocator = NULL;
36 free_nibble_func* nibble_mem_free = NULL;
37 convert_attr_to_comp_func* attr_converter = NULL;
38 convert_assert_to_comp_func* assert_converter = NULL ;
39 free_component_func* component_destructor = NULL ;
40 test_component_func* test_components = NULL;
41 test_membership_func* is_aliased_attribute = NULL;
42 component_encoder_func* component_encoder = NULL;
43 get_component_info_func* get_component_description = NULL;
44 #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
45 #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
46 #define MAX_LDAP_STR_LEN 128
47
48 static int
49 peek_componentId_type( ComponentAssertionValue* cav );
50
51 static int
52 strip_cav_str( ComponentAssertionValue* cav, char* str);
53
54 static int
55 peek_cav_str( ComponentAssertionValue* cav, char* str );
56
57 static int
58 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
59                                 ComponentFilter** filt, const char** text );
60
61 static void
62 free_comp_filter( ComponentFilter* f );
63
64 static int
65 test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, ComponentFilter *f );
66
67 int
68 componentCertificateValidate(
69         Syntax *syntax,
70         struct berval *val )
71 {
72         return LDAP_SUCCESS;
73 }
74
75 int
76 componentFilterValidate(
77         Syntax *syntax,
78         struct berval *val )
79 {
80         return LDAP_SUCCESS;
81 }
82
83 int
84 allComponentsValidate(
85         Syntax *syntax,
86         struct berval *val )
87 {
88         return LDAP_SUCCESS;
89 }
90
91 int
92 componentFilterMatch ( 
93         int *matchp, 
94         slap_mask_t flags, 
95         Syntax *syntax, 
96         MatchingRule *mr,
97         struct berval *value, 
98         void *assertedValue )
99 {
100         ComponentSyntaxInfo *csi_attr = (ComponentSyntaxInfo*)value;
101         MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
102         int num_attr, rc, i;
103
104         if ( !mr || !ma->ma_cf )
105                 return LDAP_INAPPROPRIATE_MATCHING;
106         /* Check if the component module is loaded */
107         if ( !attr_converter || !nibble_mem_allocator )
108                 return LDAP_INAPPROPRIATE_MATCHING;
109
110
111         rc = test_comp_filter( syntax, csi_attr, ma->ma_cf );
112
113         if ( rc == LDAP_COMPARE_TRUE ) {
114                 *matchp = 0;
115                 return LDAP_SUCCESS;
116         }
117         else if ( rc == LDAP_COMPARE_FALSE ) {
118                 *matchp = 1;
119                 return LDAP_SUCCESS;
120         }
121         else {
122                 return LDAP_INAPPROPRIATE_MATCHING;
123         }
124 }
125
126 int
127 directoryComponentsMatch( 
128         int *matchp, 
129         slap_mask_t flags, 
130         Syntax *syntax, 
131         MatchingRule *mr,
132         struct berval *value, 
133         void *assertedValue )
134 {
135         /* Only for Registeration */
136         *matchp = 0;
137         return LDAP_SUCCESS;
138 }
139
140 int
141 allComponentsMatch( 
142         int *matchp, 
143         slap_mask_t flags, 
144         Syntax *syntax, 
145         MatchingRule *mr,
146         struct berval *value, 
147         void *assertedValue )
148 {
149         /* Only for Registeration */
150         *matchp = 0;
151         return LDAP_SUCCESS;
152 }
153
154 static int
155 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
156 {
157         int len;
158
159         cav->cav_ptr = cav->cav_buf = bv->bv_val;
160         cav->cav_end = bv->bv_val + bv->bv_len;
161
162         return LDAP_SUCCESS;
163 }
164
165 ComponentReference*
166 dup_comp_ref ( Operation* op, ComponentReference* cr )
167 {
168         int rc, count = 0;
169         ComponentReference* dup_cr;
170         ComponentId* ci_curr;
171         ComponentId** ci_temp;
172         ber_int_t type;
173
174         dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
175
176         dup_cr->cr_len = cr->cr_len;
177         dup_cr->cr_string = cr->cr_string;
178
179         ci_temp = &dup_cr->cr_list;
180         ci_curr = cr->cr_list;
181
182         for ( ; ci_curr ; ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next ) {
183                 *ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
184                 if ( !ci_temp ) return NULL;
185                 **ci_temp = *ci_curr;
186         }
187
188         dup_cr->cr_curr = dup_cr->cr_list;
189
190         return dup_cr;
191 }
192
193 static int
194 dup_comp_filter_list (
195         Operation *op,
196         struct berval *bv,
197         ComponentFilter* in_f,
198         ComponentFilter** out_f )
199 {
200         ComponentFilter **new, *f;
201         int             rc;
202
203         new = out_f;
204         for ( f = in_f; f != NULL; f = f->cf_next ) {
205                 rc = dup_comp_filter( op, bv, f, new );
206                 if ( rc != LDAP_SUCCESS ) {
207                         return rc;
208                 }
209                 new = &(*new)->cf_next;
210         }
211         return LDAP_SUCCESS;
212 }
213
214 int
215 get_len_of_next_assert_value ( struct berval* bv, char separator )
216 {
217         int i = 0;
218         while (1) {
219                 if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
220                         break;
221                 i++;
222         }
223         bv->bv_val += (i + 1);
224         bv->bv_len -= (i + 1);
225         return i;
226 }
227
228 int
229 dup_comp_filter_item (
230         Operation *op,
231         struct berval* assert_bv,
232         ComponentAssertion* in_ca,
233         ComponentAssertion** out_ca )
234 {
235         ComponentAssertion* ca;
236         int len;
237
238         if ( !in_ca->ca_comp_ref )
239                 return SLAPD_DISCONNECT;
240
241         *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
242         if ( !(*out_ca) )
243                 return LDAP_NO_MEMORY;
244
245         (*out_ca)->ca_comp_data.cd_tree = NULL;
246         (*out_ca)->ca_comp_data.cd_mem_op = NULL;
247
248         (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
249         (*out_ca)->ca_use_def = 0;
250         (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
251
252         (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
253         len = get_len_of_next_assert_value ( assert_bv, '$' );
254         if ( len <= 0 )
255                 return SLAPD_DISCONNECT;
256         (*out_ca)->ca_ma_value.bv_len = len;
257         
258         return LDAP_SUCCESS;
259 }
260
261 int
262 dup_comp_filter (
263         Operation* op,
264         struct berval *bv,
265         ComponentFilter *in_f,
266         ComponentFilter **out_f )
267 {
268         int     rc;
269         ComponentFilter dup_f = {0};
270
271         if ( !in_f ) return LDAP_PROTOCOL_ERROR;
272
273         switch ( in_f->cf_choice ) {
274         case LDAP_COMP_FILTER_AND:
275                 rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
276                 dup_f.cf_choice = LDAP_COMP_FILTER_AND;
277                 break;
278         case LDAP_COMP_FILTER_OR:
279                 rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
280                 dup_f.cf_choice = LDAP_COMP_FILTER_OR;
281                 break;
282         case LDAP_COMP_FILTER_NOT:
283                 rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
284                 dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
285                 break;
286         case LDAP_COMP_FILTER_ITEM:
287                 rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
288                 dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
289                 break;
290         default:
291                 rc = LDAP_PROTOCOL_ERROR;
292         }
293
294         if ( rc == LDAP_SUCCESS ) {
295                 *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
296                 **out_f = dup_f;
297         }
298
299         return( rc );
300 }
301
302
303 int
304 get_aliased_filter ( Operation* op, MatchingRuleAssertion* ma, AttributeAliasing* aa, const char** text )
305 {
306         int rc;
307         struct berval assert_bv;
308         ComponentAssertion* ca;
309
310         Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
311
312         if ( !aa->aa_cf  ) return LDAP_PROTOCOL_ERROR;
313
314         assert_bv = ma->ma_value;
315         /* Attribute Description is replaced with aliased one */
316         ma->ma_desc = aa->aa_aliased_ad;
317         ma->ma_rule = aa->aa_mr;
318         /*
319          * Duplicate aa->aa_cf to ma->ma_cf by replacing the
320          * the component assertion value in assert_bv
321          * Multiple values may be separated with '$'
322          */
323         return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
324 }
325
326 int
327 get_comp_filter( Operation* op, struct berval* bv, ComponentFilter** filt,
328                  const char **text )
329 {
330         ComponentAssertionValue cav;
331         int rc;
332
333         Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
334         if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
335                 return rc;
336         }
337         rc = parse_comp_filter( op, &cav, filt, text );
338         bv->bv_val = cav.cav_ptr;
339
340         return rc;
341 }
342
343 static void
344 eat_whsp( ComponentAssertionValue* cav )
345 {
346         for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
347                 cav->cav_ptr++;
348         }
349 }
350
351 static int
352 cav_cur_len( ComponentAssertionValue* cav )
353 {
354         return cav->cav_end - cav->cav_ptr;
355 }
356
357 static ber_tag_t
358 comp_first_element( ComponentAssertionValue* cav )
359 {
360         eat_whsp( cav );
361         if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
362                 return LDAP_COMP_FILTER_ITEM;
363         }
364         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
365                 return LDAP_COMP_FILTER_AND;
366         }
367         else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
368                 return LDAP_COMP_FILTER_OR;
369         }
370         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
371                 return LDAP_COMP_FILTER_NOT;
372         }
373         else
374                 return LDAP_COMP_FILTER_UNDEFINED;
375 }
376
377 static ber_tag_t
378 comp_next_element( ComponentAssertionValue* cav )
379 {
380
381         eat_whsp( cav );
382         if ( *(cav->cav_ptr) == ',' ) {
383                 /* move pointer to the next CA */
384                 cav->cav_ptr++;
385                 return comp_first_element( cav );
386         }
387         else return LDAP_COMP_FILTER_UNDEFINED;
388 }
389
390 static int
391 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
392                         ComponentFilter** f, const char** text )
393 {
394         ComponentFilter **new;
395         int             err;
396         ber_tag_t       tag;
397
398         Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
399         new = f;
400         for ( tag = comp_first_element( cav ); tag != LDAP_COMP_FILTER_UNDEFINED;
401                 tag = comp_next_element( cav ) )
402         {
403                 err = parse_comp_filter( op, cav, new, text );
404                 if ( err != LDAP_SUCCESS )
405                         return ( err );
406                 new = &(*new)->cf_next;
407         }
408         *new = NULL;
409
410         return( LDAP_SUCCESS );
411 }
412
413 static int
414 get_componentId( Operation *op, ComponentAssertionValue* cav,
415                         ComponentId ** cid, const char** text )
416 {
417         ber_tag_t type;
418         ComponentId _cid;
419         int len;
420
421         type = peek_componentId_type( cav );
422
423         Debug( LDAP_DEBUG_FILTER, "get_compId [%d]\n", type, 0, 0 );
424         len = 0;
425         _cid.ci_type = type;
426         _cid.ci_next = NULL;
427         switch ( type ) {
428         case LDAP_COMPREF_IDENTIFIER :
429                 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
430                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
431                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
432                 _cid.ci_val.ci_identifier.bv_len = len;
433                 cav->cav_ptr += len;
434                 break;
435         case LDAP_COMPREF_FROM_BEGINNING :
436                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
437                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
438                 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
439                 cav->cav_ptr += len;
440                 break;
441         case LDAP_COMPREF_FROM_END :
442                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
443                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
444                 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
445                 cav->cav_ptr += len;
446                 break;
447         case LDAP_COMPREF_COUNT :
448                 _cid.ci_val.ci_count = 0;
449                 cav->cav_ptr++;
450                 break;
451         case LDAP_COMPREF_CONTENT :
452                 _cid.ci_val.ci_content = 1;
453                 cav->cav_ptr += strlen("content");
454                 break;
455         case LDAP_COMPREF_SELECT :
456                 if ( cav->cav_ptr[len] != '(' )
457                         return LDAP_COMPREF_UNDEFINED;
458                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
459                       cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
460                         ; len++ );
461                 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
462                 _cid.ci_val.ci_select_value.bv_len = len - 1 ;
463                 cav->cav_ptr += len + 1;
464                 break;
465         case LDAP_COMPREF_ALL :
466                 _cid.ci_val.ci_all = '*';
467                 cav->cav_ptr++;
468                 break;
469         default :
470                 return LDAP_COMPREF_UNDEFINED;
471         }
472
473         if ( op )
474                 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
475         else
476                 *cid = malloc( sizeof( ComponentId ) );
477         **cid = _cid;
478         return LDAP_SUCCESS;
479 }
480
481 static int
482 peek_componentId_type( ComponentAssertionValue* cav )
483 {
484         eat_whsp( cav );
485         if ( cav->cav_ptr[0] == '-' )
486                 return LDAP_COMPREF_FROM_END;
487         else if ( cav->cav_ptr[0] == '(' )
488                 return LDAP_COMPREF_SELECT;
489         else if ( cav->cav_ptr[0] == '*' )
490                 return LDAP_COMPREF_ALL;
491         else if ( cav->cav_ptr[0] == '0' )
492                 return LDAP_COMPREF_COUNT;
493         else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' )
494                 return LDAP_COMPREF_FROM_BEGINNING;
495         else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
496                 strncmp(cav->cav_ptr,"content",7) == 0 )
497                 return LDAP_COMPREF_CONTENT;
498         else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
499                         (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
500                  
501                 return LDAP_COMPREF_IDENTIFIER;
502         else
503                 return LDAP_COMPREF_UNDEFINED;
504 }
505
506 static ber_tag_t
507 comp_next_id( ComponentAssertionValue* cav )
508 {
509
510         if ( *(cav->cav_ptr) == '.' ) {
511                 cav->cav_ptr++;
512                 return LDAP_COMPREF_DEFINED;
513         }
514         else return LDAP_COMPREF_UNDEFINED;
515 }
516
517
518
519 static int
520 get_component_reference( Operation *op, ComponentAssertionValue* cav,
521                         ComponentReference** cr, const char** text )
522 {
523         int rc, count = 0;
524         ber_int_t type;
525         ComponentReference* ca_comp_ref;
526         ComponentId** cr_list;
527         char* start, *end;
528
529         eat_whsp( cav );
530
531         start = cav->cav_ptr;
532         if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS )
533                 return rc;
534         if ( op )
535                 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
536         else
537                 ca_comp_ref = malloc( sizeof( ComponentReference ) );
538
539         if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
540
541         cr_list = &ca_comp_ref->cr_list;
542
543         for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
544                 ; type = comp_next_id( cav ), count++ ) {
545                 rc = get_componentId( op, cav, cr_list, text );
546                 if ( rc == LDAP_SUCCESS ) {
547                         if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
548                         cr_list = &(*cr_list)->ci_next;
549                 }
550                 else if ( rc == LDAP_COMPREF_UNDEFINED )
551                         return rc;
552         }
553         ca_comp_ref->cr_len = count;
554         end = cav->cav_ptr;
555         if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
556                 if ( op )
557                         op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
558                 else
559                         free( ca_comp_ref );
560                 return rc;
561         }
562
563         if ( rc == LDAP_SUCCESS ) {     
564                 *cr = ca_comp_ref;
565                 **cr = *ca_comp_ref;    
566         }
567         else if ( op )
568                  op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
569         else
570                  free( ca_comp_ref ) ;
571
572         (*cr)->cr_string.bv_val = start;
573         (*cr)->cr_string.bv_len = end - start + 1;
574         
575         return rc;
576 }
577
578 int
579 insert_component_reference( ComponentReference *cr, ComponentReference** cr_list) {
580         if ( !cr )
581                 return LDAP_PARAM_ERROR;
582         if ( !(*cr_list) ) {
583                 *cr_list = cr;
584                 cr->cr_next = NULL;
585         } else {
586                 cr->cr_next = *cr_list;
587                 *cr_list = cr;
588         }
589         return LDAP_SUCCESS;
590 }
591
592 /*
593  * If there is '.' in the name of a given attribute
594  * the first '.'- following characters are considered
595  * as a component reference of the attribute
596  * EX) userCertificate.toBeSigned.serialNumber
597  * attribute : userCertificate
598  * component reference : toBeSigned.serialNumber
599  */
600 int
601 is_component_reference( char* attr ) {
602         int i;
603         for ( i=0; attr[i] != '\0' ; i++ ) {
604                 if ( attr[i] == '.' )
605                         return (1);
606         }
607         return (0);
608 }
609
610 int
611 extract_component_reference( char* attr, ComponentReference** cr ) {
612         int i, rc;
613         char* cr_ptr;
614         int cr_len;
615         ComponentAssertionValue cav;
616         char text[1][128];
617
618         for ( i=0; attr[i] != '\0' ; i++ ) {
619                 if ( attr[i] == '.' ) break;
620         }
621
622         if (attr[i] != '.' )
623                 return LDAP_PARAM_ERROR;
624         else
625                 attr[i] = '\0';
626         cr_ptr = attr + i + 1 ;
627         cr_len = strlen ( cr_ptr );
628         if ( cr_len <= 0 )
629                 return LDAP_PARAM_ERROR;
630
631         /* enclosed between double quotes*/
632         cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
633         memcpy( cav.cav_buf+1, cr_ptr, cr_len );
634         cav.cav_buf[0] = '"';
635         cav.cav_buf[cr_len+1] = '"';
636         cav.cav_end = cr_ptr + cr_len + 2;
637
638         rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
639         if ( rc != LDAP_SUCCESS )
640                 return rc;
641         (*cr)->cr_string.bv_val = cav.cav_buf;
642         (*cr)->cr_string.bv_len = cr_len + 2;
643
644         return LDAP_SUCCESS;
645 }
646 static int
647 get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
648                 int* ca_use_def, const char**  text )
649 {
650         strip_cav_str( cav, "useDefaultValues" );
651         if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
652                 strip_cav_str( cav, "TRUE" );
653                 *ca_use_def = 1;
654         } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
655                 strip_cav_str( cav, "FALSE" );
656                 *ca_use_def = 0;
657         } else {
658                 return LDAP_INVALID_SYNTAX;
659         }
660
661         return LDAP_SUCCESS;
662 }
663
664 static int
665 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
666                 MatchingRule** mr, const char**  text )
667 {
668         int count = 0;
669         struct berval rule_text = { 0L, NULL };
670
671         eat_whsp( cav );
672
673         for ( ; ; count++ ) {
674                 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
675                         cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
676                         cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
677                         break;
678         }
679
680         if ( count == 0 ) {
681                 *text = "component matching rule not recognized";
682                 return LDAP_INAPPROPRIATE_MATCHING;
683         }
684         
685         rule_text.bv_len = count;
686         rule_text.bv_val = cav->cav_ptr;
687         *mr = mr_bvfind( &rule_text );
688         cav->cav_ptr += count;
689         Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
690         if ( *mr == NULL ) {
691                 *text = "component matching rule not recognized";
692                 return LDAP_INAPPROPRIATE_MATCHING;
693         }
694         return LDAP_SUCCESS;
695 }
696
697 static int
698 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
699 {
700         int count, sequent_dquote, unclosed_brace, succeed;
701
702         eat_whsp( cav );
703         /*
704          * Four cases of GSER <Values>
705          * 1) "..." :
706          *      StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
707          * 2) '...'B or '...'H :
708          *      BitStringVal, OctetStringVal
709          * 3) {...} :
710          *      SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
711          * 4) Between two white spaces
712          *      INTEGER, BOOLEAN, NULL,ENUMERATE, etc
713          */
714
715         succeed = 0;
716         if ( cav->cav_ptr[0] == '"' ) {
717                 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
718                         /* In order to find escaped double quote */
719                         if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
720                         else sequent_dquote = 0;
721
722                         if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
723                                 break;
724                         }
725                                 
726                         if ( ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') ||
727                         ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) {
728                                 succeed = 1;
729                                 break;
730                         }
731                 }
732                 
733                 if ( !succeed || cav->cav_ptr[count] != '"' )
734                         return LDAP_FILTER_ERROR;
735
736                 bv->bv_val = cav->cav_ptr + 1;
737                 bv->bv_len = count - 1; /* exclude '"' */
738         }
739         else if ( cav->cav_ptr[0] == '\'' ) {
740                 for( count = 1 ; ; count++ ) {
741                         if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
742                                 break;
743                         }
744                         if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B')||
745                         (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') ) {
746                                 succeed = 1;
747                                 break;
748                         }
749                 }
750
751                 if ( !succeed || !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
752                         return LDAP_FILTER_ERROR;
753
754                 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
755                 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
756                                 
757         }
758         else if ( cav->cav_ptr[0] == '{' ) {
759                 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
760                         if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
761                         if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
762
763                         if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end )
764                                 break;
765                         if ( unclosed_brace == 0 ) {
766                                 succeed = 1;
767                                 break;
768                         }
769                 }
770
771                 if ( !succeed || cav->cav_ptr[count] != '}' )
772                         return LDAP_FILTER_ERROR;
773
774                 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
775                 bv->bv_len = count - 1;/* exclude  "'B" */
776         }
777         else {
778                 succeed = 1;
779                 /*Find  following white space where the value is ended*/
780                 for( count = 1 ; ; count++ ) {
781                         if ( cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '{' || (cav->cav_ptr+count) > cav->cav_end ) {
782                                 break;
783                         }
784                 }
785                 bv->bv_val = cav->cav_ptr;
786                 bv->bv_len = count;
787         }
788
789         cav->cav_ptr += bv->bv_len;
790
791         return LDAP_SUCCESS;
792 }
793
794 static int
795 get_matching_value( Operation *op, ComponentAssertion* ca,
796                         ComponentAssertionValue* cav, struct berval* bv,
797                         const char**  text )
798 {
799         if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
800                 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
801                         return LDAP_FILTER_ERROR;
802                 }
803
804         } else {
805                 /* embeded componentFilterMatch Description */
806                 bv->bv_val = cav->cav_ptr;
807                 bv->bv_len = cav_cur_len( cav );
808         }
809
810         return LDAP_SUCCESS;
811 }
812
813 /* Don't move the position pointer, just peek given string */
814 static int
815 peek_cav_str( ComponentAssertionValue* cav, char* str )
816 {
817         eat_whsp( cav );
818         if ( cav_cur_len( cav ) >= strlen( str ) &&
819                 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
820                 return LDAP_SUCCESS;
821         else 
822                 return LDAP_INVALID_SYNTAX;
823 }
824
825 static int
826 strip_cav_str( ComponentAssertionValue* cav, char* str)
827 {
828         eat_whsp( cav );
829         if ( cav_cur_len( cav ) >= strlen( str ) &&
830                 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) {
831                 cav->cav_ptr += strlen( str );
832                 return LDAP_SUCCESS;
833         }
834         else 
835                 return LDAP_INVALID_SYNTAX;
836 }
837
838 /*
839  * TAG : "item", "and", "or", "not"
840  */
841 static int
842 strip_cav_tag( ComponentAssertionValue* cav )
843 {
844
845         eat_whsp( cav );
846         if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
847                 strip_cav_str( cav , "item:" );
848                 return LDAP_COMP_FILTER_ITEM;
849         }
850         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
851                 strip_cav_str( cav , "and:" );
852                 return LDAP_COMP_FILTER_AND;
853         }
854         else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
855                 strip_cav_str( cav , "or:" );
856                 return LDAP_COMP_FILTER_OR;
857         }
858         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
859                 strip_cav_str( cav , "not:" );
860                 return LDAP_COMP_FILTER_NOT;
861         }
862         else
863                 return LBER_ERROR;
864 }
865
866 /*
867  * when encoding, "item" is denotation of ComponentAssertion
868  * ComponentAssertion :: SEQUENCE {
869  *      component               ComponentReference (SIZE(1..MAX)) OPTIONAL,
870  *      useDefaultValues        BOOLEAN DEFAULT TRUE,
871  *      rule                    MATCHING-RULE.&id,
872  *      value                   MATCHING-RULE.&AssertionType }
873  */
874 static int
875 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
876                 const char** text )
877 {
878         int rc;
879         ComponentAssertion* _ca;
880         struct berval t_bv;
881         struct berval value;
882         MatchingRule* mr;
883
884         Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
885         if ( op )
886                 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
887         else
888                 _ca = malloc( sizeof( ComponentAssertion ) );
889
890         if ( !_ca ) return LDAP_NO_MEMORY;
891
892         _ca->ca_comp_data.cd_tree = NULL;
893         _ca->ca_comp_data.cd_mem_op = NULL;
894
895         rc = peek_cav_str( cav, "component" );
896         if ( rc == LDAP_SUCCESS ) {
897                 strip_cav_str( cav, "component" );
898                 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
899                 if ( rc != LDAP_SUCCESS ) {
900                         if ( op )
901                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
902                         else
903                                 free( _ca );
904                         return LDAP_INVALID_SYNTAX;
905                 }
906                 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
907                         return rc;
908         } else {
909                 _ca->ca_comp_ref = NULL;
910         }
911
912         rc = peek_cav_str( cav, "useDefaultValues");
913         if ( rc == LDAP_SUCCESS ) {
914                 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
915                 if ( rc != LDAP_SUCCESS ) {
916                         if ( op )
917                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
918                         else
919                                 free( _ca );
920                         return LDAP_INVALID_SYNTAX;
921                 }
922                 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
923                         return rc;
924         }
925         else _ca->ca_use_def = 1;
926
927         if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
928                 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
929                 if ( op )
930                         op->o_tmpfree( _ca, op->o_tmpmemctx );
931                 else
932                         free( _ca );
933                 return LDAP_INAPPROPRIATE_MATCHING;
934         }
935         
936         if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
937                 return rc;
938         if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
939                 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
940                 if ( op )
941                         op->o_tmpfree( _ca, op->o_tmpmemctx );
942                 else
943                         free( _ca );
944                 return LDAP_INVALID_SYNTAX;
945         }
946
947         /*
948          * Normalize the value of this component assertion when the matching
949          * rule is one of existing matching rules
950          */
951         mr = _ca->ca_ma_rule;
952         if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
953
954                 value.bv_val[value.bv_len] = '\0';
955                 rc = mr->smr_normalize (
956                         SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
957                         NULL, mr,
958                         &value, &_ca->ca_ma_value, op->o_tmpmemctx );
959                 if ( rc != LDAP_SUCCESS )
960                         return rc;
961         }
962         else
963                 _ca->ca_ma_value = value;
964         /*
965          * Validate the value of this component assertion
966          */
967         if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
968                 return LDAP_INVALID_SYNTAX;
969         }
970
971
972         /* componentFilterMatch contains componentFilterMatch in it */
973         if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
974                 struct berval bv;
975                 bv.bv_val = cav->cav_ptr;
976                 bv.bv_len = cav_cur_len( cav );
977                 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
978                 if ( rc != LDAP_SUCCESS ) {
979                         if ( op )
980                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
981                         else
982                                 free( _ca );
983                         return rc;
984                 }
985                 cav->cav_ptr = bv.bv_val;
986                 assert( cav->cav_end >= bv.bv_val );
987         }
988
989         *ca = _ca;
990         return LDAP_SUCCESS;
991 }
992
993 static int
994 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
995                                 ComponentFilter** filt, const char** text )
996 {
997         /*
998          * A component filter looks like this coming in:
999          *      Filter ::= CHOICE {
1000          *              item    [0]     ComponentAssertion,
1001          *              and     [1]     SEQUENCE OF ComponentFilter,
1002          *              or      [2]     SEQUENCE OF ComponentFilter,
1003          *              not     [3]     ComponentFilter,
1004          *      }
1005          */
1006
1007         ber_tag_t       tag;
1008         int             err;
1009         ComponentFilter f;
1010         /* TAG : item, and, or, not in RFC 2254 */
1011         tag = strip_cav_tag( cav );
1012
1013         if ( tag == LBER_ERROR ) {
1014                 *text = "error decoding comp filter";
1015                 return LDAP_PROTOCOL_ERROR;
1016         }
1017
1018         if ( tag != LDAP_COMP_FILTER_NOT )
1019                 strip_cav_str( cav, "{");
1020
1021         err = LDAP_SUCCESS;
1022
1023         f.cf_next = NULL;
1024         f.cf_choice = tag; 
1025
1026         switch ( f.cf_choice ) {
1027         case LDAP_COMP_FILTER_AND:
1028         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1029                 err = get_comp_filter_list( op, cav, &f.cf_and, text );
1030                 if ( err != LDAP_SUCCESS ) {
1031                         break;
1032                 }
1033                 if ( f.cf_and == NULL ) {
1034                         f.cf_choice = SLAPD_FILTER_COMPUTED;
1035                         f.cf_result = LDAP_COMPARE_TRUE;
1036                 }
1037                 break;
1038
1039         case LDAP_COMP_FILTER_OR:
1040         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1041                 err = get_comp_filter_list( op, cav, &f.cf_or, text );
1042                 if ( err != LDAP_SUCCESS ) {
1043                         break;
1044                 }
1045                 if ( f.cf_or == NULL ) {
1046                         f.cf_choice = SLAPD_FILTER_COMPUTED;
1047                         f.cf_result = LDAP_COMPARE_FALSE;
1048                 }
1049                 /* no assert - list could be empty */
1050                 break;
1051
1052         case LDAP_COMP_FILTER_NOT:
1053         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1054                 err = parse_comp_filter( op, cav, &f.cf_not, text );
1055                 if ( err != LDAP_SUCCESS ) {
1056                         break;
1057                 }
1058
1059                 assert( f.cf_not != NULL );
1060                 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1061                         int fresult = f.cf_not->cf_result;
1062                         f.cf_choice = SLAPD_FILTER_COMPUTED;
1063                         op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1064                         f.cf_not = NULL;
1065
1066                         switch ( fresult ) {
1067                         case LDAP_COMPARE_TRUE:
1068                                 f.cf_result = LDAP_COMPARE_FALSE;
1069                                 break;
1070                         case LDAP_COMPARE_FALSE:
1071                                 f.cf_result = LDAP_COMPARE_TRUE;
1072                                 break;
1073                         default: ;
1074                                 /* (!Undefined) is Undefined */
1075                         }
1076                 }
1077                 break;
1078
1079         case LDAP_COMP_FILTER_ITEM:
1080         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1081                 err = get_item( op, cav, &f.cf_ca, text );
1082                 if ( err != LDAP_SUCCESS ) {
1083                         break;
1084                 }
1085
1086                 assert( f.cf_ca != NULL );
1087                 break;
1088
1089         default:
1090                 f.cf_choice = SLAPD_FILTER_COMPUTED;
1091                 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1092                 break;
1093         }
1094
1095         if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1096                 *text = "Component Filter Syntax Error";
1097                 return err;
1098         }
1099
1100         if ( tag != LDAP_COMP_FILTER_NOT )
1101                 strip_cav_str( cav, "}");
1102
1103         if ( err == LDAP_SUCCESS ) {
1104                 if ( op ) {
1105                         *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1106                 } else {
1107                         *filt = malloc( sizeof(f) );
1108                 }
1109                 **filt = f;
1110         }
1111
1112         return( err );
1113 }
1114
1115 static int
1116 test_comp_filter_and(
1117         Syntax *syn,
1118         ComponentSyntaxInfo *a,
1119         ComponentFilter *flist )
1120 {
1121         ComponentFilter *f;
1122         int rtn = LDAP_COMPARE_TRUE;
1123
1124         for ( f = flist ; f != NULL; f = f->cf_next ) {
1125                 int rc = test_comp_filter( syn, a, f );
1126                 if ( rc == LDAP_COMPARE_FALSE ) {
1127                         rtn = rc;
1128                         break;
1129                 }
1130         
1131                 if ( rc != LDAP_COMPARE_TRUE ) {
1132                         rtn = rc;
1133                 }
1134         }
1135
1136         return rtn;
1137 }
1138
1139 static int
1140 test_comp_filter_or(
1141         Syntax *syn,
1142         ComponentSyntaxInfo *a,
1143         ComponentFilter *flist )
1144 {
1145         ComponentFilter *f;
1146         int rtn = LDAP_COMPARE_TRUE;
1147
1148         for ( f = flist ; f != NULL; f = f->cf_next ) {
1149                 int rc = test_comp_filter( syn, a, f );
1150                 if ( rc == LDAP_COMPARE_TRUE ) {
1151                         rtn = rc;
1152                         break;
1153                 }
1154         
1155                 if ( rc != LDAP_COMPARE_FALSE ) {
1156                         rtn = rc;
1157                 }
1158         }
1159
1160         return rtn;
1161 }
1162
1163 int
1164 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1165                 struct berval* bv_assert )
1166 {
1167         int rc;
1168         int match;
1169
1170         assert( mr != NULL );
1171         assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1172
1173         if( !mr->smr_match ) {
1174                 return LDAP_INAPPROPRIATE_MATCHING;
1175         }
1176
1177         rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1178                                 mr, bv_attr, bv_assert );
1179         if ( rc == LDAP_SUCCESS )
1180                 return match? LDAP_COMPARE_FALSE:LDAP_COMPARE_TRUE;
1181         else
1182                 return rc;
1183 }
1184
1185 /*
1186  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1187  */
1188 static int
1189 test_comp_filter_item(
1190         Syntax *syn,
1191         ComponentSyntaxInfo *csi_attr,
1192         ComponentAssertion *ca )
1193 {
1194         int rc, len;
1195         void *attr_nm, *assert_nm;
1196
1197         if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1198                 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1199                 /* componentFilterMatch inside of componentFilterMatch */
1200                 rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1201                 return rc;
1202         }
1203
1204         /* Memory for storing will-be-extracted attribute values */
1205         attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1206         if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1207
1208         /* Memory for storing component assertion values */
1209         if( !ca->ca_comp_data.cd_mem_op ) {
1210                 assert_nm = nibble_mem_allocator ( 256, 64 );
1211                 if ( !assert_nm ) {
1212                         nibble_mem_free ( attr_nm );
1213                         return LDAP_PROTOCOL_ERROR;
1214                 }
1215                 ca->ca_comp_data.cd_mem_op = assert_nm;
1216         }
1217         else {
1218                 assert_nm = ca->ca_comp_data.cd_mem_op;
1219         }
1220
1221         /* component reference initialization */
1222         if ( ca->ca_comp_ref )
1223                 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1224         rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1225
1226         /* free memory used for storing extracted attribute value */
1227         nibble_mem_free ( attr_nm );
1228         return rc;
1229 }
1230
1231 static int
1232 test_comp_filter(
1233     Syntax *syn,
1234     ComponentSyntaxInfo *a,
1235     ComponentFilter *f )
1236 {
1237         int     rc;
1238
1239         if ( !f ) return LDAP_PROTOCOL_ERROR;
1240
1241         Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1242         switch ( f->cf_choice ) {
1243         case SLAPD_FILTER_COMPUTED:
1244                 rc = f->cf_result;
1245                 break;
1246         case LDAP_COMP_FILTER_AND:
1247                 rc = test_comp_filter_and( syn, a, f->cf_and );
1248                 break;
1249         case LDAP_COMP_FILTER_OR:
1250                 rc = test_comp_filter_or( syn, a, f->cf_or );
1251                 break;
1252         case LDAP_COMP_FILTER_NOT:
1253                 rc = test_comp_filter( syn, a, f->cf_not );
1254
1255                 switch ( rc ) {
1256                 case LDAP_COMPARE_TRUE:
1257                         rc = LDAP_COMPARE_FALSE;
1258                         break;
1259                 case LDAP_COMPARE_FALSE:
1260                         rc = LDAP_COMPARE_TRUE;
1261                         break;
1262                 }
1263                 break;
1264         case LDAP_COMP_FILTER_ITEM:
1265                 rc = test_comp_filter_item( syn, a, f->cf_ca );
1266                 break;
1267         default:
1268                 rc = LDAP_PROTOCOL_ERROR;
1269         }
1270
1271         return( rc );
1272 }
1273
1274 static void
1275 free_comp_filter_list( ComponentFilter* f )
1276 {
1277         ComponentFilter* tmp;
1278         for ( tmp = f; tmp; tmp = tmp->cf_next )
1279         {
1280                 free_comp_filter( tmp );
1281         }
1282 }
1283
1284 static void
1285 free_comp_filter( ComponentFilter* f )
1286 {
1287         if ( !f ) {
1288                 Debug( LDAP_DEBUG_FILTER, "free_comp_filter:Invalid filter so failed to release memory\n", 0, 0, 0 );
1289                 return;
1290         }
1291         switch ( f->cf_choice ) {
1292         case LDAP_COMP_FILTER_AND:
1293         case LDAP_COMP_FILTER_OR:
1294                 free_comp_filter_list( f->cf_any );
1295                 break;
1296         case LDAP_COMP_FILTER_NOT:
1297                 free_comp_filter( f->cf_any );
1298                 break;
1299         case LDAP_COMP_FILTER_ITEM:
1300                 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op )
1301                         nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1302                 break;
1303
1304         default:
1305                 break;
1306         }
1307 }
1308
1309 void
1310 component_free( ComponentFilter *f ) {
1311         free_comp_filter( f );
1312 }
1313
1314 #endif