diff options
Diffstat (limited to 'servers/slapd/verbs.c')
-rw-r--r-- | servers/slapd/verbs.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/servers/slapd/verbs.c b/servers/slapd/verbs.c new file mode 100644 index 0000000..36c53e3 --- /dev/null +++ b/servers/slapd/verbs.c @@ -0,0 +1,276 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 1998-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ + +#include "portable.h" + +#include "slap.h" +#include "slap-config.h" + +int +bverb_to_mask( struct berval *bword, slap_verbmasks *v ) { + int i; + for ( i = 0; !BER_BVISNULL(&v[i].word); i++ ) { + if ( !ber_bvstrcasecmp( bword, &v[i].word) ) break; + } + return i; +} + +int +verb_to_mask( const char *word, slap_verbmasks *v ) { + struct berval bword; + ber_str2bv( word, 0, 0, &bword ); + return bverb_to_mask( &bword, v ); +} + +int +verbs_to_mask( int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m ) { + int i, j; + for (i = 1; i < argc; i++ ) { + j = verb_to_mask( argv[i], v ); + if ( BER_BVISNULL(&v[j].word) ) return i; + while ( !v[j].mask ) j--; + *m |= v[j].mask; + } + return 0; +} + +/* + * Mask keywords that represent multiple bits should occur before single + * bit keywords in the verbmasks array. + */ +int +mask_to_verbs( slap_verbmasks *v, slap_mask_t m, BerVarray *bva ) { + int i, rc = 1; + + if ( m ) { + for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) { + if (!v[i].mask) continue; + if ( ( m & v[i].mask ) == v[i].mask ) { + value_add_one( bva, &v[i].word ); + rc = 0; + m ^= v[i].mask; + if ( !m ) break; + } + } + } + return rc; +} + +/* Return the verbs as a single string, separated by delim */ +int +mask_to_verbstring( slap_verbmasks *v, slap_mask_t m0, char delim, struct berval *bv ) +{ + int i, rc = 1; + + BER_BVZERO( bv ); + if ( m0 ) { + slap_mask_t m = m0; + char *ptr; + for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) { + if ( !v[i].mask ) continue; + if ( ( m & v[i].mask ) == v[i].mask ) { + bv->bv_len += v[i].word.bv_len + 1; + rc = 0; + m ^= v[i].mask; + if ( !m ) break; + } + } + bv->bv_val = ch_malloc(bv->bv_len); + bv->bv_len--; + ptr = bv->bv_val; + m = m0; + for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) { + if ( !v[i].mask ) continue; + if ( ( m & v[i].mask ) == v[i].mask ) { + ptr = lutil_strcopy( ptr, v[i].word.bv_val ); + *ptr++ = delim; + m ^= v[i].mask; + if ( !m ) break; + } + } + ptr[-1] = '\0'; + } + return rc; +} + +/* Parse a verbstring */ +int +verbstring_to_mask( slap_verbmasks *v, char *str, char delim, slap_mask_t *m ) { + int j; + char *d; + struct berval bv; + + do { + bv.bv_val = str; + d = strchr( str, delim ); + if ( d ) + bv.bv_len = d - str; + else + bv.bv_len = strlen( str ); + j = bverb_to_mask( &bv, v ); + if ( BER_BVISNULL(&v[j].word) ) return 1; + while ( !v[j].mask ) j--; + *m |= v[j].mask; + str += bv.bv_len + 1; + } while ( d ); + return 0; +} + +int +slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v ) +{ + int i; + + assert( *vp == NULL ); + + for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) /* EMPTY */; + + *vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) ); + + for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) { + ber_dupbv( &(*vp)[ i ].word, &v[ i ].word ); + *((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask; + } + + BER_BVZERO( &(*vp)[ i ].word ); + + return 0; +} + +int +slap_verbmasks_destroy( slap_verbmasks *v ) +{ + int i; + + assert( v != NULL ); + + for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) { + ch_free( v[ i ].word.bv_val ); + } + + ch_free( v ); + + return 0; +} + +int +slap_verbmasks_append( + slap_verbmasks **vp, + slap_mask_t m, + struct berval *v, + slap_mask_t *ignore ) +{ + int i; + + if ( !m ) { + return LDAP_OPERATIONS_ERROR; + } + + for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) { + if ( !(*vp)[ i ].mask ) continue; + + if ( ignore != NULL ) { + int j; + + for ( j = 0; ignore[ j ] != 0; j++ ) { + if ( (*vp)[ i ].mask == ignore[ j ] ) { + goto check_next; + } + } + } + + if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) { + if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) { + /* already set; ignore */ + return LDAP_SUCCESS; + } + /* conflicts */ + return LDAP_TYPE_OR_VALUE_EXISTS; + } + + if ( m & (*vp)[ i ].mask ) { + /* conflicts */ + return LDAP_CONSTRAINT_VIOLATION; + } +check_next:; + } + + *vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) ); + ber_dupbv( &(*vp)[ i ].word, v ); + *((slap_mask_t *)&(*vp)[ i ].mask) = m; + BER_BVZERO( &(*vp)[ i + 1 ].word ); + + return LDAP_SUCCESS; +} + +int +enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) { + int i; + + for (i=0; !BER_BVISNULL(&v[i].word); i++) { + if ( m == v[i].mask ) { + if ( bv != NULL ) { + *bv = v[i].word; + } + return i; + } + } + return -1; +} + +/* register a new verbmask */ +int +slap_verbmask_register( + slap_verbmasks *vm_, + slap_verbmasks **vmp, + struct berval *bv, + int mask ) +{ + slap_verbmasks *vm = *vmp; + int i; + + /* check for duplicate word */ + /* NOTE: we accept duplicate codes; the first occurrence will be used + * when mapping from mask to verb */ + i = verb_to_mask( bv->bv_val, vm ); + if ( !BER_BVISNULL( &vm[ i ].word ) ) { + return -1; + } + + for ( i = 0; !BER_BVISNULL( &vm[ i ].word ); i++ ) + ; + + if ( vm == vm_ ) { + /* first time: duplicate array */ + vm = ch_calloc( i + 2, sizeof( slap_verbmasks ) ); + for ( i = 0; !BER_BVISNULL( &vm_[ i ].word ); i++ ) + { + ber_dupbv( &vm[ i ].word, &vm_[ i ].word ); + *((slap_mask_t*)&vm[ i ].mask) = vm_[ i ].mask; + } + + } else { + vm = ch_realloc( vm, (i + 2) * sizeof( slap_verbmasks ) ); + } + + ber_dupbv( &vm[ i ].word, bv ); + *((slap_mask_t*)&vm[ i ].mask) = mask; + + BER_BVZERO( &vm[ i+1 ].word ); + + *vmp = vm; + + return i; +} |