X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fvalsort.c;h=5d89eb0554c776d55c43969d259caf027671023a;hb=c6b5abbfd20567116846ebc38f0005c429284c98;hp=3d064e03e63a9d2127062bcdb2e3772ce2521b40;hpb=02f52030b01abf2692b5347abc7a848b933dfd17;p=openldap diff --git a/servers/slapd/overlays/valsort.c b/servers/slapd/overlays/valsort.c index 3d064e03e6..5d89eb0554 100644 --- a/servers/slapd/overlays/valsort.c +++ b/servers/slapd/overlays/valsort.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005 The OpenLDAP Foundation. + * Copyright 2005-2012 The OpenLDAP Foundation. * Portions copyright 2005 Symas Corporation. * All rights reserved. * @@ -51,6 +51,8 @@ typedef struct valsort_info { slap_mask_t vi_sort; } valsort_info; +static int valsort_cid; + static ConfigDriver valsort_cf_func; static ConfigTable valsort_cfats[] = { @@ -76,18 +78,20 @@ static slap_verbmasks sorts[] = { { BER_BVC("alpha-ascend"), VALSORT_ASCEND|VALSORT_ALPHA }, { BER_BVC("alpha-descend"), VALSORT_DESCEND|VALSORT_ALPHA }, { BER_BVC("numeric-ascend"), VALSORT_ASCEND|VALSORT_NUMERIC }, - { BER_BVC("numeric-ascend"), VALSORT_DESCEND|VALSORT_NUMERIC }, + { BER_BVC("numeric-descend"), VALSORT_DESCEND|VALSORT_NUMERIC }, { BER_BVC("weighted"), VALSORT_WEIGHTED }, { BER_BVNULL, 0 } }; +static Syntax *syn_numericString; + static int valsort_cf_func(ConfigArgs *c) { slap_overinst *on = (slap_overinst *)c->bi; valsort_info vitmp, *vi; const char *text = NULL; - int i; - struct berval bv; + int i, is_numeric; + struct berval bv = BER_BVNULL; if ( c->op == SLAP_CONFIG_EMIT ) { for ( vi = on->on_bi.bi_private; vi; vi = vi->vi_next ) { @@ -95,15 +99,17 @@ valsort_cf_func(ConfigArgs *c) { char *ptr; int len; - len = vi->vi_ad->ad_cname.bv_len + 1 + vi->vi_dn.bv_len + 3; + len = vi->vi_ad->ad_cname.bv_len + 1 + vi->vi_dn.bv_len + 2; i = vi->vi_sort; if ( i & VALSORT_WEIGHTED ) { enum_to_verb( sorts, VALSORT_WEIGHTED, &bv2 ); len += bv2.bv_len + 1; i ^= VALSORT_WEIGHTED; } - enum_to_verb( sorts, i, &bv ); - len += bv.bv_len; + if ( i ) { + enum_to_verb( sorts, i, &bv ); + len += bv.bv_len + 1; + } bvret.bv_val = ch_malloc( len+1 ); bvret.bv_len = len; @@ -112,19 +118,21 @@ valsort_cf_func(ConfigArgs *c) { *ptr++ = '"'; ptr = lutil_strcopy( ptr, vi->vi_dn.bv_val ); *ptr++ = '"'; - *ptr++ = ' '; if ( vi->vi_sort & VALSORT_WEIGHTED ) { + *ptr++ = ' '; ptr = lutil_strcopy( ptr, bv2.bv_val ); + } + if ( i ) { *ptr++ = ' '; + strcpy( ptr, bv.bv_val ); } - strcpy( ptr, bv.bv_val ); ber_bvarray_add( &c->rvalue_vals, &bvret ); } i = ( c->rvalue_vals != NULL ) ? 0 : 1; return i; } else if ( c->op == LDAP_MOD_DELETE ) { if ( c->valx < 0 ) { - for ( vi = on->on_bi.bi_private; vi; vi = c->be->be_private ) { + for ( vi = on->on_bi.bi_private; vi; vi = on->on_bi.bi_private ) { on->on_bi.bi_private = vi->vi_next; ch_free( vi->vi_dn.bv_val ); ch_free( vi ); @@ -144,37 +152,54 @@ valsort_cf_func(ConfigArgs *c) { vitmp.vi_ad = NULL; i = slap_str2ad( c->argv[1], &vitmp.vi_ad, &text ); if ( i ) { - sprintf( c->msg, "<%s> %s", c->argv[0], text ); + snprintf( c->cr_msg, sizeof( c->cr_msg), "<%s> %s", c->argv[0], text ); Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n", - c->log, c->msg, c->argv[1] ); + c->log, c->cr_msg, c->argv[1] ); return(1); } + if ( is_at_single_value( vitmp.vi_ad->ad_type )) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> %s is single-valued, ignoring", c->argv[0], + vitmp.vi_ad->ad_cname.bv_val ); + Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n", + c->log, c->cr_msg, c->argv[1] ); + return(0); + } + is_numeric = ( vitmp.vi_ad->ad_type->sat_syntax == syn_numericString || + vitmp.vi_ad->ad_type->sat_syntax == slap_schema.si_syn_integer ) ? 1 + : 0; ber_str2bv( c->argv[2], 0, 0, &bv ); i = dnNormalize( 0, NULL, NULL, &bv, &vitmp.vi_dn, NULL ); if ( i ) { - sprintf( c->msg, "<%s> unable to normalize DN", c->argv[0] ); + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to normalize DN", c->argv[0] ); Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n", - c->log, c->msg, c->argv[2] ); + c->log, c->cr_msg, c->argv[2] ); return(1); } i = verb_to_mask( c->argv[3], sorts ); if ( BER_BVISNULL( &sorts[i].word )) { - sprintf( c->msg, "<%s> unrecognized sort type", c->argv[0] ); + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unrecognized sort type", c->argv[0] ); Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n", - c->log, c->msg, c->argv[3] ); + c->log, c->cr_msg, c->argv[3] ); return(1); } vitmp.vi_sort = sorts[i].mask; if ( sorts[i].mask == VALSORT_WEIGHTED && c->argc == 5 ) { i = verb_to_mask( c->argv[4], sorts ); if ( BER_BVISNULL( &sorts[i].word )) { - sprintf( c->msg, "<%s> unrecognized sort type", c->argv[0] ); + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unrecognized sort type", c->argv[0] ); Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n", - c->log, c->msg, c->argv[4] ); + c->log, c->cr_msg, c->argv[4] ); return(1); } vitmp.vi_sort |= sorts[i].mask; } + if (( vitmp.vi_sort & VALSORT_NUMERIC ) && !is_numeric ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> numeric sort specified for non-numeric syntax", + c->argv[0] ); + Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n", + c->log, c->cr_msg, c->argv[1] ); + return(1); + } vi = ch_malloc( sizeof(valsort_info) ); *vi = vitmp; vi->vi_next = on->on_bi.bi_private; @@ -187,7 +212,7 @@ static void do_sort( Operation *op, Attribute *a, int beg, int num, slap_mask_t sort ) { int i, j, gotnvals; - struct berval tmp, ntmp, *vals, *nvals; + struct berval tmp, ntmp, *vals = NULL, *nvals; gotnvals = (a->a_vals != a->a_nvals ); @@ -247,9 +272,14 @@ valsort_response( Operation *op, SlapReply *rs ) valsort_info *vi; Attribute *a; - /* We only want search responses */ - if ( rs->sr_type != REP_SEARCH ) return SLAP_CB_CONTINUE; - + /* If this is not a search response, or it is a syncrepl response, + * or the valsort control wants raw results, pass thru unmodified. + */ + if ( rs->sr_type != REP_SEARCH || + ( _SCM(op->o_sync) > SLAP_CONTROL_IGNORED ) || + ( op->o_ctrlflag[valsort_cid] & SLAP_CONTROL_DATA0)) + return SLAP_CB_CONTINUE; + on = (slap_overinst *) op->o_bd->bd_info; vi = on->on_bi.bi_private; @@ -267,16 +297,11 @@ valsort_response( Operation *op, SlapReply *rs ) a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad ); if ( !a ) continue; - if (( rs->sr_flags & ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED )) != - ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED )) { - rs->sr_entry = entry_dup( rs->sr_entry ); - rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED; + if ( rs_entry2modifiable( op, rs, on )) { a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad ); } - /* count values */ - for ( n = 0; !BER_BVISNULL( &a->a_vals[n] ); n++ ); - + n = a->a_numvals; if ( vi->vi_sort & VALSORT_WEIGHTED ) { int j, gotnvals; long *index = op->o_tmpalloc( n * sizeof(long), op->o_tmpmemctx ); @@ -284,7 +309,7 @@ valsort_response( Operation *op, SlapReply *rs ) gotnvals = (a->a_vals != a->a_nvals ); for (i=0; ia_nvals[i].bv_val, '{' ); + char *ptr = ber_bvchr( &a->a_nvals[i], '{' ); char *end = NULL; if ( !ptr ) { Debug(LDAP_DEBUG_TRACE, "weights missing from attr %s " @@ -309,7 +334,9 @@ valsort_response( Operation *op, SlapReply *rs ) if ( a->a_vals != a->a_nvals ) { ptr = a->a_vals[i].bv_val; - end = strchr( ptr, '}' ) + 1; + end = ber_bvchr( &a->a_vals[i], '}' ); + assert( end != NULL ); + end++; for (;*end;) *ptr++ = *end++; *ptr = '\0'; @@ -377,7 +404,7 @@ valsort_add( Operation *op, SlapReply *rs ) if ( !a ) continue; for (i=0; !BER_BVISNULL( &a->a_vals[i] ); i++) { - ptr = strchr(a->a_vals[i].bv_val, '{' ); + ptr = ber_bvchr(&a->a_vals[i], '{' ); if ( !ptr ) { Debug(LDAP_DEBUG_TRACE, "weight missing from attribute %s\n", vi->vi_ad->ad_cname.bv_val, 0, 0); @@ -415,13 +442,16 @@ valsort_modify( Operation *op, SlapReply *rs ) if ( !(vi->vi_sort & VALSORT_WEIGHTED )) continue; for (ml = op->orm_modlist; ml; ml=ml->sml_next ) { + /* Must be a Delete Attr op, so no values to consider */ + if ( !ml->sml_values ) + continue; if ( ml->sml_desc == vi->vi_ad ) break; } if ( !ml ) continue; for (i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++) { - ptr = strchr(ml->sml_values[i].bv_val, '{' ); + ptr = ber_bvchr(&ml->sml_values[i], '{' ); if ( !ptr ) { Debug(LDAP_DEBUG_TRACE, "weight missing from attribute %s\n", vi->vi_ad->ad_cname.bv_val, 0, 0); @@ -442,14 +472,28 @@ valsort_modify( Operation *op, SlapReply *rs ) return SLAP_CB_CONTINUE; } +static int +valsort_db_open( + BackendDB *be, + ConfigReply *cr +) +{ + return overlay_register_control( be, LDAP_CONTROL_VALSORT ); +} + static int valsort_destroy( - BackendDB *be + BackendDB *be, + ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; valsort_info *vi = on->on_bi.bi_private, *next; +#ifdef SLAP_CONFIG_DELETE + overlay_unregister_control( be, LDAP_CONTROL_VALSORT ); +#endif /* SLAP_CONFIG_DELETE */ + for (; vi; vi = next) { next = vi->vi_next; ch_free( vi->vi_dn.bv_val ); @@ -459,14 +503,50 @@ valsort_destroy( return 0; } +static int +valsort_parseCtrl( + Operation *op, + SlapReply *rs, + LDAPControl *ctrl ) +{ + ber_tag_t tag; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *)&berbuf; + ber_int_t flag = 0; + + if ( BER_BVISNULL( &ctrl->ldctl_value )) { + rs->sr_text = "valSort control value is absent"; + return LDAP_PROTOCOL_ERROR; + } + + if ( BER_BVISEMPTY( &ctrl->ldctl_value )) { + rs->sr_text = "valSort control value is empty"; + return LDAP_PROTOCOL_ERROR; + } + + ber_init2( ber, &ctrl->ldctl_value, 0 ); + if (( tag = ber_scanf( ber, "{b}", &flag )) == LBER_ERROR ) { + rs->sr_text = "valSort control: flag decoding error"; + return LDAP_PROTOCOL_ERROR; + } + + op->o_ctrlflag[valsort_cid] = ctrl->ldctl_iscritical ? + SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; + if ( flag ) + op->o_ctrlflag[valsort_cid] |= SLAP_CONTROL_DATA0; + + return LDAP_SUCCESS; +} + static slap_overinst valsort; -int valsort_init() +int valsort_initialize( void ) { - int i, rc; + int rc; valsort.on_bi.bi_type = "valsort"; valsort.on_bi.bi_db_destroy = valsort_destroy; + valsort.on_bi.bi_db_open = valsort_db_open; valsort.on_bi.bi_op_add = valsort_add; valsort.on_bi.bi_op_modify = valsort_modify; @@ -475,6 +555,16 @@ int valsort_init() valsort.on_bi.bi_cf_ocs = valsort_cfocs; + rc = register_supported_control( LDAP_CONTROL_VALSORT, + SLAP_CTRL_SEARCH | SLAP_CTRL_HIDE, NULL, valsort_parseCtrl, + &valsort_cid ); + if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, "Failed to register control %d\n", rc, 0, 0 ); + return rc; + } + + syn_numericString = syn_find( "1.3.6.1.4.1.1466.115.121.1.36" ); + rc = config_register_schema( valsort_cfats, valsort_cfocs ); if ( rc ) return rc; @@ -483,7 +573,7 @@ int valsort_init() #if SLAPD_OVER_VALSORT == SLAPD_MOD_DYNAMIC int init_module( int argc, char *argv[]) { - return valsort_init(); + return valsort_initialize(); } #endif