feat: api: quoteForCommandLine: some very shady CLI escaping
This commit is contained in:
parent
d2f0077254
commit
442ef9361c
@ -10,6 +10,7 @@ module Hledger.Utils.String (
|
|||||||
-- quoting
|
-- quoting
|
||||||
quoteIfNeeded,
|
quoteIfNeeded,
|
||||||
singleQuoteIfNeeded,
|
singleQuoteIfNeeded,
|
||||||
|
quoteForCommandLine,
|
||||||
-- quotechars,
|
-- quotechars,
|
||||||
-- whitespacechars,
|
-- whitespacechars,
|
||||||
words',
|
words',
|
||||||
@ -118,15 +119,44 @@ quoteIfNeeded s | any (`elem` s) (quotechars++whitespacechars++redirectchars) =
|
|||||||
escapeQuotes (c:cs) x = showChar c $ escapeQuotes cs x
|
escapeQuotes (c:cs) x = showChar c $ escapeQuotes cs x
|
||||||
|
|
||||||
-- | Single-quote this string if it contains whitespace or double-quotes.
|
-- | Single-quote this string if it contains whitespace or double-quotes.
|
||||||
-- No good for strings containing single quotes.
|
-- Does not work for strings containing single quotes.
|
||||||
singleQuoteIfNeeded :: String -> String
|
singleQuoteIfNeeded :: String -> String
|
||||||
singleQuoteIfNeeded s | any (`elem` s) (quotechars++whitespacechars) = "'"++s++"'"
|
singleQuoteIfNeeded s | any (`elem` s) (quotechars++whitespacechars) = singleQuote s
|
||||||
| otherwise = s
|
| otherwise = s
|
||||||
|
|
||||||
quotechars, whitespacechars, redirectchars :: [Char]
|
-- | Prepend and append single quotes to a string.
|
||||||
|
singleQuote :: String -> String
|
||||||
|
singleQuote s = "'"++s++"'"
|
||||||
|
|
||||||
|
-- | Try to single- and backslash-quote a string as needed to make it usable
|
||||||
|
-- as an argument on a (sh/bash) shell command line. At least, well enough
|
||||||
|
-- to handle common currency symbols, like $. Probably broken in many ways.
|
||||||
|
--
|
||||||
|
-- >>> quoteForCommandLine "a"
|
||||||
|
-- "a"
|
||||||
|
-- >>> quoteForCommandLine "\""
|
||||||
|
-- "'\"'"
|
||||||
|
-- >>> quoteForCommandLine "$"
|
||||||
|
-- "'\\$'"
|
||||||
|
--
|
||||||
|
quoteForCommandLine :: String -> String
|
||||||
|
quoteForCommandLine s
|
||||||
|
| any (`elem` s) (quotechars++whitespacechars++shellchars) = singleQuote $ quoteShellChars s
|
||||||
|
| otherwise = s
|
||||||
|
|
||||||
|
-- | Try to backslash-quote common shell-significant characters in this string.
|
||||||
|
-- Doesn't handle single quotes, & probably others.
|
||||||
|
quoteShellChars :: String -> String
|
||||||
|
quoteShellChars = concatMap escapeShellChar
|
||||||
|
where
|
||||||
|
escapeShellChar c | c `elem` shellchars = ['\\',c]
|
||||||
|
escapeShellChar c = [c]
|
||||||
|
|
||||||
|
quotechars, whitespacechars, redirectchars, shellchars :: [Char]
|
||||||
quotechars = "'\""
|
quotechars = "'\""
|
||||||
whitespacechars = " \t\n\r"
|
whitespacechars = " \t\n\r"
|
||||||
redirectchars = "<>"
|
redirectchars = "<>"
|
||||||
|
shellchars = "<>(){}[]$7?#!~`"
|
||||||
|
|
||||||
-- | Quote-aware version of words - don't split on spaces which are inside quotes.
|
-- | Quote-aware version of words - don't split on spaces which are inside quotes.
|
||||||
-- NB correctly handles "a'b" but not "''a''". Can raise an error if parsing fails.
|
-- NB correctly handles "a'b" but not "''a''". Can raise an error if parsing fails.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user