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