Esempio n. 1
0
/*
 * Substitutes a portion of rewritten string according to substitution
 * pattern using submatches
 */
int
rewrite_subst_apply(
		struct rewrite_info *info,
		struct rewrite_op *op,
		struct rewrite_subst *subst,
		const char *string,
		const regmatch_t *match,
		struct berval *val
)
{
	struct berval *submatch = NULL;
	char *res = NULL;
	int n = 0, l, cl;
	int rc = REWRITE_REGEXEC_OK;

	assert( info != NULL );
	assert( op != NULL );
	assert( subst != NULL );
	assert( string != NULL );
	assert( match != NULL );
	assert( val != NULL );

	assert( val->bv_val == NULL );

	val->bv_val = NULL;
	val->bv_len = 0;

	/*
	 * Prepare room for submatch expansion
	 */
	if ( subst->lt_num_submatch > 0 ) {
		submatch = calloc( sizeof( struct berval ),
				subst->lt_num_submatch );
		if ( submatch == NULL ) {
			return REWRITE_REGEXEC_ERR;
		}
	}
	
	/*
	 * Resolve submatches (simple subst, map expansion and so).
	 */
	for ( n = 0, l = 0; n < subst->lt_num_submatch; n++ ) {
		struct berval	key = { 0, NULL };

		submatch[ n ].bv_val = NULL;
		
		/*
		 * Get key
		 */
		switch ( subst->lt_submatch[ n ].ls_type ) {
		case REWRITE_SUBMATCH_ASIS:
		case REWRITE_SUBMATCH_XMAP:
			rc = submatch_copy( &subst->lt_submatch[ n ],
					string, match, &key );
			if ( rc != REWRITE_SUCCESS ) {
				rc = REWRITE_REGEXEC_ERR;
				goto cleanup;
			}
			break;
			
		case REWRITE_SUBMATCH_MAP_W_ARG:
			switch ( subst->lt_submatch[ n ].ls_map->lm_type ) {
			case REWRITE_MAP_GET_OP_VAR:
			case REWRITE_MAP_GET_SESN_VAR:
			case REWRITE_MAP_GET_PARAM:
				rc = REWRITE_SUCCESS;
				break;

			default:
				rc = rewrite_subst_apply( info, op, 
					subst->lt_submatch[ n ].ls_map->lm_subst,
					string, match, &key);
			}
			
			if ( rc != REWRITE_SUCCESS ) {
				goto cleanup;
			}
			break;

		default:
			Debug( LDAP_DEBUG_ANY, "Not Implemented\n", 0, 0, 0 );
			rc = REWRITE_ERR;
			break;
		}
		
		if ( rc != REWRITE_SUCCESS ) {
			rc = REWRITE_REGEXEC_ERR;
			goto cleanup;
		}

		/*
		 * Resolve key
		 */
		switch ( subst->lt_submatch[ n ].ls_type ) {
		case REWRITE_SUBMATCH_ASIS:
			submatch[ n ] = key;
			rc = REWRITE_SUCCESS;
			break;
			
		case REWRITE_SUBMATCH_XMAP:
			rc = rewrite_xmap_apply( info, op,
					subst->lt_submatch[ n ].ls_map,
					&key, &submatch[ n ] );
			free( key.bv_val );
			key.bv_val = NULL;
			break;
			
		case REWRITE_SUBMATCH_MAP_W_ARG:
			rc = rewrite_map_apply( info, op,
					subst->lt_submatch[ n ].ls_map,
					&key, &submatch[ n ] );
			free( key.bv_val );
			key.bv_val = NULL;
			break;

		default:
			/*
			 * When implemented, this might return the
                         * exit status of a rewrite context,
                         * which may include a stop, or an
                         * unwilling to perform
                         */
			rc = REWRITE_ERR;
			break;
		}

		if ( rc != REWRITE_SUCCESS ) {
			rc = REWRITE_REGEXEC_ERR;
			goto cleanup;
		}
		
		/*
                 * Increment the length of the resulting string
                 */
		l += submatch[ n ].bv_len;
	}
	
	/*
         * Alloc result buffer
         */
	l += subst->lt_subs_len;
	res = malloc( l + 1 );
	if ( res == NULL ) {
		rc = REWRITE_REGEXEC_ERR;
		goto cleanup;
	}

	/*
	 * Apply submatches (possibly resolved thru maps)
	 */
        for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) {
		if ( subst->lt_subs[ n ].bv_val != NULL ) {
                	AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
					subst->lt_subs[ n ].bv_len );
			cl += subst->lt_subs[ n ].bv_len;
		}
		AC_MEMCPY( res + cl, submatch[ n ].bv_val, 
				submatch[ n ].bv_len );
		cl += submatch[ n ].bv_len;
	}
	if ( subst->lt_subs[ n ].bv_val != NULL ) {
		AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
				subst->lt_subs[ n ].bv_len );
		cl += subst->lt_subs[ n ].bv_len;
	}
	res[ cl ] = '\0';

	val->bv_val = res;
	val->bv_len = l;

cleanup:;
	if ( submatch ) {
        	for ( ; --n >= 0; ) {
			if ( submatch[ n ].bv_val ) {
				free( submatch[ n ].bv_val );
			}
		}
		free( submatch );
	}

	return rc;
}
Esempio n. 2
0
/*
 * Rewrites string according to rule; may return:
 *      OK:     fine; if *result != NULL rule matched and rewrite succeeded.
 *      STOP:   fine, rule matched; stop processing following rules
 *      UNWILL: rule matched; force 'unwilling to perform'
 */
int
rewrite_rule_apply(
		struct rewrite_info *info,
		struct rewrite_op *op,
		struct rewrite_rule *rule,
		const char *arg,
		char **result
		)
{
	size_t nmatch = REWRITE_MAX_MATCH;
	regmatch_t match[ REWRITE_MAX_MATCH ];

	int rc = REWRITE_SUCCESS;

	char *string;
	int strcnt = 0;
	struct berval val = { 0, NULL };

	assert( info != NULL );
	assert( op != NULL );
	assert( rule != NULL );
	assert( arg != NULL );
	assert( result != NULL );

	*result = NULL;

	string = (char *)arg;
	
	/*
	 * In case recursive match is required (default)
	 */
recurse:;

	Debug( LDAP_DEBUG_TRACE, "==> rewrite_rule_apply"
			" rule='%s' string='%s' [%d pass(es)]\n", 
			rule->lr_pattern, string, strcnt + 1 );
	
	op->lo_num_passes++;

	rc = regexec( &rule->lr_regex, string, nmatch, match, 0 );
	if ( rc != 0 ) {
		if ( *result == NULL && string != arg ) {
			free( string );
		}

		/*
		 * No match is OK; *result = NULL means no match
		 */
		return REWRITE_REGEXEC_OK;
	}

	rc = rewrite_subst_apply( info, op, rule->lr_subst, string,
			match, &val );

	*result = val.bv_val;
	val.bv_val = NULL;
	if ( string != arg ) {
		free( string );
		string = NULL;
	}

	if ( rc != REWRITE_REGEXEC_OK ) {
		return rc;
	}

	if ( ( rule->lr_mode & REWRITE_RECURSE ) == REWRITE_RECURSE 
			&& op->lo_num_passes < info->li_max_passes
			&& ++strcnt < rule->lr_max_passes ) {
		string = *result;

		goto recurse;
	}

	return REWRITE_REGEXEC_OK;
}