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 }
};
+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;
+ int i, is_numeric;
struct berval bv = BER_BVNULL;
if ( c->op == SLAP_CONFIG_EMIT ) {
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;
*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 );
c->log, c->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 ) {
}
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",
+ c->argv[0] );
+ Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
+ c->log, c->msg, c->argv[1] );
+ return(1);
+ }
vi = ch_malloc( sizeof(valsort_info) );
*vi = vitmp;
vi->vi_next = on->on_bi.bi_private;
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;
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 ( !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
+)
+{
+ return overlay_register_control( be, LDAP_CONTROL_VALSORT );
+}
+
static int
valsort_destroy(
BackendDB *be
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 ( ctrl->ldctl_value.bv_len == 0 ) {
+ rs->sr_text = "valSort control value is empty (or absent)";
+ 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 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 ( rc ) return rc;