/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2005 The OpenLDAP Foundation.
+ * Copyright 2005-2009 The OpenLDAP Foundation.
* Portions copyright 2005 Symas Corporation.
* All rights reserved.
*
slap_mask_t vi_sort;
} valsort_info;
+static int valsort_cid;
+
static ConfigDriver valsort_cf_func;
static ConfigTable valsort_cfats[] = {
{ 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 }
};
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;
}
- BER_BVZERO( &bv );
- 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;
*ptr++ = ' ';
ptr = lutil_strcopy( ptr, bv2.bv_val );
}
- if ( !BER_BVISNULL( &bv )) {
+ if ( i ) {
*ptr++ = ' ';
strcpy( ptr, bv.bv_val );
}
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 );
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 )) {
- sprintf( c->msg, "<%s> %s is single-valued, ignoring", c->argv[0],
+ 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->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return(0);
}
is_numeric = ( vitmp.vi_ad->ad_type->sat_syntax == syn_numericString ||
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 ) {
- sprintf( c->msg, "<%s> numeric sort specified for non-numeric syntax",
+ 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->msg, c->argv[1] );
+ c->log, c->cr_msg, c->argv[1] );
return(1);
}
vi = ch_malloc( sizeof(valsort_info) );
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 );
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;
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 );
+ if (( rs->sr_flags & ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) ) !=
+ ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) )
+ {
+ Entry *e;
+
+ e = entry_dup( rs->sr_entry );
+ if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
+ overlay_entry_release_ov( op, rs->sr_entry, 0, on );
+ rs->sr_flags &= ~REP_ENTRY_MUSTRELEASE;
+ } else if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
+ entry_free( rs->sr_entry );
+ }
+ rs->sr_entry = e;
rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED;
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 );
gotnvals = (a->a_vals != a->a_nvals );
for (i=0; i<n; i++) {
- char *ptr = strchr( a->a_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 "
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';
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);
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);
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;
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;
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 ) {
+ fprintf( stderr, "Failed to register control %d\n", rc );
+ 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 SLAPD_OVER_VALSORT == SLAPD_MOD_DYNAMIC
int init_module( int argc, char *argv[]) {
- return valsort_init();
+ return valsort_initialize();
}
#endif