- /* very unforgiving validation, requires no normalization
- * before simplistic matching
- */
-
- if( in->bv_len == 4 ) {
- if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
- return LDAP_SUCCESS;
- }
- } else if( in->bv_len == 5 ) {
- if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
- return LDAP_SUCCESS;
- }
- }
-
- return LDAP_INVALID_SYNTAX;
-}
-
-static int
-booleanMatch(
- int *matchp,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *value,
- void *assertedValue )
-{
- /* simplistic matching allowed by rigid validation */
- struct berval *asserted = (struct berval *) assertedValue;
- *matchp = value->bv_len != asserted->bv_len;
- return LDAP_SUCCESS;
-}
-
-/*-------------------------------------------------------------------
-LDAP/X.500 string syntax / matching rules have a few oddities. This
-comment attempts to detail how slapd(8) treats them.
-
-Summary:
- StringSyntax X.500 LDAP Matching
- DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
- PrintableString subset subset i/e + ignore insignificant spaces
- NumericString subset subset ignore all spaces
- IA5String ASCII ASCII i/e + ignore insignificant spaces
- TeletexString T.61 T.61 i/e + ignore insignificant spaces
-
- TelephoneNumber subset subset i + ignore all spaces and "-"
-
- See draft-ietf-ldapbis-strpro for details (once published).
-
-
-Directory String -
- In X.500(93), a directory string can be either a PrintableString,
- a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
- In later versions, more CHOICEs were added. In all cases the string
- must be non-empty.
-
- In LDAPv3, a directory string is a UTF-8 encoded UCS string.
-
- For matching, there are both case ignore and exact rules. Both
- also require that "insignificant" spaces be ignored.
- spaces before the first non-space are ignored;
- spaces after the last non-space are ignored;
- spaces after a space are ignored.
- Note: by these rules (and as clarified in X.520), a string of only
- spaces is to be treated as if held one space, not empty (which
- would be a syntax error).
-
-NumericString
- In ASN.1, numeric string is just a string of digits and spaces
- and could be empty. However, in X.500, all attribute values of
- numeric string carry a non-empty constraint. For example:
-
- internationalISDNNumber ATTRIBUTE ::= {
- WITH SYNTAX InternationalISDNNumber
- EQUALITY MATCHING RULE numericStringMatch
- SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
- ID id-at-internationalISDNNumber }
- InternationalISDNNumber ::=
- NumericString (SIZE(1..ub-international-isdn-number))
-
- Unforunately, some assertion values are don't carry the same
- constraint (but its unclear how such an assertion could ever
- be true). In LDAP, there is one syntax (numericString) not two
- (numericString with constraint, numericString without constraint).
- This should be treated as numericString with non-empty constraint.
- Note that while someone may have no ISDN number, there are no ISDN
- numbers which are zero length.
-
- In matching, spaces are ignored.
-
-PrintableString
- In ASN.1, Printable string is just a string of printable characters
- and can be empty. In X.500, semantics much like NumericString (see
- serialNumber for a like example) excepting uses insignificant space
- handling instead of ignore all spaces.
-
-IA5String
- Basically same as PrintableString. There are no examples in X.500,
- but same logic applies. So we require them to be non-empty as
- well.
-
--------------------------------------------------------------------*/
-
-static int
-UTF8StringValidate(
- Syntax *syntax,
- struct berval *in )
-{
- ber_len_t count;
- int len;
- unsigned char *u = in->bv_val;
-
- if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
-
- for( count = in->bv_len; count > 0; count-=len, u+=len ) {
- /* get the length indicated by the first byte */
- len = LDAP_UTF8_CHARLEN2( u, len );
-
- /* very basic checks */
- switch( len ) {
- case 6:
- if( (u[5] & 0xC0) != 0x80 ) {
- return LDAP_INVALID_SYNTAX;
- }
- case 5:
- if( (u[4] & 0xC0) != 0x80 ) {
- return LDAP_INVALID_SYNTAX;
- }
- case 4:
- if( (u[3] & 0xC0) != 0x80 ) {
- return LDAP_INVALID_SYNTAX;
- }
- case 3:
- if( (u[2] & 0xC0 )!= 0x80 ) {
- return LDAP_INVALID_SYNTAX;
- }
- case 2:
- if( (u[1] & 0xC0) != 0x80 ) {
- return LDAP_INVALID_SYNTAX;
- }
- case 1:
- /* CHARLEN already validated it */
- break;
- default:
- return LDAP_INVALID_SYNTAX;
- }
-
- /* make sure len corresponds with the offset
- to the next character */
- if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
- }
-
- if( count != 0 ) return LDAP_INVALID_SYNTAX;
-
- return LDAP_SUCCESS;
-}
-
-#ifndef SLAP_NVALUES
-
-static int
-xUTF8StringNormalize(
- Syntax *syntax,
- struct berval *val,
- struct berval *normalized )
-{
- char *p, *q, *s, *e;
- int len = 0;
-
- /* validator should have refused an empty string */
- assert( val->bv_len );
-
- p = val->bv_val;
-
- /* Ignore initial whitespace */
- /* All space is ASCII. All ASCII is 1 byte */
- for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
-
- normalized->bv_len = val->bv_len - (p - val->bv_val);
-
- if( !normalized->bv_len ) {
- ber_mem2bv( " ", 1, 1, normalized );
- return LDAP_SUCCESS;
- }
-
- ber_mem2bv( p, normalized->bv_len, 1, normalized );
- e = normalized->bv_val + normalized->bv_len;
-
- assert( normalized->bv_val );
-
- p = q = normalized->bv_val;
- s = NULL;
-
- while ( p < e ) {
- q += len;
- if ( ASCII_SPACE( *p ) ) {
- s = q - len;
- len = 1;
- *q = *p++;
-
- /* Ignore the extra whitespace */
- while ( ASCII_SPACE( *p ) ) {
- p++;
- }
- } else {
- len = LDAP_UTF8_COPY(q,p);
- s=NULL;
- p+=len;
- }
- }
-
- assert( normalized->bv_val <= p );
- assert( q+len <= p );
-
- /* cannot start with a space */
- assert( !ASCII_SPACE( normalized->bv_val[0] ) );
-
- /*
- * If the string ended in space, backup the pointer one
- * position. One is enough because the above loop collapsed
- * all whitespace to a single space.
- */
-
- if ( s != NULL ) {
- len = q - s;
- q = s;
- }
-
- /* cannot end with a space */
- assert( !ASCII_SPACE( *q ) );
-
- q += len;
-
- /* null terminate */
- *q = '\0';
-
- normalized->bv_len = q - normalized->bv_val;
-
- return LDAP_SUCCESS;
-}
-
-/* Returns Unicode canonically normalized copy of a substring assertion
- * Skipping attribute description */
-static SubstringsAssertion *
-UTF8SubstringsAssertionNormalize(
- SubstringsAssertion *sa,
- unsigned casefold )
-{
- SubstringsAssertion *nsa;
- int i;
-
- nsa = (SubstringsAssertion *)SLAP_CALLOC( 1, sizeof(SubstringsAssertion) );
- if( nsa == NULL ) {
- return NULL;
- }
-
- if( sa->sa_initial.bv_val != NULL ) {
- UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
- if( nsa->sa_initial.bv_val == NULL ) {
- goto err;
- }
- }
-
- if( sa->sa_any != NULL ) {
- for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
- /* empty */
- }
- nsa->sa_any = (struct berval *)
- SLAP_MALLOC( (i + 1) * sizeof(struct berval) );
- if( nsa->sa_any == NULL ) {
- goto err;
- }
-
- for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
- UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i],
- casefold );
- if( nsa->sa_any[i].bv_val == NULL ) {
- goto err;
- }
- }
- nsa->sa_any[i].bv_val = NULL;
- }
-
- if( sa->sa_final.bv_val != NULL ) {
- UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
- if( nsa->sa_final.bv_val == NULL ) {
- goto err;
- }
- }
-
- return nsa;
-
-err:
- if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
- if ( nsa->sa_any ) ber_bvarray_free( nsa->sa_any );
- if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
- ch_free( nsa );
- return NULL;
-}
-
-#ifndef SLAPD_APPROX_OLDSINGLESTRING
-
-#if defined(SLAPD_APPROX_INITIALS)
-#define SLAPD_APPROX_DELIMITER "._ "
-#define SLAPD_APPROX_WORDLEN 2
-#else
-#define SLAPD_APPROX_DELIMITER " "
-#define SLAPD_APPROX_WORDLEN 1
-#endif
-
-static int
-approxMatch(
- int *matchp,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *value,
- void *assertedValue )
-{
- struct berval *nval, *assertv;
- char *val, **values, **words, *c;
- int i, count, len, nextchunk=0, nextavail=0;
-
- /* Yes, this is necessary */
- nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
- if( nval == NULL ) {
- *matchp = 1;
- return LDAP_SUCCESS;
- }
-
- /* Yes, this is necessary */
- assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
- NULL, LDAP_UTF8_APPROX );
- if( assertv == NULL ) {
- ber_bvfree( nval );
- *matchp = 1;
- return LDAP_SUCCESS;
- }
-
- /* Isolate how many words there are */
- for ( c = nval->bv_val, count = 1; *c; c++ ) {
- c = strpbrk( c, SLAPD_APPROX_DELIMITER );
- if ( c == NULL ) break;
- *c = '\0';
- count++;
- }
-
- /* Get a phonetic copy of each word */
- words = (char **)ch_malloc( count * sizeof(char *) );
- values = (char **)ch_malloc( count * sizeof(char *) );
- for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
- words[i] = c;
- values[i] = phonetic(c);
- }
-
- /* Work through the asserted value's words, to see if at least some
- of the words are there, in the same order. */
- len = 0;
- while ( (ber_len_t) nextchunk < assertv->bv_len ) {
- len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
- if( len == 0 ) {
- nextchunk++;
- continue;
- }
-#if defined(SLAPD_APPROX_INITIALS)
- else if( len == 1 ) {
- /* Single letter words need to at least match one word's initial */
- for( i=nextavail; i<count; i++ )
- if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
- nextavail=i+1;
- break;
- }
- }
-#endif
- else {
- /* Isolate the next word in the asserted value and phonetic it */
- assertv->bv_val[nextchunk+len] = '\0';
- val = phonetic( assertv->bv_val + nextchunk );
-
- /* See if this phonetic chunk is in the remaining words of *value */
- for( i=nextavail; i<count; i++ ){
- if( !strcmp( val, values[i] ) ){
- nextavail = i+1;
- break;
- }
- }
- ch_free( val );
- }
-
- /* This chunk in the asserted value was NOT within the *value. */
- if( i >= count ) {
- nextavail=-1;
- break;
- }
-
- /* Go on to the next word in the asserted value */
- nextchunk += len+1;
- }
-
- /* If some of the words were seen, call it a match */
- if( nextavail > 0 ) {
- *matchp = 0;
- }
- else {
- *matchp = 1;
- }
-
- /* Cleanup allocs */
- ber_bvfree( assertv );
- for( i=0; i<count; i++ ) {
- ch_free( values[i] );
- }
- ch_free( values );
- ch_free( words );
- ber_bvfree( nval );
-
- return LDAP_SUCCESS;
-}
-
-static int
-approxIndexer(
- slap_mask_t use,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *prefix,
- BerVarray values,
- BerVarray *keysp )
-{
- char *c;
- int i,j, len, wordcount, keycount=0;
- struct berval *newkeys;
- BerVarray keys=NULL;
-
- for( j=0; values[j].bv_val != NULL; j++ ) {
- struct berval val = { 0, NULL };
- /* Yes, this is necessary */
- UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
- assert( val.bv_val != NULL );
-
- /* Isolate how many words there are. There will be a key for each */
- for( wordcount = 0, c = val.bv_val; *c; c++) {
- len = strcspn(c, SLAPD_APPROX_DELIMITER);
- if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
- c+= len;
- if (*c == '\0') break;
- *c = '\0';
- }
-
- /* Allocate/increase storage to account for new keys */
- newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
- * sizeof(struct berval) );
- AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
- if( keys ) ch_free( keys );
- keys = newkeys;
-
- /* Get a phonetic copy of each word */
- for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
- len = strlen( c );
- if( len < SLAPD_APPROX_WORDLEN ) continue;
- ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
- keycount++;
- i++;
- }
-
- ber_memfree( val.bv_val );
- }
- keys[keycount].bv_val = NULL;
- *keysp = keys;
-
- return LDAP_SUCCESS;
-}
-
-static int
-approxFilter(
- slap_mask_t use,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *prefix,
- void * assertedValue,
- BerVarray *keysp )
-{
- char *c;
- int i, count, len;
- struct berval *val;
- BerVarray keys;
-
- /* Yes, this is necessary */
- val = UTF8bvnormalize( ((struct berval *)assertedValue),
- NULL, LDAP_UTF8_APPROX );
- if( val == NULL || val->bv_val == NULL ) {
- keys = (struct berval *)ch_malloc( sizeof(struct berval) );
- keys[0].bv_val = NULL;
- *keysp = keys;
- ber_bvfree( val );
- return LDAP_SUCCESS;
- }
-
- /* Isolate how many words there are. There will be a key for each */
- for( count = 0,c = val->bv_val; *c; c++) {
- len = strcspn(c, SLAPD_APPROX_DELIMITER);
- if( len >= SLAPD_APPROX_WORDLEN ) count++;
- c+= len;
- if (*c == '\0') break;
- *c = '\0';
- }
-
- /* Allocate storage for new keys */
- keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
-
- /* Get a phonetic copy of each word */
- for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
- len = strlen(c);
- if( len < SLAPD_APPROX_WORDLEN ) continue;
- ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
- i++;
- }
-
- ber_bvfree( val );
-
- keys[count].bv_val = NULL;
- *keysp = keys;
-
- return LDAP_SUCCESS;
-}
-
-
-#else
-/* No other form of Approximate Matching is defined */
-
-static int
-approxMatch(
- int *matchp,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *value,
- void *assertedValue )
-{
- char *vapprox, *avapprox;
- char *s, *t;
-
- /* Yes, this is necessary */
- s = UTF8normalize( value, UTF8_NOCASEFOLD );
- if( s == NULL ) {
- *matchp = 1;
- return LDAP_SUCCESS;
- }
-
- /* Yes, this is necessary */
- t = UTF8normalize( ((struct berval *)assertedValue),
- UTF8_NOCASEFOLD );
- if( t == NULL ) {
- free( s );
- *matchp = -1;
- return LDAP_SUCCESS;
- }
-
- vapprox = phonetic( strip8bitChars( s ) );
- avapprox = phonetic( strip8bitChars( t ) );
-
- free( s );
- free( t );
-
- *matchp = strcmp( vapprox, avapprox );
-
- ch_free( vapprox );
- ch_free( avapprox );
-
- return LDAP_SUCCESS;
-}
-
-static int
-approxIndexer(
- slap_mask_t use,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *prefix,
- BerVarray values,
- BerVarray *keysp )
-{
- int i;
- BerVarray *keys;
- char *s;
-
- for( i=0; values[i].bv_val != NULL; i++ ) {
- /* empty - just count them */
- }
-
- /* we should have at least one value at this point */
- assert( i > 0 );
-
- keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
-
- /* Copy each value and run it through phonetic() */
- for( i=0; values[i].bv_val != NULL; i++ ) {
- /* Yes, this is necessary */
- s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
-
- /* strip 8-bit chars and run through phonetic() */
- ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
- free( s );
- }
- keys[i].bv_val = NULL;
-
- *keysp = keys;
- return LDAP_SUCCESS;
-}
-
-
-static int
-approxFilter(
- slap_mask_t use,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *prefix,
- void * assertedValue,
- BerVarray *keysp )
-{
- BerVarray keys;
- char *s;
-
- keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
-
- /* Yes, this is necessary */
- s = UTF8normalize( ((struct berval *)assertedValue),
- UTF8_NOCASEFOLD );
- if( s == NULL ) {
- keys[0] = NULL;
- } else {
- /* strip 8-bit chars and run through phonetic() */
- keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
- free( s );
- keys[1] = NULL;
- }
-
- *keysp = keys;
- return LDAP_SUCCESS;
-}
-#endif
-
-
-static int
-caseExactMatch(
- int *matchp,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *value,
- void *assertedValue )
-{
- *matchp = UTF8bvnormcmp( value,
- (struct berval *) assertedValue,
- LDAP_UTF8_NOCASEFOLD );
- return LDAP_SUCCESS;
-}
-
-static int
-caseExactIgnoreSubstringsMatch(
- int *matchp,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *value,
- void *assertedValue )
-{
- int match = 0;
- SubstringsAssertion *sub = NULL;
- struct berval left = { 0, NULL };
- int i;
- ber_len_t inlen=0;
- char *nav = NULL;
- unsigned casefold;
-
- casefold = ( mr != slap_schema.si_mr_caseExactSubstringsMatch )
- ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
-
- if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
- match = 1;
- goto done;
- }
- nav = left.bv_val;
-
- sub = UTF8SubstringsAssertionNormalize( assertedValue, casefold );
- if( sub == NULL ) {
- match = -1;
- goto done;
- }
-
- /* Add up asserted input length */
- if( sub->sa_initial.bv_val ) {
- inlen += sub->sa_initial.bv_len;
- }
- if( sub->sa_any ) {
- for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
- inlen += sub->sa_any[i].bv_len;
- }
- }
- if( sub->sa_final.bv_val ) {
- inlen += sub->sa_final.bv_len;
- }
-
- if( sub->sa_initial.bv_val ) {
- if( inlen > left.bv_len ) {
- match = 1;
- goto done;
- }
-
- match = memcmp( sub->sa_initial.bv_val, left.bv_val,
- sub->sa_initial.bv_len );
-
- if( match != 0 ) {
- goto done;
- }
-
- left.bv_val += sub->sa_initial.bv_len;
- left.bv_len -= sub->sa_initial.bv_len;
- inlen -= sub->sa_initial.bv_len;
- }
-
- if( sub->sa_final.bv_val ) {
- if( inlen > left.bv_len ) {
- match = 1;
- goto done;
- }
-
- match = memcmp( sub->sa_final.bv_val,
- &left.bv_val[left.bv_len - sub->sa_final.bv_len],
- sub->sa_final.bv_len );
-
- if( match != 0 ) {
- goto done;
- }
-
- left.bv_len -= sub->sa_final.bv_len;
- inlen -= sub->sa_final.bv_len;
- }
-
- if( sub->sa_any ) {
- for(i=0; sub->sa_any[i].bv_val; i++) {
- ber_len_t idx;
- char *p;
-
-retry:
- if( inlen > left.bv_len ) {
- /* not enough length */
- match = 1;
- goto done;
- }
-
- if( sub->sa_any[i].bv_len == 0 ) {
- continue;
- }
-
- p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
- if ( p == NULL ) {
- match = 1;
- goto done;
- }
-
- idx = p - left.bv_val;
-
- if( idx >= left.bv_len ) {
- /* this shouldn't happen */
- free( nav );
- if ( sub->sa_final.bv_val )
- ch_free( sub->sa_final.bv_val );
- if ( sub->sa_any )
- ber_bvarray_free( sub->sa_any );
- if ( sub->sa_initial.bv_val )
- ch_free( sub->sa_initial.bv_val );
- ch_free( sub );
- return LDAP_OTHER;
- }
-
- left.bv_val = p;
- left.bv_len -= idx;
-
- if( sub->sa_any[i].bv_len > left.bv_len ) {
- /* not enough left */
- match = 1;
- goto done;
- }
-
- match = memcmp( left.bv_val,
- sub->sa_any[i].bv_val,
- sub->sa_any[i].bv_len );
-
- if( match != 0 ) {
- left.bv_val++;
- left.bv_len--;
- goto retry;
- }
-
- left.bv_val += sub->sa_any[i].bv_len;
- left.bv_len -= sub->sa_any[i].bv_len;
- inlen -= sub->sa_any[i].bv_len;
- }
- }
-
-done:
- free( nav );
- if( sub != NULL ) {
- if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
- if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
- if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
- ch_free( sub );
- }
- *matchp = match;
- return LDAP_SUCCESS;
-}
-
-/* Index generation function */
-static int caseExactIgnoreIndexer(
- slap_mask_t use,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *prefix,
- BerVarray values,
- BerVarray *keysp )
-{
- int i,j;
- unsigned casefold,wasspace;
- size_t slen, mlen;
- BerVarray keys;
- HASH_CONTEXT HASHcontext;
- unsigned char HASHdigest[HASH_BYTES];
- struct berval digest;
- digest.bv_val = HASHdigest;
- digest.bv_len = sizeof(HASHdigest);
-
- for( i=0; values[i].bv_val != NULL; i++ ) {
- /* empty - just count them */
- }
-
- /* we should have at least one value at this point */
- assert( i > 0 );
-
- keys = ch_malloc( sizeof( struct berval ) * (i+1) );
-
- slen = syntax->ssyn_oidlen;
- mlen = mr->smr_oidlen;
-
- casefold = ( mr != slap_schema.si_mr_caseExactMatch )
- ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
-
- for( i=0; values[i].bv_val != NULL; i++ ) {
- struct berval value, nvalue;
- UTF8bvnormalize( &values[i], &value, casefold );
-
- /* collapse spaces (in place) */
- nvalue.bv_len = 0;
- nvalue.bv_val = value.bv_val;
-
- wasspace=1;
- for( j=0; j<value.bv_len; j++) {
- if ( ASCII_SPACE( value.bv_val[j] )) {
- if( wasspace++ == 0 ) {
- nvalue.bv_val[nvalue.bv_len++] = value.bv_val[j];
- }
- } else {
- wasspace = 0;
- nvalue.bv_val[nvalue.bv_len++] = value.bv_val[j];
- }
- }
-
- if( nvalue.bv_len == 0 ) {
- nvalue.bv_val = " ";
- nvalue.bv_len = sizeof(" ")-1;
- } else {
- if( wasspace ) --nvalue.bv_len;
- nvalue.bv_val[nvalue.bv_len] = '\0';
- }
-
- HASH_Init( &HASHcontext );
- if( prefix != NULL && prefix->bv_len > 0 ) {
- HASH_Update( &HASHcontext,
- prefix->bv_val, prefix->bv_len );
- }
- HASH_Update( &HASHcontext,
- syntax->ssyn_oid, slen );
- HASH_Update( &HASHcontext,
- mr->smr_oid, mlen );
- HASH_Update( &HASHcontext,
- nvalue.bv_val, nvalue.bv_len );
- HASH_Final( HASHdigest, &HASHcontext );
-
- free( value.bv_val );
- ber_dupbv( &keys[i], &digest );
- }
-
- keys[i].bv_val = NULL;
- *keysp = keys;
- return LDAP_SUCCESS;
-}
-
-/* Index generation function */
-static int caseExactIgnoreFilter(
- slap_mask_t use,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *prefix,
- void * assertedValue,
- BerVarray *keysp )
-{
- unsigned casefold;
- size_t slen, mlen;
- BerVarray keys;
- HASH_CONTEXT HASHcontext;
- unsigned char HASHdigest[HASH_BYTES];
- struct berval value = { 0, NULL };
- struct berval digest;
-
- digest.bv_val = HASHdigest;
- digest.bv_len = sizeof(HASHdigest);
-
- slen = syntax->ssyn_oidlen;
- mlen = mr->smr_oidlen;
-
- casefold = ( mr != slap_schema.si_mr_caseExactMatch )
- ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
-
- UTF8bvnormalize( (struct berval *) assertedValue, &value, casefold );
- /* This usually happens if filter contains bad UTF8 */
- if( value.bv_val == NULL ) {
- keys = ch_malloc( sizeof( struct berval ) );
- keys[0].bv_val = NULL;
- return LDAP_SUCCESS;
- }
-
- keys = ch_malloc( sizeof( struct berval ) * 2 );
-
- HASH_Init( &HASHcontext );
- if( prefix != NULL && prefix->bv_len > 0 ) {
- HASH_Update( &HASHcontext,
- prefix->bv_val, prefix->bv_len );
- }
- HASH_Update( &HASHcontext,
- syntax->ssyn_oid, slen );
- HASH_Update( &HASHcontext,
- mr->smr_oid, mlen );
- HASH_Update( &HASHcontext,
- value.bv_val, value.bv_len );
- HASH_Final( HASHdigest, &HASHcontext );
-
- ber_dupbv( keys, &digest );
- keys[1].bv_val = NULL;
-
- free( value.bv_val );
-
- *keysp = keys;
- return LDAP_SUCCESS;
-}
-
-/* Substrings Index generation function */
-static int caseExactIgnoreSubstringsIndexer(
- slap_mask_t use,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *prefix,
- BerVarray values,
- BerVarray *keysp )
-{
- unsigned casefold, wasspace;
- ber_len_t i, j, nkeys;
- size_t slen, mlen;
- BerVarray keys;
- BerVarray tvalues, nvalues;
-
- HASH_CONTEXT HASHcontext;
- unsigned char HASHdigest[HASH_BYTES];
- struct berval digest;
- digest.bv_val = HASHdigest;
- digest.bv_len = sizeof(HASHdigest);
-
- nkeys=0;
-
- for( i=0; values[i].bv_val != NULL; i++ ) {
- /* empty - just count them */
- }
-
- /* we should have at least one value at this point */
- assert( i > 0 );
-
- casefold = ( mr != slap_schema.si_mr_caseExactSubstringsMatch )
- ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
-
- tvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
- nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
-
- for( i=0; values[i].bv_val != NULL; i++ ) {
- UTF8bvnormalize( &values[i], &tvalues[i], casefold );
-
- /* collapse spaces (in place) */
- nvalues[i].bv_len = 0;
- nvalues[i].bv_val = tvalues[i].bv_val;
-
- wasspace=1;
- for( j=0; j<tvalues[i].bv_len; j++) {
- if ( ASCII_SPACE( tvalues[i].bv_val[j] )) {
- if( wasspace++ == 0 ) {
- nvalues[i].bv_val[nvalues[i].bv_len++] =
- tvalues[i].bv_val[j];
- }
- } else {
- wasspace = 0;
- nvalues[i].bv_val[nvalues[i].bv_len++] = tvalues[i].bv_val[j];
- }
- }
-
- if( nvalues[i].bv_len == 0 ) {
- nvalues[i].bv_val = " ";
- nvalues[i].bv_len = sizeof(" ")-1;
- } else {
- if( wasspace ) --nvalues[i].bv_len;
- nvalues[i].bv_val[nvalues[i].bv_len] = '\0';
- }
- }
-
- tvalues[i].bv_val = NULL;
- nvalues[i].bv_val = NULL;
- values = nvalues;
-
- for( i=0; values[i].bv_val != NULL; i++ ) {
- /* count number of indices to generate */
- if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
- continue;
- }
-
- if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
- if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
- nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
- ( SLAP_INDEX_SUBSTR_MINLEN - 1);
- } else {
- nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
- }
- }
-
- if( flags & SLAP_INDEX_SUBSTR_ANY ) {
- if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
- nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
- }
- }
-
- if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
- if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
- nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
- ( SLAP_INDEX_SUBSTR_MINLEN - 1);
- } else {
- nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
- }
- }
- }
-
- if( nkeys == 0 ) {
- /* no keys to generate */
- *keysp = NULL;
- ber_bvarray_free( tvalues );
- ch_free( nvalues );
- return LDAP_SUCCESS;
- }
-
- keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
-
- slen = syntax->ssyn_oidlen;
- mlen = mr->smr_oidlen;
-
- nkeys=0;
- for( i=0; values[i].bv_val != NULL; i++ ) {
- ber_len_t j,max;
-
- if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
-
- if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
- ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
- {
- char pre = SLAP_INDEX_SUBSTR_PREFIX;
- max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
-
- for( j=0; j<max; j++ ) {
- HASH_Init( &HASHcontext );
- if( prefix != NULL && prefix->bv_len > 0 ) {
- HASH_Update( &HASHcontext,
- prefix->bv_val, prefix->bv_len );
- }
-
- HASH_Update( &HASHcontext,
- &pre, sizeof( pre ) );
- HASH_Update( &HASHcontext,
- syntax->ssyn_oid, slen );
- HASH_Update( &HASHcontext,
- mr->smr_oid, mlen );
- HASH_Update( &HASHcontext,
- &values[i].bv_val[j],
- SLAP_INDEX_SUBSTR_MAXLEN );
- HASH_Final( HASHdigest, &HASHcontext );
-
- ber_dupbv( &keys[nkeys++], &digest );
- }
- }
-
- max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
- ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
-
- for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
- char pre;
-
- if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
- pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
- HASH_Init( &HASHcontext );
- if( prefix != NULL && prefix->bv_len > 0 ) {
- HASH_Update( &HASHcontext,
- prefix->bv_val, prefix->bv_len );
- }
- HASH_Update( &HASHcontext,
- &pre, sizeof( pre ) );
- HASH_Update( &HASHcontext,
- syntax->ssyn_oid, slen );
- HASH_Update( &HASHcontext,
- mr->smr_oid, mlen );
- HASH_Update( &HASHcontext,
- values[i].bv_val, j );
- HASH_Final( HASHdigest, &HASHcontext );
-
- ber_dupbv( &keys[nkeys++], &digest );
- }
-
- if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
- pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
- HASH_Init( &HASHcontext );
- if( prefix != NULL && prefix->bv_len > 0 ) {
- HASH_Update( &HASHcontext,
- prefix->bv_val, prefix->bv_len );
- }
- HASH_Update( &HASHcontext,
- &pre, sizeof( pre ) );
- HASH_Update( &HASHcontext,
- syntax->ssyn_oid, slen );
- HASH_Update( &HASHcontext,
- mr->smr_oid, mlen );
- HASH_Update( &HASHcontext,
- &values[i].bv_val[values[i].bv_len-j], j );
- HASH_Final( HASHdigest, &HASHcontext );
-
- ber_dupbv( &keys[nkeys++], &digest );
- }
-
- }
-
- }
-
- if( nkeys > 0 ) {
- keys[nkeys].bv_val = NULL;
- *keysp = keys;
- } else {
- ch_free( keys );
- *keysp = NULL;
- }
-
- ber_bvarray_free( tvalues );
- ch_free( nvalues );
-
- return LDAP_SUCCESS;
-}
-
-static int caseExactIgnoreSubstringsFilter(
- slap_mask_t use,
- slap_mask_t flags,
- Syntax *syntax,
- MatchingRule *mr,
- struct berval *prefix,
- void * assertedValue,
- BerVarray *keysp )
-{
- SubstringsAssertion *sa;
- char pre;
- unsigned casefold;
- ber_len_t nkeys = 0;
- size_t slen, mlen, klen;