From cb095ead90c4c5d9aea7ab62443c67413861d407 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Fri, 23 Nov 2007 13:34:55 +0100 Subject: [PATCH] Finished i;ascii-numeric comparator and fixed a segfault bug in the process. --- README | 2 +- src/lib-sieve/cmd-if.c | 2 +- .../ext-cmp-i-ascii-numeric.c | 63 ++++++++++--------- .../plugins/relational/relational.sieve | 51 +++++++++++---- src/lib-sieve/tst-allof.c | 2 +- src/lib-sieve/tst-anyof.c | 2 +- 6 files changed, 78 insertions(+), 44 deletions(-) diff --git a/README b/README index e56772fef..05595f836 100644 --- a/README +++ b/README @@ -50,7 +50,7 @@ Extensions and their implementation status: Other RFCs/drafts: subaddress: full - comparator-i;ascii-numeric: full, but fails to handle leading zeros + comparator-i;ascii-numeric: full relational: full regex: full, but suboptimal vacation: validation, generation and interpretation; no execution diff --git a/src/lib-sieve/cmd-if.c b/src/lib-sieve/cmd-if.c index 6c09f0cae..06bbfa07d 100644 --- a/src/lib-sieve/cmd-if.c +++ b/src/lib-sieve/cmd-if.c @@ -165,7 +165,7 @@ static bool cmd_if_generate * anyway. */ if ( !sieve_command_block_exits_unconditionally(ctx) ) { - sieve_operation_emit_code(sbin, SIEVE_OPCODE_JMP); + sieve_operation_emit_code(sbin, &sieve_jmp_opcode); ctx_data->exit_jump = sieve_binary_emit_offset(sbin, 0); ctx_data->jump_generated = TRUE; } diff --git a/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c b/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c index f8634fd74..c9a3a88e6 100644 --- a/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c +++ b/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c @@ -3,7 +3,7 @@ * * Author: Stephan Bosch * Specification: RFC 2244 - * Implementation: full, but fails to handle leading zeros. + * Implementation: full * Status: experimental, largely untested * */ @@ -97,35 +97,40 @@ static bool ext_cmp_i_ascii_numeric_interpreter_load static int cmp_i_ascii_numeric_compare (const struct sieve_comparator *cmp ATTR_UNUSED, - const char *val1, size_t val1_size, const char *val2, size_t val2_size) -{ - unsigned int i = 0; - int result = 0; - const char *nval1 = (const char *) val1, *nval2 = (const char *) val2; - - while ( i < val1_size && i < val2_size ) { - if ( isdigit(nval1[i]) ) { - if ( isdigit(nval2[i]) ) { - if ( result == 0 && nval1[i] != nval2[i] ) { - if ( nval1[i] > nval2[i] ) - result = 1; - else - result = 0; - } - } else { - return 1; - } - } else { - if ( isdigit(nval2[i]) ) { - return -1; - } else { - return result; - } - } - - i++; + const char *val, size_t val_size, const char *key, size_t key_size) +{ + const char *vend = val + val_size; + const char *kend = key + key_size; + const char *vp = val; + const char *kp = key; + + /* Ignore leading zeros */ + + while ( *vp == '0' && vp < vend ) + vp++; + + while ( *kp == '0' && kp < kend ) + kp++; + + while ( vp < vend && kp < kend ) { + if ( !isdigit(*vp) || !isdigit(*kp) ) + break; + + if ( *vp != *kp ) + break; + + vp++; + kp++; } + + if ( vp == vend || !isdigit(*vp) ) { + if ( kp == kend || !isdigit(*kp) ) + return 0; + else + return -1; + } else if ( kp == kend || !isdigit(*kp) ) + return 1; - return result; + return (*vp > *kp); } diff --git a/src/lib-sieve/plugins/relational/relational.sieve b/src/lib-sieve/plugins/relational/relational.sieve index 520ff5502..22f655dad 100644 --- a/src/lib-sieve/plugins/relational/relational.sieve +++ b/src/lib-sieve/plugins/relational/relational.sieve @@ -1,28 +1,57 @@ -require ["comparator-i;ascii-numeric", "relational"]; +require ["comparator-i;ascii-numeric", "relational", "fileinto"]; if header :value "eq" :comparator "i;ascii-numeric" "x-spam-score" "2" { - discard; - stop; + fileinto "INBOX.fail"; +} else { + fileinto "INBOX.succeed"; } if header :value "lt" :comparator "i;ascii-numeric" "x-spam-score" "2" { - discard; - stop; + fileinto "INBOX.fail"; +} else { + fileinto "INBOX.succeed"; } if header :value "lt" :comparator "i;ascii-numeric" "x-spam-score" "2" { - discard; - stop; + fileinto "INBOX.fail"; +} else { + fileinto "INBOX.succeed"; +} + +if header :value "le" :comparator "i;ascii-numeric" "x-spam-score" "300" { + fileinto "INBOX.succeed"; +} else { + fileinto "INBOX.fail"; +} + +if header :value "le" :comparator "i;ascii-numeric" "x-spam-score" "302" { + fileinto "INBOX.succeed"; +} else { + fileinto "INBOX.fail"; +} + +if header :value "le" :comparator "i;ascii-numeric" "x-spam-score" "00302" { + fileinto "INBOX.succeed"; +} else { + fileinto "INBOX.fail"; } if header :count "ne" :comparator "i;ascii-numeric" "to" "2" { - discard; - stop; + fileinto "INBOX.fail"; +} else { + fileinto "INBOX.succeed"; } if header :count "ge" :comparator "i;ascii-numeric" "to" "2" { - discard; - stop; + fileinto "INBOX.succeed"; +} else { + fileinto "INBOX.fail"; +} + +if header :count "ge" :comparator "i;ascii-numeric" "to" "002" { + fileinto "INBOX.succeed"; +} else { + fileinto "INBOX.fail"; } keep; diff --git a/src/lib-sieve/tst-allof.c b/src/lib-sieve/tst-allof.c index 9fd899524..d23090ab1 100644 --- a/src/lib-sieve/tst-allof.c +++ b/src/lib-sieve/tst-allof.c @@ -56,7 +56,7 @@ static bool tst_allof_generate if ( jump_true ) { /* All tests succeeded, jump to case TRUE */ - sieve_generator_emit_opcode(generator, SIEVE_OPCODE_JMP); + sieve_generator_emit_opcode(generator, &sieve_jmp_opcode); sieve_jumplist_add(jumps, sieve_binary_emit_offset(sbin, 0)); /* All false exits jump here */ diff --git a/src/lib-sieve/tst-anyof.c b/src/lib-sieve/tst-anyof.c index 17f5dbaad..55fca774b 100644 --- a/src/lib-sieve/tst-anyof.c +++ b/src/lib-sieve/tst-anyof.c @@ -54,7 +54,7 @@ static bool tst_anyof_generate if ( !jump_true ) { /* All tests failed, jump to case FALSE */ - sieve_operation_emit_code(sbin, SIEVE_OPCODE_JMP); + sieve_operation_emit_code(sbin, &sieve_jmp_opcode); sieve_jumplist_add(jumps, sieve_binary_emit_offset(sbin, 0)); /* All true exits jump here */ -- GitLab