diff --git a/src/lib-sieve/plugins/regex/mcht-regex.c b/src/lib-sieve/plugins/regex/mcht-regex.c index c3156f36ce1945f9fb27644ce7fb088b2170fc91..1c631e174f4f9e385369112af91cc98814f09228 100644 --- a/src/lib-sieve/plugins/regex/mcht-regex.c +++ b/src/lib-sieve/plugins/regex/mcht-regex.c @@ -20,6 +20,11 @@ #include <ctype.h> #include <regex.h> +/* + * Configuration + */ + +#define MCHT_REGEX_MAX_SUBSTITUTIONS 64 /* * Forward declarations */ @@ -108,7 +113,7 @@ bool mcht_regex_validate_context if ( sieve_comparator_tag_is(carg, &i_ascii_casemap_comparator) ) cflags = REG_EXTENDED | REG_NOSUB | REG_ICASE; else if ( sieve_comparator_tag_is(carg, &i_octet_comparator) ) - cflags = REG_EXTENDED | REG_NOSUB ; + cflags = REG_EXTENDED | REG_NOSUB; else { sieve_command_validate_error(validator, ctx->command_ctx, "regex match type only supports " @@ -121,7 +126,7 @@ bool mcht_regex_validate_context carg = sieve_ast_argument_next(carg); } - + /* Validate regular expression(s) */ if ( sieve_ast_argument_type(key_arg) == SAAT_STRING ) { /* Single string */ @@ -156,6 +161,9 @@ bool mcht_regex_validate_context struct mcht_regex_context { ARRAY_DEFINE(reg_expressions, regex_t *); int value_index; + struct sieve_match_values *mvalues; + regmatch_t *pmatch; + size_t nmatch; }; void mcht_regex_match_init @@ -167,7 +175,15 @@ void mcht_regex_match_init t_array_init(&ctx->reg_expressions, 4); ctx->value_index = -1; - + ctx->mvalues = sieve_match_values_start(mctx->interp); + if ( ctx->mvalues != NULL ) { + ctx->pmatch = t_new(regmatch_t, MCHT_REGEX_MAX_SUBSTITUTIONS); + ctx->nmatch = MCHT_REGEX_MAX_SUBSTITUTIONS; + } else { + ctx->pmatch = NULL; + ctx->nmatch = 0; + } + mctx->data = (void *) ctx; } @@ -182,17 +198,19 @@ static regex_t *mcht_regex_get int cflags; if ( ctx->value_index <= 0 ) { - regexp = p_new(pool_datastack_create(), regex_t, 1); + regexp = t_new(regex_t, 1); if ( cmp == &i_octet_comparator ) - cflags = REG_EXTENDED | REG_NOSUB; + cflags = REG_EXTENDED; else if ( cmp == &i_ascii_casemap_comparator ) - cflags = REG_EXTENDED | REG_NOSUB | REG_ICASE; + cflags = REG_EXTENDED | REG_ICASE; else return NULL; + + if ( ctx->mvalues == NULL ) cflags |= REG_NOSUB; if ( (ret=regcomp(regexp, key, cflags)) != 0 ) { - /* FIXME: Do something useful, i.e. report error somewhere */ + /* FIXME: Do something useful, i.e. report error somewhere */ return NULL; } @@ -219,7 +237,28 @@ static bool mcht_regex_match regexp = mcht_regex_get(ctx, mctx->comparator, key, key_index); - return ( regexec(regexp, val, 0, NULL, 0) == 0 ); + if ( regexec(regexp, val, ctx->nmatch, ctx->pmatch, 0) == 0 ) { + size_t i; + int skipped = 0; + string_t *subst = t_str_new(32); + + for ( i = 0; i < ctx->nmatch; i++ ) { + str_truncate(subst, 0); + + if ( ctx->pmatch[i].rm_so != -1 ) { + if ( skipped > 0 ) + sieve_match_values_skip(ctx->mvalues, skipped); + + str_append_n(subst, val + ctx->pmatch[i].rm_so, + ctx->pmatch[i].rm_eo - ctx->pmatch[i].rm_so); + sieve_match_values_add(ctx->mvalues, subst); + } else + skipped++; + } + return TRUE; + } + + return FALSE; } bool mcht_regex_match_deinit diff --git a/src/lib-sieve/plugins/variables/Makefile.am b/src/lib-sieve/plugins/variables/Makefile.am index 413a0b17080f3147b963604a2eae709ccfb51418..afcc3401ac20bd4d37681c22cada3d01f53b8a5d 100644 --- a/src/lib-sieve/plugins/variables/Makefile.am +++ b/src/lib-sieve/plugins/variables/Makefile.am @@ -22,6 +22,6 @@ libsieve_ext_variables_la_SOURCES = \ noinst_HEADERS = \ ext-variables-common.h \ - ext-variables-name.h - + ext-variables-name.h \ + sieve-ext-variables.h diff --git a/src/lib-sieve/plugins/variables/variables-regex.sieve b/src/lib-sieve/plugins/variables/variables-regex.sieve new file mode 100644 index 0000000000000000000000000000000000000000..263be5ea78761710ab47c6cf6110af557545e1d7 --- /dev/null +++ b/src/lib-sieve/plugins/variables/variables-regex.sieve @@ -0,0 +1,18 @@ +require "variables"; +require "regex"; +require "fileinto"; + +set "match1" "Hutseflutsfropfrml"; + +if string :regex "${match1}" "Hutse(.+)fropfrml" { + fileinto "${0}:${1}:${2}"; +} + +if string :regex "${match1}" "(.+)f((.+)f(.+))f(.+)" { + fileinto "${0}:${1}:${2}:${3}:${4}:${5}"; +} + +if string :regex "${match1}" "(.+)((g(.+)friep)|(f(.+)frop))(.+)" { + fileinto "${0}:${1}:${2}:${3}:${4}:${5}:${6}:${7}"; +} + diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c index 5c901e12e00a37f97b1e1b70cbdb31d023c1b966..079b2fe75f1a70f5c857445dbdd64c7d07802c33 100644 --- a/src/lib-sieve/sieve-match-types.c +++ b/src/lib-sieve/sieve-match-types.c @@ -303,6 +303,15 @@ void sieve_match_values_add_char str_append_c(entry, c); } +void sieve_match_values_skip + (struct sieve_match_values *mvalues, int num) +{ + int i; + + for ( i = 0; i < num; i++ ) + (void) sieve_match_values_add_entry(mvalues); +} + void sieve_match_values_get (struct sieve_interpreter *interp, unsigned int index, string_t **value_r) { diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h index 96263f63d4066da876c6088cb812d6dd43c1e8d7..f4d358c4f9877f8d1a5c9aa29070799a1e19c9e1 100644 --- a/src/lib-sieve/sieve-match-types.h +++ b/src/lib-sieve/sieve-match-types.h @@ -83,6 +83,8 @@ void sieve_match_values_add (struct sieve_match_values *mvalues, string_t *value); void sieve_match_values_add_char (struct sieve_match_values *mvalues, char c); +void sieve_match_values_skip + (struct sieve_match_values *mvalues, int num); void sieve_match_values_get (struct sieve_interpreter *interp, unsigned int index, string_t **value_r);