]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
Made caseIgnoreSubstringsMatch and caseExactSubstringsMatch use proper
[openldap] / servers / slapd / schema_init.c
1 /* schema_init.c - init builtin schema */
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/ctype.h>
13 #include <ac/string.h>
14 #include <ac/socket.h>
15
16 #include "slap.h"
17 #include "ldap_pvt.h"
18
19 #define UTF8MATCH 1
20
21 #ifdef USE_MD5
22 #include "lutil_md5.h"
23 /* We should replace MD5 with a faster hash */
24 #define HASH_BYTES                              LUTIL_MD5_BYTES
25 #define HASH_CONTEXT                    lutil_MD5_CTX
26 #define HASH_Init(c)                    lutil_MD5Init(c)
27 #define HASH_Update(c,buf,len)  lutil_MD5Update(c,buf,len)
28 #define HASH_Final(d,c)                 lutil_MD5Final(d,c)
29 #else
30 #include "lutil_hash.h"
31 /* We should replace MD5 with a faster hash */
32 #define HASH_BYTES                              LUTIL_HASH_BYTES
33 #define HASH_CONTEXT                    lutil_HASH_CTX
34 #define HASH_Init(c)                    lutil_HASHInit(c)
35 #define HASH_Update(c,buf,len)  lutil_HASHUpdate(c,buf,len)
36 #define HASH_Final(d,c)                 lutil_HASHFinal(d,c)
37 #endif
38
39 /* recycled validatation routines */
40 #define berValidate                                             blobValidate
41
42 /* unimplemented pretters */
43 #define dnPretty                                                NULL
44 #define integerPretty                                   NULL
45
46 /* recycled matching routines */
47 #define bitStringMatch                                  octetStringMatch
48 #define integerMatch                                    caseIgnoreIA5Match
49 #define numericStringMatch                              caseIgnoreIA5Match
50 #define objectIdentifierMatch                   caseIgnoreIA5Match
51 #define telephoneNumberMatch                    caseIgnoreIA5Match
52 #define telephoneNumberSubstringsMatch  caseIgnoreIA5SubstringsMatch
53 #define generalizedTimeMatch                    caseIgnoreIA5Match
54 #define generalizedTimeOrderingMatch    caseIgnoreIA5Match
55 #define uniqueMemberMatch                               dnMatch
56
57 /* approx matching rules */
58 #define directoryStringApproxMatchOID   "1.3.6.1.4.1.4203.666.4.4"
59 #define directoryStringApproxMatch      approxMatch
60 #define directoryStringApproxIndexer    approxIndexer
61 #define directoryStringApproxFilter     approxFilter
62 #define IA5StringApproxMatchOID                 "1.3.6.1.4.1.4203.666.4.5"
63 #define IA5StringApproxMatch                    approxMatch
64 #define IA5StringApproxIndexer                  approxIndexer
65 #define IA5StringApproxFilter                   approxFilter
66
67 /* orderring matching rules */
68 #define caseIgnoreOrderingMatch                 caseIgnoreMatch
69 #define caseExactOrderingMatch                  caseExactMatch
70
71 /* unimplemented matching routines */
72 #define caseIgnoreListMatch                             NULL
73 #define caseIgnoreListSubstringsMatch   NULL
74 #define protocolInformationMatch                NULL
75 #define integerFirstComponentMatch              NULL
76
77 #define OpenLDAPaciMatch                                NULL
78 #define authPasswordMatch                               NULL
79
80 /* recycled indexing/filtering routines */
81 #define dnIndexer                                               caseIgnoreIndexer
82 #define dnFilter                                                caseIgnoreFilter
83 #define integerIndexer                                  caseIgnoreIA5Indexer
84 #define integerFilter                                   caseIgnoreIA5Filter
85
86 #define telephoneNumberIndexer                  caseIgnoreIA5Indexer
87 #define telephoneNumberFilter                   caseIgnoreIA5Filter
88 #define telephoneNumberSubstringsIndexer        caseIgnoreIA5SubstringsIndexer
89 #define telephoneNumberSubstringsFilter         caseIgnoreIA5SubstringsFilter
90
91 static char *strcasechr( const char *str, int c )
92 {
93         char *lower = strchr( str, TOLOWER(c) );
94         char *upper = strchr( str, TOUPPER(c) );
95
96         if( lower && upper ) {
97                 return lower < upper ? lower : upper;
98         } else if ( lower ) {
99                 return lower;
100         } else {
101                 return upper;
102         }
103 }
104
105 static int
106 octetStringMatch(
107         int *matchp,
108         slap_mask_t flags,
109         Syntax *syntax,
110         MatchingRule *mr,
111         struct berval *value,
112         void *assertedValue )
113 {
114         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
115
116         if( match == 0 ) {
117                 match = memcmp( value->bv_val,
118                         ((struct berval *) assertedValue)->bv_val,
119                         value->bv_len );
120         }
121
122         *matchp = match;
123         return LDAP_SUCCESS;
124 }
125
126 /* Index generation function */
127 int octetStringIndexer(
128         slap_mask_t use,
129         slap_mask_t flags,
130         Syntax *syntax,
131         MatchingRule *mr,
132         struct berval *prefix,
133         struct berval **values,
134         struct berval ***keysp )
135 {
136         int i;
137         size_t slen, mlen;
138         struct berval **keys;
139         HASH_CONTEXT   HASHcontext;
140         unsigned char   HASHdigest[HASH_BYTES];
141         struct berval digest;
142         digest.bv_val = HASHdigest;
143         digest.bv_len = sizeof(HASHdigest);
144
145         /* we should have at least one value at this point */
146         assert( values != NULL && values[0] != NULL );
147
148         for( i=0; values[i] != NULL; i++ ) {
149                 /* just count them */
150         }
151
152         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
153
154         slen = strlen( syntax->ssyn_oid );
155         mlen = strlen( mr->smr_oid );
156
157         for( i=0; values[i] != NULL; i++ ) {
158                 HASH_Init( &HASHcontext );
159                 if( prefix != NULL && prefix->bv_len > 0 ) {
160                         HASH_Update( &HASHcontext,
161                                 prefix->bv_val, prefix->bv_len );
162                 }
163                 HASH_Update( &HASHcontext,
164                         syntax->ssyn_oid, slen );
165                 HASH_Update( &HASHcontext,
166                         mr->smr_oid, mlen );
167                 HASH_Update( &HASHcontext,
168                         values[i]->bv_val, values[i]->bv_len );
169                 HASH_Final( HASHdigest, &HASHcontext );
170
171                 keys[i] = ber_bvdup( &digest );
172         }
173
174         keys[i] = NULL;
175
176         *keysp = keys;
177
178         return LDAP_SUCCESS;
179 }
180
181 /* Index generation function */
182 int octetStringFilter(
183         slap_mask_t use,
184         slap_mask_t flags,
185         Syntax *syntax,
186         MatchingRule *mr,
187         struct berval *prefix,
188         void * assertValue,
189         struct berval ***keysp )
190 {
191         size_t slen, mlen;
192         struct berval **keys;
193         HASH_CONTEXT   HASHcontext;
194         unsigned char   HASHdigest[HASH_BYTES];
195         struct berval *value = (struct berval *) assertValue;
196         struct berval digest;
197         digest.bv_val = HASHdigest;
198         digest.bv_len = sizeof(HASHdigest);
199
200         slen = strlen( syntax->ssyn_oid );
201         mlen = strlen( mr->smr_oid );
202
203         keys = ch_malloc( sizeof( struct berval * ) * 2 );
204
205         HASH_Init( &HASHcontext );
206         if( prefix != NULL && prefix->bv_len > 0 ) {
207                 HASH_Update( &HASHcontext,
208                         prefix->bv_val, prefix->bv_len );
209         }
210         HASH_Update( &HASHcontext,
211                 syntax->ssyn_oid, slen );
212         HASH_Update( &HASHcontext,
213                 mr->smr_oid, mlen );
214         HASH_Update( &HASHcontext,
215                 value->bv_val, value->bv_len );
216         HASH_Final( HASHdigest, &HASHcontext );
217
218         keys[0] = ber_bvdup( &digest );
219         keys[1] = NULL;
220
221         *keysp = keys;
222
223         return LDAP_SUCCESS;
224 }
225
226 static int
227 dnValidate(
228         Syntax *syntax,
229         struct berval *in )
230 {
231         int rc;
232         char *dn;
233
234         if( in->bv_len == 0 ) return LDAP_SUCCESS;
235
236         dn = get_validated_dn( in->bv_val, 0, 0 );
237
238         rc = ( dn == NULL ) ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
239
240         if ( dn != NULL )
241                 ch_free( dn );
242
243         return rc;
244 }
245
246 int
247 dnNormalize(
248         Syntax *syntax,
249         struct berval *val,
250         struct berval **normalized )
251 {
252         struct berval *out;
253
254         if ( val->bv_len == 0 ) {
255                 out = ber_bvdup( val );
256         } else {
257                 char *dn;
258 #ifdef USE_DN_NORMALIZE
259                 dn = get_validated_dn( val->bv_val, 1, 1 );
260 #else
261                 dn = get_validated_dn( val->bv_val, 0, 0 );
262 #endif
263                 if( dn == NULL ) {
264                         return LDAP_INVALID_SYNTAX;
265                 }
266
267                 out = (struct berval *)ch_malloc(sizeof(struct berval));
268                 out->bv_val = dn;
269                 out->bv_len = strlen( dn );
270         }
271
272         *normalized = out;
273         return LDAP_SUCCESS;
274 }
275
276 static int
277 dnMatch(
278         int *matchp,
279         slap_mask_t flags,
280         Syntax *syntax,
281         MatchingRule *mr,
282         struct berval *value,
283         void *assertedValue )
284 {
285         int match;
286         struct berval *asserted = (struct berval *) assertedValue;
287         
288         match = value->bv_len - asserted->bv_len;
289
290         if( match == 0 ) {
291 #ifdef USE_DN_NORMALIZE
292                 match = strcmp( value->bv_val, asserted->bv_val );
293 #else
294                 match = strcasecmp( value->bv_val, asserted->bv_val );
295 #endif
296         }
297
298 #ifdef NEW_LOGGING
299         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
300                    "dnMatch: %d\n    %s\n    %s\n", match,
301                    value->bv_val, asserted->bv_val ));
302 #else
303         Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
304             match, value->bv_val, asserted->bv_val );
305 #endif
306
307
308         *matchp = match;
309         return LDAP_SUCCESS;
310 }
311
312 static int
313 nameUIDValidate(
314         Syntax *syntax,
315         struct berval *in )
316 {
317         int rc;
318         struct berval *dn;
319
320         if( in->bv_len == 0 ) return LDAP_SUCCESS;
321
322         dn = ber_bvdup( in );
323
324         if( dn->bv_val[dn->bv_len-1] == '\'' ) {
325                 /* assume presence of optional UID */
326                 ber_len_t i;
327
328                 for(i=dn->bv_len-2; i>2; i--) {
329                         if( dn->bv_val[i] != '0' &&     dn->bv_val[i] != '1' ) {
330                                 break;
331                         }
332                 }
333                 if( dn->bv_val[i] != '\'' ) {
334                         return LDAP_INVALID_SYNTAX;
335                 }
336                 if( dn->bv_val[i-1] != 'B' ) {
337                         return LDAP_INVALID_SYNTAX;
338                 }
339                 if( dn->bv_val[i-2] != '#' ) {
340                         return LDAP_INVALID_SYNTAX;
341                 }
342
343                 /* trim the UID to allow use of dn_validate */
344                 dn->bv_val[i-2] = '\0';
345         }
346
347         rc = dn_validate( dn->bv_val ) == NULL
348                 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
349
350         ber_bvfree( dn );
351         return rc;
352 }
353
354 static int
355 nameUIDNormalize(
356         Syntax *syntax,
357         struct berval *val,
358         struct berval **normalized )
359 {
360         struct berval *out = ber_bvdup( val );
361
362         if( out->bv_len != 0 ) {
363                 char *dn;
364                 ber_len_t dnlen;
365                 char *uid = NULL;
366                 ber_len_t uidlen = 0;
367
368                 if( out->bv_val[out->bv_len-1] == '\'' ) {
369                         /* assume presence of optional UID */
370                         uid = strrchr( out->bv_val, '#' );
371
372                         if( uid == NULL ) {
373                                 ber_bvfree( out );
374                                 return LDAP_INVALID_SYNTAX;
375                         }
376
377                         uidlen = out->bv_len - (out->bv_val - uid);
378                         /* temporarily trim the UID */
379                         *uid = '\0';
380                 }
381
382 #ifdef USE_DN_NORMALIZE
383                 dn = dn_normalize( out->bv_val );
384 #else
385                 dn = dn_validate( out->bv_val );
386 #endif
387
388                 if( dn == NULL ) {
389                         ber_bvfree( out );
390                         return LDAP_INVALID_SYNTAX;
391                 }
392
393                 dnlen = strlen(dn);
394
395                 if( uidlen ) {
396                         /* restore the separator */
397                         *uid = '#';
398                         /* shift the UID */
399                         SAFEMEMCPY( &dn[dnlen], uid, uidlen );
400                 }
401
402                 out->bv_val = dn;
403                 out->bv_len = dnlen + uidlen;
404         }
405
406         *normalized = out;
407         return LDAP_SUCCESS;
408 }
409
410 static int
411 inValidate(
412         Syntax *syntax,
413         struct berval *in )
414 {
415         /* any value allowed */
416         return LDAP_OTHER;
417 }
418
419 static int
420 blobValidate(
421         Syntax *syntax,
422         struct berval *in )
423 {
424         /* any value allowed */
425         return LDAP_SUCCESS;
426 }
427
428 static int
429 bitStringValidate(
430         Syntax *syntax,
431         struct berval *in )
432 {
433         ber_len_t i;
434
435         /* very unforgiving validation, requires no normalization
436          * before simplistic matching
437          */
438         if( in->bv_len < 3 ) {
439                 return LDAP_INVALID_SYNTAX;
440         }
441
442         if( in->bv_val[0] != 'B' ||
443                 in->bv_val[1] != '\'' ||
444                 in->bv_val[in->bv_len-1] != '\'' )
445         {
446                 return LDAP_INVALID_SYNTAX;
447         }
448
449         for( i=in->bv_len-2; i>1; i-- ) {
450                 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
451                         return LDAP_INVALID_SYNTAX;
452                 }
453         }
454
455         return LDAP_SUCCESS;
456 }
457
458 /*
459  * Handling boolean syntax and matching is quite rigid.
460  * A more flexible approach would be to allow a variety
461  * of strings to be normalized and prettied into TRUE
462  * and FALSE.
463  */
464 static int
465 booleanValidate(
466         Syntax *syntax,
467         struct berval *in )
468 {
469         /* very unforgiving validation, requires no normalization
470          * before simplistic matching
471          */
472
473         if( in->bv_len == 4 ) {
474                 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
475                         return LDAP_SUCCESS;
476                 }
477         } else if( in->bv_len == 5 ) {
478                 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
479                         return LDAP_SUCCESS;
480                 }
481         }
482
483         return LDAP_INVALID_SYNTAX;
484 }
485
486 static int
487 booleanMatch(
488         int *matchp,
489         slap_mask_t flags,
490         Syntax *syntax,
491         MatchingRule *mr,
492         struct berval *value,
493         void *assertedValue )
494 {
495         /* simplistic matching allowed by rigid validation */
496         struct berval *asserted = (struct berval *) assertedValue;
497         *matchp = value->bv_len != asserted->bv_len;
498         return LDAP_SUCCESS;
499 }
500
501 static int
502 UTF8StringValidate(
503         Syntax *syntax,
504         struct berval *in )
505 {
506         ber_len_t count;
507         int len;
508         unsigned char *u = in->bv_val;
509
510         if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
511
512         for( count = in->bv_len; count > 0; count-=len, u+=len ) {
513                 /* get the length indicated by the first byte */
514                 len = LDAP_UTF8_CHARLEN( u );
515
516                 /* should not be zero */
517                 if( len == 0 ) return LDAP_INVALID_SYNTAX;
518
519                 /* make sure len corresponds with the offset
520                         to the next character */
521                 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
522         }
523
524         if( count != 0 ) return LDAP_INVALID_SYNTAX;
525
526         return LDAP_SUCCESS;
527 }
528
529 static int
530 UTF8StringNormalize(
531         Syntax *syntax,
532         struct berval *val,
533         struct berval **normalized )
534 {
535         struct berval *newval;
536         char *p, *q, *s;
537
538         newval = ch_malloc( sizeof( struct berval ) );
539
540         p = val->bv_val;
541
542         /* Ignore initial whitespace */
543         while ( ldap_utf8_isspace( p ) ) {
544                 LDAP_UTF8_INCR( p );
545         }
546
547         if( *p == '\0' ) {
548                 ch_free( newval );
549                 return LDAP_INVALID_SYNTAX;
550         }
551
552         newval->bv_val = ch_strdup( p );
553         p = q = newval->bv_val;
554         s = NULL;
555
556         while ( *p ) {
557                 int len;
558
559                 if ( ldap_utf8_isspace( p ) ) {
560                         len = LDAP_UTF8_COPY(q,p);
561                         s=q;
562                         p+=len;
563                         q+=len;
564
565                         /* Ignore the extra whitespace */
566                         while ( ldap_utf8_isspace( p ) ) {
567                                 LDAP_UTF8_INCR( p );
568                         }
569                 } else {
570                         len = LDAP_UTF8_COPY(q,p);
571                         s=NULL;
572                         p+=len;
573                         q+=len;
574                 }
575         }
576
577         assert( *newval->bv_val );
578         assert( newval->bv_val < p );
579         assert( q <= p );
580
581         /* cannot start with a space */
582         assert( !ldap_utf8_isspace(newval->bv_val) );
583
584         /*
585          * If the string ended in space, backup the pointer one
586          * position.  One is enough because the above loop collapsed
587          * all whitespace to a single space.
588          */
589
590         if ( s != NULL ) {
591                 q = s;
592         }
593
594         /* cannot end with a space */
595         assert( !ldap_utf8_isspace( LDAP_UTF8_PREV(q) ) );
596
597         /* null terminate */
598         *q = '\0';
599
600         newval->bv_len = q - newval->bv_val;
601         *normalized = newval;
602
603         return LDAP_SUCCESS;
604 }
605
606 #if UTF8MATCH
607 /* Returns Unicode cannonically normalized copy of a substring assertion
608  * Skipping attribute description */
609 SubstringsAssertion *
610 UTF8SubstringsassertionNormalize(
611         SubstringsAssertion *sa,
612         char casefold )
613 {
614         SubstringsAssertion *nsa;
615         int i;
616
617         nsa = (SubstringsAssertion *)ch_calloc( 1, sizeof(SubstringsAssertion) );
618         if( nsa == NULL ) {
619                 return NULL;
620         }
621
622         if( sa->sa_initial != NULL ) {
623                 nsa->sa_initial = ber_bvstr( UTF8normalize( sa->sa_initial->bv_val, casefold ) );
624                 if( nsa->sa_initial == NULL ) {
625                         goto err;
626                 }
627         }
628
629         if( sa->sa_any != NULL ) {
630                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
631                         /* empty */
632                 }
633                 nsa->sa_any = (struct berval **)ch_malloc( (i + 1) * sizeof(struct berval *) );
634                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
635                         nsa->sa_any[i] = ber_bvstr( UTF8normalize( sa->sa_any[i]->bv_val, casefold ) );
636                         if( nsa->sa_any[i] == NULL ) {
637                                 goto err;
638                         }
639                 }
640                 nsa->sa_any[i] = NULL;
641         }
642
643         if( sa->sa_final != NULL ) {
644                 nsa->sa_final = ber_bvstr( UTF8normalize( sa->sa_final->bv_val, casefold ) );
645                 if( nsa->sa_final == NULL ) {
646                         goto err;
647                 }
648         }
649
650         return nsa;
651
652 err:
653         ch_free( nsa->sa_final );
654         ber_bvecfree( nsa->sa_any );
655         ch_free( nsa->sa_initial );
656         ch_free( nsa );
657         return NULL;
658 }
659 #endif
660
661 #if defined(SLAPD_APPROX_MULTISTRING)
662
663 #if defined(SLAPD_APPROX_INITIALS)
664 #define SLAPD_APPROX_DELIMITER "._ "
665 #define SLAPD_APPROX_WORDLEN 2
666 #else
667 #define SLAPD_APPROX_DELIMITER " "
668 #define SLAPD_APPROX_WORDLEN 1
669 #endif
670
671 static int
672 approxMatch(
673         int *matchp,
674         slap_mask_t flags,
675         Syntax *syntax,
676         MatchingRule *mr,
677         struct berval *value,
678         void *assertedValue )
679 {
680         char *val, *assertv, **values, **words, *c;
681         int i, count, len, nextchunk=0, nextavail=0;
682
683
684         /* Isolate how many words there are */
685         val = ch_strdup( value->bv_val );
686         for( c=val,count=1; *c; c++ ) {
687                 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
688                 if ( c == NULL ) break;
689                 *c = '\0';
690                 count++;
691         }
692
693         /* Get a phonetic copy of each word */
694         words = (char **)ch_malloc( count * sizeof(char *) );
695         values = (char **)ch_malloc( count * sizeof(char *) );
696         for( c=val,i=0;  i<count;  i++,c+=strlen(c)+1 ) {
697                 words[i] = c;
698                 values[i] = phonetic(c);
699         }
700
701
702         /* Work through the asserted value's words, to see if  at least some
703            of the words are there, in the same order. */
704         assertv = ch_strdup( ((struct berval *)assertedValue)->bv_val );
705         len = 0;
706         while ( nextchunk < ((struct berval *)assertedValue)->bv_len ) {
707                 len = strcspn( assertv + nextchunk, SLAPD_APPROX_DELIMITER);
708                 if( len == 0 ) {
709                         nextchunk++;
710                         continue;
711                 }
712 #if defined(SLAPD_APPROX_INITIALS)
713                 else if( len == 1 ) {
714                         /* Single letter words need to at least match one word's initial */
715                         for( i=nextavail; i<count; i++ )
716                                 if( !strncasecmp( assertv+nextchunk, words[i], 1 )) {
717                                         nextavail=i+1;
718                                         break;
719                                 }
720                 }
721 #endif
722                 else {
723                         /* Isolate the next word in the asserted value and phonetic it */
724                         assertv[nextchunk+len] = '\0';
725                         val = phonetic( assertv + nextchunk );
726
727                         /* See if this phonetic chunk is in the remaining words of *value */
728                         for( i=nextavail; i<count; i++ ){
729                                 if( !strcmp( val, values[i] ) ){
730                                         nextavail = i+1;
731                                         break;
732                                 }
733                         }
734                 }
735
736                 /* This chunk in the asserted value was NOT within the *value. */
737                 if( i >= count ) {
738                         nextavail=-1;
739                         break;
740                 }
741
742                 /* Go on to the next word in the asserted value */
743                 nextchunk += len+1;
744         }
745
746         /* If some of the words were seen, call it a match */
747         if( nextavail > 0 ) {
748                 *matchp = 0;
749         }
750         else {
751                 *matchp = 1;
752         }
753
754         /* Cleanup allocs */
755         ch_free( assertv );
756         for( i=0; i<count; i++ ) {
757                 ch_free( values[i] );
758         }
759         ch_free( values );
760         ch_free( words );
761         ch_free( val );
762
763         return LDAP_SUCCESS;
764 }
765
766
767 int 
768 approxIndexer(
769         slap_mask_t use,
770         slap_mask_t flags,
771         Syntax *syntax,
772         MatchingRule *mr,
773         struct berval *prefix,
774         struct berval **values,
775         struct berval ***keysp )
776 {
777         char *val, *c;
778         int i,j, len, wordcount, keycount=0;
779         struct berval **newkeys, **keys=NULL;
780
781
782         for( j=0; values[j] != NULL; j++ ) {
783
784                 /* Isolate how many words there are. There will be a key for each */
785                 val = ch_strdup( values[j]->bv_val );
786                 for( wordcount=0,c=val;  *c;  c++) {
787                         len = strcspn(c, SLAPD_APPROX_DELIMITER);
788                         if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
789                         c+= len;
790                         if (*c == '\0') break;
791                         *c = '\0';
792                 }
793
794                 /* Allocate/increase storage to account for new keys */
795                 newkeys = (struct berval **)ch_malloc( (keycount + wordcount + 1) 
796                    * sizeof(struct berval *) );
797                 memcpy( newkeys, keys, keycount * sizeof(struct berval *) );
798                 if( keys ) ch_free( keys );
799                 keys = newkeys;
800
801                 /* Get a phonetic copy of each word */
802                 for( c=val,i=0;  i<wordcount;  c+=len+1  ) {
803                         len = strlen( c );
804                         if( len < SLAPD_APPROX_WORDLEN ) continue;
805                         keys[keycount] = (struct berval *)ch_malloc( sizeof(struct berval) );
806                         keys[keycount]->bv_val = phonetic( c );
807                         keys[keycount]->bv_len = strlen( keys[keycount]->bv_val );
808                         keycount++;
809                         i++;
810                 }
811
812                 ch_free( val );
813         }
814         keys[keycount] = NULL;
815         *keysp = keys;
816
817         return LDAP_SUCCESS;
818 }
819
820
821 int 
822 approxFilter(
823         slap_mask_t use,
824         slap_mask_t flags,
825         Syntax *syntax,
826         MatchingRule *mr,
827         struct berval *prefix,
828         void * assertValue,
829         struct berval ***keysp )
830 {
831         char *val, *c;
832         int i, count, len;
833         struct berval **keys;
834
835
836         /* Isolate how many words there are. There will be a key for each */
837         val = ch_strdup( ((struct berval *)assertValue)->bv_val );
838         for( count=0,c=val;  *c;  c++) {
839                 len = strcspn(c, SLAPD_APPROX_DELIMITER);
840                 if( len >= SLAPD_APPROX_WORDLEN ) count++;
841                 c+= len;
842                 if (*c == '\0') break;
843                 *c = '\0';
844         }
845
846         /* Allocate storage for new keys */
847         keys = (struct berval **)ch_malloc( (count + 1) * sizeof(struct berval *) );
848
849         /* Get a phonetic copy of each word */
850         for( c=val,i=0;  i<count; c+=len+1 ) {
851                 len = strlen(c);
852                 if( len < SLAPD_APPROX_WORDLEN ) continue;
853                 keys[i] = (struct berval *)ch_malloc( sizeof(struct berval) );
854                 keys[i]->bv_val = phonetic( c );
855                 keys[i]->bv_len = strlen( keys[i]->bv_val );
856                 i++;
857         }
858
859         ch_free( val );
860
861         keys[count] = NULL;
862         *keysp = keys;
863
864         return LDAP_SUCCESS;
865 }
866
867
868 #else
869 /* No other form of Approximate Matching is defined */
870
871 static int
872 approxMatch(
873         int *matchp,
874         slap_mask_t flags,
875         Syntax *syntax,
876         MatchingRule *mr,
877         struct berval *value,
878         void *assertedValue )
879 {
880         char *vapprox, *avapprox;
881
882         vapprox = phonetic( value->bv_val );
883         avapprox = phonetic( ((struct berval *)assertedValue)->bv_val);
884
885         *matchp = strcmp( vapprox, avapprox );
886
887         ch_free( vapprox );
888         ch_free( avapprox );
889
890         return LDAP_SUCCESS;
891 }
892
893 int 
894 approxIndexer(
895         slap_mask_t use,
896         slap_mask_t flags,
897         Syntax *syntax,
898         MatchingRule *mr,
899         struct berval *prefix,
900         struct berval **values,
901         struct berval ***keysp )
902 {
903         int i;
904         struct berval **keys;
905
906
907         for( i=0; values[i] != NULL; i++ ) {
908                 /* just count them */
909         }
910         assert( i > 0 );
911
912         keys = (struct berval **)ch_malloc( sizeof( struct berval * ) * (i+1) );
913
914         /* Copy each value and run it through phonetic() */
915         for( i=0; values[i] != NULL; i++ ) {
916                 keys[i] = ch_malloc( sizeof( struct berval * ) );
917                 keys[i]->bv_val = phonetic( values[i]->bv_val );
918                 keys[i]->bv_len = strlen( keys[i]->bv_val );
919         }
920         keys[i] = NULL;
921
922         *keysp = keys;
923         return LDAP_SUCCESS;
924 }
925
926
927 int 
928 approxFilter(
929         slap_mask_t use,
930         slap_mask_t flags,
931         Syntax *syntax,
932         MatchingRule *mr,
933         struct berval *prefix,
934         void * assertValue,
935         struct berval ***keysp )
936 {
937         struct berval **keys;
938
939
940         keys = (struct berval **)ch_malloc( sizeof( struct berval * ) * 2 );
941
942         /* Copy the value and run it through phonetic() */
943         keys[0] = ch_malloc( sizeof( struct berval * ) );
944         keys[0]->bv_val = phonetic( ((struct berval *)assertValue)->bv_val );
945         keys[0]->bv_len = strlen( keys[0]->bv_val );
946         keys[1] = NULL;
947
948         *keysp = keys;
949         return LDAP_SUCCESS;
950 }
951 #endif
952
953
954 static int
955 caseExactMatch(
956         int *matchp,
957         slap_mask_t flags,
958         Syntax *syntax,
959         MatchingRule *mr,
960         struct berval *value,
961         void *assertedValue )
962 {
963         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
964
965         if( match == 0 ) {
966                 match = strncmp( value->bv_val,
967                         ((struct berval *) assertedValue)->bv_val,
968                         value->bv_len );
969         }
970
971         *matchp = match;
972         return LDAP_SUCCESS;
973 }
974
975 static int
976 caseExactSubstringsMatch(
977         int *matchp,
978         slap_mask_t flags,
979         Syntax *syntax,
980         MatchingRule *mr,
981         struct berval *value,
982         void *assertedValue )
983 {
984         int match = 0;
985         SubstringsAssertion *sub;
986         struct berval left;
987         int i;
988         ber_len_t inlen=0;
989 #if UTF8MATCH
990         char *nav;
991 #endif
992
993 #if UTF8MATCH
994         nav = UTF8normalize( value->bv_val, UTF8_NOCASEFOLD );
995         if( nav == NULL ) {
996                 match = 1;
997                 goto done;
998         }
999         left.bv_val = nav;
1000         left.bv_len = strlen( nav );
1001         sub = UTF8SubstringsassertionNormalize( assertedValue, UTF8_NOCASEFOLD );
1002 #else
1003         left = *value;
1004         sub = assertedValue;
1005 #endif
1006         if( sub == NULL ) {
1007                 match = -1;
1008                 goto done;
1009         }
1010
1011         /* Add up asserted input length */
1012         if( sub->sa_initial ) {
1013                 inlen += sub->sa_initial->bv_len;
1014         }
1015         if( sub->sa_any ) {
1016                 for(i=0; sub->sa_any[i] != NULL; i++) {
1017                         inlen += sub->sa_any[i]->bv_len;
1018                 }
1019         }
1020         if( sub->sa_final ) {
1021                 inlen += sub->sa_final->bv_len;
1022         }
1023
1024         if( sub->sa_initial ) {
1025                 if( inlen > left.bv_len ) {
1026                         match = 1;
1027                         goto done;
1028                 }
1029
1030                 match = strncmp( sub->sa_initial->bv_val, left.bv_val,
1031                         sub->sa_initial->bv_len );
1032
1033                 if( match != 0 ) {
1034                         goto done;
1035                 }
1036
1037                 left.bv_val += sub->sa_initial->bv_len;
1038                 left.bv_len -= sub->sa_initial->bv_len;
1039                 inlen -= sub->sa_initial->bv_len;
1040         }
1041
1042         if( sub->sa_final ) {
1043                 if( inlen > left.bv_len ) {
1044                         match = 1;
1045                         goto done;
1046                 }
1047
1048                 match = strncmp( sub->sa_final->bv_val,
1049                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
1050                         sub->sa_final->bv_len );
1051
1052                 if( match != 0 ) {
1053                         goto done;
1054                 }
1055
1056                 left.bv_len -= sub->sa_final->bv_len;
1057                 inlen -= sub->sa_final->bv_len;
1058         }
1059
1060         if( sub->sa_any ) {
1061                 for(i=0; sub->sa_any[i]; i++) {
1062                         ber_len_t idx;
1063                         char *p;
1064
1065 retry:
1066                         if( inlen > left.bv_len ) {
1067                                 /* not enough length */
1068                                 match = 1;
1069                                 goto done;
1070                         }
1071
1072                         if( sub->sa_any[i]->bv_len == 0 ) {
1073                                 continue;
1074                         }
1075
1076                         p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
1077
1078                         if( p == NULL ) {
1079                                 match = 1;
1080                                 goto done;
1081                         }
1082
1083                         idx = p - left.bv_val;
1084                         assert( idx < left.bv_len );
1085
1086                         if( idx >= left.bv_len ) {
1087                                 /* this shouldn't happen */
1088                                 return LDAP_OTHER;
1089                         }
1090
1091                         left.bv_val = p;
1092                         left.bv_len -= idx;
1093
1094                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
1095                                 /* not enough left */
1096                                 match = 1;
1097                                 goto done;
1098                         }
1099
1100                         match = strncmp( left.bv_val,
1101                                 sub->sa_any[i]->bv_val,
1102                                 sub->sa_any[i]->bv_len );
1103
1104                         if( match != 0 ) {
1105                                 left.bv_val++;
1106                                 left.bv_len--;
1107                                 goto retry;
1108                         }
1109
1110                         left.bv_val += sub->sa_any[i]->bv_len;
1111                         left.bv_len -= sub->sa_any[i]->bv_len;
1112                         inlen -= sub->sa_any[i]->bv_len;
1113                 }
1114         }
1115
1116 done:
1117 #if UTF8MATCH
1118         free( nav );
1119         if( sub != NULL ) {
1120                 ch_free( sub->sa_final );
1121                 ber_bvecfree( sub->sa_any );
1122                 ch_free( sub->sa_initial );
1123                 ch_free( sub );
1124         }
1125 #endif
1126         *matchp = match;
1127         return LDAP_SUCCESS;
1128 }
1129
1130 /* Index generation function */
1131 int caseExactIndexer(
1132         slap_mask_t use,
1133         slap_mask_t flags,
1134         Syntax *syntax,
1135         MatchingRule *mr,
1136         struct berval *prefix,
1137         struct berval **values,
1138         struct berval ***keysp )
1139 {
1140         int i;
1141         size_t slen, mlen;
1142         struct berval **keys;
1143         HASH_CONTEXT   HASHcontext;
1144         unsigned char   HASHdigest[HASH_BYTES];
1145         struct berval digest;
1146         digest.bv_val = HASHdigest;
1147         digest.bv_len = sizeof(HASHdigest);
1148
1149         /* we should have at least one value at this point */
1150         assert( values != NULL && values[0] != NULL );
1151
1152         for( i=0; values[i] != NULL; i++ ) {
1153                 /* just count them */
1154         }
1155
1156         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
1157
1158         slen = strlen( syntax->ssyn_oid );
1159         mlen = strlen( mr->smr_oid );
1160
1161         for( i=0; values[i] != NULL; i++ ) {
1162                 struct berval *value;
1163 #if UTF8MATCH
1164                 value = ber_bvstr( UTF8normalize( values[i]->bv_val, UTF8_NOCASEFOLD ) );
1165 #else
1166                 value = values[i];
1167 #endif
1168
1169                 HASH_Init( &HASHcontext );
1170                 if( prefix != NULL && prefix->bv_len > 0 ) {
1171                         HASH_Update( &HASHcontext,
1172                                 prefix->bv_val, prefix->bv_len );
1173                 }
1174                 HASH_Update( &HASHcontext,
1175                         syntax->ssyn_oid, slen );
1176                 HASH_Update( &HASHcontext,
1177                         mr->smr_oid, mlen );
1178                 HASH_Update( &HASHcontext,
1179                         value->bv_val, value->bv_len );
1180                 HASH_Final( HASHdigest, &HASHcontext );
1181
1182 #if UTF8MATCH
1183                 ber_bvfree( value );
1184 #endif
1185
1186                 keys[i] = ber_bvdup( &digest );
1187         }
1188
1189         keys[i] = NULL;
1190         *keysp = keys;
1191         return LDAP_SUCCESS;
1192 }
1193
1194 /* Index generation function */
1195 int caseExactFilter(
1196         slap_mask_t use,
1197         slap_mask_t flags,
1198         Syntax *syntax,
1199         MatchingRule *mr,
1200         struct berval *prefix,
1201         void * assertValue,
1202         struct berval ***keysp )
1203 {
1204         size_t slen, mlen;
1205         struct berval **keys;
1206         HASH_CONTEXT   HASHcontext;
1207         unsigned char   HASHdigest[HASH_BYTES];
1208         struct berval *value;
1209         struct berval digest;
1210         digest.bv_val = HASHdigest;
1211         digest.bv_len = sizeof(HASHdigest);
1212
1213         slen = strlen( syntax->ssyn_oid );
1214         mlen = strlen( mr->smr_oid );
1215
1216 #if UTF8MATCH
1217         value = ber_bvstr( UTF8normalize( ((struct berval *) assertValue)->bv_val,
1218                 UTF8_NOCASEFOLD ) );
1219         /* This usually happens if filter contains bad UTF8 */
1220         if( value == NULL ) {
1221                 keys = ch_malloc( sizeof( struct berval * ) );
1222                 keys[0] = NULL;
1223                 return LDAP_SUCCESS;
1224         }
1225 #else
1226         value = (struct berval *) assertValue;
1227 #endif
1228
1229         keys = ch_malloc( sizeof( struct berval * ) * 2 );
1230
1231         HASH_Init( &HASHcontext );
1232         if( prefix != NULL && prefix->bv_len > 0 ) {
1233                 HASH_Update( &HASHcontext,
1234                         prefix->bv_val, prefix->bv_len );
1235         }
1236         HASH_Update( &HASHcontext,
1237                 syntax->ssyn_oid, slen );
1238         HASH_Update( &HASHcontext,
1239                 mr->smr_oid, mlen );
1240         HASH_Update( &HASHcontext,
1241                 value->bv_val, value->bv_len );
1242         HASH_Final( HASHdigest, &HASHcontext );
1243
1244         keys[0] = ber_bvdup( &digest );
1245         keys[1] = NULL;
1246
1247 #if UTF8MATCH
1248         ber_bvfree( value );
1249 #endif
1250
1251         *keysp = keys;
1252         return LDAP_SUCCESS;
1253 }
1254
1255 /* Substrings Index generation function */
1256 int caseExactSubstringsIndexer(
1257         slap_mask_t use,
1258         slap_mask_t flags,
1259         Syntax *syntax,
1260         MatchingRule *mr,
1261         struct berval *prefix,
1262         struct berval **values,
1263         struct berval ***keysp )
1264 {
1265         ber_len_t i, nkeys;
1266         size_t slen, mlen;
1267         struct berval **keys;
1268 #if UTF8MATCH
1269         struct berval **nvalues;
1270 #endif
1271
1272         HASH_CONTEXT   HASHcontext;
1273         unsigned char   HASHdigest[HASH_BYTES];
1274         struct berval digest;
1275         digest.bv_val = HASHdigest;
1276         digest.bv_len = sizeof(HASHdigest);
1277
1278         /* we should have at least one value at this point */
1279         assert( values != NULL && values[0] != NULL );
1280
1281         nkeys=0;
1282
1283 #if UTF8MATCH
1284         /* create normalized copy of values */
1285         for( i=0; values[i] != NULL; i++ ) {
1286                 /* empty */
1287         }
1288         nvalues = ch_malloc( sizeof( struct berval * ) * (i+1) );
1289         for( i=0; values[i] != NULL; i++ ) {
1290                 nvalues[i] = ber_bvstr( UTF8normalize( values[i]->bv_val, UTF8_NOCASEFOLD ) );
1291         }
1292         nvalues[i] = NULL;
1293         values = nvalues;
1294 #endif
1295
1296         for( i=0; values[i] != NULL; i++ ) {
1297                 /* count number of indices to generate */
1298                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1299                         continue;
1300                 }
1301
1302                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1303                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1304                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1305                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1306                         } else {
1307                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1308                         }
1309                 }
1310
1311                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1312                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1313                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1314                         }
1315                 }
1316
1317                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1318                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1319                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1320                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1321                         } else {
1322                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1323                         }
1324                 }
1325         }
1326
1327         if( nkeys == 0 ) {
1328                 /* no keys to generate */
1329                 *keysp = NULL;
1330                 return LDAP_SUCCESS;
1331         }
1332
1333         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1334
1335         slen = strlen( syntax->ssyn_oid );
1336         mlen = strlen( mr->smr_oid );
1337
1338         nkeys=0;
1339         for( i=0; values[i] != NULL; i++ ) {
1340                 ber_len_t j,max;
1341                 struct berval *value;
1342
1343                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1344
1345                 value = values[i];
1346
1347                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1348                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1349                 {
1350                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
1351                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1352
1353                         for( j=0; j<max; j++ ) {
1354                                 HASH_Init( &HASHcontext );
1355                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1356                                         HASH_Update( &HASHcontext,
1357                                                 prefix->bv_val, prefix->bv_len );
1358                                 }
1359
1360                                 HASH_Update( &HASHcontext,
1361                                         &pre, sizeof( pre ) );
1362                                 HASH_Update( &HASHcontext,
1363                                         syntax->ssyn_oid, slen );
1364                                 HASH_Update( &HASHcontext,
1365                                         mr->smr_oid, mlen );
1366                                 HASH_Update( &HASHcontext,
1367                                         &value->bv_val[j],
1368                                         SLAP_INDEX_SUBSTR_MAXLEN );
1369                                 HASH_Final( HASHdigest, &HASHcontext );
1370
1371                                 keys[nkeys++] = ber_bvdup( &digest );
1372                         }
1373                 }
1374
1375                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1376                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1377
1378                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1379                         char pre;
1380
1381                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1382                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1383                                 HASH_Init( &HASHcontext );
1384                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1385                                         HASH_Update( &HASHcontext,
1386                                                 prefix->bv_val, prefix->bv_len );
1387                                 }
1388                                 HASH_Update( &HASHcontext,
1389                                         &pre, sizeof( pre ) );
1390                                 HASH_Update( &HASHcontext,
1391                                         syntax->ssyn_oid, slen );
1392                                 HASH_Update( &HASHcontext,
1393                                         mr->smr_oid, mlen );
1394                                 HASH_Update( &HASHcontext,
1395                                         value->bv_val, j );
1396                                 HASH_Final( HASHdigest, &HASHcontext );
1397
1398                                 keys[nkeys++] = ber_bvdup( &digest );
1399                         }
1400
1401                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1402                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1403                                 HASH_Init( &HASHcontext );
1404                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1405                                         HASH_Update( &HASHcontext,
1406                                                 prefix->bv_val, prefix->bv_len );
1407                                 }
1408                                 HASH_Update( &HASHcontext,
1409                                         &pre, sizeof( pre ) );
1410                                 HASH_Update( &HASHcontext,
1411                                         syntax->ssyn_oid, slen );
1412                                 HASH_Update( &HASHcontext,
1413                                         mr->smr_oid, mlen );
1414                                 HASH_Update( &HASHcontext,
1415                                         &value->bv_val[value->bv_len-j], j );
1416                                 HASH_Final( HASHdigest, &HASHcontext );
1417
1418                                 keys[nkeys++] = ber_bvdup( &digest );
1419                         }
1420
1421                 }
1422
1423         }
1424
1425         if( nkeys > 0 ) {
1426                 keys[nkeys] = NULL;
1427                 *keysp = keys;
1428         } else {
1429                 ch_free( keys );
1430                 *keysp = NULL;
1431         }
1432
1433 #if UTF8MATCH
1434         ber_bvecfree( nvalues );
1435 #endif
1436
1437         return LDAP_SUCCESS;
1438 }
1439
1440 int caseExactSubstringsFilter(
1441         slap_mask_t use,
1442         slap_mask_t flags,
1443         Syntax *syntax,
1444         MatchingRule *mr,
1445         struct berval *prefix,
1446         void * assertValue,
1447         struct berval ***keysp )
1448 {
1449         SubstringsAssertion *sa;
1450         char pre;
1451         ber_len_t nkeys = 0;
1452         size_t slen, mlen, klen;
1453         struct berval **keys;
1454         HASH_CONTEXT   HASHcontext;
1455         unsigned char   HASHdigest[HASH_BYTES];
1456         struct berval *value;
1457         struct berval digest;
1458
1459 #if UTF8MATCH
1460         sa = UTF8SubstringsassertionNormalize( assertValue, UTF8_NOCASEFOLD );
1461 #else
1462         sa = assertValue;
1463 #endif
1464         if( sa == NULL ) {
1465                 *keysp = NULL;
1466                 return LDAP_SUCCESS;
1467         }
1468
1469         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
1470                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1471         {
1472                 nkeys++;
1473         }
1474
1475         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1476                 ber_len_t i;
1477                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1478                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1479                                 /* don't bother accounting for stepping */
1480                                 nkeys += sa->sa_any[i]->bv_len -
1481                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1482                         }
1483                 }
1484         }
1485
1486         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
1487                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1488         {
1489                 nkeys++;
1490         }
1491
1492         if( nkeys == 0 ) {
1493                 *keysp = NULL;
1494                 return LDAP_SUCCESS;
1495         }
1496
1497         digest.bv_val = HASHdigest;
1498         digest.bv_len = sizeof(HASHdigest);
1499
1500         slen = strlen( syntax->ssyn_oid );
1501         mlen = strlen( mr->smr_oid );
1502
1503         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1504         nkeys = 0;
1505
1506         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
1507                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1508         {
1509                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1510                 value = sa->sa_initial;
1511
1512                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1513                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1514
1515                 HASH_Init( &HASHcontext );
1516                 if( prefix != NULL && prefix->bv_len > 0 ) {
1517                         HASH_Update( &HASHcontext,
1518                                 prefix->bv_val, prefix->bv_len );
1519                 }
1520                 HASH_Update( &HASHcontext,
1521                         &pre, sizeof( pre ) );
1522                 HASH_Update( &HASHcontext,
1523                         syntax->ssyn_oid, slen );
1524                 HASH_Update( &HASHcontext,
1525                         mr->smr_oid, mlen );
1526                 HASH_Update( &HASHcontext,
1527                         value->bv_val, klen );
1528                 HASH_Final( HASHdigest, &HASHcontext );
1529
1530                 keys[nkeys++] = ber_bvdup( &digest );
1531         }
1532
1533         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1534                 ber_len_t i, j;
1535                 pre = SLAP_INDEX_SUBSTR_PREFIX;
1536                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1537
1538                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1539                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1540                                 continue;
1541                         }
1542
1543                         value = sa->sa_any[i];
1544
1545                         for(j=0;
1546                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1547                                 j += SLAP_INDEX_SUBSTR_STEP )
1548                         {
1549                                 HASH_Init( &HASHcontext );
1550                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1551                                         HASH_Update( &HASHcontext,
1552                                                 prefix->bv_val, prefix->bv_len );
1553                                 }
1554                                 HASH_Update( &HASHcontext,
1555                                         &pre, sizeof( pre ) );
1556                                 HASH_Update( &HASHcontext,
1557                                         syntax->ssyn_oid, slen );
1558                                 HASH_Update( &HASHcontext,
1559                                         mr->smr_oid, mlen );
1560                                 HASH_Update( &HASHcontext,
1561                                         &value->bv_val[j], klen ); 
1562                                 HASH_Final( HASHdigest, &HASHcontext );
1563
1564                                 keys[nkeys++] = ber_bvdup( &digest );
1565                         }
1566
1567                 }
1568         }
1569
1570         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
1571                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1572         {
1573                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1574                 value = sa->sa_final;
1575
1576                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1577                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1578
1579                 HASH_Init( &HASHcontext );
1580                 if( prefix != NULL && prefix->bv_len > 0 ) {
1581                         HASH_Update( &HASHcontext,
1582                                 prefix->bv_val, prefix->bv_len );
1583                 }
1584                 HASH_Update( &HASHcontext,
1585                         &pre, sizeof( pre ) );
1586                 HASH_Update( &HASHcontext,
1587                         syntax->ssyn_oid, slen );
1588                 HASH_Update( &HASHcontext,
1589                         mr->smr_oid, mlen );
1590                 HASH_Update( &HASHcontext,
1591                         &value->bv_val[value->bv_len-klen], klen );
1592                 HASH_Final( HASHdigest, &HASHcontext );
1593
1594                 keys[nkeys++] = ber_bvdup( &digest );
1595         }
1596
1597         if( nkeys > 0 ) {
1598                 keys[nkeys] = NULL;
1599                 *keysp = keys;
1600         } else {
1601                 ch_free( keys );
1602                 *keysp = NULL;
1603         }
1604 #if UTF8MATCH
1605         ch_free( sa->sa_final );
1606         ber_bvecfree( sa->sa_any );
1607         ch_free( sa->sa_initial );
1608         ch_free( sa );
1609 #endif
1610
1611         return LDAP_SUCCESS;
1612 }
1613         
1614 static int
1615 caseIgnoreMatch(
1616         int *matchp,
1617         slap_mask_t flags,
1618         Syntax *syntax,
1619         MatchingRule *mr,
1620         struct berval *value,
1621         void *assertedValue )
1622 {
1623 #if UTF8MATCH
1624         *matchp = UTF8normcmp( value->bv_val,
1625                 ((struct berval *) assertedValue)->bv_val,
1626                 UTF8_CASEFOLD );
1627 #else
1628         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
1629
1630         if( match == 0 ) {
1631                 match = strncasecmp( value->bv_val,
1632                         ((struct berval *) assertedValue)->bv_val,
1633                         value->bv_len );
1634         }
1635
1636         *matchp = match;
1637 #endif
1638         return LDAP_SUCCESS;
1639 }
1640
1641 static int
1642 caseIgnoreSubstringsMatch(
1643         int *matchp,
1644         slap_mask_t flags,
1645         Syntax *syntax,
1646         MatchingRule *mr,
1647         struct berval *value,
1648         void *assertedValue )
1649 {
1650         int match = 0;
1651         SubstringsAssertion *sub;
1652         struct berval left;
1653         int i;
1654         ber_len_t inlen=0;
1655 #if UTF8MATCH
1656         char *nav;
1657 #endif
1658
1659 #if UTF8MATCH
1660         nav = UTF8normalize( value->bv_val, UTF8_CASEFOLD );
1661         if( nav == NULL ) {
1662                 match = 1;
1663                 goto done;
1664         }
1665         left.bv_val = nav;
1666         left.bv_len = strlen( nav );
1667         sub = UTF8SubstringsassertionNormalize( assertedValue, UTF8_CASEFOLD );
1668 #else
1669         left = *value;
1670         sub = assertedValue;
1671 #endif
1672         if( sub == NULL ) {
1673                 match = -1;
1674                 goto done;
1675         }
1676
1677         /* Add up asserted input length */
1678         if( sub->sa_initial ) {
1679                 inlen += sub->sa_initial->bv_len;
1680         }
1681         if( sub->sa_any ) {
1682                 for(i=0; sub->sa_any[i] != NULL; i++) {
1683                         inlen += sub->sa_any[i]->bv_len;
1684                 }
1685         }
1686         if( sub->sa_final ) {
1687                 inlen += sub->sa_final->bv_len;
1688         }
1689
1690         if( sub->sa_initial ) {
1691                 if( inlen > left.bv_len ) {
1692                         match = 1;
1693                         goto done;
1694                 }
1695
1696 #if UTF8MATCH
1697                 match = strncmp( sub->sa_initial->bv_val, left.bv_val,
1698                         sub->sa_initial->bv_len );
1699 #else           
1700                 match = strncasecmp( sub->sa_initial->bv_val, left.bv_val,
1701                         sub->sa_initial->bv_len );
1702 #endif
1703
1704                 if( match != 0 ) {
1705                         goto done;
1706                 }
1707
1708                 left.bv_val += sub->sa_initial->bv_len;
1709                 left.bv_len -= sub->sa_initial->bv_len;
1710                 inlen -= sub->sa_initial->bv_len;
1711         }
1712
1713         if( sub->sa_final ) {
1714                 if( inlen > left.bv_len ) {
1715                         match = 1;
1716                         goto done;
1717                 }
1718
1719 #if UTF8MATCH
1720                 match = strncmp( sub->sa_final->bv_val,
1721                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
1722                         sub->sa_final->bv_len );
1723 #else           
1724                 match = strncasecmp( sub->sa_final->bv_val,
1725                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
1726                         sub->sa_final->bv_len );
1727 #endif
1728
1729                 if( match != 0 ) {
1730                         goto done;
1731                 }
1732
1733                 left.bv_len -= sub->sa_final->bv_len;
1734                 inlen -= sub->sa_final->bv_len;
1735         }
1736
1737         if( sub->sa_any ) {
1738                 for(i=0; sub->sa_any[i]; i++) {
1739                         ber_len_t idx;
1740                         char *p;
1741
1742 retry:
1743                         if( inlen > left.bv_len ) {
1744                                 /* not enough length */
1745                                 match = 1;
1746                                 goto done;
1747                         }
1748
1749                         if( sub->sa_any[i]->bv_len == 0 ) {
1750                                 continue;
1751                         }
1752
1753 #if UTF8MATCH
1754                         p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
1755 #else
1756                         p = strcasechr( left.bv_val, *sub->sa_any[i]->bv_val );
1757 #endif
1758
1759                         if( p == NULL ) {
1760                                 match = 1;
1761                                 goto done;
1762                         }
1763
1764                         idx = p - left.bv_val;
1765                         assert( idx < left.bv_len );
1766
1767                         if( idx >= left.bv_len ) {
1768                                 /* this shouldn't happen */
1769                                 return LDAP_OTHER;
1770                         }
1771
1772                         left.bv_val = p;
1773                         left.bv_len -= idx;
1774
1775                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
1776                                 /* not enough left */
1777                                 match = 1;
1778                                 goto done;
1779                         }
1780
1781 #if UTF8MATCH
1782                         match = strncmp( left.bv_val,
1783                                 sub->sa_any[i]->bv_val,
1784                                 sub->sa_any[i]->bv_len );
1785 #else                   
1786                         match = strncasecmp( left.bv_val,
1787                                 sub->sa_any[i]->bv_val,
1788                                 sub->sa_any[i]->bv_len );
1789 #endif
1790
1791                         if( match != 0 ) {
1792                                 left.bv_val++;
1793                                 left.bv_len--;
1794
1795                                 goto retry;
1796                         }
1797
1798                         left.bv_val += sub->sa_any[i]->bv_len;
1799                         left.bv_len -= sub->sa_any[i]->bv_len;
1800                         inlen -= sub->sa_any[i]->bv_len;
1801                 }
1802         }
1803
1804 done:
1805 #if UTF8MATCH
1806         free( nav );
1807         if( sub != NULL ) {
1808                 ch_free( sub->sa_final );
1809                 ber_bvecfree( sub->sa_any );
1810                 ch_free( sub->sa_initial );
1811                 ch_free( sub );
1812         }
1813 #endif
1814         *matchp = match;
1815         return LDAP_SUCCESS;
1816 }
1817
1818 /* Index generation function */
1819 int caseIgnoreIndexer(
1820         slap_mask_t use,
1821         slap_mask_t flags,
1822         Syntax *syntax,
1823         MatchingRule *mr,
1824         struct berval *prefix,
1825         struct berval **values,
1826         struct berval ***keysp )
1827 {
1828         int i;
1829         size_t slen, mlen;
1830         struct berval **keys;
1831         HASH_CONTEXT   HASHcontext;
1832         unsigned char   HASHdigest[HASH_BYTES];
1833         struct berval digest;
1834         digest.bv_val = HASHdigest;
1835         digest.bv_len = sizeof(HASHdigest);
1836
1837         /* we should have at least one value at this point */
1838         assert( values != NULL && values[0] != NULL );
1839
1840         for( i=0; values[i] != NULL; i++ ) {
1841                 /* just count them */
1842         }
1843
1844         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
1845
1846         slen = strlen( syntax->ssyn_oid );
1847         mlen = strlen( mr->smr_oid );
1848
1849         for( i=0; values[i] != NULL; i++ ) {
1850                 struct berval *value;
1851 #if UTF8MATCH
1852                 value = ber_bvstr( UTF8normalize( values[i]->bv_val, UTF8_CASEFOLD ) );
1853 #else
1854                 value = ber_bvdup( values[i] );
1855                 ldap_pvt_str2upper( value->bv_val );
1856 #endif
1857                 HASH_Init( &HASHcontext );
1858                 if( prefix != NULL && prefix->bv_len > 0 ) {
1859                         HASH_Update( &HASHcontext,
1860                                 prefix->bv_val, prefix->bv_len );
1861                 }
1862                 HASH_Update( &HASHcontext,
1863                         syntax->ssyn_oid, slen );
1864                 HASH_Update( &HASHcontext,
1865                         mr->smr_oid, mlen );
1866                 HASH_Update( &HASHcontext,
1867                         value->bv_val, value->bv_len );
1868                 HASH_Final( HASHdigest, &HASHcontext );
1869
1870                 ber_bvfree( value );
1871
1872                 keys[i] = ber_bvdup( &digest );
1873         }
1874
1875         keys[i] = NULL;
1876         *keysp = keys;
1877         return LDAP_SUCCESS;
1878 }
1879
1880 /* Index generation function */
1881 int caseIgnoreFilter(
1882         slap_mask_t use,
1883         slap_mask_t flags,
1884         Syntax *syntax,
1885         MatchingRule *mr,
1886         struct berval *prefix,
1887         void * assertValue,
1888         struct berval ***keysp )
1889 {
1890         size_t slen, mlen;
1891         struct berval **keys;
1892         HASH_CONTEXT   HASHcontext;
1893         unsigned char   HASHdigest[HASH_BYTES];
1894         struct berval *value;
1895         struct berval digest;
1896         digest.bv_val = HASHdigest;
1897         digest.bv_len = sizeof(HASHdigest);
1898
1899         slen = strlen( syntax->ssyn_oid );
1900         mlen = strlen( mr->smr_oid );
1901
1902 #if UTF8MATCH
1903         value = ber_bvstr( UTF8normalize( ((struct berval *) assertValue)->bv_val,
1904                 UTF8_CASEFOLD ) );
1905         /* This usually happens if filter contains bad UTF8 */
1906         if( value == NULL ) {
1907                 keys = ch_malloc( sizeof( struct berval * ) );
1908                 keys[0] = NULL;
1909                 return LDAP_SUCCESS;
1910         }
1911 #else
1912         value = ber_bvdup( (struct berval *) assertValue );
1913         ldap_pvt_str2upper( value->bv_val );
1914 #endif
1915
1916         keys = ch_malloc( sizeof( struct berval * ) * 2 );
1917
1918         HASH_Init( &HASHcontext );
1919         if( prefix != NULL && prefix->bv_len > 0 ) {
1920                 HASH_Update( &HASHcontext,
1921                         prefix->bv_val, prefix->bv_len );
1922         }
1923         HASH_Update( &HASHcontext,
1924                 syntax->ssyn_oid, slen );
1925         HASH_Update( &HASHcontext,
1926                 mr->smr_oid, mlen );
1927         HASH_Update( &HASHcontext,
1928                 value->bv_val, value->bv_len );
1929         HASH_Final( HASHdigest, &HASHcontext );
1930
1931         keys[0] = ber_bvdup( &digest );
1932         keys[1] = NULL;
1933
1934         ber_bvfree( value );
1935
1936         *keysp = keys;
1937
1938         return LDAP_SUCCESS;
1939 }
1940
1941 /* Substrings Index generation function */
1942 int caseIgnoreSubstringsIndexer(
1943         slap_mask_t use,
1944         slap_mask_t flags,
1945         Syntax *syntax,
1946         MatchingRule *mr,
1947         struct berval *prefix,
1948         struct berval **values,
1949         struct berval ***keysp )
1950 {
1951         ber_len_t i, nkeys;
1952         size_t slen, mlen;
1953         struct berval **keys;
1954 #if UTF8MATCH
1955         struct berval **nvalues;
1956 #endif
1957
1958         HASH_CONTEXT   HASHcontext;
1959         unsigned char   HASHdigest[HASH_BYTES];
1960         struct berval digest;
1961         digest.bv_val = HASHdigest;
1962         digest.bv_len = sizeof(HASHdigest);
1963
1964         /* we should have at least one value at this point */
1965         assert( values != NULL && values[0] != NULL );
1966
1967         nkeys=0;
1968
1969 #if UTF8MATCH
1970         /* create normalized copy of values */
1971         for( i=0; values[i] != NULL; i++ ) {
1972                 /* empty */
1973         }
1974         nvalues = ch_malloc( sizeof( struct berval * ) * (i+1) );
1975         for( i=0; values[i] != NULL; i++ ) {
1976                 nvalues[i] = ber_bvstr( UTF8normalize( values[i]->bv_val, UTF8_CASEFOLD ) );
1977         }
1978         nvalues[i] = NULL;
1979         values = nvalues;
1980 #endif
1981
1982         for( i=0; values[i] != NULL; i++ ) {
1983                 /* count number of indices to generate */
1984                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1985                         continue;
1986                 }
1987
1988                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1989                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1990                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1991                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1992                         } else {
1993                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1994                         }
1995                 }
1996
1997                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1998                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1999                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2000                         }
2001                 }
2002
2003                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2004                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2005                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2006                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2007                         } else {
2008                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2009                         }
2010                 }
2011         }
2012
2013         if( nkeys == 0 ) {
2014                 /* no keys to generate */
2015                 *keysp = NULL;
2016                 return LDAP_SUCCESS;
2017         }
2018
2019         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2020
2021         slen = strlen( syntax->ssyn_oid );
2022         mlen = strlen( mr->smr_oid );
2023
2024         nkeys=0;
2025         for( i=0; values[i] != NULL; i++ ) {
2026                 int j,max;
2027                 struct berval *value;
2028
2029                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2030
2031 #if UTF8MATCH
2032                 value = values[i];
2033 #else
2034                 value = ber_bvdup( values[i] );
2035                 ldap_pvt_str2upper( value->bv_val );
2036 #endif
2037
2038                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2039                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2040                 {
2041                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
2042                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2043
2044                         for( j=0; j<max; j++ ) {
2045                                 HASH_Init( &HASHcontext );
2046                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2047                                         HASH_Update( &HASHcontext,
2048                                                 prefix->bv_val, prefix->bv_len );
2049                                 }
2050
2051                                 HASH_Update( &HASHcontext,
2052                                         &pre, sizeof( pre ) );
2053                                 HASH_Update( &HASHcontext,
2054                                         syntax->ssyn_oid, slen );
2055                                 HASH_Update( &HASHcontext,
2056                                         mr->smr_oid, mlen );
2057                                 HASH_Update( &HASHcontext,
2058                                         &value->bv_val[j],
2059                                         SLAP_INDEX_SUBSTR_MAXLEN );
2060                                 HASH_Final( HASHdigest, &HASHcontext );
2061
2062                                 keys[nkeys++] = ber_bvdup( &digest );
2063                         }
2064                 }
2065
2066                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2067                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2068
2069                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2070                         char pre;
2071
2072                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2073                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2074                                 HASH_Init( &HASHcontext );
2075                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2076                                         HASH_Update( &HASHcontext,
2077                                                 prefix->bv_val, prefix->bv_len );
2078                                 }
2079                                 HASH_Update( &HASHcontext,
2080                                         &pre, sizeof( pre ) );
2081                                 HASH_Update( &HASHcontext,
2082                                         syntax->ssyn_oid, slen );
2083                                 HASH_Update( &HASHcontext,
2084                                         mr->smr_oid, mlen );
2085                                 HASH_Update( &HASHcontext,
2086                                         value->bv_val, j );
2087                                 HASH_Final( HASHdigest, &HASHcontext );
2088
2089                                 keys[nkeys++] = ber_bvdup( &digest );
2090                         }
2091
2092                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2093                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2094                                 HASH_Init( &HASHcontext );
2095                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2096                                         HASH_Update( &HASHcontext,
2097                                                 prefix->bv_val, prefix->bv_len );
2098                                 }
2099                                 HASH_Update( &HASHcontext,
2100                                         &pre, sizeof( pre ) );
2101                                 HASH_Update( &HASHcontext,
2102                                         syntax->ssyn_oid, slen );
2103                                 HASH_Update( &HASHcontext,
2104                                         mr->smr_oid, mlen );
2105                                 HASH_Update( &HASHcontext,
2106                                         &value->bv_val[value->bv_len-j], j );
2107                                 HASH_Final( HASHdigest, &HASHcontext );
2108
2109                                 keys[nkeys++] = ber_bvdup( &digest );
2110                         }
2111
2112                 }
2113 #if !UTF8MATCH
2114                 ber_bvfree( value );
2115 #endif
2116         }
2117
2118         if( nkeys > 0 ) {
2119                 keys[nkeys] = NULL;
2120                 *keysp = keys;
2121         } else {
2122                 ch_free( keys );
2123                 *keysp = NULL;
2124         }
2125
2126 #if UTF8MATCH
2127         ber_bvecfree( nvalues );
2128 #endif
2129         return LDAP_SUCCESS;
2130 }
2131
2132 int caseIgnoreSubstringsFilter(
2133         slap_mask_t use,
2134         slap_mask_t flags,
2135         Syntax *syntax,
2136         MatchingRule *mr,
2137         struct berval *prefix,
2138         void * assertValue,
2139         struct berval ***keysp )
2140 {
2141         SubstringsAssertion *sa;
2142         char pre;
2143         ber_len_t nkeys = 0;
2144         size_t slen, mlen, klen;
2145         struct berval **keys;
2146         HASH_CONTEXT   HASHcontext;
2147         unsigned char   HASHdigest[HASH_BYTES];
2148         struct berval *value;
2149         struct berval digest;
2150
2151 #if UTF8MATCH
2152         sa = UTF8SubstringsassertionNormalize( assertValue, UTF8_CASEFOLD );
2153 #else
2154         sa = assertValue;
2155 #endif
2156         if( sa == NULL ) {
2157                 *keysp = NULL;
2158                 return LDAP_SUCCESS;
2159         }
2160
2161         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
2162                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2163         {
2164                 nkeys++;
2165         }
2166
2167         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
2168                 ber_len_t i;
2169                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2170                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2171                                 /* don't bother accounting for stepping */
2172                                 nkeys += sa->sa_any[i]->bv_len -
2173                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2174                         }
2175                 }
2176         }
2177
2178         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
2179                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2180         {
2181                 nkeys++;
2182         }
2183
2184         if( nkeys == 0 ) {
2185                 *keysp = NULL;
2186                 return LDAP_SUCCESS;
2187         }
2188
2189         digest.bv_val = HASHdigest;
2190         digest.bv_len = sizeof(HASHdigest);
2191
2192         slen = strlen( syntax->ssyn_oid );
2193         mlen = strlen( mr->smr_oid );
2194
2195         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2196         nkeys = 0;
2197
2198         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
2199                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2200         {
2201                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2202 #if UTF8MATCH
2203                 value = sa->sa_initial;
2204 #else
2205                 value = ber_bvdup( sa->sa_initial );
2206                 ldap_pvt_str2upper( value->bv_val );
2207 #endif
2208
2209                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2210                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2211
2212                 HASH_Init( &HASHcontext );
2213                 if( prefix != NULL && prefix->bv_len > 0 ) {
2214                         HASH_Update( &HASHcontext,
2215                                 prefix->bv_val, prefix->bv_len );
2216                 }
2217                 HASH_Update( &HASHcontext,
2218                         &pre, sizeof( pre ) );
2219                 HASH_Update( &HASHcontext,
2220                         syntax->ssyn_oid, slen );
2221                 HASH_Update( &HASHcontext,
2222                         mr->smr_oid, mlen );
2223                 HASH_Update( &HASHcontext,
2224                         value->bv_val, klen );
2225                 HASH_Final( HASHdigest, &HASHcontext );
2226
2227 #if !UTF8MATCH
2228                 ber_bvfree( value );
2229 #endif
2230                 keys[nkeys++] = ber_bvdup( &digest );
2231         }
2232
2233         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
2234                 ber_len_t i, j;
2235                 pre = SLAP_INDEX_SUBSTR_PREFIX;
2236                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2237
2238                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2239                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2240                                 continue;
2241                         }
2242
2243 #if UTF8MATCH
2244                         value = sa->sa_any[i];
2245 #else
2246                         value = ber_bvdup( sa->sa_any[i] );
2247                         ldap_pvt_str2upper( value->bv_val );
2248 #endif
2249
2250                         for(j=0;
2251                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2252                                 j += SLAP_INDEX_SUBSTR_STEP )
2253                         {
2254                                 HASH_Init( &HASHcontext );
2255                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2256                                         HASH_Update( &HASHcontext,
2257                                                 prefix->bv_val, prefix->bv_len );
2258                                 }
2259                                 HASH_Update( &HASHcontext,
2260                                         &pre, sizeof( pre ) );
2261                                 HASH_Update( &HASHcontext,
2262                                         syntax->ssyn_oid, slen );
2263                                 HASH_Update( &HASHcontext,
2264                                         mr->smr_oid, mlen );
2265                                 HASH_Update( &HASHcontext,
2266                                         &value->bv_val[j], klen );
2267                                 HASH_Final( HASHdigest, &HASHcontext );
2268
2269                                 keys[nkeys++] = ber_bvdup( &digest );
2270                         }
2271
2272 #if !UTF8MATCH
2273                         ber_bvfree( value );
2274 #endif
2275                 }
2276         }
2277
2278         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
2279                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2280         {
2281                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2282 #if UTF8MATCH
2283                 value = sa->sa_final;
2284 #else
2285                 value = ber_bvdup( sa->sa_final );
2286                 ldap_pvt_str2upper( value->bv_val );
2287 #endif
2288
2289                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2290                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2291
2292                 HASH_Init( &HASHcontext );
2293                 if( prefix != NULL && prefix->bv_len > 0 ) {
2294                         HASH_Update( &HASHcontext,
2295                                 prefix->bv_val, prefix->bv_len );
2296                 }
2297                 HASH_Update( &HASHcontext,
2298                         &pre, sizeof( pre ) );
2299                 HASH_Update( &HASHcontext,
2300                         syntax->ssyn_oid, slen );
2301                 HASH_Update( &HASHcontext,
2302                         mr->smr_oid, mlen );
2303                 HASH_Update( &HASHcontext,
2304                         &value->bv_val[value->bv_len-klen], klen );
2305                 HASH_Final( HASHdigest, &HASHcontext );
2306
2307 #if !UTF8MATCH
2308                 ber_bvfree( value );
2309 #endif
2310                 keys[nkeys++] = ber_bvdup( &digest );
2311         }
2312
2313         if( nkeys > 0 ) {
2314                 keys[nkeys] = NULL;
2315                 *keysp = keys;
2316         } else {
2317                 ch_free( keys );
2318                 *keysp = NULL;
2319         }
2320 #if UTF8MATCH
2321         ch_free( sa->sa_final );
2322         ber_bvecfree( sa->sa_any );
2323         ch_free( sa->sa_initial );
2324         ch_free( sa );
2325 #endif
2326
2327         return LDAP_SUCCESS;
2328 }
2329         
2330 static int
2331 oidValidate(
2332         Syntax *syntax,
2333         struct berval *val )
2334 {
2335         ber_len_t i;
2336
2337         if( val->bv_len == 0 ) {
2338                 /* disallow empty strings */
2339                 return LDAP_INVALID_SYNTAX;
2340         }
2341
2342         if( OID_LEADCHAR(val->bv_val[0]) ) {
2343                 int dot = 0;
2344                 for(i=1; i < val->bv_len; i++) {
2345                         if( OID_SEPARATOR( val->bv_val[i] ) ) {
2346                                 if( dot++ ) return 1;
2347                         } else if ( OID_CHAR( val->bv_val[i] ) ) {
2348                                 dot = 0;
2349                         } else {
2350                                 return LDAP_INVALID_SYNTAX;
2351                         }
2352                 }
2353
2354                 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
2355
2356         } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
2357                 for(i=1; i < val->bv_len; i++) {
2358                         if( !DESC_CHAR(val->bv_val[i] ) ) {
2359                                 return LDAP_INVALID_SYNTAX;
2360                         }
2361                 }
2362
2363                 return LDAP_SUCCESS;
2364         }
2365         
2366         return LDAP_INVALID_SYNTAX;
2367 }
2368
2369 static int
2370 integerValidate(
2371         Syntax *syntax,
2372         struct berval *val )
2373 {
2374         ber_len_t i;
2375
2376         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2377
2378         if( val->bv_val[0] == '+' || val->bv_val[0] == '-' ) {
2379                 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
2380         } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
2381                 return LDAP_INVALID_SYNTAX;
2382         }
2383
2384         for(i=1; i < val->bv_len; i++) {
2385                 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
2386         }
2387
2388         return LDAP_SUCCESS;
2389 }
2390
2391 static int
2392 integerNormalize(
2393         Syntax *syntax,
2394         struct berval *val,
2395         struct berval **normalized )
2396 {
2397         int negative;
2398         struct berval *newval;
2399         char *p;
2400
2401         p = val->bv_val;
2402
2403         /* save sign */
2404         negative = ( *p == '-' );
2405         if( *p == '-' || *p == '+' ) p++;
2406
2407         /* Ignore leading zeros */
2408         while ( *p == '0' ) p++;
2409
2410         newval = (struct berval *) ch_malloc( sizeof(struct berval) );
2411
2412         if( *p == '\0' ) {
2413                 newval->bv_val = ch_strdup("0");
2414                 newval->bv_len = 1;
2415                 goto done;
2416         }
2417
2418         newval->bv_val = ch_malloc( val->bv_len + 1 );
2419         newval->bv_len = 0;
2420
2421         if( negative ) {
2422                 newval->bv_val[newval->bv_len++] = '-';
2423         }
2424
2425         for( ; *p != '\0'; p++ ) {
2426                 newval->bv_val[newval->bv_len++] = *p;
2427         }
2428
2429 done:
2430         *normalized = newval;
2431         return LDAP_SUCCESS;
2432 }
2433
2434 static int
2435 countryStringValidate(
2436         Syntax *syntax,
2437         struct berval *val )
2438 {
2439         if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2440
2441         if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2442                 return LDAP_INVALID_SYNTAX;
2443         }
2444         if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2445                 return LDAP_INVALID_SYNTAX;
2446         }
2447
2448         return LDAP_SUCCESS;
2449 }
2450
2451 static int
2452 printableStringValidate(
2453         Syntax *syntax,
2454         struct berval *val )
2455 {
2456         ber_len_t i;
2457
2458         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2459
2460         for(i=0; i < val->bv_len; i++) {
2461                 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2462                         return LDAP_INVALID_SYNTAX;
2463                 }
2464         }
2465
2466         return LDAP_SUCCESS;
2467 }
2468
2469 static int
2470 printablesStringValidate(
2471         Syntax *syntax,
2472         struct berval *val )
2473 {
2474         ber_len_t i;
2475
2476         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2477
2478         for(i=0; i < val->bv_len; i++) {
2479                 if( !SLAP_PRINTABLES(val->bv_val[i]) ) {
2480                         return LDAP_INVALID_SYNTAX;
2481                 }
2482         }
2483
2484         return LDAP_SUCCESS;
2485 }
2486
2487 static int
2488 IA5StringValidate(
2489         Syntax *syntax,
2490         struct berval *val )
2491 {
2492         ber_len_t i;
2493
2494         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2495
2496         for(i=0; i < val->bv_len; i++) {
2497                 if( !isascii(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
2498         }
2499
2500         return LDAP_SUCCESS;
2501 }
2502
2503 static int
2504 IA5StringNormalize(
2505         Syntax *syntax,
2506         struct berval *val,
2507         struct berval **normalized )
2508 {
2509         struct berval *newval;
2510         char *p, *q;
2511
2512         newval = ch_malloc( sizeof( struct berval ) );
2513
2514         p = val->bv_val;
2515
2516         /* Ignore initial whitespace */
2517         while ( ASCII_SPACE( *p ) ) {
2518                 p++;
2519         }
2520
2521         if( *p == '\0' ) {
2522                 ch_free( newval );
2523                 return LDAP_INVALID_SYNTAX;
2524         }
2525
2526         newval->bv_val = ch_strdup( p );
2527         p = q = newval->bv_val;
2528
2529         while ( *p ) {
2530                 if ( ASCII_SPACE( *p ) ) {
2531                         *q++ = *p++;
2532
2533                         /* Ignore the extra whitespace */
2534                         while ( ASCII_SPACE( *p ) ) {
2535                                 p++;
2536                         }
2537                 } else {
2538                         *q++ = *p++;
2539                 }
2540         }
2541
2542         assert( *newval->bv_val );
2543         assert( newval->bv_val < p );
2544         assert( q <= p );
2545
2546         /* cannot start with a space */
2547         assert( !ASCII_SPACE(*newval->bv_val) );
2548
2549         /*
2550          * If the string ended in space, backup the pointer one
2551          * position.  One is enough because the above loop collapsed
2552          * all whitespace to a single space.
2553          */
2554
2555         if ( ASCII_SPACE( q[-1] ) ) {
2556                 --q;
2557         }
2558
2559         /* cannot end with a space */
2560         assert( !ASCII_SPACE( q[-1] ) );
2561
2562         /* null terminate */
2563         *q = '\0';
2564
2565         newval->bv_len = q - newval->bv_val;
2566         *normalized = newval;
2567
2568         return LDAP_SUCCESS;
2569 }
2570
2571 static int
2572 caseExactIA5Match(
2573         int *matchp,
2574         slap_mask_t flags,
2575         Syntax *syntax,
2576         MatchingRule *mr,
2577         struct berval *value,
2578         void *assertedValue )
2579 {
2580         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2581
2582         if( match == 0 ) {
2583                 match = strncmp( value->bv_val,
2584                         ((struct berval *) assertedValue)->bv_val,
2585                         value->bv_len );
2586         }
2587
2588         *matchp = match;
2589         return LDAP_SUCCESS;
2590 }
2591
2592 static int
2593 caseExactIA5SubstringsMatch(
2594         int *matchp,
2595         slap_mask_t flags,
2596         Syntax *syntax,
2597         MatchingRule *mr,
2598         struct berval *value,
2599         void *assertedValue )
2600 {
2601         int match = 0;
2602         SubstringsAssertion *sub = assertedValue;
2603         struct berval left = *value;
2604         int i;
2605         ber_len_t inlen=0;
2606
2607         /* Add up asserted input length */
2608         if( sub->sa_initial ) {
2609                 inlen += sub->sa_initial->bv_len;
2610         }
2611         if( sub->sa_any ) {
2612                 for(i=0; sub->sa_any[i] != NULL; i++) {
2613                         inlen += sub->sa_any[i]->bv_len;
2614                 }
2615         }
2616         if( sub->sa_final ) {
2617                 inlen += sub->sa_final->bv_len;
2618         }
2619
2620         if( sub->sa_initial ) {
2621                 if( inlen > left.bv_len ) {
2622                         match = 1;
2623                         goto done;
2624                 }
2625
2626                 match = strncmp( sub->sa_initial->bv_val, left.bv_val,
2627                         sub->sa_initial->bv_len );
2628
2629                 if( match != 0 ) {
2630                         goto done;
2631                 }
2632
2633                 left.bv_val += sub->sa_initial->bv_len;
2634                 left.bv_len -= sub->sa_initial->bv_len;
2635                 inlen -= sub->sa_initial->bv_len;
2636         }
2637
2638         if( sub->sa_final ) {
2639                 if( inlen > left.bv_len ) {
2640                         match = 1;
2641                         goto done;
2642                 }
2643
2644                 match = strncmp( sub->sa_final->bv_val,
2645                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
2646                         sub->sa_final->bv_len );
2647
2648                 if( match != 0 ) {
2649                         goto done;
2650                 }
2651
2652                 left.bv_len -= sub->sa_final->bv_len;
2653                 inlen -= sub->sa_final->bv_len;
2654         }
2655
2656         if( sub->sa_any ) {
2657                 for(i=0; sub->sa_any[i]; i++) {
2658                         ber_len_t idx;
2659                         char *p;
2660
2661 retry:
2662                         if( inlen > left.bv_len ) {
2663                                 /* not enough length */
2664                                 match = 1;
2665                                 goto done;
2666                         }
2667
2668                         if( sub->sa_any[i]->bv_len == 0 ) {
2669                                 continue;
2670                         }
2671
2672                         p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
2673
2674                         if( p == NULL ) {
2675                                 match = 1;
2676                                 goto done;
2677                         }
2678
2679                         idx = p - left.bv_val;
2680                         assert( idx < left.bv_len );
2681
2682                         if( idx >= left.bv_len ) {
2683                                 /* this shouldn't happen */
2684                                 return LDAP_OTHER;
2685                         }
2686
2687                         left.bv_val = p;
2688                         left.bv_len -= idx;
2689
2690                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
2691                                 /* not enough left */
2692                                 match = 1;
2693                                 goto done;
2694                         }
2695
2696                         match = strncmp( left.bv_val,
2697                                 sub->sa_any[i]->bv_val,
2698                                 sub->sa_any[i]->bv_len );
2699
2700                         if( match != 0 ) {
2701                                 left.bv_val++;
2702                                 left.bv_len--;
2703                                 goto retry;
2704                         }
2705
2706                         left.bv_val += sub->sa_any[i]->bv_len;
2707                         left.bv_len -= sub->sa_any[i]->bv_len;
2708                         inlen -= sub->sa_any[i]->bv_len;
2709                 }
2710         }
2711
2712 done:
2713         *matchp = match;
2714         return LDAP_SUCCESS;
2715 }
2716
2717 /* Index generation function */
2718 int caseExactIA5Indexer(
2719         slap_mask_t use,
2720         slap_mask_t flags,
2721         Syntax *syntax,
2722         MatchingRule *mr,
2723         struct berval *prefix,
2724         struct berval **values,
2725         struct berval ***keysp )
2726 {
2727         int i;
2728         size_t slen, mlen;
2729         struct berval **keys;
2730         HASH_CONTEXT   HASHcontext;
2731         unsigned char   HASHdigest[HASH_BYTES];
2732         struct berval digest;
2733         digest.bv_val = HASHdigest;
2734         digest.bv_len = sizeof(HASHdigest);
2735
2736         /* we should have at least one value at this point */
2737         assert( values != NULL && values[0] != NULL );
2738
2739         for( i=0; values[i] != NULL; i++ ) {
2740                 /* just count them */
2741         }
2742
2743         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
2744
2745         slen = strlen( syntax->ssyn_oid );
2746         mlen = strlen( mr->smr_oid );
2747
2748         for( i=0; values[i] != NULL; i++ ) {
2749                 struct berval *value = values[i];
2750
2751                 HASH_Init( &HASHcontext );
2752                 if( prefix != NULL && prefix->bv_len > 0 ) {
2753                         HASH_Update( &HASHcontext,
2754                                 prefix->bv_val, prefix->bv_len );
2755                 }
2756                 HASH_Update( &HASHcontext,
2757                         syntax->ssyn_oid, slen );
2758                 HASH_Update( &HASHcontext,
2759                         mr->smr_oid, mlen );
2760                 HASH_Update( &HASHcontext,
2761                         value->bv_val, value->bv_len );
2762                 HASH_Final( HASHdigest, &HASHcontext );
2763
2764                 keys[i] = ber_bvdup( &digest );
2765         }
2766
2767         keys[i] = NULL;
2768         *keysp = keys;
2769         return LDAP_SUCCESS;
2770 }
2771
2772 /* Index generation function */
2773 int caseExactIA5Filter(
2774         slap_mask_t use,
2775         slap_mask_t flags,
2776         Syntax *syntax,
2777         MatchingRule *mr,
2778         struct berval *prefix,
2779         void * assertValue,
2780         struct berval ***keysp )
2781 {
2782         size_t slen, mlen;
2783         struct berval **keys;
2784         HASH_CONTEXT   HASHcontext;
2785         unsigned char   HASHdigest[HASH_BYTES];
2786         struct berval *value;
2787         struct berval digest;
2788         digest.bv_val = HASHdigest;
2789         digest.bv_len = sizeof(HASHdigest);
2790
2791         slen = strlen( syntax->ssyn_oid );
2792         mlen = strlen( mr->smr_oid );
2793
2794         value = (struct berval *) assertValue;
2795
2796         keys = ch_malloc( sizeof( struct berval * ) * 2 );
2797
2798         HASH_Init( &HASHcontext );
2799         if( prefix != NULL && prefix->bv_len > 0 ) {
2800                 HASH_Update( &HASHcontext,
2801                         prefix->bv_val, prefix->bv_len );
2802         }
2803         HASH_Update( &HASHcontext,
2804                 syntax->ssyn_oid, slen );
2805         HASH_Update( &HASHcontext,
2806                 mr->smr_oid, mlen );
2807         HASH_Update( &HASHcontext,
2808                 value->bv_val, value->bv_len );
2809         HASH_Final( HASHdigest, &HASHcontext );
2810
2811         keys[0] = ber_bvdup( &digest );
2812         keys[1] = NULL;
2813
2814         *keysp = keys;
2815         return LDAP_SUCCESS;
2816 }
2817
2818 /* Substrings Index generation function */
2819 int caseExactIA5SubstringsIndexer(
2820         slap_mask_t use,
2821         slap_mask_t flags,
2822         Syntax *syntax,
2823         MatchingRule *mr,
2824         struct berval *prefix,
2825         struct berval **values,
2826         struct berval ***keysp )
2827 {
2828         ber_len_t i, nkeys;
2829         size_t slen, mlen;
2830         struct berval **keys;
2831         HASH_CONTEXT   HASHcontext;
2832         unsigned char   HASHdigest[HASH_BYTES];
2833         struct berval digest;
2834         digest.bv_val = HASHdigest;
2835         digest.bv_len = sizeof(HASHdigest);
2836
2837         /* we should have at least one value at this point */
2838         assert( values != NULL && values[0] != NULL );
2839
2840         nkeys=0;
2841         for( i=0; values[i] != NULL; i++ ) {
2842                 /* count number of indices to generate */
2843                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2844                         continue;
2845                 }
2846
2847                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2848                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2849                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2850                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2851                         } else {
2852                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2853                         }
2854                 }
2855
2856                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2857                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2858                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2859                         }
2860                 }
2861
2862                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2863                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2864                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2865                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2866                         } else {
2867                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2868                         }
2869                 }
2870         }
2871
2872         if( nkeys == 0 ) {
2873                 /* no keys to generate */
2874                 *keysp = NULL;
2875                 return LDAP_SUCCESS;
2876         }
2877
2878         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2879
2880         slen = strlen( syntax->ssyn_oid );
2881         mlen = strlen( mr->smr_oid );
2882
2883         nkeys=0;
2884         for( i=0; values[i] != NULL; i++ ) {
2885                 ber_len_t j,max;
2886                 struct berval *value;
2887
2888                 value = values[i];
2889                 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2890
2891                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2892                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2893                 {
2894                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
2895                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2896
2897                         for( j=0; j<max; j++ ) {
2898                                 HASH_Init( &HASHcontext );
2899                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2900                                         HASH_Update( &HASHcontext,
2901                                                 prefix->bv_val, prefix->bv_len );
2902                                 }
2903
2904                                 HASH_Update( &HASHcontext,
2905                                         &pre, sizeof( pre ) );
2906                                 HASH_Update( &HASHcontext,
2907                                         syntax->ssyn_oid, slen );
2908                                 HASH_Update( &HASHcontext,
2909                                         mr->smr_oid, mlen );
2910                                 HASH_Update( &HASHcontext,
2911                                         &value->bv_val[j],
2912                                         SLAP_INDEX_SUBSTR_MAXLEN );
2913                                 HASH_Final( HASHdigest, &HASHcontext );
2914
2915                                 keys[nkeys++] = ber_bvdup( &digest );
2916                         }
2917                 }
2918
2919                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2920                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2921
2922                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2923                         char pre;
2924
2925                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2926                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2927                                 HASH_Init( &HASHcontext );
2928                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2929                                         HASH_Update( &HASHcontext,
2930                                                 prefix->bv_val, prefix->bv_len );
2931                                 }
2932                                 HASH_Update( &HASHcontext,
2933                                         &pre, sizeof( pre ) );
2934                                 HASH_Update( &HASHcontext,
2935                                         syntax->ssyn_oid, slen );
2936                                 HASH_Update( &HASHcontext,
2937                                         mr->smr_oid, mlen );
2938                                 HASH_Update( &HASHcontext,
2939                                         value->bv_val, j );
2940                                 HASH_Final( HASHdigest, &HASHcontext );
2941
2942                                 keys[nkeys++] = ber_bvdup( &digest );
2943                         }
2944
2945                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2946                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2947                                 HASH_Init( &HASHcontext );
2948                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2949                                         HASH_Update( &HASHcontext,
2950                                                 prefix->bv_val, prefix->bv_len );
2951                                 }
2952                                 HASH_Update( &HASHcontext,
2953                                         &pre, sizeof( pre ) );
2954                                 HASH_Update( &HASHcontext,
2955                                         syntax->ssyn_oid, slen );
2956                                 HASH_Update( &HASHcontext,
2957                                         mr->smr_oid, mlen );
2958                                 HASH_Update( &HASHcontext,
2959                                         &value->bv_val[value->bv_len-j], j );
2960                                 HASH_Final( HASHdigest, &HASHcontext );
2961
2962                                 keys[nkeys++] = ber_bvdup( &digest );
2963                         }
2964
2965                 }
2966         }
2967
2968         if( nkeys > 0 ) {
2969                 keys[nkeys] = NULL;
2970                 *keysp = keys;
2971         } else {
2972                 ch_free( keys );
2973                 *keysp = NULL;
2974         }
2975
2976         return LDAP_SUCCESS;
2977 }
2978
2979 int caseExactIA5SubstringsFilter(
2980         slap_mask_t use,
2981         slap_mask_t flags,
2982         Syntax *syntax,
2983         MatchingRule *mr,
2984         struct berval *prefix,
2985         void * assertValue,
2986         struct berval ***keysp )
2987 {
2988         SubstringsAssertion *sa = assertValue;
2989         char pre;
2990         ber_len_t nkeys = 0;
2991         size_t slen, mlen, klen;
2992         struct berval **keys;
2993         HASH_CONTEXT   HASHcontext;
2994         unsigned char   HASHdigest[HASH_BYTES];
2995         struct berval *value;
2996         struct berval digest;
2997
2998         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
2999                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3000         {
3001                 nkeys++;
3002         }
3003
3004         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
3005                 ber_len_t i;
3006                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
3007                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3008                                 /* don't bother accounting for stepping */
3009                                 nkeys += sa->sa_any[i]->bv_len -
3010                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3011                         }
3012                 }
3013         }
3014
3015         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
3016                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3017         {
3018                 nkeys++;
3019         }
3020
3021         if( nkeys == 0 ) {
3022                 *keysp = NULL;
3023                 return LDAP_SUCCESS;
3024         }
3025
3026         digest.bv_val = HASHdigest;
3027         digest.bv_len = sizeof(HASHdigest);
3028
3029         slen = strlen( syntax->ssyn_oid );
3030         mlen = strlen( mr->smr_oid );
3031
3032         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
3033         nkeys = 0;
3034
3035         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
3036                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3037         {
3038                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3039                 value = sa->sa_initial;
3040
3041                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3042                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3043
3044                 HASH_Init( &HASHcontext );
3045                 if( prefix != NULL && prefix->bv_len > 0 ) {
3046                         HASH_Update( &HASHcontext,
3047                                 prefix->bv_val, prefix->bv_len );
3048                 }
3049                 HASH_Update( &HASHcontext,
3050                         &pre, sizeof( pre ) );
3051                 HASH_Update( &HASHcontext,
3052                         syntax->ssyn_oid, slen );
3053                 HASH_Update( &HASHcontext,
3054                         mr->smr_oid, mlen );
3055                 HASH_Update( &HASHcontext,
3056                         value->bv_val, klen );
3057                 HASH_Final( HASHdigest, &HASHcontext );
3058
3059                 keys[nkeys++] = ber_bvdup( &digest );
3060         }
3061
3062         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
3063                 ber_len_t i, j;
3064                 pre = SLAP_INDEX_SUBSTR_PREFIX;
3065                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3066
3067                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
3068                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3069                                 continue;
3070                         }
3071
3072                         value = sa->sa_any[i];
3073
3074                         for(j=0;
3075                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3076                                 j += SLAP_INDEX_SUBSTR_STEP )
3077                         {
3078                                 HASH_Init( &HASHcontext );
3079                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3080                                         HASH_Update( &HASHcontext,
3081                                                 prefix->bv_val, prefix->bv_len );
3082                                 }
3083                                 HASH_Update( &HASHcontext,
3084                                         &pre, sizeof( pre ) );
3085                                 HASH_Update( &HASHcontext,
3086                                         syntax->ssyn_oid, slen );
3087                                 HASH_Update( &HASHcontext,
3088                                         mr->smr_oid, mlen );
3089                                 HASH_Update( &HASHcontext,
3090                                         &value->bv_val[j], klen ); 
3091                                 HASH_Final( HASHdigest, &HASHcontext );
3092
3093                                 keys[nkeys++] = ber_bvdup( &digest );
3094                         }
3095                 }
3096         }
3097
3098         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
3099                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3100         {
3101                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3102                 value = sa->sa_final;
3103
3104                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3105                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3106
3107                 HASH_Init( &HASHcontext );
3108                 if( prefix != NULL && prefix->bv_len > 0 ) {
3109                         HASH_Update( &HASHcontext,
3110                                 prefix->bv_val, prefix->bv_len );
3111                 }
3112                 HASH_Update( &HASHcontext,
3113                         &pre, sizeof( pre ) );
3114                 HASH_Update( &HASHcontext,
3115                         syntax->ssyn_oid, slen );
3116                 HASH_Update( &HASHcontext,
3117                         mr->smr_oid, mlen );
3118                 HASH_Update( &HASHcontext,
3119                         &value->bv_val[value->bv_len-klen], klen );
3120                 HASH_Final( HASHdigest, &HASHcontext );
3121
3122                 keys[nkeys++] = ber_bvdup( &digest );
3123         }
3124
3125         if( nkeys > 0 ) {
3126                 keys[nkeys] = NULL;
3127                 *keysp = keys;
3128         } else {
3129                 ch_free( keys );
3130                 *keysp = NULL;
3131         }
3132
3133         return LDAP_SUCCESS;
3134 }
3135         
3136 static int
3137 caseIgnoreIA5Match(
3138         int *matchp,
3139         slap_mask_t flags,
3140         Syntax *syntax,
3141         MatchingRule *mr,
3142         struct berval *value,
3143         void *assertedValue )
3144 {
3145         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
3146
3147         if( match == 0 && value->bv_len ) {
3148                 match = strncasecmp( value->bv_val,
3149                         ((struct berval *) assertedValue)->bv_val,
3150                         value->bv_len );
3151         }
3152
3153         *matchp = match;
3154         return LDAP_SUCCESS;
3155 }
3156
3157 static int
3158 caseIgnoreIA5SubstringsMatch(
3159         int *matchp,
3160         slap_mask_t flags,
3161         Syntax *syntax,
3162         MatchingRule *mr,
3163         struct berval *value,
3164         void *assertedValue )
3165 {
3166         int match = 0;
3167         SubstringsAssertion *sub = assertedValue;
3168         struct berval left = *value;
3169         int i;
3170         ber_len_t inlen=0;
3171
3172         /* Add up asserted input length */
3173         if( sub->sa_initial ) {
3174                 inlen += sub->sa_initial->bv_len;
3175         }
3176         if( sub->sa_any ) {
3177                 for(i=0; sub->sa_any[i] != NULL; i++) {
3178                         inlen += sub->sa_any[i]->bv_len;
3179                 }
3180         }
3181         if( sub->sa_final ) {
3182                 inlen += sub->sa_final->bv_len;
3183         }
3184
3185         if( sub->sa_initial ) {
3186                 if( inlen > left.bv_len ) {
3187                         match = 1;
3188                         goto done;
3189                 }
3190
3191                 match = strncasecmp( sub->sa_initial->bv_val, left.bv_val,
3192                         sub->sa_initial->bv_len );
3193
3194                 if( match != 0 ) {
3195                         goto done;
3196                 }
3197
3198                 left.bv_val += sub->sa_initial->bv_len;
3199                 left.bv_len -= sub->sa_initial->bv_len;
3200                 inlen -= sub->sa_initial->bv_len;
3201         }
3202
3203         if( sub->sa_final ) {
3204                 if( inlen > left.bv_len ) {
3205                         match = 1;
3206                         goto done;
3207                 }
3208
3209                 match = strncasecmp( sub->sa_final->bv_val,
3210                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
3211                         sub->sa_final->bv_len );
3212
3213                 if( match != 0 ) {
3214                         goto done;
3215                 }
3216
3217                 left.bv_len -= sub->sa_final->bv_len;
3218                 inlen -= sub->sa_final->bv_len;
3219         }
3220
3221         if( sub->sa_any ) {
3222                 for(i=0; sub->sa_any[i]; i++) {
3223                         ber_len_t idx;
3224                         char *p;
3225
3226 retry:
3227                         if( inlen > left.bv_len ) {
3228                                 /* not enough length */
3229                                 match = 1;
3230                                 goto done;
3231                         }
3232
3233                         if( sub->sa_any[i]->bv_len == 0 ) {
3234                                 continue;
3235                         }
3236
3237                         p = strcasechr( left.bv_val, *sub->sa_any[i]->bv_val );
3238
3239                         if( p == NULL ) {
3240                                 match = 1;
3241                                 goto done;
3242                         }
3243
3244                         idx = p - left.bv_val;
3245                         assert( idx < left.bv_len );
3246
3247                         if( idx >= left.bv_len ) {
3248                                 /* this shouldn't happen */
3249                                 return LDAP_OTHER;
3250                         }
3251
3252                         left.bv_val = p;
3253                         left.bv_len -= idx;
3254
3255                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
3256                                 /* not enough left */
3257                                 match = 1;
3258                                 goto done;
3259                         }
3260
3261                         match = strncasecmp( left.bv_val,
3262                                 sub->sa_any[i]->bv_val,
3263                                 sub->sa_any[i]->bv_len );
3264
3265                         if( match != 0 ) {
3266                                 left.bv_val++;
3267                                 left.bv_len--;
3268
3269                                 goto retry;
3270                         }
3271
3272                         left.bv_val += sub->sa_any[i]->bv_len;
3273                         left.bv_len -= sub->sa_any[i]->bv_len;
3274                         inlen -= sub->sa_any[i]->bv_len;
3275                 }
3276         }
3277
3278 done:
3279         *matchp = match;
3280         return LDAP_SUCCESS;
3281 }
3282
3283 /* Index generation function */
3284 int caseIgnoreIA5Indexer(
3285         slap_mask_t use,
3286         slap_mask_t flags,
3287         Syntax *syntax,
3288         MatchingRule *mr,
3289         struct berval *prefix,
3290         struct berval **values,
3291         struct berval ***keysp )
3292 {
3293         int i;
3294         size_t slen, mlen;
3295         struct berval **keys;
3296         HASH_CONTEXT   HASHcontext;
3297         unsigned char   HASHdigest[HASH_BYTES];
3298         struct berval digest;
3299         digest.bv_val = HASHdigest;
3300         digest.bv_len = sizeof(HASHdigest);
3301
3302         /* we should have at least one value at this point */
3303         assert( values != NULL && values[0] != NULL );
3304
3305         for( i=0; values[i] != NULL; i++ ) {
3306                 /* just count them */
3307         }
3308
3309         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
3310
3311         slen = strlen( syntax->ssyn_oid );
3312         mlen = strlen( mr->smr_oid );
3313
3314         for( i=0; values[i] != NULL; i++ ) {
3315                 struct berval *value = ber_bvdup( values[i] );
3316                 ldap_pvt_str2upper( value->bv_val );
3317
3318                 HASH_Init( &HASHcontext );
3319                 if( prefix != NULL && prefix->bv_len > 0 ) {
3320                         HASH_Update( &HASHcontext,
3321                                 prefix->bv_val, prefix->bv_len );
3322                 }
3323                 HASH_Update( &HASHcontext,
3324                         syntax->ssyn_oid, slen );
3325                 HASH_Update( &HASHcontext,
3326                         mr->smr_oid, mlen );
3327                 HASH_Update( &HASHcontext,
3328                         value->bv_val, value->bv_len );
3329                 HASH_Final( HASHdigest, &HASHcontext );
3330
3331                 ber_bvfree( value );
3332
3333                 keys[i] = ber_bvdup( &digest );
3334         }
3335
3336         keys[i] = NULL;
3337         *keysp = keys;
3338         return LDAP_SUCCESS;
3339 }
3340
3341 /* Index generation function */
3342 int caseIgnoreIA5Filter(
3343         slap_mask_t use,
3344         slap_mask_t flags,
3345         Syntax *syntax,
3346         MatchingRule *mr,
3347         struct berval *prefix,
3348         void * assertValue,
3349         struct berval ***keysp )
3350 {
3351         size_t slen, mlen;
3352         struct berval **keys;
3353         HASH_CONTEXT   HASHcontext;
3354         unsigned char   HASHdigest[HASH_BYTES];
3355         struct berval *value;
3356         struct berval digest;
3357         digest.bv_val = HASHdigest;
3358         digest.bv_len = sizeof(HASHdigest);
3359
3360         slen = strlen( syntax->ssyn_oid );
3361         mlen = strlen( mr->smr_oid );
3362
3363         value = ber_bvdup( (struct berval *) assertValue );
3364         ldap_pvt_str2upper( value->bv_val );
3365
3366         keys = ch_malloc( sizeof( struct berval * ) * 2 );
3367
3368         HASH_Init( &HASHcontext );
3369         if( prefix != NULL && prefix->bv_len > 0 ) {
3370                 HASH_Update( &HASHcontext,
3371                         prefix->bv_val, prefix->bv_len );
3372         }
3373         HASH_Update( &HASHcontext,
3374                 syntax->ssyn_oid, slen );
3375         HASH_Update( &HASHcontext,
3376                 mr->smr_oid, mlen );
3377         HASH_Update( &HASHcontext,
3378                 value->bv_val, value->bv_len );
3379         HASH_Final( HASHdigest, &HASHcontext );
3380
3381         keys[0] = ber_bvdup( &digest );
3382         keys[1] = NULL;
3383
3384         ber_bvfree( value );
3385
3386         *keysp = keys;
3387
3388         return LDAP_SUCCESS;
3389 }
3390
3391 /* Substrings Index generation function */
3392 int caseIgnoreIA5SubstringsIndexer(
3393         slap_mask_t use,
3394         slap_mask_t flags,
3395         Syntax *syntax,
3396         MatchingRule *mr,
3397         struct berval *prefix,
3398         struct berval **values,
3399         struct berval ***keysp )
3400 {
3401         ber_len_t i, nkeys;
3402         size_t slen, mlen;
3403         struct berval **keys;
3404         HASH_CONTEXT   HASHcontext;
3405         unsigned char   HASHdigest[HASH_BYTES];
3406         struct berval digest;
3407         digest.bv_val = HASHdigest;
3408         digest.bv_len = sizeof(HASHdigest);
3409
3410         /* we should have at least one value at this point */
3411         assert( values != NULL && values[0] != NULL );
3412
3413         nkeys=0;
3414         for( i=0; values[i] != NULL; i++ ) {
3415                 /* count number of indices to generate */
3416                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3417                         continue;
3418                 }
3419
3420                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3421                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3422                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3423                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3424                         } else {
3425                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3426                         }
3427                 }
3428
3429                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3430                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3431                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3432                         }
3433                 }
3434
3435                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3436                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3437                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3438                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3439                         } else {
3440                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3441                         }
3442                 }
3443         }
3444
3445         if( nkeys == 0 ) {
3446                 /* no keys to generate */
3447                 *keysp = NULL;
3448                 return LDAP_SUCCESS;
3449         }
3450
3451         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
3452
3453         slen = strlen( syntax->ssyn_oid );
3454         mlen = strlen( mr->smr_oid );
3455
3456         nkeys=0;
3457         for( i=0; values[i] != NULL; i++ ) {
3458                 int j,max;
3459                 struct berval *value;
3460
3461                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3462
3463                 value = ber_bvdup( values[i] );
3464                 ldap_pvt_str2upper( value->bv_val );
3465
3466                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3467                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3468                 {
3469                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
3470                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3471
3472                         for( j=0; j<max; j++ ) {
3473                                 HASH_Init( &HASHcontext );
3474                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3475                                         HASH_Update( &HASHcontext,
3476                                                 prefix->bv_val, prefix->bv_len );
3477                                 }
3478
3479                                 HASH_Update( &HASHcontext,
3480                                         &pre, sizeof( pre ) );
3481                                 HASH_Update( &HASHcontext,
3482                                         syntax->ssyn_oid, slen );
3483                                 HASH_Update( &HASHcontext,
3484                                         mr->smr_oid, mlen );
3485                                 HASH_Update( &HASHcontext,
3486                                         &value->bv_val[j],
3487                                         SLAP_INDEX_SUBSTR_MAXLEN );
3488                                 HASH_Final( HASHdigest, &HASHcontext );
3489
3490                                 keys[nkeys++] = ber_bvdup( &digest );
3491                         }
3492                 }
3493
3494                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3495                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3496
3497                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3498                         char pre;
3499
3500                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3501                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3502                                 HASH_Init( &HASHcontext );
3503                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3504                                         HASH_Update( &HASHcontext,
3505                                                 prefix->bv_val, prefix->bv_len );
3506                                 }
3507                                 HASH_Update( &HASHcontext,
3508                                         &pre, sizeof( pre ) );
3509                                 HASH_Update( &HASHcontext,
3510                                         syntax->ssyn_oid, slen );
3511                                 HASH_Update( &HASHcontext,
3512                                         mr->smr_oid, mlen );
3513                                 HASH_Update( &HASHcontext,
3514                                         value->bv_val, j );
3515                                 HASH_Final( HASHdigest, &HASHcontext );
3516
3517                                 keys[nkeys++] = ber_bvdup( &digest );
3518                         }
3519
3520                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3521                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3522                                 HASH_Init( &HASHcontext );
3523                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3524                                         HASH_Update( &HASHcontext,
3525                                                 prefix->bv_val, prefix->bv_len );
3526                                 }
3527                                 HASH_Update( &HASHcontext,
3528                                         &pre, sizeof( pre ) );
3529                                 HASH_Update( &HASHcontext,
3530                                         syntax->ssyn_oid, slen );
3531                                 HASH_Update( &HASHcontext,
3532                                         mr->smr_oid, mlen );
3533                                 HASH_Update( &HASHcontext,
3534                                         &value->bv_val[value->bv_len-j], j );
3535                                 HASH_Final( HASHdigest, &HASHcontext );
3536
3537                                 keys[nkeys++] = ber_bvdup( &digest );
3538                         }
3539
3540                 }
3541
3542                 ber_bvfree( value );
3543         }
3544
3545         if( nkeys > 0 ) {
3546                 keys[nkeys] = NULL;
3547                 *keysp = keys;
3548         } else {
3549                 ch_free( keys );
3550                 *keysp = NULL;
3551         }
3552
3553         return LDAP_SUCCESS;
3554 }
3555
3556 int caseIgnoreIA5SubstringsFilter(
3557         slap_mask_t use,
3558         slap_mask_t flags,
3559         Syntax *syntax,
3560         MatchingRule *mr,
3561         struct berval *prefix,
3562         void * assertValue,
3563         struct berval ***keysp )
3564 {
3565         SubstringsAssertion *sa = assertValue;
3566         char pre;
3567         ber_len_t nkeys = 0;
3568         size_t slen, mlen, klen;
3569         struct berval **keys;
3570         HASH_CONTEXT   HASHcontext;
3571         unsigned char   HASHdigest[HASH_BYTES];
3572         struct berval *value;
3573         struct berval digest;
3574
3575         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
3576                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3577         {
3578                 nkeys++;
3579         }
3580
3581         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3582                 ber_len_t i;
3583                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
3584                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3585                                 /* don't bother accounting for stepping */
3586                                 nkeys += sa->sa_any[i]->bv_len -
3587                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3588                         }
3589                 }
3590         }
3591
3592         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
3593                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3594         {
3595                 nkeys++;
3596         }
3597
3598         if( nkeys == 0 ) {
3599                 *keysp = NULL;
3600                 return LDAP_SUCCESS;
3601         }
3602
3603         digest.bv_val = HASHdigest;
3604         digest.bv_len = sizeof(HASHdigest);
3605
3606         slen = strlen( syntax->ssyn_oid );
3607         mlen = strlen( mr->smr_oid );
3608
3609         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
3610         nkeys = 0;
3611
3612         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
3613                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3614         {
3615                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3616                 value = ber_bvdup( sa->sa_initial );
3617                 ldap_pvt_str2upper( value->bv_val );
3618
3619                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3620                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3621
3622                 HASH_Init( &HASHcontext );
3623                 if( prefix != NULL && prefix->bv_len > 0 ) {
3624                         HASH_Update( &HASHcontext,
3625                                 prefix->bv_val, prefix->bv_len );
3626                 }
3627                 HASH_Update( &HASHcontext,
3628                         &pre, sizeof( pre ) );
3629                 HASH_Update( &HASHcontext,
3630                         syntax->ssyn_oid, slen );
3631                 HASH_Update( &HASHcontext,
3632                         mr->smr_oid, mlen );
3633                 HASH_Update( &HASHcontext,
3634                         value->bv_val, klen );
3635                 HASH_Final( HASHdigest, &HASHcontext );
3636
3637                 ber_bvfree( value );
3638                 keys[nkeys++] = ber_bvdup( &digest );
3639         }
3640
3641         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3642                 ber_len_t i, j;
3643                 pre = SLAP_INDEX_SUBSTR_PREFIX;
3644                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3645
3646                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
3647                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3648                                 continue;
3649                         }
3650
3651                         value = ber_bvdup( sa->sa_any[i] );
3652                         ldap_pvt_str2upper( value->bv_val );
3653
3654                         for(j=0;
3655                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3656                                 j += SLAP_INDEX_SUBSTR_STEP )
3657                         {
3658                                 HASH_Init( &HASHcontext );
3659                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3660                                         HASH_Update( &HASHcontext,
3661                                                 prefix->bv_val, prefix->bv_len );
3662                                 }
3663                                 HASH_Update( &HASHcontext,
3664                                         &pre, sizeof( pre ) );
3665                                 HASH_Update( &HASHcontext,
3666                                         syntax->ssyn_oid, slen );
3667                                 HASH_Update( &HASHcontext,
3668                                         mr->smr_oid, mlen );
3669                                 HASH_Update( &HASHcontext,
3670                                         &value->bv_val[j], klen );
3671                                 HASH_Final( HASHdigest, &HASHcontext );
3672
3673                                 keys[nkeys++] = ber_bvdup( &digest );
3674                         }
3675
3676                         ber_bvfree( value );
3677                 }
3678         }
3679
3680         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
3681                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3682         {
3683                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3684                 value = ber_bvdup( sa->sa_final );
3685                 ldap_pvt_str2upper( value->bv_val );
3686
3687                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3688                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3689
3690                 HASH_Init( &HASHcontext );
3691                 if( prefix != NULL && prefix->bv_len > 0 ) {
3692                         HASH_Update( &HASHcontext,
3693                                 prefix->bv_val, prefix->bv_len );
3694                 }
3695                 HASH_Update( &HASHcontext,
3696                         &pre, sizeof( pre ) );
3697                 HASH_Update( &HASHcontext,
3698                         syntax->ssyn_oid, slen );
3699                 HASH_Update( &HASHcontext,
3700                         mr->smr_oid, mlen );
3701                 HASH_Update( &HASHcontext,
3702                         &value->bv_val[value->bv_len-klen], klen );
3703                 HASH_Final( HASHdigest, &HASHcontext );
3704
3705                 ber_bvfree( value );
3706                 keys[nkeys++] = ber_bvdup( &digest );
3707         }
3708
3709         if( nkeys > 0 ) {
3710                 keys[nkeys] = NULL;
3711                 *keysp = keys;
3712         } else {
3713                 ch_free( keys );
3714                 *keysp = NULL;
3715         }
3716
3717         return LDAP_SUCCESS;
3718 }
3719         
3720 static int
3721 numericStringValidate(
3722         Syntax *syntax,
3723         struct berval *in )
3724 {
3725         ber_len_t i;
3726
3727         for(i=0; i < in->bv_len; i++) {
3728                 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3729                         return LDAP_INVALID_SYNTAX;
3730                 }
3731         }
3732
3733         return LDAP_SUCCESS;
3734 }
3735
3736 static int
3737 numericStringNormalize(
3738         Syntax *syntax,
3739         struct berval *val,
3740         struct berval **normalized )
3741 {
3742         /* removal all spaces */
3743         struct berval *newval;
3744         char *p, *q;
3745
3746         newval = ch_malloc( sizeof( struct berval ) );
3747         newval->bv_val = ch_malloc( val->bv_len + 1 );
3748
3749         p = val->bv_val;
3750         q = newval->bv_val;
3751
3752         while ( *p ) {
3753                 if ( ASCII_SPACE( *p ) ) {
3754                         /* Ignore whitespace */
3755                         p++;
3756                 } else {
3757                         *q++ = *p++;
3758                 }
3759         }
3760
3761         assert( newval->bv_val <= p );
3762         assert( q <= p );
3763
3764         /* null terminate */
3765         *q = '\0';
3766
3767         newval->bv_len = q - newval->bv_val;
3768         *normalized = newval;
3769
3770         return LDAP_SUCCESS;
3771 }
3772
3773 static int
3774 objectIdentifierFirstComponentMatch(
3775         int *matchp,
3776         slap_mask_t flags,
3777         Syntax *syntax,
3778         MatchingRule *mr,
3779         struct berval *value,
3780         void *assertedValue )
3781 {
3782         int rc = LDAP_SUCCESS;
3783         int match;
3784         struct berval *asserted = (struct berval *) assertedValue;
3785         ber_len_t i;
3786         struct berval oid;
3787
3788         if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3789                 return LDAP_INVALID_SYNTAX;
3790         }
3791
3792         /* trim leading white space */
3793         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3794                 /* empty */
3795         }
3796
3797         /* grab next word */
3798         oid.bv_val = &value->bv_val[i];
3799         oid.bv_len = value->bv_len - i;
3800         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3801                 /* empty */
3802         }
3803         oid.bv_len = i;
3804
3805         /* insert attributeTypes, objectclass check here */
3806         if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3807                 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3808
3809         } else {
3810                 char *stored = ch_malloc( oid.bv_len + 1 );
3811                 AC_MEMCPY( stored, oid.bv_val, oid.bv_len );
3812                 stored[oid.bv_len] = '\0';
3813
3814                 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3815                         MatchingRule *asserted_mr = mr_find( asserted->bv_val );
3816                         MatchingRule *stored_mr = mr_find( stored );
3817
3818                         if( asserted_mr == NULL ) {
3819                                 rc = SLAPD_COMPARE_UNDEFINED;
3820                         } else {
3821                                 match = asserted_mr != stored_mr;
3822                         }
3823
3824                 } else if ( !strcmp( syntax->ssyn_oid,
3825                         SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3826                 {
3827                         AttributeType *asserted_at = at_find( asserted->bv_val );
3828                         AttributeType *stored_at = at_find( stored );
3829
3830                         if( asserted_at == NULL ) {
3831                                 rc = SLAPD_COMPARE_UNDEFINED;
3832                         } else {
3833                                 match = asserted_at != stored_at;
3834                         }
3835
3836                 } else if ( !strcmp( syntax->ssyn_oid,
3837                         SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3838                 {
3839                         ObjectClass *asserted_oc = oc_find( asserted->bv_val );
3840                         ObjectClass *stored_oc = oc_find( stored );
3841
3842                         if( asserted_oc == NULL ) {
3843                                 rc = SLAPD_COMPARE_UNDEFINED;
3844                         } else {
3845                                 match = asserted_oc != stored_oc;
3846                         }
3847                 }
3848
3849                 ch_free( stored );
3850         }
3851
3852 #ifdef NEW_LOGGING
3853         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3854                    "objectIdentifierFirstComponentMatch: %d\n    %s\n    %s\n",
3855                    match, value->bv_val, asserted->bv_val ));
3856 #else
3857         Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3858                 "%d\n\t\"%s\"\n\t\"%s\"\n",
3859             match, value->bv_val, asserted->bv_val );
3860 #endif
3861
3862
3863         if( rc == LDAP_SUCCESS ) *matchp = match;
3864         return rc;
3865 }
3866
3867 static int
3868 check_time_syntax (struct berval *val,
3869         int start,
3870         int *parts)
3871 {
3872         static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3873         static int mdays[2][12] = {
3874                 /* non-leap years */
3875                 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3876                 /* leap years */
3877                 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3878         };
3879         char *p, *e;
3880         int part, c, tzoffset, leapyear = 0 ;
3881
3882         if( val->bv_len == 0 ) {
3883                 return LDAP_INVALID_SYNTAX;
3884         }
3885
3886         p = (char *)val->bv_val;
3887         e = p + val->bv_len;
3888
3889         /* Ignore initial whitespace */
3890         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3891                 p++;
3892         }
3893
3894         if (e - p < 13 - (2 * start)) {
3895                 return LDAP_INVALID_SYNTAX;
3896         }
3897
3898         for (part = 0; part < 9; part++) {
3899                 parts[part] = 0;
3900         }
3901
3902         for (part = start; part < 7; part++) {
3903                 c = *p;
3904                 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3905                         part++;
3906                         break;
3907                 }
3908                 p++;
3909                 c -= '0';
3910                 if (p == e) {
3911                         return LDAP_INVALID_SYNTAX;
3912                 }
3913                 if (c < 0 || c > 9) {
3914                         return LDAP_INVALID_SYNTAX;
3915                 }
3916                 parts[part] = c;
3917
3918                 c = *p++ - '0';
3919                 if (p == e) {
3920                         return LDAP_INVALID_SYNTAX;
3921                 }
3922                 if (c < 0 || c > 9) {
3923                         return LDAP_INVALID_SYNTAX;
3924                 }
3925                 parts[part] *= 10;
3926                 parts[part] += c;
3927
3928                 if (part == 2 || part == 3) {
3929                         parts[part]--;
3930                 }
3931                 if (parts[part] < 0) {
3932                         return LDAP_INVALID_SYNTAX;
3933                 }
3934                 if (parts[part] > ceiling[part]) {
3935                         return LDAP_INVALID_SYNTAX;
3936                 }
3937         }
3938
3939         /* leapyear check for the Gregorian calendar (year>1581) */
3940         if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
3941                 ((parts[0] % 4 == 0) && (parts[1] == 0)))
3942         {
3943                 leapyear = 1;
3944         }
3945
3946         if (parts[3] > mdays[leapyear][parts[2]]) {
3947                 return LDAP_INVALID_SYNTAX;
3948         }
3949         
3950         c = *p++;
3951         if (c == 'Z') {
3952                 tzoffset = 0; /* UTC */
3953         } else if (c != '+' && c != '-') {
3954                 return LDAP_INVALID_SYNTAX;
3955         } else {
3956                 if (c == '-') {
3957                         tzoffset = -1;
3958                 } else /* c == '+' */ {
3959                         tzoffset = 1;
3960                 }
3961
3962                 if (p > e - 4) {
3963                         return LDAP_INVALID_SYNTAX;
3964                 }
3965
3966                 for (part = 7; part < 9; part++) {
3967                         c = *p++ - '0';
3968                         if (c < 0 || c > 9) {
3969                                 return LDAP_INVALID_SYNTAX;
3970                         }
3971                         parts[part] = c;
3972
3973                         c = *p++ - '0';
3974                         if (c < 0 || c > 9) {
3975                                 return LDAP_INVALID_SYNTAX;
3976                         }
3977                         parts[part] *= 10;
3978                         parts[part] += c;
3979                         if (parts[part] < 0 || parts[part] > ceiling[part]) {
3980                                 return LDAP_INVALID_SYNTAX;
3981                         }
3982                 }
3983         }
3984
3985         /* Ignore trailing whitespace */
3986         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3987                 p++;
3988         }
3989         if (p != e) {
3990                 return LDAP_INVALID_SYNTAX;
3991         }
3992
3993         switch ( tzoffset ) {
3994         case -1: /* negativ offset to UTC, ie west of Greenwich  */
3995                 parts[4] += parts[7];
3996                 parts[5] += parts[8];
3997                 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
3998                         if (part != 3) {
3999                                 c = ceiling[part];
4000                         } else {
4001                                 c = mdays[leapyear][parts[2]];
4002                         }
4003                         if (parts[part] > c) {
4004                                 parts[part] -= c + 1;
4005                                 parts[part - 1]++;
4006                         }
4007                 }
4008                 break;
4009         case 1: /* positive offset to UTC, ie east of Greenwich */
4010                 parts[4] -= parts[7];
4011                 parts[5] -= parts[8];
4012                 for (part = 6; --part > 0; ) {
4013                         if (part != 3) {
4014                                 c = ceiling[part];
4015                         } else {
4016                                 /* first arg to % needs to be non negativ */
4017                                 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4018                         }
4019                         if (parts[part] < 0) {
4020                                 parts[part] += c + 1;
4021                                 parts[part - 1]--;
4022                         }
4023                 }
4024                 break;
4025         case 0: /* already UTC */
4026                 break;
4027         }
4028
4029         return LDAP_SUCCESS;
4030 }
4031
4032 static int
4033 utcTimeNormalize(
4034         Syntax *syntax,
4035         struct berval *val,
4036         struct berval **normalized )
4037 {
4038         struct berval *out;
4039         int parts[9], rc;
4040
4041         rc = check_time_syntax(val, 1, parts);
4042         if (rc != LDAP_SUCCESS) {
4043                 return rc;
4044         }
4045
4046         *normalized = NULL;
4047         out = ch_malloc( sizeof(struct berval) );
4048         if( out == NULL ) {
4049                 return LBER_ERROR_MEMORY;
4050         }
4051
4052         out->bv_val = ch_malloc( 14 );
4053         if ( out->bv_val == NULL ) {
4054                 ch_free( out );
4055                 return LBER_ERROR_MEMORY;
4056         }
4057
4058         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ldZ",
4059                 parts[1], parts[2] + 1, parts[3] + 1,
4060                 parts[4], parts[5], parts[6] );
4061         out->bv_len = 13;
4062         *normalized = out;
4063
4064         return LDAP_SUCCESS;
4065 }
4066
4067 static int
4068 utcTimeValidate(
4069         Syntax *syntax,
4070         struct berval *in )
4071 {
4072         int parts[9];
4073
4074         return check_time_syntax(in, 1, parts);
4075 }
4076
4077 static int
4078 generalizedTimeValidate(
4079         Syntax *syntax,
4080         struct berval *in )
4081 {
4082         int parts[9];
4083
4084         return check_time_syntax(in, 0, parts);
4085 }
4086
4087 static int
4088 generalizedTimeNormalize(
4089         Syntax *syntax,
4090         struct berval *val,
4091         struct berval **normalized )
4092 {
4093         struct berval *out;
4094         int parts[9], rc;
4095
4096         rc = check_time_syntax(val, 0, parts);
4097         if (rc != LDAP_SUCCESS) {
4098                 return rc;
4099         }
4100
4101         *normalized = NULL;
4102         out = ch_malloc( sizeof(struct berval) );
4103         if( out == NULL ) {
4104                 return LBER_ERROR_MEMORY;
4105         }
4106
4107         out->bv_val = ch_malloc( 16 );
4108         if ( out->bv_val == NULL ) {
4109                 ch_free( out );
4110                 return LBER_ERROR_MEMORY;
4111         }
4112
4113         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ld%02ldZ",
4114                 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4115                 parts[4], parts[5], parts[6] );
4116         out->bv_len = 15;
4117         *normalized = out;
4118
4119         return LDAP_SUCCESS;
4120 }
4121
4122 static int
4123 nisNetgroupTripleValidate(
4124         Syntax *syntax,
4125         struct berval *val )
4126 {
4127         char *p, *e;
4128         int commas = 0;
4129
4130         if ( val->bv_len == 0 ) {
4131                 return LDAP_INVALID_SYNTAX;
4132         }
4133
4134         p = (char *)val->bv_val;
4135         e = p + val->bv_len;
4136
4137 #if 0
4138         /* syntax does not allow leading white space */
4139         /* Ignore initial whitespace */
4140         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4141                 p++;
4142         }
4143 #endif
4144
4145         if ( *p != '(' /*')'*/ ) {
4146                 return LDAP_INVALID_SYNTAX;
4147         }
4148
4149         for ( p++; ( p < e ) && ( *p != ')' ); p++ ) {
4150                 if ( *p == ',' ) {
4151                         commas++;
4152                         if ( commas > 2 ) {
4153                                 return LDAP_INVALID_SYNTAX;
4154                         }
4155
4156                 } else if ( !ATTR_CHAR( *p ) ) {
4157                         return LDAP_INVALID_SYNTAX;
4158                 }
4159         }
4160
4161         if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4162                 return LDAP_INVALID_SYNTAX;
4163         }
4164
4165         p++;
4166
4167 #if 0
4168         /* syntax does not allow trailing white space */
4169         /* Ignore trailing whitespace */
4170         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4171                 p++;
4172         }
4173 #endif
4174
4175         if (p != e) {
4176                 return LDAP_INVALID_SYNTAX;
4177         }
4178
4179         return LDAP_SUCCESS;
4180 }
4181
4182 static int
4183 bootParameterValidate(
4184         Syntax *syntax,
4185         struct berval *val )
4186 {
4187         char *p, *e;
4188
4189         if ( val->bv_len == 0 ) {
4190                 return LDAP_INVALID_SYNTAX;
4191         }
4192
4193         p = (char *)val->bv_val;
4194         e = p + val->bv_len;
4195
4196         /* key */
4197         for (; ( p < e ) && ( *p != '=' ); p++ ) {
4198                 if ( !ATTR_CHAR( *p ) ) {
4199                         return LDAP_INVALID_SYNTAX;
4200                 }
4201         }
4202
4203         if ( *p != '=' ) {
4204                 return LDAP_INVALID_SYNTAX;
4205         }
4206
4207         /* server */
4208         for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4209                 if ( !ATTR_CHAR( *p ) ) {
4210                         return LDAP_INVALID_SYNTAX;
4211                 }
4212         }
4213
4214         if ( *p != ':' ) {
4215                 return LDAP_INVALID_SYNTAX;
4216         }
4217
4218         /* path */
4219         for ( p++; p < e; p++ ) {
4220                 if ( !ATTR_CHAR( *p ) ) {
4221                         return LDAP_INVALID_SYNTAX;
4222                 }
4223         }
4224
4225         return LDAP_SUCCESS;
4226 }
4227
4228 struct syntax_defs_rec {
4229         char *sd_desc;
4230         int sd_flags;
4231         slap_syntax_validate_func *sd_validate;
4232         slap_syntax_transform_func *sd_normalize;
4233         slap_syntax_transform_func *sd_pretty;
4234 #ifdef SLAPD_BINARY_CONVERSION
4235         slap_syntax_transform_func *sd_ber2str;
4236         slap_syntax_transform_func *sd_str2ber;
4237 #endif
4238 };
4239
4240 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4241 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4242
4243 struct syntax_defs_rec syntax_defs[] = {
4244         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")",
4245                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4246         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4247                 0, NULL, NULL, NULL},
4248         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4249                 0, NULL, NULL, NULL},
4250         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")",
4251                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4252         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_NOT_H_R ")",
4253                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4254         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4255                 0, bitStringValidate, NULL, NULL },
4256         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4257                 0, booleanValidate, NULL, NULL},
4258         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4259                 X_BINARY X_NOT_H_R ")",
4260                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4261         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4262                 X_BINARY X_NOT_H_R ")",
4263                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4264         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4265                 X_BINARY X_NOT_H_R ")",
4266                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4267         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4268                 0, countryStringValidate, IA5StringNormalize, NULL},
4269         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4270                 0, dnValidate, dnNormalize, dnPretty},
4271         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4272                 0, NULL, NULL, NULL},
4273         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4274                 0, NULL, NULL, NULL},
4275         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4276                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4277         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4278                 0, NULL, NULL, NULL},
4279         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4280                 0, NULL, NULL, NULL},
4281         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4282                 0, NULL, NULL, NULL},
4283         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4284                 0, NULL, NULL, NULL},
4285         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4286                 0, NULL, NULL, NULL},
4287         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4288                 0, printablesStringValidate, IA5StringNormalize, NULL},
4289         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4290                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4291         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4292                 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4293         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4294                 0, NULL, NULL, NULL},
4295         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4296                 0, IA5StringValidate, IA5StringNormalize, NULL},
4297         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4298                 0, integerValidate, integerNormalize, integerPretty},
4299         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4300                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4301         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4302                 0, NULL, NULL, NULL},
4303         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4304                 0, NULL, NULL, NULL},
4305         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4306                 0, NULL, NULL, NULL},
4307         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4308                 0, NULL, NULL, NULL},
4309         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4310                 0, NULL, NULL, NULL},
4311         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4312                 0, nameUIDValidate, nameUIDNormalize, NULL},
4313         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4314                 0, NULL, NULL, NULL},
4315         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4316                 0, numericStringValidate, numericStringNormalize, NULL},
4317         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4318                 0, NULL, NULL, NULL},
4319         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4320                 0, oidValidate, NULL, NULL},
4321         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4322                 0, IA5StringValidate, IA5StringNormalize, NULL},
4323         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4324                 0, blobValidate, NULL, NULL},
4325         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4326                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4327         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4328                 0, NULL, NULL, NULL},
4329         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4330                 0, NULL, NULL, NULL},
4331         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4332                 0, printableStringValidate, IA5StringNormalize, NULL},
4333         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4334                 X_BINARY X_NOT_H_R ")",
4335                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4336         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4337                 0, printableStringValidate, IA5StringNormalize, NULL},
4338         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4339                 0, NULL, NULL, NULL},
4340         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4341                 0, printableStringValidate, IA5StringNormalize, NULL},
4342         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4343                 0, utcTimeValidate, utcTimeNormalize, NULL},
4344         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4345                 0, NULL, NULL, NULL},
4346         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4347                 0, NULL, NULL, NULL},
4348         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4349                 0, NULL, NULL, NULL},
4350         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4351                 0, NULL, NULL, NULL},
4352         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4353                 0, NULL, NULL, NULL},
4354
4355         /* RFC 2307 NIS Syntaxes */
4356         {"( 1.3.6.1.1.1.0.0  DESC 'RFC2307 NIS Netgroup Triple' )",
4357                 0, nisNetgroupTripleValidate, NULL, NULL},
4358         {"( 1.3.6.1.1.1.0.1  DESC 'RFC2307 Boot Parameter' )",
4359                 0, bootParameterValidate, NULL, NULL},
4360
4361         /* OpenLDAP Experimental Syntaxes */
4362         {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4363                 0, UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4364                 NULL, NULL},
4365         {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4366                 0, NULL, NULL, NULL},
4367
4368         /* OpenLDAP Void Syntax */
4369         {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4370                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4371         {NULL, 0, NULL, NULL, NULL}
4372 };
4373
4374 struct mrule_defs_rec {
4375         char *                                          mrd_desc;
4376         slap_mask_t                                     mrd_usage;
4377         slap_mr_convert_func *          mrd_convert;
4378         slap_mr_normalize_func *        mrd_normalize;
4379         slap_mr_match_func *            mrd_match;
4380         slap_mr_indexer_func *          mrd_indexer;
4381         slap_mr_filter_func *           mrd_filter;
4382
4383         char *                                          mrd_associated;
4384 };
4385
4386 /*
4387  * Other matching rules in X.520 that we do not use (yet):
4388  *
4389  * 2.5.13.9             numericStringOrderingMatch
4390  * 2.5.13.15    integerOrderingMatch
4391  * 2.5.13.18    octetStringOrderingMatch
4392  * 2.5.13.19    octetStringSubstringsMatch
4393  * 2.5.13.25    uTCTimeMatch
4394  * 2.5.13.26    uTCTimeOrderingMatch
4395  * 2.5.13.31    directoryStringFirstComponentMatch
4396  * 2.5.13.32    wordMatch
4397  * 2.5.13.33    keywordMatch
4398  * 2.5.13.34    certificateExactMatch
4399  * 2.5.13.35    certificateMatch
4400  * 2.5.13.36    certificatePairExactMatch
4401  * 2.5.13.37    certificatePairMatch
4402  * 2.5.13.38    certificateListExactMatch
4403  * 2.5.13.39    certificateListMatch
4404  * 2.5.13.40    algorithmIdentifierMatch
4405  * 2.5.13.41    storedPrefixMatch
4406  * 2.5.13.42    attributeCertificateMatch
4407  * 2.5.13.43    readerAndKeyIDMatch
4408  * 2.5.13.44    attributeIntegrityMatch
4409  */
4410
4411 struct mrule_defs_rec mrule_defs[] = {
4412         /*
4413          * EQUALITY matching rules must be listed after associated APPROX
4414          * matching rules.  So, we list all APPROX matching rules first.
4415          */
4416         {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4417                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4418                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4419                 NULL, NULL,
4420                 directoryStringApproxMatch,
4421                 directoryStringApproxIndexer, 
4422                 directoryStringApproxFilter,
4423                 NULL},
4424
4425         {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4426                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4427                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4428                 NULL, NULL,
4429                 IA5StringApproxMatch,
4430                 IA5StringApproxIndexer, 
4431                 IA5StringApproxFilter,
4432                 NULL},
4433
4434         /*
4435          * Other matching rules
4436          */
4437         
4438         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4439                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4440                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4441                 NULL, NULL,
4442                 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4443                 NULL},
4444
4445         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4446                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4447                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4448                 NULL, NULL,
4449                 dnMatch, dnIndexer, dnFilter,
4450                 NULL},
4451
4452         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4453                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4454                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4455                 NULL, NULL,
4456                 caseIgnoreMatch, caseIgnoreIndexer, caseIgnoreFilter,
4457                 directoryStringApproxMatchOID },
4458
4459         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4460                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4461                 SLAP_MR_ORDERING,
4462                 NULL, NULL,
4463                 caseIgnoreOrderingMatch, NULL, NULL,
4464                 NULL},
4465
4466         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4467                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4468                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4469                 NULL, NULL,
4470                 caseIgnoreSubstringsMatch,
4471                 caseIgnoreSubstringsIndexer,
4472                 caseIgnoreSubstringsFilter,
4473                 NULL},
4474
4475         {"( 2.5.13.5 NAME 'caseExactMatch' "
4476                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4477                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4478                 NULL, NULL,
4479                 caseExactMatch, caseExactIndexer, caseExactFilter,
4480                 directoryStringApproxMatchOID },
4481
4482         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4483                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4484                 SLAP_MR_ORDERING,
4485                 NULL, NULL,
4486                 caseExactOrderingMatch, NULL, NULL,
4487                 NULL},
4488
4489         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4490                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4491                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4492                 NULL, NULL,
4493                 caseExactSubstringsMatch,
4494                 caseExactSubstringsIndexer,
4495                 caseExactSubstringsFilter,
4496                 NULL},
4497
4498         {"( 2.5.13.8 NAME 'numericStringMatch' "
4499                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4500                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4501                 NULL, NULL,
4502                 caseIgnoreIA5Match,
4503                 caseIgnoreIA5Indexer,
4504                 caseIgnoreIA5Filter,
4505                 NULL},
4506
4507         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4508                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4509                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4510                 NULL, NULL,
4511                 caseIgnoreIA5SubstringsMatch,
4512                 caseIgnoreIA5SubstringsIndexer,
4513                 caseIgnoreIA5SubstringsFilter,
4514                 NULL},
4515
4516         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4517                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4518                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4519                 NULL, NULL,
4520                 caseIgnoreListMatch, NULL, NULL,
4521                 NULL},
4522
4523         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4524                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4525                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4526                 NULL, NULL,
4527                 caseIgnoreListSubstringsMatch, NULL, NULL,
4528                 NULL},
4529
4530         {"( 2.5.13.13 NAME 'booleanMatch' "
4531                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4532                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4533                 NULL, NULL,
4534                 booleanMatch, NULL, NULL,
4535                 NULL},
4536
4537         {"( 2.5.13.14 NAME 'integerMatch' "
4538                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4539                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4540                 NULL, NULL,
4541                 integerMatch, integerIndexer, integerFilter,
4542                 NULL},
4543
4544         {"( 2.5.13.16 NAME 'bitStringMatch' "
4545                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4546                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4547                 NULL, NULL,
4548                 bitStringMatch, NULL, NULL,
4549                 NULL},
4550
4551         {"( 2.5.13.17 NAME 'octetStringMatch' "
4552                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4553                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4554                 NULL, NULL,
4555                 octetStringMatch, octetStringIndexer, octetStringFilter,
4556                 NULL},
4557
4558         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4559                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4560                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4561                 NULL, NULL,
4562                 telephoneNumberMatch,
4563                 telephoneNumberIndexer,
4564                 telephoneNumberFilter,
4565                 NULL},
4566
4567         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4568                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4569                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4570                 NULL, NULL,
4571                 telephoneNumberSubstringsMatch,
4572                 telephoneNumberSubstringsIndexer,
4573                 telephoneNumberSubstringsFilter,
4574                 NULL},
4575
4576         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4577                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4578                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4579                 NULL, NULL,
4580                 NULL, NULL, NULL,
4581                 NULL},
4582
4583         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4584                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4585                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4586                 NULL, NULL,
4587                 uniqueMemberMatch, NULL, NULL,
4588                 NULL},
4589
4590         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4591                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4592                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4593                 NULL, NULL,
4594                 protocolInformationMatch, NULL, NULL,
4595                 NULL},
4596
4597         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4598                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4599                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4600                 NULL, NULL,
4601                 generalizedTimeMatch, NULL, NULL,
4602                 NULL},
4603
4604         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4605                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4606                 SLAP_MR_ORDERING,
4607                 NULL, NULL,
4608                 generalizedTimeOrderingMatch, NULL, NULL,
4609                 NULL},
4610
4611         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4612                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4613                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4614                 NULL, NULL,
4615                 integerFirstComponentMatch, NULL, NULL,
4616                 NULL},
4617
4618         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4619                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4620                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4621                 NULL, NULL,
4622                 objectIdentifierFirstComponentMatch, NULL, NULL,
4623                 NULL},
4624
4625         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4626                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4627                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4628                 NULL, NULL,
4629                 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4630                 IA5StringApproxMatchOID },
4631
4632         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4633                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4634                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4635                 NULL, NULL,
4636                 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4637                 IA5StringApproxMatchOID },
4638
4639         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4640                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4641                 SLAP_MR_SUBSTR,
4642                 NULL, NULL,
4643                 caseIgnoreIA5SubstringsMatch,
4644                 caseIgnoreIA5SubstringsIndexer,
4645                 caseIgnoreIA5SubstringsFilter,
4646                 NULL},
4647
4648         {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4649                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4650                 SLAP_MR_SUBSTR,
4651                 NULL, NULL,
4652                 caseExactIA5SubstringsMatch,
4653                 caseExactIA5SubstringsIndexer,
4654                 caseExactIA5SubstringsFilter,
4655                 NULL},
4656
4657         {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4658                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4659                 SLAP_MR_EQUALITY,
4660                 NULL, NULL,
4661                 authPasswordMatch, NULL, NULL,
4662                 NULL},
4663
4664         {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4665                 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4666                 SLAP_MR_EQUALITY,
4667                 NULL, NULL,
4668                 OpenLDAPaciMatch, NULL, NULL,
4669                 NULL},
4670
4671         {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
4672 };
4673
4674 int
4675 schema_init( void )
4676 {
4677         int             res;
4678         int             i;
4679
4680         /* we should only be called once (from main) */
4681         assert( schema_init_done == 0 );
4682
4683         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4684                 res = register_syntax( syntax_defs[i].sd_desc,
4685                     syntax_defs[i].sd_flags,
4686                     syntax_defs[i].sd_validate,
4687                     syntax_defs[i].sd_normalize,
4688                         syntax_defs[i].sd_pretty
4689 #ifdef SLAPD_BINARY_CONVERSION
4690                         ,
4691                     syntax_defs[i].sd_ber2str,
4692                         syntax_defs[i].sd_str2ber
4693 #endif
4694                 );
4695
4696                 if ( res ) {
4697                         fprintf( stderr, "schema_init: Error registering syntax %s\n",
4698                                  syntax_defs[i].sd_desc );
4699                         return LDAP_OTHER;
4700                 }
4701         }
4702
4703         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4704                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
4705                         fprintf( stderr,
4706                                 "schema_init: Ingoring unusable matching rule %s\n",
4707                                  mrule_defs[i].mrd_desc );
4708                         continue;
4709                 }
4710
4711                 res = register_matching_rule(
4712                         mrule_defs[i].mrd_desc,
4713                         mrule_defs[i].mrd_usage,
4714                         mrule_defs[i].mrd_convert,
4715                         mrule_defs[i].mrd_normalize,
4716                     mrule_defs[i].mrd_match,
4717                         mrule_defs[i].mrd_indexer,
4718                         mrule_defs[i].mrd_filter,
4719                         mrule_defs[i].mrd_associated );
4720
4721                 if ( res ) {
4722                         fprintf( stderr,
4723                                 "schema_init: Error registering matching rule %s\n",
4724                                  mrule_defs[i].mrd_desc );
4725                         return LDAP_OTHER;
4726                 }
4727         }
4728         schema_init_done = 1;
4729         return LDAP_SUCCESS;
4730 }