git.iko.soy/typeable/pandoc
on master help sign in
Properly escape URIs in all readers.
c87d522John MacFarlane
src/Text/Pandoc/Readers/HTML.hs+3−3
@@ -182,7 +182,7 @@ unsanitaryURI u =
182 "ldaps:", "magnet:", "mms:", "msnim:", "notes:", "rsync:",
182 "ldaps:", "magnet:", "mms:", "msnim:", "notes:", "rsync:",
183 "secondlife:", "skype:", "ssh:", "sftp:", "smb:", "sms:",
183 "secondlife:", "skype:", "ssh:", "sftp:", "smb:", "sms:",
184 "snews:", "webcal:", "ymsgr:"]
184 "snews:", "webcal:", "ymsgr:"]
185− in case parseURIReference (stringToURI u) of
185+ in case parseURIReference (escapeURI u) of
186 Just p -> (map toLower $ uriScheme p) `notElem` safeURISchemes
186 Just p -> (map toLower $ uriScheme p) `notElem` safeURISchemes
187 Nothing -> True
187 Nothing -> True
188
188
@@ -746,7 +746,7 @@ link = try $ do
746 Nothing -> fail "no href"
746 Nothing -> fail "no href"
747 let title = fromMaybe "" $ extractAttribute "title" attributes
747 let title = fromMaybe "" $ extractAttribute "title" attributes
748 lab <- inlinesTilEnd "a"
748 lab <- inlinesTilEnd "a"
749− return $ Link (normalizeSpaces lab) (url, title)
749+ return $ Link (normalizeSpaces lab) (escapeURI url, title)
750
750
751image :: GenParser Char ParserState Inline
751image :: GenParser Char ParserState Inline
752image = try $ do
752image = try $ do
@@ -756,5 +756,5 @@ image = try $ do
756 Nothing -> fail "no src"
756 Nothing -> fail "no src"
757 let title = fromMaybe "" $ extractAttribute "title" attributes
757 let title = fromMaybe "" $ extractAttribute "title" attributes
758 let alt = fromMaybe "" (extractAttribute "alt" attributes)
758 let alt = fromMaybe "" (extractAttribute "alt" attributes)
759− return $ Image [Str alt] (url, title)
759+ return $ Image [Str alt] (escapeURI url, title)
760
760
src/Text/Pandoc/Readers/LaTeX.hs+6−7
@@ -738,7 +738,7 @@ url :: GenParser Char ParserState Inline
738url = try $ do
738url = try $ do
739 string "\\url"
739 string "\\url"
740 url' <- charsInBalanced '{' '}'
740 url' <- charsInBalanced '{' '}'
741− return $ Link [Code url'] (url', "")
741+ return $ Link [Code url'] (escapeURI url', "")
742
742
743link :: GenParser Char ParserState Inline
743link :: GenParser Char ParserState Inline
744link = try $ do
744link = try $ do
@@ -746,17 +746,16 @@ link = try $ do
746 url' <- manyTill anyChar (char '}')
746 url' <- manyTill anyChar (char '}')
747 char '{'
747 char '{'
748 label' <- manyTill inline (char '}')
748 label' <- manyTill inline (char '}')
749− return $ Link (normalizeSpaces label') (url', "")
749+ return $ Link (normalizeSpaces label') (escapeURI url', "")
750
750
751image :: GenParser Char ParserState Inline
751image :: GenParser Char ParserState Inline
752image = try $ do
752image = try $ do
753 ("includegraphics", _, args) <- command
753 ("includegraphics", _, args) <- command
754 let args' = filter isArg args -- filter out options
754 let args' = filter isArg args -- filter out options
755− let src = if null args' then
755+ let (src,tit) = case args' of
756− ("", "")
756+ [] -> ("", "")
757− else
758− (stripFirstAndLast (head args'), "")
757+ (x:_) -> (stripFirstAndLast x, "")
759− return $ Image [Str "image"] src
758+ return $ Image [Str "image"] (escapeURI src, tit)
760
759
761footnote :: GenParser Char ParserState Inline
760footnote :: GenParser Char ParserState Inline
762footnote = try $ do
761footnote = try $ do
src/Text/Pandoc/Readers/Markdown.hs+9−16
@@ -31,7 +31,7 @@ module Text.Pandoc.Readers.Markdown (
31 readMarkdown
31 readMarkdown
32 ) where
32 ) where
33
33
34−import Data.List ( transpose, isPrefixOf, isSuffixOf, sortBy, findIndex, intercalate )
34+import Data.List ( transpose, isSuffixOf, sortBy, findIndex, intercalate )
35import Data.Ord ( comparing )
35import Data.Ord ( comparing )
36import Data.Char ( isAlphaNum )
36import Data.Char ( isAlphaNum )
37import Data.Maybe
37import Data.Maybe
@@ -73,10 +73,6 @@ specialChars = "\\[]*_~`<>$!^-.&'\"\8216\8217\8220\8221;"
73-- auxiliary functions
73-- auxiliary functions
74--
74--
75
75
76−-- | Replace spaces with %20
77−uriEscapeSpaces :: String -> String
78−uriEscapeSpaces = substitute " " "%20"
79−
80indentSpaces :: GenParser Char ParserState [Char]
76indentSpaces :: GenParser Char ParserState [Char]
81indentSpaces = try $ do
77indentSpaces = try $ do
82 state <- getState
78 state <- getState
@@ -206,7 +202,7 @@ referenceKey = try $ do
206 tit <- option "" referenceTitle
202 tit <- option "" referenceTitle
207 blanklines
203 blanklines
208 endPos <- getPosition
204 endPos <- getPosition
209− let newkey = (lab, (uriEscapeSpaces $ removeTrailingSpace src, tit))
205+ let newkey = (lab, (escapeURI $ removeTrailingSpace src, tit))
210 st <- getState
206 st <- getState
211 let oldkeys = stateKeys st
207 let oldkeys = stateKeys st
212 updateState $ \s -> s { stateKeys = newkey : oldkeys }
208 updateState $ \s -> s { stateKeys = newkey : oldkeys }
@@ -1194,7 +1190,7 @@ source' = do
1194 tit <- option "" linkTitle
1190 tit <- option "" linkTitle
1195 skipSpaces
1191 skipSpaces
1196 eof
1192 eof
1197− return (uriEscapeSpaces $ removeTrailingSpace src, tit)
1193+ return (escapeURI $ removeTrailingSpace src, tit)
1198
1194
1199linkTitle :: GenParser Char st String
1195linkTitle :: GenParser Char st String
1200linkTitle = try $ do
1196linkTitle = try $ do
@@ -1208,11 +1204,11 @@ linkTitle = try $ do
1208link :: GenParser Char ParserState Inline
1204link :: GenParser Char ParserState Inline
1209link = try $ do
1205link = try $ do
1210 lab <- reference
1206 lab <- reference
1211− src <- source <|> referenceLink lab
1207+ (src, tit) <- source <|> referenceLink lab
1212 sanitize <- getState >>= return . stateSanitizeHTML
1208 sanitize <- getState >>= return . stateSanitizeHTML
1213− if sanitize && unsanitaryURI (fst src)
1209+ if sanitize && unsanitaryURI src
1214 then fail "Unsanitary URI"
1210 then fail "Unsanitary URI"
1215− else return $ Link lab src
1211+ else return $ Link lab (src, tit)
1216
1212
1217-- a link like [this][ref] or [this][] or [this]
1213-- a link like [this][ref] or [this][] or [this]
1218referenceLink :: [Inline]
1214referenceLink :: [Inline]
@@ -1229,18 +1225,15 @@ referenceLink lab = do
1229autoLink :: GenParser Char ParserState Inline
1225autoLink :: GenParser Char ParserState Inline
1230autoLink = try $ do
1226autoLink = try $ do
1231 char '<'
1227 char '<'
1232− src <- uri <|> (emailAddress >>= (return . ("mailto:" ++)))
1228+ (orig, src) <- uri <|> emailAddress
1233 char '>'
1229 char '>'
1234− let src' = if "mailto:" `isPrefixOf` src
1235− then drop 7 src
1236− else src
1237 st <- getState
1230 st <- getState
1238 let sanitize = stateSanitizeHTML st
1231 let sanitize = stateSanitizeHTML st
1239 if sanitize && unsanitaryURI src
1232 if sanitize && unsanitaryURI src
1240 then fail "Unsanitary URI"
1233 then fail "Unsanitary URI"
1241 else return $ if stateStrict st
1234 else return $ if stateStrict st
1242− then Link [Str src'] (src, "")
1235+ then Link [Str orig] (src, "")
1243− else Link [Code src'] (src, "")
1236+ else Link [Code orig] (src, "")
1244
1237
1245image :: GenParser Char ParserState Inline
1238image :: GenParser Char ParserState Inline
1246image = try $ do
1239image = try $ do
src/Text/Pandoc/Readers/RST.hs+19−18
@@ -556,7 +556,7 @@ targetURI = do
556 contents <- many1 (try (many spaceChar >> newline >>
556 contents <- many1 (try (many spaceChar >> newline >>
557 many1 spaceChar >> noneOf " \t\n") <|> noneOf "\n")
557 many1 spaceChar >> noneOf " \t\n") <|> noneOf "\n")
558 blanklines
558 blanklines
559− return contents
559+ return $ escapeURI $ removeLeadingTrailingSpace $ contents
560
560
561imageKey :: GenParser Char ParserState ([Inline], (String, [Char]))
561imageKey :: GenParser Char ParserState ([Inline], (String, [Char]))
562imageKey = try $ do
562imageKey = try $ do
@@ -565,13 +565,13 @@ imageKey = try $ do
565 skipSpaces
565 skipSpaces
566 string "image::"
566 string "image::"
567 src <- targetURI
567 src <- targetURI
568− return (normalizeSpaces ref, (removeLeadingTrailingSpace src, ""))
568+ return (normalizeSpaces ref, (src, ""))
569
569
570anonymousKey :: GenParser Char st ([Inline], (String, [Char]))
570anonymousKey :: GenParser Char st ([Inline], (String, [Char]))
571anonymousKey = try $ do
571anonymousKey = try $ do
572 oneOfStrings [".. __:", "__"]
572 oneOfStrings [".. __:", "__"]
573 src <- targetURI
573 src <- targetURI
574− return ([Str "_"], (removeLeadingTrailingSpace src, ""))
574+ return ([Str "_"], (src, ""))
575
575
576regularKey :: GenParser Char ParserState ([Inline], (String, [Char]))
576regularKey :: GenParser Char ParserState ([Inline], (String, [Char]))
577regularKey = try $ do
577regularKey = try $ do
@@ -579,7 +579,7 @@ regularKey = try $ do
579 ref <- referenceName
579 ref <- referenceName
580 char ':'
580 char ':'
581 src <- targetURI
581 src <- targetURI
582− return (normalizeSpaces ref, (removeLeadingTrailingSpace src, ""))
582+ return (normalizeSpaces ref, (src, ""))
583
583
584--
584--
585-- tables
585-- tables
@@ -883,7 +883,8 @@ explicitLink = try $ do
883 src <- manyTill (noneOf ">\n") (char '>')
883 src <- manyTill (noneOf ">\n") (char '>')
884 skipSpaces
884 skipSpaces
885 string "`_"
885 string "`_"
886− return $ Link (normalizeSpaces label') (removeLeadingTrailingSpace src, "")
886+ return $ Link (normalizeSpaces label')
887+ (escapeURI $ removeLeadingTrailingSpace src, "")
887
888
888referenceLink :: GenParser Char ParserState Inline
889referenceLink :: GenParser Char ParserState Inline
889referenceLink = try $ do
890referenceLink = try $ do
@@ -891,25 +892,25 @@ referenceLink = try $ do
891 key <- option label' (do{char '_'; return [Str "_"]}) -- anonymous link
892 key <- option label' (do{char '_'; return [Str "_"]}) -- anonymous link
892 state <- getState
893 state <- getState
893 let keyTable = stateKeys state
894 let keyTable = stateKeys state
894− src <- case lookupKeySrc keyTable key of
895+ (src,tit) <- case lookupKeySrc keyTable key of
895− Nothing -> fail "no corresponding key"
896+ Nothing -> fail "no corresponding key"
896− Just target -> return target
897+ Just target -> return target
897 -- if anonymous link, remove first anon key so it won't be used again
898 -- if anonymous link, remove first anon key so it won't be used again
898 let keyTable' = if (key == [Str "_"]) -- anonymous link?
899 let keyTable' = if (key == [Str "_"]) -- anonymous link?
899− then delete ([Str "_"], src) keyTable -- remove first anon key
900+ then delete ([Str "_"], (src,tit)) keyTable -- remove first anon key
900 else keyTable
901 else keyTable
901 setState $ state { stateKeys = keyTable' }
902 setState $ state { stateKeys = keyTable' }
902− return $ Link (normalizeSpaces label') src
903+ return $ Link (normalizeSpaces label') (src, tit)
903
904
904autoURI :: GenParser Char ParserState Inline
905autoURI :: GenParser Char ParserState Inline
905autoURI = do
906autoURI = do
906− src <- uri
907+ (orig, src) <- uri
907− return $ Link [Str src] (src, "")
908+ return $ Link [Str orig] (src, "")
908
909
909autoEmail :: GenParser Char ParserState Inline
910autoEmail :: GenParser Char ParserState Inline
910autoEmail = do
911autoEmail = do
911− src <- emailAddress
912+ (orig, src) <- emailAddress
912− return $ Link [Str src] ("mailto:" ++ src, "")
913+ return $ Link [Str orig] (src, "")
913
914
914autoLink :: GenParser Char ParserState Inline
915autoLink :: GenParser Char ParserState Inline
915autoLink = autoURI <|> autoEmail
916autoLink = autoURI <|> autoEmail
@@ -921,7 +922,7 @@ image = try $ do
921 ref <- manyTill inline (char '|')
922 ref <- manyTill inline (char '|')
922 state <- getState
923 state <- getState
923 let keyTable = stateKeys state
924 let keyTable = stateKeys state
924− src <- case lookupKeySrc keyTable ref of
925+ (src,tit) <- case lookupKeySrc keyTable ref of
925− Nothing -> fail "no corresponding key"
926+ Nothing -> fail "no corresponding key"
926− Just target -> return target
927+ Just target -> return target
927− return $ Image (normalizeSpaces ref) src
928+ return $ Image (normalizeSpaces ref) (src, tit)