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