diff --git a/Text/HTML/SanitizeXSS.hs b/Text/HTML/SanitizeXSS.hs index e024eef..79d7a96 100644 --- a/Text/HTML/SanitizeXSS.hs +++ b/Text/HTML/SanitizeXSS.hs @@ -32,7 +32,6 @@ import Network.URI ( parseURIReference, URI (..), isAllowedInURI, escapeURIString, uriScheme ) import Codec.Binary.UTF8.String ( encodeString ) -import qualified Data.Map as Map import Data.Maybe (catMaybes) @@ -51,7 +50,7 @@ sanitizeBalance = filterTags (balanceTags . safeTags) -- | Filter which makes sure the tags are balanced. Use with 'filterTags' and 'safeTags' to create a custom filter. balanceTags :: [Tag Text] -> [Tag Text] -balanceTags = balance Map.empty +balanceTags = balance [] -- | Parse the given text to a list of tags, apply the given filtering function, and render back to HTML. -- You can insert your own custom filtering but make sure you compose your filtering function with 'safeTags'! @@ -63,29 +62,16 @@ filterTags f = renderTagsOptions renderOptions { voidElems :: Set T.Text voidElems = fromAscList $ T.words $ T.pack "area base br col command embed hr img input keygen link meta param source track wbr" -balance :: Map.Map Text Int -> [Tag Text] -> [Tag Text] -balance m [] = - concatMap go $ Map.toList m - where - go (name, i) - | noClosing name = [] - | otherwise = replicate i $ TagClose name - noClosing = flip member voidElems -balance m (t@(TagClose name):tags) = - case Map.lookup name m of - Nothing -> TagOpen name [] : TagClose name : balance m tags - Just i -> - let m' = if i == 1 - then Map.delete name m - else Map.insert name (i - 1) m - in t : balance m' tags -balance m (TagOpen name as : tags) = - TagOpen name as : balance m' tags - where - m' = case Map.lookup name m of - Nothing -> Map.insert name 1 m - Just i -> Map.insert name (i + 1) m -balance m (t:ts) = t : balance m ts +balance :: [Text] -- ^ unclosed tags + -> [Tag Text] -> [Tag Text] +balance unclosed [] = map TagClose $ filter (`notMember` voidElems) unclosed +balance (x:xs) tags'@(TagClose name:tags) + | x == name = TagClose name : balance xs tags + | x `member` voidElems = balance xs tags' + | otherwise = TagOpen name [] : TagClose name : balance (x:xs) tags +balance unclosed (TagOpen name as : tags) = + TagOpen name as : balance (name : unclosed) tags +balance unclosed (t:ts) = t : balance unclosed ts -- | Filters out any usafe tags and attributes. Use with filterTags to create a custom filter. safeTags :: [Tag Text] -> [Tag Text] diff --git a/test/main.hs b/test/main.hs index 9a1f605..40b9af5 100644 --- a/test/main.hs +++ b/test/main.hs @@ -86,4 +86,4 @@ main = hspec $ do it "removes closing voids" $ do sanitizedB "" "" it "interleaved" $ - sanitizedB "helloworld" "helloworld" + sanitizedB "helloworld" "helloworld" diff --git a/xss-sanitize.cabal b/xss-sanitize.cabal index a926c4b..472b222 100644 --- a/xss-sanitize.cabal +++ b/xss-sanitize.cabal @@ -1,5 +1,5 @@ name: xss-sanitize -version: 0.3.5.3 +version: 0.3.5.4 license: BSD3 license-file: LICENSE author: Greg Weber