/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * 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 * . */ #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; }