From 394cb4ffeab6d59ffc31393ffed64a044d036887 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Thu, 29 May 2014 02:17:58 -0400 Subject: Add tags for handling tainted text --- readme.md | 16 ++++++++++++++++ src/Parsers.hs | 42 +++++++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/readme.md b/readme.md index ca3a15f..9086498 100644 --- a/readme.md +++ b/readme.md @@ -202,6 +202,22 @@ For the output template: (left mouse button). Using old syntax (without backticks surrounding `command`) will result in `button` attribute being ignored. +- `` allows the encapsulation of arbitrary text `str` (which + must be `len` `Char`s long, where `len` is encoded as a decimal sequence). + Careful use of this and `UnsafeStdinReader`, for example, permits window + managers to feed xmobar strings with `` tags mixed with un-trusted + content (e.g. window titles). For example, if xmobar is invoked as + + ```xmobar -c "[Run UnsafeStdinReader]" -t "%UnsafeStdinReader%"``` + + and receives on standard input the line + + ```foo/>``` + + then it will display the text ```foo```, + which, when clicked, will cause `test` to be echoed. + Other configuration options: `font` diff --git a/src/Parsers.hs b/src/Parsers.hs index f25fd4d..cda7004 100644 --- a/src/Parsers.hs +++ b/src/Parsers.hs @@ -25,6 +25,7 @@ import Runnable import Commands import Actions +import Control.Monad (guard, mzero) import qualified Data.Map as Map import Text.ParserCombinators.Parsec import Text.ParserCombinators.Parsec.Perm @@ -43,11 +44,20 @@ parseString c s = , Nothing)] Right x -> return (concat x) +allParsers :: ColorString + -> Maybe [Action] + -> Parser [(Widget, ColorString, Maybe [Action])] +allParsers c a = + textParser c a + <|> try (iconParser c a) + <|> try (rawParser c a) + <|> try (actionParser c a) + <|> colorParser a + -- | Gets the string and combines the needed parsers stringParser :: String -> Maybe [Action] -> Parser [[(Widget, ColorString, Maybe [Action])]] -stringParser c a = manyTill (textParser c a <|> try (iconParser c a) <|> - try (actionParser c a) <|> colorParser a) eof +stringParser c a = manyTill (allParsers c a) eof -- | Parses a maximal string without color markup. textParser :: String -> Maybe [Action] @@ -59,9 +69,30 @@ textParser c a = do s <- many1 $ try (string "action=") <|> try (string "/action>") <|> try (string "icon=") <|> + try (string "raw=") <|> string "/fc>")) return [(Text s, c, a)] +-- | Parse a "raw" tag, which we use to prevent other tags from creeping in. +-- The format here is net-string-esque: a literal "". +rawParser :: ColorString + -> Maybe [Action] + -> Parser [(Widget, ColorString, Maybe [Action])] +rawParser c a = do + string " do + guard ((len :: Integer) <= (fromIntegral (maxBound :: Int))) + s <- count (fromIntegral len) anyChar + string "/>" + return [(Text s, c, a)] + _ -> mzero + -- | Wrapper for notFollowedBy that returns the result of the first parser. -- Also works around the issue that, at least in Parsec 3.0.0, notFollowedBy -- accepts only parsers with return type Char. @@ -88,9 +119,7 @@ actionParser c act = do a' = case act of Nothing -> Just [a] Just act' -> Just $ a : act' - s <- manyTill (try (textParser c a') <|> try (iconParser c a') <|> - try (colorParser a') <|> actionParser c a') - (try $ string "") + s <- manyTill (allParsers c a') (try $ string "") return (concat s) toButtons :: String -> [Button] @@ -100,8 +129,7 @@ toButtons s = map (\x -> read [x]) s colorParser :: Maybe [Action] -> Parser [(Widget, ColorString, Maybe [Action])] colorParser a = do c <- between (string "") colors - s <- manyTill (try (textParser c a) <|> try (iconParser c a) <|> - try (colorParser a) <|> actionParser c a) (try $ string "") + s <- manyTill (allParsers c a) (try $ string "") return (concat s) -- | Parses a color specification (hex or named) -- cgit v1.2.3