mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-01 20:49:35 -05:00
allow to set max passes per rule
This commit is contained in:
parent
9e86d9ffe2
commit
3994dc645a
5 changed files with 79 additions and 12 deletions
|
|
@ -332,8 +332,8 @@ server will possibly enforce additional restrictions to "foo".
|
|||
A string is rewritten according to a set of rules, called a `rewrite
|
||||
context'.
|
||||
The rules are based on Regular Expressions (POSIX regex) with
|
||||
substring matching; extensions are planned to allow basic variable
|
||||
substitution and map resolution of substrings.
|
||||
substring matching; basic variable substitution and map resolution
|
||||
of substrings is allowed by specific mechanisms detailed in the following.
|
||||
The behavior of pattern matching/substitution can be altered by a set
|
||||
of flags.
|
||||
.LP
|
||||
|
|
@ -341,14 +341,17 @@ The underlying concept is to build a lightweight rewrite module
|
|||
for the slapd server (initially dedicated to the LDAP backend).
|
||||
.SH Passes
|
||||
An incoming string is matched agains a set of rules.
|
||||
Rules are made of a match pattern, a substitution pattern and a set of
|
||||
actions.
|
||||
Rules are made of a regex match pattern, a substitution pattern
|
||||
and a set of actions, described by a set of flags.
|
||||
In case of match a string rewriting is performed according to the
|
||||
substitution pattern that allows to refer to substrings matched in the
|
||||
incoming string.
|
||||
The actions, if any, are finally performed.
|
||||
The substitution pattern allows map resolution of substrings.
|
||||
A map is a generic object that maps a substitution pattern to a value.
|
||||
The flags are divided in "Pattern matching Flags" and "Action Flags";
|
||||
the former alter the regex match pattern behaviorm while the latter
|
||||
alter the action that is taken after substitution.
|
||||
.SH "Pattern Matching Flags"
|
||||
.TP
|
||||
.B `C'
|
||||
|
|
@ -356,6 +359,12 @@ honors case in matching (default is case insensitive)
|
|||
.TP
|
||||
.B `R'
|
||||
use POSIX Basic Regular Expressions (default is Extended)
|
||||
.TP
|
||||
.B `M{n}'
|
||||
allow no more than
|
||||
.B n
|
||||
recursive passes for a specific rule; does not alter the max total count
|
||||
of passes, so it can only enforce a stricter limit for a specific rule.
|
||||
.SH "Action Flags"
|
||||
.TP
|
||||
.B `:'
|
||||
|
|
@ -398,7 +407,7 @@ or, in other words, `@' is equivalent to `U{0}'.
|
|||
By convention, the freely available codes are above 16 included;
|
||||
the others are reserved.
|
||||
.LP
|
||||
The ordering of the flags is significant.
|
||||
The ordering of the flags can be significant.
|
||||
For instance: `IG{2}' means ignore errors and jump two lines ahead
|
||||
both in case of match and in case of error, while `G{2}I' means ignore
|
||||
errors, but jump two lines ahead only in case of match.
|
||||
|
|
@ -549,7 +558,7 @@ In this case the alias context contains no rule, and any reference to
|
|||
it will result in accessing the aliased one.
|
||||
.TP
|
||||
.B rewriteRule "<regex match pattern>" "<substitution pattern>" "[ <flags> ]"
|
||||
Determines how a tring can be rewritten if a pattern is matched.
|
||||
Determines how a string can be rewritten if a pattern is matched.
|
||||
Examples are reported below.
|
||||
.SH "Additional configuration syntax:"
|
||||
.TP
|
||||
|
|
@ -562,9 +571,16 @@ The map is referenced inside the substitution pattern of a rule.
|
|||
Sets a value with global scope, that can be dereferenced by the
|
||||
command `%{$paramName}'.
|
||||
.TP
|
||||
.B rewriteMaxPasses <number of passes>
|
||||
.B rewriteMaxPasses <number of passes> [<number of passes per rule>]
|
||||
Sets the maximum number of total rewriting passes that can be
|
||||
performed in a single rewrite operation (to avoid loops).
|
||||
A safe default is set to 100; note that reaching this limit is still
|
||||
treated as a success; recursive invocation of rules is simply
|
||||
interrupted.
|
||||
The count applies to the rewriting operation as a whole, not
|
||||
to any single rule; an optional per-rule limit can be set.
|
||||
This limit is overridden by setting specific per-rule limits
|
||||
with the `M{n}' flag.
|
||||
.SH "Configuration examples:"
|
||||
.nf
|
||||
# set to `off' to disable rewriting
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ rewrite_parse_builtin_map(
|
|||
* lines handled are of the form:
|
||||
*
|
||||
* rewriteEngine {on|off}
|
||||
* rewriteMaxPasses numPasses
|
||||
* rewriteMaxPasses numPasses [numPassesPerRule]
|
||||
* rewriteContext contextName [alias aliasedContextName]
|
||||
* rewriteRule pattern substPattern [ruleFlags]
|
||||
* rewriteMap mapType mapName [mapArgs]
|
||||
|
|
@ -103,7 +103,25 @@ rewrite_parse(
|
|||
fname, lineno, "" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
info->li_max_passes = atoi( argv[ 1 ] );
|
||||
if ( info->li_max_passes <= 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"[%s:%d] negative or null rewriteMaxPasses'\n",
|
||||
fname, lineno, 0 );
|
||||
}
|
||||
|
||||
if ( argc > 2 ) {
|
||||
info->li_max_passes_per_rule = atoi( argv[ 2 ] );
|
||||
if ( info->li_max_passes_per_rule <= 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"[%s:%d] negative or null rewriteMaxPassesPerRule'\n",
|
||||
fname, lineno, 0 );
|
||||
}
|
||||
|
||||
} else {
|
||||
info->li_max_passes_per_rule = info->li_max_passes;
|
||||
}
|
||||
rc = REWRITE_SUCCESS;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ rewrite_info_init(
|
|||
|
||||
info->li_state = REWRITE_DEFAULT;
|
||||
info->li_max_passes = REWRITE_MAX_PASSES;
|
||||
info->li_max_passes_per_rule = REWRITE_MAX_PASSES;
|
||||
info->li_rewrite_mode = mode;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@
|
|||
#define REWRITE_FLAG_UNWILLING '#'
|
||||
#define REWRITE_FLAG_GOTO 'G' /* requires an arg */
|
||||
#define REWRITE_FLAG_USER 'U' /* requires an arg */
|
||||
#define REWRITE_FLAG_MAX_PASSES 'M' /* requires an arg */
|
||||
#define REWRITE_FLAG_IGNORE_ERR 'I'
|
||||
|
||||
/*
|
||||
|
|
@ -219,6 +220,7 @@ struct rewrite_rule {
|
|||
#define REWRITE_RECURSE 0x0001
|
||||
#define REWRITE_EXEC_ONCE 0x0002
|
||||
int lr_mode;
|
||||
int lr_max_passes;
|
||||
|
||||
struct rewrite_action *lr_action;
|
||||
};
|
||||
|
|
@ -304,6 +306,7 @@ struct rewrite_info {
|
|||
*/
|
||||
#define REWRITE_MAXPASSES 100
|
||||
int li_max_passes;
|
||||
int li_max_passes_per_rule;
|
||||
|
||||
/*
|
||||
* Behavior in case a NULL or non-existent context is required
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ rewrite_rule_compile(
|
|||
{
|
||||
int flags = REWRITE_REGEX_EXTENDED | REWRITE_REGEX_ICASE;
|
||||
int mode = REWRITE_RECURSE;
|
||||
int max_passes = info->li_max_passes_per_rule;
|
||||
|
||||
struct rewrite_rule *rule = NULL;
|
||||
struct rewrite_subst *subst = NULL;
|
||||
|
|
@ -264,6 +265,33 @@ rewrite_rule_compile(
|
|||
break;
|
||||
}
|
||||
|
||||
case REWRITE_FLAG_MAX_PASSES: { /* 'U' */
|
||||
/*
|
||||
* Set the number of max passes per rule
|
||||
*/
|
||||
char *next = NULL;
|
||||
|
||||
if ( p[ 1 ] != '{' ) {
|
||||
/* XXX Need to free stuff */
|
||||
return REWRITE_ERR;
|
||||
}
|
||||
|
||||
max_passes = strtol( &p[ 2 ], &next, 0 );
|
||||
if ( next == NULL || next == &p[ 2 ] || next[0] != '}' ) {
|
||||
/* XXX Need to free stuff */
|
||||
return REWRITE_ERR;
|
||||
}
|
||||
|
||||
if ( max_passes < 1 ) {
|
||||
/* FIXME: nonsense ... */
|
||||
max_passes = 1;
|
||||
}
|
||||
|
||||
p = next; /* p is incremented by the for ... */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case REWRITE_FLAG_IGNORE_ERR: /* 'I' */
|
||||
/*
|
||||
* Ignore errors!
|
||||
|
|
@ -337,6 +365,7 @@ rewrite_rule_compile(
|
|||
*/
|
||||
rule->lr_flags = flags; /* don't really need any longer ... */
|
||||
rule->lr_mode = mode;
|
||||
rule->lr_max_passes = max_passes;
|
||||
rule->lr_action = first_action;
|
||||
|
||||
/*
|
||||
|
|
@ -387,8 +416,8 @@ rewrite_rule_apply(
|
|||
recurse:;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "==> rewrite_rule_apply"
|
||||
" rule='%s' string='%s'\n",
|
||||
rule->lr_pattern, string, 0 );
|
||||
" rule='%s' string='%s' [%s pass(es)]\n",
|
||||
rule->lr_pattern, string, strcnt + 1 );
|
||||
|
||||
op->lo_num_passes++;
|
||||
if ( regexec( &rule->lr_regex, string, nmatch, match, 0 ) != 0 ) {
|
||||
|
|
@ -418,9 +447,9 @@ recurse:;
|
|||
}
|
||||
|
||||
if ( ( rule->lr_mode & REWRITE_RECURSE ) == REWRITE_RECURSE
|
||||
&& op->lo_num_passes <= info->li_max_passes ) {
|
||||
&& op->lo_num_passes < info->li_max_passes
|
||||
&& ++strcnt < rule->lr_max_passes ) {
|
||||
string = *result;
|
||||
strcnt++;
|
||||
|
||||
goto recurse;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue