⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 valsort.c

📁 ldap服务器源码
💻 C
字号:
/* valsort.c - sort attribute values *//* $OpenLDAP: pkg/ldap/servers/slapd/overlays/valsort.c,v 1.9.2.6 2007/01/02 21:44:09 kurt Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 2005-2007 The OpenLDAP Foundation. * Portions copyright 2005 Symas Corporation. * 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>. *//* ACKNOWLEDGEMENTS: * This work was initially developed by Howard Chu for inclusion in * OpenLDAP Software. This work was sponsored by Stanford University. *//* * This overlay sorts the values of multi-valued attributes when returning * them in a search response. */#include "portable.h"#ifdef SLAPD_OVER_VALSORT#include <stdio.h>#include <ac/string.h>#include <ac/ctype.h>#include "slap.h"#include "config.h"#include "lutil.h"#define	VALSORT_ASCEND	0#define	VALSORT_DESCEND	1#define	VALSORT_ALPHA	2#define	VALSORT_NUMERIC	4#define	VALSORT_WEIGHTED	8typedef struct valsort_info {	struct valsort_info *vi_next;	struct berval vi_dn;	AttributeDescription *vi_ad;	slap_mask_t vi_sort;} valsort_info;static int valsort_cid;static ConfigDriver valsort_cf_func;static ConfigTable valsort_cfats[] = {	{ "valsort-attr", "attribute> <dn> <sort-type", 4, 5, 0, ARG_MAGIC,		valsort_cf_func, "( OLcfgOvAt:5.1 NAME 'olcValSortAttr' "			"DESC 'Sorting rule for attribute under given DN' "			"EQUALITY caseIgnoreMatch "			"SYNTAX OMsDirectoryString )", NULL, NULL },	{ NULL }};static ConfigOCs valsort_cfocs[] = {	{ "( OLcfgOvOc:5.1 "		"NAME 'olcValSortConfig' "		"DESC 'Value Sorting configuration' "		"SUP olcOverlayConfig "		"MUST olcValSortAttr )",			Cft_Overlay, valsort_cfats },	{ NULL }};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-descend"), VALSORT_DESCEND|VALSORT_NUMERIC },	{ BER_BVC("weighted"), VALSORT_WEIGHTED },	{ BER_BVNULL, 0 }};static Syntax *syn_numericString;static intvalsort_cf_func(ConfigArgs *c) {	slap_overinst *on = (slap_overinst *)c->bi;	valsort_info vitmp, *vi;	const char *text = NULL;	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 ) {			struct berval bv2 = BER_BVNULL, bvret;			char *ptr;			int len;						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;			}			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 = lutil_strcopy( bvret.bv_val, vi->vi_ad->ad_cname.bv_val );			*ptr++ = ' ';			*ptr++ = '"';			ptr = lutil_strcopy( ptr, vi->vi_dn.bv_val );			*ptr++ = '"';			if ( vi->vi_sort & VALSORT_WEIGHTED ) {				*ptr++ = ' ';				ptr = lutil_strcopy( ptr, bv2.bv_val );			}			if ( i ) {				*ptr++ = ' ';				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 = on->on_bi.bi_private ) {				on->on_bi.bi_private = vi->vi_next;				ch_free( vi->vi_dn.bv_val );				ch_free( vi );			}		} else {			valsort_info **prev;			for (i=0, prev = (valsort_info **)&on->on_bi.bi_private,				vi = *prev; vi && i<c->valx;				prev = &vi->vi_next, vi = vi->vi_next, i++ );			(*prev)->vi_next = vi->vi_next;			ch_free( vi->vi_dn.bv_val );			ch_free( vi );		}		return 0;	}	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 );		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",			c->log, c->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],			vitmp.vi_ad->ad_cname.bv_val );		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",			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 ) {		sprintf( c->msg, "<%s> unable to normalize DN", c->argv[0] );		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",			c->log, c->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] );		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",			c->log, c->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] );			Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",				c->log, c->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",			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;	on->on_bi.bi_private = vi;	return 0;}/* Use Insertion Sort algorithm on selected values */static voiddo_sort( Operation *op, Attribute *a, int beg, int num, slap_mask_t sort ){	int i, j, gotnvals;	struct berval tmp, ntmp, *vals = NULL, *nvals;	gotnvals = (a->a_vals != a->a_nvals );	nvals = a->a_nvals + beg;	if ( gotnvals )		vals = a->a_vals + beg;	if ( sort & VALSORT_NUMERIC ) {		long *numbers = op->o_tmpalloc( num * sizeof(long), op->o_tmpmemctx ),			idx;		for (i=0; i<num; i++)			numbers[i] = strtol( nvals[i].bv_val, NULL, 0 );		for (i=1; i<num; i++) {			idx = numbers[i];			ntmp = nvals[i];			if ( gotnvals ) tmp = vals[i];			j = i;			while ( j>0 ) {				int cmp = (sort & VALSORT_DESCEND) ? numbers[j-1] < idx :					numbers[j-1] > idx;				if ( !cmp ) break;				numbers[j] = numbers[j-1];				nvals[j] = nvals[j-1];				if ( gotnvals ) vals[j] = vals[j-1];				j--;			}			numbers[j] = idx;			nvals[j] = ntmp;			if ( gotnvals ) vals[j] = tmp;		}		op->o_tmpfree( numbers, op->o_tmpmemctx );	} else {		for (i=1; i<num; i++) {			ntmp = nvals[i];			if ( gotnvals ) tmp = vals[i];			j = i;			while ( j>0 ) {				int cmp = strcmp( nvals[j-1].bv_val, ntmp.bv_val );				cmp = (sort & VALSORT_DESCEND) ? (cmp < 0) : (cmp > 0);				if ( !cmp ) break;				nvals[j] = nvals[j-1];				if ( gotnvals ) vals[j] = vals[j-1];				j--;			}			nvals[j] = ntmp;			if ( gotnvals ) vals[j] = tmp;		}	}}static intvalsort_response( Operation *op, SlapReply *rs ){	slap_overinst *on;	valsort_info *vi;	Attribute *a;	/* 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;	/* And we must have something configured */	if ( !vi ) return SLAP_CB_CONTINUE;	/* Find a rule whose baseDN matches this entry */	for (; vi; vi = vi->vi_next ) {		int i, n;		if ( !dnIsSuffix( &rs->sr_entry->e_nname, &vi->vi_dn ))			continue;		/* Find attr that this rule affects */		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;			a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad );		}		/* count values */		for ( n = 0; !BER_BVISNULL( &a->a_vals[n] ); n++ );		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 = ber_bvchr( &a->a_nvals[i], '{' );				char *end = NULL;				if ( !ptr ) {					Debug(LDAP_DEBUG_TRACE, "weights missing from attr %s "						"in entry %s\n", vi->vi_ad->ad_cname.bv_val,						rs->sr_entry->e_name.bv_val, 0 );					break;				}				index[i] = strtol( ptr+1, &end, 0 );				if ( *end != '}' ) {					Debug(LDAP_DEBUG_TRACE, "weights misformatted "						"in entry %s\n", 						rs->sr_entry->e_name.bv_val, 0, 0 );					break;				}				/* Strip out weights */				ptr = a->a_nvals[i].bv_val;				end++;				for (;*end;)					*ptr++ = *end++;				*ptr = '\0';				a->a_nvals[i].bv_len = ptr - a->a_nvals[i].bv_val;				if ( a->a_vals != a->a_nvals ) {					ptr = a->a_vals[i].bv_val;					end = ber_bvchr( &a->a_vals[i], '}' );					assert( end != NULL );					end++;					for (;*end;)						*ptr++ = *end++;					*ptr = '\0';					a->a_vals[i].bv_len = ptr - a->a_vals[i].bv_val;				}			}			/* An attr was missing weights here, ignore it */			if ( i<n ) {				op->o_tmpfree( index, op->o_tmpmemctx );				continue;			}			/* Insertion sort */			for ( i=1; i<n; i++) {				long idx = index[i];				struct berval tmp = a->a_vals[i], ntmp;				if ( gotnvals ) ntmp = a->a_nvals[i];				j = i;				while (( j>0 ) && (index[j-1] > idx )) {					index[j] = index[j-1];					a->a_vals[j] = a->a_vals[j-1];					if ( gotnvals ) a->a_nvals[j] = a->a_nvals[j-1];					j--;				}				index[j] = idx;				a->a_vals[j] = tmp;				if ( gotnvals ) a->a_nvals[j] = ntmp;			}			/* Check for secondary sort */			if ( vi->vi_sort ^ VALSORT_WEIGHTED ) {				for ( i=0; i<n;) {					for (j=i+1; j<n; j++) {						if (index[i] != index[j])							break;					}					if( j-i > 1 )						do_sort( op, a, i, j-i, vi->vi_sort );					i = j;				}			}			op->o_tmpfree( index, op->o_tmpmemctx );		} else {			do_sort( op, a, 0, n, vi->vi_sort );		}	}	return SLAP_CB_CONTINUE;}static intvalsort_add( Operation *op, SlapReply *rs ){	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;	valsort_info *vi = on->on_bi.bi_private;	Attribute *a;	int i;	char *ptr, *end;	/* See if any weighted sorting applies to this entry */	for ( ;vi;vi=vi->vi_next ) {		if ( !dnIsSuffix( &op->o_req_ndn, &vi->vi_dn ))			continue;		if ( !(vi->vi_sort & VALSORT_WEIGHTED ))			continue;		a = attr_find( op->ora_e->e_attrs, vi->vi_ad );		if ( !a )			continue;		for (i=0; !BER_BVISNULL( &a->a_vals[i] ); i++) {			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);				send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION,					"weight missing from attribute" );				return rs->sr_err;			}			strtol( ptr+1, &end, 0 );			if ( *end != '}' ) {				Debug(LDAP_DEBUG_TRACE, "weight is misformatted in %s\n",					vi->vi_ad->ad_cname.bv_val, 0, 0);				send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION,					"weight is misformatted" );				return rs->sr_err;			}		}	}	return SLAP_CB_CONTINUE;}static intvalsort_modify( Operation *op, SlapReply *rs ){	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;	valsort_info *vi = on->on_bi.bi_private;	Modifications *ml;	int i;	char *ptr, *end;	/* See if any weighted sorting applies to this entry */	for ( ;vi;vi=vi->vi_next ) {		if ( !dnIsSuffix( &op->o_req_ndn, &vi->vi_dn ))			continue;		if ( !(vi->vi_sort & VALSORT_WEIGHTED ))			continue;		for (ml = op->orm_modlist; ml; ml=ml->sml_next ) {			if ( ml->sml_desc == vi->vi_ad )				break;		}		if ( !ml )			continue;		for (i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++) {			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);				send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION,					"weight missing from attribute" );				return rs->sr_err;			}			strtol( ptr+1, &end, 0 );			if ( *end != '}' ) {				Debug(LDAP_DEBUG_TRACE, "weight is misformatted in %s\n",					vi->vi_ad->ad_cname.bv_val, 0, 0);				send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION,					"weight is misformatted" );				return rs->sr_err;			}		}	}	return SLAP_CB_CONTINUE;}static intvalsort_db_open(	BackendDB *be){	return overlay_register_control( be, LDAP_CONTROL_VALSORT );}static intvalsort_destroy(	BackendDB *be){	slap_overinst *on = (slap_overinst *)be->bd_info;	valsort_info *vi = on->on_bi.bi_private, *next;	for (; vi; vi = next) {		next = vi->vi_next;		ch_free( vi->vi_dn.bv_val );		ch_free( vi );	}	return 0;}static intvalsort_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_initialize( void ){	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_response = valsort_response;	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;	return overlay_register(&valsort);}#if SLAPD_OVER_VALSORT == SLAPD_MOD_DYNAMICint init_module( int argc, char *argv[]) {	return valsort_initialize();}#endif#endif /* SLAPD_OVER_VALSORT */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -