From: Michael Orlitzky Date: Sun, 5 Jul 2015 06:15:17 +0000 (-0400) Subject: Add weight parsing to DnsblSite.hs. X-Git-Url: http://gitweb.michael.orlitzky.com/?p=dead%2Fharbl.git;a=commitdiff_plain;h=6f177422a389b2361e4f66280d8f4021774dd475;ds=sidebyside Add weight parsing to DnsblSite.hs. --- diff --git a/src/DnsblSite.hs b/src/DnsblSite.hs index df4437d..24d8c96 100644 --- a/src/DnsblSite.hs +++ b/src/DnsblSite.hs @@ -1,18 +1,88 @@ -- | This module contains the 'DnsblSite' data type representing one --- blacklist with its associated return codes and multiplier. For example, +-- blacklist with its associated return codes and weight. For example, -- in Postfix's main.cf you might have, -- -- postscreen_dnsbl_sites = bl.mailspike.net=127.0.0.[2;10;11]*2, ... -- -- Here, the 'Domain' is \"bl.mailspike.net\", the return code --- pattern is \"127.0.0.[2;10;11]\", and the multiplier is \"2". +-- pattern is \"127.0.0.[2;10;11]\", and the weight is \"2". -- module DnsblSite where +import Text.Parsec ( + ParseError, + (<|>), + char, + digit, + eof, + many1, + option, + parse, + string, + try, + unexpected ) +import Text.Parsec.String ( Parser ) +import Text.Read ( readMaybe ) + + import IPv4Pattern ( IPv4Pattern ) +newtype Weight = Weight Int deriving (Eq, Show) + +-- | Parse the weight multiplier at the end of a dnsbl_site. +-- +-- ==== _Examples_ +-- +-- >>> import Text.Parsec ( parseTest ) +-- +-- Negative, zero, and positive integers are all supported: +-- +-- >>> parseTest weight "*-5" +-- Weight (-5) +-- +-- >>> parseTest weight "*0" +-- Weight 0 +-- +-- >>> parseTest weight "*17" +-- Weight 17 +-- +-- A bare asterisk doesn't work: +-- +-- >>> parseTest weight "*" +-- parse error at (line 1, column 2): +-- unexpected end of input +-- expecting "-", "+" or digit +-- +-- If the weight is empty, it defaults to @1@: +-- +-- >>> parseTest weight "" +-- Weight 1 +-- +-- But the default is only used if the weight is really empty, +-- not if parsing simply fails: +-- +-- >>> parseTest weight "*hello" +-- parse error at (line 1, column 2): +-- unexpected "h" +-- expecting "-", "+" or digit +-- +weight :: Parser Weight +weight = try parse_weight <|> (eof >> return (Weight 1)) + where + parse_weight = do + _ <- char '*' + sign <- (char '-') <|> (option '+' (char '+')) + w <- many1 digit + case ( readMaybe w :: Maybe Int ) of + -- If "many1 digit" gives us a list of digits, we should be able + -- to convert that to an Int! It will overflow rather than fail + -- if the input is too big/small, so it should really always + -- succeed. + Nothing -> unexpected "weight: readMaybe failed on a sequence of digits!" + Just k -> return $ Weight (if sign == '-' then negate k else k) + newtype Domain = Domain String -newtype Multiplier = Multiplier Int -data DnsblSite = DnsblSite Domain IPv4Pattern Multiplier +data DnsblSite = DnsblSite Domain IPv4Pattern Weight +