]> gitweb.michael.orlitzky.com - dead/harbl.git/blobdiff - src/Network/DNS/RBL/Host.hs
Add the Network.DNS.RBL.Host module.
[dead/harbl.git] / src / Network / DNS / RBL / Host.hs
diff --git a/src/Network/DNS/RBL/Host.hs b/src/Network/DNS/RBL/Host.hs
new file mode 100644 (file)
index 0000000..ea7d4c8
--- /dev/null
@@ -0,0 +1,73 @@
+module Network.DNS.RBL.Host
+where
+
+import Data.ByteString.Char8 (
+  ByteString,
+  intercalate,
+  pack,
+  split )
+import qualified Network.DNS as DNS ( Domain )
+
+import Network.DNS.RBL.Domain ( UserDomain(..) )
+import Network.DNS.RBL.Pretty ( Pretty(..) )
+
+
+-- | A data type representing a host that we would like to look up on
+--   a blacklist. This can be either an IP address (for normal
+--   blacklists) or a domain name (for name-based blacklists).
+--
+--   Rather than make a distinction, we rely on the fact that we can
+--   parse all-digit \"domain names\". That is, we'll happily accept
+--   e.g. \"127.0.0.1\" as a name, and anything that isn't a valid IP
+--   address will implicitly be treated as a name and not an address.
+--
+newtype Host = Host UserDomain
+
+instance Pretty Host where pretty_show (Host d) = pretty_show d
+
+
+-- | Reverse the labels of this host in preparation for making a
+--   lookup (using the DNS library). We need to reverse the labels
+--   (the stuff between the dots) whether we're looking up a host or a
+--   name. The only tricky part here is that we need to turn an
+--   absolute 'UserDomain' into a relative one.
+--
+--   ==== _Examples_
+--
+--   >>> import Text.Parsec ( parse )
+--   >>> import Network.DNS.RBL.Domain ( user_domain )
+--
+--   >>> let (Right r) = parse user_domain "" "1.2.3.4"
+--   >>> let h = Host r
+--   >>> reverse_labels h
+--   "4.3.2.1"
+--
+--   >>> let (Right r) = parse user_domain "" "www.example.com"
+--   >>> let h = Host r
+--   >>> reverse_labels h
+--   "com.example.www"
+--
+--   Make sure absolute names are made relative:
+--
+--   >>> let (Right r) = parse user_domain "" "www.example.com."
+--   >>> let h = Host r
+--   >>> reverse_labels h
+--   "com.example.www"
+--
+reverse_labels :: Host -> DNS.Domain
+reverse_labels (Host h) = reversed
+  where
+    -- | It's possible that we are given an absolute domain name to
+    --   look up. This is legit; say I want to look up
+    --   \"www.example.com.\" That's fine, but before we make the
+    --   actual query we'll need to make it relative and then append
+    --   the DNSBL's suffix to it.
+    relative_host_string :: String
+    relative_host_string =
+      case h of
+        (UserDomainRelative _) -> pretty_show h
+        (UserDomainAbsolute d) -> pretty_show d
+
+    dot = pack "."
+    labels = split '.' (pack relative_host_string)
+    reversed = intercalate dot (reverse labels)