From a493b63b84453a38ac405e59f5409a5d9d40ccb8 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sat, 22 Mar 2008 18:35:48 +0100 Subject: [PATCH] Finished :matches function for now, but it can still be improved and it needs more testing. --- .../plugins/variables/variables-match.sieve | 52 ++++++++++ src/lib-sieve/sieve-match-types.c | 99 ++++++++++++++----- 2 files changed, 124 insertions(+), 27 deletions(-) diff --git a/src/lib-sieve/plugins/variables/variables-match.sieve b/src/lib-sieve/plugins/variables/variables-match.sieve index a8fff99d7..55ece77b6 100644 --- a/src/lib-sieve/plugins/variables/variables-match.sieve +++ b/src/lib-sieve/plugins/variables/variables-match.sieve @@ -81,3 +81,55 @@ if string :matches "${match6}" "*one?zero?five" { fileinto "FAILED 8: ${match6}"; stop; } + +# Test 9 + +set "match7" "frop"; + +if string :matches "${match7}" "??op" { + fileinto "TEST 9: ${1}-${2}-op"; +} else { + fileinto "FAILED 9: ${match7}"; + stop; +} + +# Test 10 + +if string :matches "${match7}" "fr??" { + fileinto "TEST 10: fr-${1}-${2}"; +} else { + fileinto "FAILED 10: ${match7}"; + stop; +} + +# Test 11 + +set "match8" "klopfropstroptop"; + +if string :matches "${match8}" "*fr??*top" { + fileinto "TEST 11: ${1}: fr-${2}-${3}: ${4}"; +} else { + fileinto "FAILED 11: ${match8}"; + stop; +} + +if string :matches "${match8}" "?*fr??*top" { + fileinto "TEST 12: ${1}-${2}: fr-${3}-${4}: ${5}"; +} else { + fileinto "FAILED 12: ${match8}"; + stop; +} + +if string :matches "${match8}" "*?op" { + fileinto "TEST 13: ${1} ${2} op"; +} else { + fileinto "FAILED 13: ${match8}"; + stop; +} + +if string :matches "${match8}" "*?op*" { + fileinto "TEST 14: (*?op*): ${1}:${2}:${3}:${4}:${5}:${6}:${7}:"; +} else { + fileinto "FAILED 14: ${match8}"; + stop; +} diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c index 5bddd821f..8fe555291 100644 --- a/src/lib-sieve/sieve-match-types.c +++ b/src/lib-sieve/sieve-match-types.c @@ -661,7 +661,7 @@ static bool mtch_contains_match /* :matches */ /* Quick 'n dirty debug */ -#define MATCH_DEBUG +//#define MATCH_DEBUG #ifdef MATCH_DEBUG #define debug_printf(...) printf (__VA_ARGS__) #else @@ -684,7 +684,7 @@ static inline bool _string_find(const struct sieve_comparator *cmp, static char _scan_key_section (string_t *section, const char **wcardp, const char *key_end) { - /* Find next * wildcard and resolve escape sequences */ + /* Find next wildcard and resolve escape sequences */ str_truncate(section, 0); while ( *wcardp < key_end && **wcardp != '*' && **wcardp != '?') { if ( **wcardp == '\\' ) { @@ -709,19 +709,24 @@ static bool mtch_matches_match { const struct sieve_comparator *cmp = mctx->comparator; struct sieve_match_values *mvalues; - string_t *mvalue = t_str_new(32); - string_t *mchars = t_str_new(32); - string_t *section = t_str_new(32); - string_t *subsection = t_str_new(32); + + string_t *mvalue = t_str_new(32); /* Match value (*) */ + string_t *mchars = t_str_new(32); /* Match characters (.?..?.??) */ + string_t *section = t_str_new(32); /* Section (after beginning or *) */ + string_t *subsection = t_str_new(32); /* Sub-section (after ?) */ + const char *vend = (const char *) val + val_size; const char *kend = (const char *) key + key_size; - const char *vp = val; /* Value pointer */ - const char *kp = key; /* Key pointer */ - const char *wp = key; /* Wildcard (key) pointer */ - const char *pvp = val; - bool backtrack = FALSE; - char wcard = '\0', next_wcard = '\0'; - unsigned int i, j = 0; + const char *vp = val; /* Value pointer */ + const char *kp = key; /* Key pointer */ + const char *wp = key; /* Wildcard (key) pointer */ + const char *pvp = val; /* Previous value Pointer */ + + bool backtrack = FALSE; /* TRUE: match of '?'-connected sections failed */ + char wcard = '\0'; /* Current wildcard */ + char next_wcard = '\0'; /* Next widlcard */ + unsigned int key_offset = 0; + unsigned int j = 0; /* Reset match values list */ mvalues = sieve_match_values_start(mctx->interp); @@ -742,8 +747,27 @@ static bool mtch_matches_match const char *needle, *nend; if ( !backtrack ) { - wcard = next_wcard; - next_wcard = _scan_key_section(section, &wp, kend); + wcard = next_wcard; + + /* Find the needle to look for in the string */ + key_offset = 0; + for (;;) { + next_wcard = _scan_key_section(section, &wp, kend); + + if ( wcard == '\0' || str_len(section) > 0 ) + break; + + if ( next_wcard == '*' ) { + break; + } + + if ( wp < kend ) + wp++; + else + break; + key_offset++; + } + debug_printf("MATCH found wildcard '%c' at pos [%d]\n", next_wcard, (int) (wp-key)); @@ -760,7 +784,9 @@ static bool mtch_matches_match debug_printf("MATCH sval: '%s'\n", t_strdup_until(vp, vend)); pvp = vp; - if ( next_wcard == '\0' ) { + if ( next_wcard == '\0' ) { + const char *qp, *qend; + debug_printf("MATCH find end.\n"); /* Find substring at the end of string */ @@ -769,24 +795,33 @@ static bool mtch_matches_match } vp = PTR_OFFSET(vend, -str_len(section)); - str_append_n(mvalue, pvp, vp-pvp); - sieve_match_values_add(mvalues, mvalue); - + qend = vp; + qp = vp - key_offset; + str_append_n(mvalue, pvp, qp-pvp); + if ( !cmp->char_match(cmp, &vp, vend, &needle, nend) ) { - debug_printf("MATCH failed fixed\n"); + debug_printf("MATCH failed end\n"); break; } + + sieve_match_values_add(mvalues, mvalue); + for ( ; qp < qend; qp++ ) + sieve_match_values_add_char(mvalues, *qp); - if ( wp < kend ) wp++; - kp = wp; + kp = kend; + vp = vend; + break; } else { const char *prv = NULL; const char *prk = NULL; const char *prw = NULL; const char *chars; debug_printf("MATCH find.\n"); - + + str_truncate(mchars, 0); + if ( wcard == '\0' ) { + /* Match needs to happen right at the beginning */ debug_printf("MATCH bkey: '%s'\n", t_strdup_until(needle, nend)); debug_printf("MATCH bval: '%s'\n", t_strdup_until(vp, vend)); @@ -796,7 +831,9 @@ static bool mtch_matches_match } } else { - /* Find substring (enclosed between wildcards) */ + const char *qp, *qend; + + /* Match may happen at any offset: find substring */ if ( !_string_find(cmp, &vp, vend, &needle, nend) ) { debug_printf("MATCH failed find\n"); break; @@ -805,14 +842,19 @@ static bool mtch_matches_match prv = vp - str_len(section); prk = kp; prw = wp; - str_append_n(mvalue, pvp, vp-pvp-str_len(section)); - debug_printf("MATCH :: %s\n", t_strdup_until(pvp, vp-str_len(section))); + + qend = vp - str_len(section); + qp = qend - key_offset; + str_append_n(mvalue, pvp, qp-pvp); + for ( ; qp < qend; qp++ ) + str_append_c(mchars, *qp); + //sieve_match_values_add_char(mvalues, *qp); + debug_printf("MATCH :: %s\n", str_c(mvalue)); } if ( wp < kend ) wp++; kp = wp; - str_truncate(mchars, 0); while ( next_wcard == '?' ) { debug_printf("MATCH ?\n"); @@ -853,6 +895,8 @@ static bool mtch_matches_match } if ( !backtrack ) { + unsigned int i; + if ( next_wcard != '*' && next_wcard != '\0' ) { debug_printf("MATCH failed '?'\n"); break; @@ -871,6 +915,7 @@ static bool mtch_matches_match * (avoid scanning the rest of the string) */ if ( kp == kend && next_wcard == '*' ) { + str_truncate(mvalue, 0); str_append_n(mvalue, vp, vend-vp); sieve_match_values_add(mvalues, mvalue); kp = kend; -- GitLab