module Text.Hostname
(validHostname)
where
import Control.Applicative
import Data.Attoparsec hiding (Parser)
import Data.Attoparsec.Combinator
import Data.Attoparsec.Types (Parser)
import Data.ByteString (ByteString)
import GHC.Word
validHostname :: ByteString -> Bool
validHostname = test (host >> endOfInput)
test :: Parser ByteString b -> ByteString -> Bool
test p x = either (const False) (const True) (parseOnly p x)
host :: Parser ByteString [[[Word8]]]
host = labelStart >> many label
name :: Parser ByteString [Word8]
name = (many1 (char '-') >> many1 diglet) <|> many1 diglet
label :: Parser ByteString [[Word8]]
label = char '.' >> diglet >> many name
labelStart :: Parser ByteString [[Word8]]
labelStart = diglet >> many name
char :: Char -> Parser ByteString Word8
char c = word8 (fromIntegral (fromEnum c))
diglet :: Parser ByteString Word8
diglet = satisfy (flip elem (['a'..'z'] ++ ['0'..'9']) . toEnum . fromIntegral)
testsPass :: Bool
testsPass = all validHostname correctTests && not (any validHostname incorrectTests)
correctTests :: [ByteString]
correctTests =
["a"
,"a.com"
,"a-c"
,"a--b"
,"64"
,"54.com"
,"aaa-bbb-ccc.dooo-bar--zot"
,"xn--mgbh0fb.xn--kgbechtv"
,"xn--fsqu00a.xn--0zwm56d"
,"xn--fsqu00a.xn--g6w251d"
,"xn--hxajbheg2az3al.xn--jxalpdlp"
,"xn--p1b6ci4b4b3a.xn--11b5bs3a9aj6g"
,"xn--r8jz45g.xn--zckzah"
,"xn--9n2bp8q.xn--9t4b11yi5a"
,"xn--mgbh0fb.xn--hgbk6aj7f53bba"
,"xn--e1afmkfd.xn--80akhbyknj4f"
,"xn--zkc6cc5bi7f6e.xn--hlcj6aya9esc7a"
,"xn--6dbbec0c.xn--deba0ad"
,"xn--fdbk5d8ap9b8a8d.xn--deba0ad"]
incorrectTests :: [ByteString]
incorrectTests =
[""
,"a-"
,"-"
,"-a"
,"a--"
,"a.-"
,".a"
,".a-z"]