]> git.sur5r.net Git - openldap/blob - servers/slapd/matchedValues.c
Fix approx matching when there is an equality index but no approx index.
[openldap] / servers / slapd / matchedValues.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2004 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15
16 #include "portable.h"
17
18 #include <stdio.h>
19
20 #include <ac/string.h>
21 #include <ac/socket.h>
22
23 #include "slap.h"
24
25 static int
26 test_mra_vrFilter(
27         Operation       *op,
28         Attribute       *a,
29         MatchingRuleAssertion *mra,
30         char            ***e_flags
31 );
32
33 static int
34 test_substrings_vrFilter(
35         Operation       *op,
36         Attribute       *a,
37         ValuesReturnFilter *f,
38         char            ***e_flags
39 );
40
41 static int
42 test_presence_vrFilter(
43         Operation       *op,
44         Attribute       *a,
45         AttributeDescription *desc,
46         char            ***e_flags
47 );
48
49 static int
50 test_ava_vrFilter(
51         Operation       *op,
52         Attribute       *a,
53         AttributeAssertion *ava,
54         int             type,
55         char            ***e_flags
56 );
57
58
59 int
60 filter_matched_values( 
61         Operation       *op,
62         Attribute       *a,
63         char            ***e_flags
64 )
65 {
66         ValuesReturnFilter *vrf;
67         int             rc = LDAP_SUCCESS;
68
69 #ifdef NEW_LOGGING
70         LDAP_LOG( FILTER, ENTRY, "filter_matched_values: begin\n", 0, 0, 0 );
71 #else
72         Debug( LDAP_DEBUG_FILTER, "=> filter_matched_values\n", 0, 0, 0 );
73 #endif
74
75         for ( vrf = op->o_vrFilter; vrf != NULL; vrf = vrf->vrf_next ) {
76                 switch ( vrf->vrf_choice ) {
77                 case SLAPD_FILTER_COMPUTED:
78 #ifdef NEW_LOGGING
79                         LDAP_LOG( FILTER, DETAIL1, 
80                                 "test_vrFilter: COMPUTED %s (%d)\n",
81                                 vrf->vrf_result == LDAP_COMPARE_FALSE ? "false" :
82                                 vrf->vrf_result == LDAP_COMPARE_TRUE     ? "true"  :
83                                 vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
84                                 "error", vrf->vrf_result, 0 );
85 #else
86                         Debug( LDAP_DEBUG_FILTER, "     COMPUTED %s (%d)\n",
87                                 vrf->vrf_result == LDAP_COMPARE_FALSE ? "false" :
88                                 vrf->vrf_result == LDAP_COMPARE_TRUE ? "true" :
89                                 vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
90                                 vrf->vrf_result, 0 );
91 #endif
92                         /*This type of filter does not affect the result */
93                         rc = LDAP_SUCCESS;
94                 break;
95
96                 case LDAP_FILTER_EQUALITY:
97 #ifdef NEW_LOGGING
98                         LDAP_LOG( FILTER, DETAIL1, "test_vrFilter: EQUALITY\n", 0, 0, 0 );
99 #else
100                         Debug( LDAP_DEBUG_FILTER, "     EQUALITY\n", 0, 0, 0 );
101 #endif
102                         rc = test_ava_vrFilter( op, a, vrf->vrf_ava,
103                                 LDAP_FILTER_EQUALITY, e_flags );
104                         if( rc == -1 ) {
105                                 return rc;
106                         }
107                         break;
108
109                 case LDAP_FILTER_SUBSTRINGS:
110 #ifdef NEW_LOGGING
111                         LDAP_LOG( FILTER, DETAIL1, "test_vrFilter  SUBSTRINGS\n", 0, 0, 0 );
112 #else
113                         Debug( LDAP_DEBUG_FILTER, "     SUBSTRINGS\n", 0, 0, 0 );
114 #endif
115
116                         rc = test_substrings_vrFilter( op, a,
117                                 vrf, e_flags );
118                         if( rc == -1 ) {
119                                 return rc;
120                         }
121                         break;
122
123                 case LDAP_FILTER_PRESENT:
124 #ifdef NEW_LOGGING
125                         LDAP_LOG( FILTER, DETAIL1, "test_vrFilter:      PRESENT\n", 0, 0, 0 );
126 #else
127                         Debug( LDAP_DEBUG_FILTER, "     PRESENT\n", 0, 0, 0 );
128 #endif
129                         rc = test_presence_vrFilter( op, a,
130                                 vrf->vrf_desc, e_flags );
131                         if( rc == -1 ) {
132                                 return rc;
133                         }
134                         break;
135
136                 case LDAP_FILTER_GE:
137                         rc = test_ava_vrFilter( op, a, vrf->vrf_ava,
138                                 LDAP_FILTER_GE, e_flags );
139                         if( rc == -1 ) {
140                                 return rc;
141                         }
142                         break;
143
144                 case LDAP_FILTER_LE:
145                         rc = test_ava_vrFilter( op, a, vrf->vrf_ava,
146                                 LDAP_FILTER_LE, e_flags );
147                         if( rc == -1 ) {
148                                 return rc;
149                         }
150                         break;
151
152                 case LDAP_FILTER_EXT:
153 #ifdef NEW_LOGGING
154                         LDAP_LOG( FILTER, DETAIL1, "test_vrFilter:      EXT\n", 0, 0, 0 );
155 #else
156                         Debug( LDAP_DEBUG_FILTER, "     EXT\n", 0, 0, 0 );
157 #endif
158                         rc = test_mra_vrFilter( op, a,
159                                 vrf->vrf_mra, e_flags );
160                         if( rc == -1 ) {
161                                 return rc;
162                         }
163                         break;
164
165                 default:
166 #ifdef NEW_LOGGING
167                         LDAP_LOG( FILTER, INFO, 
168                                 "test_vrFilter:  unknown filter type %lu\n", vrf->vrf_choice, 0, 0 );
169 #else
170                         Debug( LDAP_DEBUG_ANY, "        unknown filter type %lu\n",
171                                 vrf->vrf_choice, 0, 0 );
172 #endif
173                         rc = LDAP_PROTOCOL_ERROR;
174                 } 
175         }
176
177 #ifdef NEW_LOGGING
178         LDAP_LOG( FILTER, ENTRY, "filter_matched_values:  return=%d\n", rc, 0, 0 );
179 #else
180         Debug( LDAP_DEBUG_FILTER, "<= filter_matched_values %d\n", rc, 0, 0 );
181 #endif
182         return( rc );
183 }
184
185 static int
186 test_ava_vrFilter(
187         Operation       *op,
188         Attribute       *a,
189         AttributeAssertion *ava,
190         int             type,
191         char            ***e_flags
192 )
193 {
194         int             i, j;
195
196         for ( i=0; a != NULL; a = a->a_next, i++ ) {
197
198                 MatchingRule *mr;
199                 struct berval *bv;
200         
201                 if ( !is_ad_subtype( a->a_desc, ava->aa_desc ) ) {
202                         continue;
203                 }
204
205                 switch ( type ) {
206                 case LDAP_FILTER_APPROX:
207                         mr = a->a_desc->ad_type->sat_approx;
208                         if( mr != NULL ) break;
209                         /* use EQUALITY matching rule if no APPROX rule */
210
211                 case LDAP_FILTER_EQUALITY:
212                         mr = a->a_desc->ad_type->sat_equality;
213                         break;
214                 
215                 case LDAP_FILTER_GE:
216                 case LDAP_FILTER_LE:
217                         mr = a->a_desc->ad_type->sat_ordering;
218                         break;
219
220                 default:
221                         mr = NULL;
222                 }
223
224                 if( mr == NULL ) continue;
225
226                 bv = a->a_nvals;
227                 for ( j=0; bv->bv_val != NULL; bv++, j++ ) {
228                         int ret;
229                         int rc;
230                         const char *text;
231
232                         rc = value_match( &ret, a->a_desc, mr, 0,
233                                 bv, &ava->aa_value, &text );
234                         if( rc != LDAP_SUCCESS ) {
235                                 return rc;
236                         }
237
238                         switch ( type ) {
239                         case LDAP_FILTER_EQUALITY:
240                         case LDAP_FILTER_APPROX:
241                                 if ( ret == 0 ) {
242                                         (*e_flags)[i][j] = 1;
243                                 }
244                                 break;
245         
246                         case LDAP_FILTER_GE:
247                                 if ( ret >= 0 ) {
248                                         (*e_flags)[i][j] = 1;
249                                 }
250                                 break;
251         
252                         case LDAP_FILTER_LE:
253                                 if ( ret <= 0 ) {
254                                         (*e_flags)[i][j] = 1;
255                                 }
256                                 break;
257                         }
258                 }
259         }
260         return( LDAP_SUCCESS );
261 }
262
263 static int
264 test_presence_vrFilter(
265         Operation       *op,
266         Attribute       *a,
267         AttributeDescription *desc,
268         char            ***e_flags
269 )
270 {
271         int i, j;
272
273         for ( i=0; a != NULL; a = a->a_next, i++ ) {
274                 struct berval *bv;
275
276                 if ( !is_ad_subtype( a->a_desc, desc ) ) {
277                         continue;
278                 }
279
280                 for ( bv = a->a_vals, j=0; bv->bv_val != NULL; bv++, j++ );
281                 memset( (*e_flags)[i], 1, j);
282         }
283
284         return( LDAP_SUCCESS );
285 }
286
287 static int
288 test_substrings_vrFilter(
289         Operation       *op,
290         Attribute       *a,
291         ValuesReturnFilter *vrf,
292         char            ***e_flags
293 )
294 {
295         int i, j;
296
297         for ( i=0; a != NULL; a = a->a_next, i++ ) {
298                 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
299                 struct berval *bv;
300
301                 if ( !is_ad_subtype( a->a_desc, vrf->vrf_sub_desc ) ) {
302                         continue;
303                 }
304
305                 if( mr == NULL ) {
306                         continue;
307                 }
308
309                 bv = a->a_nvals;
310                 for ( j = 0; bv->bv_val != NULL; bv++, j++ ) {
311                         int ret;
312                         int rc;
313                         const char *text;
314
315                         rc = value_match( &ret, a->a_desc, mr, 0,
316                                 bv, vrf->vrf_sub, &text );
317
318                         if( rc != LDAP_SUCCESS ) {
319                                 return rc;
320                         }
321
322                         if ( ret == 0 ) {
323                                 (*e_flags)[i][j] = 1;
324                         }
325                 }
326         }
327
328         return LDAP_SUCCESS;
329 }
330
331 static int
332 test_mra_vrFilter(
333         Operation       *op,
334         Attribute       *a,
335         MatchingRuleAssertion *mra,
336         char            ***e_flags
337 )
338 {
339         int i, j;
340
341         for ( i=0; a != NULL; a = a->a_next, i++ ) {
342                 struct berval *bv, value;
343
344                 if ( mra->ma_desc ) {
345                         if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
346                                 continue;
347                         }
348                         value = mra->ma_value;
349
350                 } else {
351                         int rc;
352                         const char      *text = NULL;
353
354                         /* check if matching is appropriate */
355                         if ( strcmp( mra->ma_rule->smr_syntax->ssyn_oid,
356                                 a->a_desc->ad_type->sat_syntax->ssyn_oid ) != 0 ) {
357                                 continue;
358                         }
359
360                         rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
361                                 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
362                                 &mra->ma_value, &value, &text, op->o_tmpmemctx );
363
364                         if( rc != LDAP_SUCCESS ) continue;
365                 }
366
367                 bv = a->a_nvals;
368                 for ( j = 0; bv->bv_val != NULL; bv++, j++ ) {
369                         int ret;
370                         int rc;
371                         const char *text;
372
373                         rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
374                                 bv, &value, &text );
375                         if( rc != LDAP_SUCCESS ) {
376                                 return rc;
377                         }
378
379                         if ( ret == 0 ) {
380                                 (*e_flags)[i][j] = 1;
381                         }
382                 }
383         }
384
385         return LDAP_SUCCESS;
386 }