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