On 07/09/11 15:48, Stephan Bosch wrote: > On 9/7/2011 2:40 PM, Tom Hendrikx wrote: >> The above snippet poses some other issue that I cannot easily solve: the >> ascii-numeric comparator only handles integer values. >> >> All 0.xxxx header values are truncated to 0 by the comparator, just like >> the sieve script value "0.95". After comparision, this results in true >> for all cases. >> >> I don't really see a way to interact with floats in sieve, other than >> using regular expressions. However this gets clumsy/hairy quite fast >> when you're matching a hypothetical header value>=0.73 in stead of>=0.99. >> >> Any ideas? > > Yes. This can be a problem. However, the usual application for this is > matching against a spam header. If it is, you can use the spamtest > extension instead. Then you can configure the gory details in the > background > (http://wiki2.dovecot.org/Pigeonhole/Sieve/Extensions/SpamtestVirustest). > > Otherwise, things indeed tend to get hairy. I've puzzled a bit and came > up with the following: > > ==== > require "variables"; > require "relational"; > require "comparator-i;ascii-numeric"; > require "regex"; > > # Extract integer and fractional part separately: > set "val_int" "0"; > set "val_frac" "0"; > if header :regex "X-Header-Name" "([0-9]+)\\.([0-9]+)" { > set "val_int" "${1}"; > set "val_frac" "${2}"; > } > > if allof ( > /* Compare the integer part */ > string :comparator "i;ascii-numeric" :value "ge" "${val_int}" "5", > /* Compare the fractional part */ > string :value "ge" "${val_frac}" "34" ) { > discard; > } > ==== > > As you can see, the integer and fractional parts of the fractional > number are extracted separately using a :regex match. Then the > comparison is performed. The integer part is compared using > i;ascii-numeric. Quite counter-intuitively, the fractional part is > compared using a normal string comparison. The earlier regex match made > sure that the ${val_frac} variable only contains digits. The string > comparison makes sure that the length of the fractional part does not > matter (much) and that the comparison works as expected. A length > difference will only have an effect when there are spurious trailing > zeros and all the preceeding digits are equal, thereby causing the > longer string to have higher value, which is not strictly correct. > > The above certainly does not deserve an award for beauty, it does not > handle negative numbers (can be added), and it is not tested very well. > So, use this with caution. Unfortunately, there is no i;ascii-fractional > (or whatever) collation and afaik nothing like that is in the works at > the IETF. >
Thanks for the idea :) My first alternative way of thinking was to put the header value in a variable, then multiply it by 10000 (in my actual issue, the fraction always has 4 characters), then handle it as an int. However, doing a calculation is also not supported. I was trying to do some nifty stuff with DSPAM headers, which adds header that indicates "Spam" or "Innocent", and a fractional value between 0 and 1 that indicates the confidence that the filter has in its own classification: X-DSPAM-Result: Spam X-DSPAM-Confidence: 0.9456 ==> quite sure it is spam X-DSPAM-Result: Innocent X-DSPAM-Confidence: 0.9889 ==> even more sure that it is not spam Based on these headers, I wanted to do something with messages that the filter was really sure about, like pushing them to spamcop. Combining these headers in the sieve spamtest configuration to create a sliding scale between 1 and 10 is not really possible. -- Regards, Tom