summaryrefslogtreecommitdiffstats
path: root/Regfish/Parser.hs
diff options
context:
space:
mode:
authortv <tv@shackspace.de>2014-11-18 16:05:40 +0100
committertv <tv@shackspace.de>2014-11-18 16:05:40 +0100
commit179d8980e55578e3553bad0b237368d74e074f15 (patch)
treecee326bc5071a71866ede0487beb28d510ea989a /Regfish/Parser.hs
initial commit
Diffstat (limited to 'Regfish/Parser.hs')
-rw-r--r--Regfish/Parser.hs100
1 files changed, 100 insertions, 0 deletions
diff --git a/Regfish/Parser.hs b/Regfish/Parser.hs
new file mode 100644
index 0000000..bc294b6
--- /dev/null
+++ b/Regfish/Parser.hs
@@ -0,0 +1,100 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+
+module Regfish.Parser
+ ( readZone
+ ) where
+
+import qualified Data.ByteString.Lazy.Char8 as LBS8
+import Regfish.Types
+import Text.HTML.TagSoup
+
+
+readZone :: LBS8.ByteString -> [Record]
+readZone = parseRecords . dnszone
+
+
+parseRecords :: [Tag LBS8.ByteString] -> [Record]
+parseRecords =
+ map toRecord . filter knownRecord . rec []
+ where
+ knownRecord (_ : _ : _ : namespace : type_ : _) =
+ namespace == "IN" && type_ `elem` ["MX", "A", "CNAME"]
+
+ knownRecord x =
+ errorBadArgument "parseRecords.knownRecord" x
+
+ rec ys = \case
+ (TagOpen "tr" attrs:xs) ->
+ case getRecordId attrs of
+ Just id_ ->
+ let (r,_:xs') = span (/=TagClose "tr") xs
+ in rec (parseRecord id_ r:ys) xs'
+ _ ->
+ let xs' = drop 1 $ dropWhile (/=TagClose "tr") xs
+ in rec ys xs'
+
+ [] -> ys
+
+ x -> errorBadArgument "parseRecords.rec" x
+
+ getRecordId attrs =
+ case maybe Nothing (Just . LBS8.unpack) $ lookup "id" attrs of
+ Just ('a':'_':xs) -> Just (LBS8.pack xs)
+ _ -> Nothing
+
+
+
+toRecord :: [LBS8.ByteString] -> Record
+toRecord xs = case map LBS8.unpack xs of
+ [rrid, rrname, rrttl, "IN", rrtype, rraux, rrdata] ->
+ Record rrid rrtype rrname (read rrttl) (read rraux) rrdata
+ [rrid, rrname, rrttl, "IN", rrtype, rrdata] ->
+ Record rrid rrtype rrname (read rrttl) 0 rrdata
+ x ->
+ errorBadArgument "toRecord" x
+
+
+dnszone :: LBS8.ByteString -> [Tag LBS8.ByteString]
+dnszone =
+ filter p . (dnszoneSoup . parseTags)
+ where
+ p = \case
+ TagOpen "tr" _ -> True
+ TagClose "tr" -> True
+ TagText x
+ | x /= "\n" -> True
+ | otherwise -> False
+ _ -> False
+
+
+parseRecord :: LBS8.ByteString -> [Tag LBS8.ByteString] -> [LBS8.ByteString]
+parseRecord id_ =
+ (id_:) . add_def_ttl "0" . filter p . map f
+ where
+ f (TagText x) = x
+ f x = errorBadArgument "parseRecord" x
+ p x
+ | x == "\160" = False
+ | x == " " = False
+ | otherwise = True
+
+ add_def_ttl def_ttl (x:"IN":xs) = x : def_ttl : "IN" : xs
+ add_def_ttl _ xs = xs
+
+
+dnszoneSoup :: [Tag LBS8.ByteString] -> [Tag LBS8.ByteString]
+dnszoneSoup =
+ takeWhile (\t -> not $ t ~== dnszoneClose) .
+ dropWhile (\t -> not $ t ~== dnszoneOpen)
+
+
+dnszoneOpen, dnszoneClose :: Tag LBS8.ByteString
+dnszoneOpen = TagOpen "table" [("id", "dnszone")]
+dnszoneClose = TagClose "table"
+
+
+errorBadArgument :: Show a => String -> a -> b
+errorBadArgument name x =
+ error $ "Regfish.Parser." ++ name ++ ": bad argument: " ++ show x