1 -- | This module contains the 'DnsblSite' data type representing one
2 -- blacklist with its associated return codes and weight. For example,
3 -- in Postfix's main.cf you might have,
5 -- postscreen_dnsbl_sites = bl.mailspike.net=127.0.0.[2;10;11]*2, ...
7 -- Here, the blacklist (a 'UserDomain') is \"bl.mailspike.net\", the
8 -- return code pattern is \"127.0.0.[2;10;11]\", and the weight is
26 import Text.Parsec.String ( Parser )
27 import Text.Read ( readMaybe )
29 import Domain ( UserDomain )
30 import IPv4Pattern ( IPv4Pattern )
32 newtype Weight = Weight Int deriving (Eq, Show)
34 -- | Parse the weight multiplier at the end of a dnsbl_site.
38 -- >>> import Text.Parsec ( parseTest )
40 -- Negative, zero, and positive integers are all supported:
42 -- >>> parseTest weight "*-5"
45 -- >>> parseTest weight "*0"
48 -- >>> parseTest weight "*17"
51 -- A bare asterisk doesn't work:
53 -- >>> parseTest weight "*"
54 -- parse error at (line 1, column 2):
55 -- unexpected end of input
56 -- expecting "-", "+" or digit
58 -- If the weight is empty, it defaults to @1@:
60 -- >>> parseTest weight ""
63 -- But the default is only used if the weight is really empty,
64 -- not if parsing simply fails:
66 -- >>> parseTest weight "*hello"
67 -- parse error at (line 1, column 2):
69 -- expecting "-", "+" or digit
71 weight :: Parser Weight
72 weight = try parse_weight <|> (eof >> return (Weight 1))
76 sign <- (char '-') <|> (option '+' (char '+'))
78 case ( readMaybe w :: Maybe Int ) of
79 -- If "many1 digit" gives us a list of digits, we should be able
80 -- to convert that to an Int! It will overflow rather than fail
81 -- if the input is too big/small, so it should really always
83 Nothing -> unexpected "weight: readMaybe failed on a sequence of digits!"
84 Just k -> return $ Weight (if sign == '-' then negate k else k)
87 data DnsblSite = DnsblSite UserDomain IPv4Pattern Weight