{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE CPP #-}
{-|
This script parses the public suffix list, and constructs a data structure which can
be used with the isSuffix function in Lookup.hs. It exports a GSink which produces
the opaque 'DataStructure' and can be fed any Source as input.
This makes an few assumption about the information in the public suffix list:
namely, that no rule is a suffix of another rule. For example, if there is a rule
abc.def.ghi
then then is no other rule
def.ghi
or
!def.ghi
The actual data structure involved here is a tree where the nodes have no value and
the edges are DNS labels. There are two trees: one to handle the exception rules,
and one to handle the regular rules.
-}
module Network.PublicSuffixList.Create (PublicSuffixListException, sink) where
import Control.Exception
import qualified Data.ByteString as BS
import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL
import qualified Data.Conduit.Text as CT
import Data.Default
import qualified Data.Map as M
import qualified Data.Text as T
import Data.Typeable
import Text.IDNA
import Network.PublicSuffixList.Types
data PublicSuffixListException = PublicSuffixListExceptionderiving (Show, Typeable)
instance ExceptionPublicSuffixListExceptioninsert :: (Ord e) =>Treee -> [e] -> Treeeinsert _ [] = definsertt (p:ps) = case M.lookupp$childrent of
Nothing -> t { children = M.insert p (insert def ps) $ children t }Justl -> t { children = M.insert p (insert l ps) $ children t }foldingFunction :: DataStructure -> T.Text -> DataStructurefoldingFunctiond@(rules, exceptions) s'
| T.nulls = d
| T.take2s=="//" = d
| T.heads=='!' = (rules, insertexceptions$labelList$T.tails)
| otherwise = (insertrules$labelLists, exceptions)
where ss = filter (not.T.null) $T.wordss's
| nullss = ""
| otherwise = headsslabelList = reverse.mapinternationalize.T.split (=='.')
internationalizestr
| str=="*" = str
| otherwise = case toASCIIFalseTrue$T.toLowerstr of
Justx -> xNothing -> throwPublicSuffixListException{-
Generate the opaque 'DataStructure'
-}sink :: C.MonadThrow m =>C.SinkBS.ByteStringmDataStructuresink = CT.decodeCT.utf8C.=$CT.linesC.=$CL.foldfoldingFunctiondef