@@ -101,7 +101,7 @@ import Data.Char ( toLower, isLower, isUpper, isAlpha,
101101import Data.List ( find, isPrefixOf, intercalate )
102102import qualified Data.Map as M
103103import Network.URI ( escapeURIString, isURI, nonStrictRelativeTo,
104− unEscapeString, parseURIReference )
104+ unEscapeString, parseURIReference, isAllowedInURI )
105105import qualified Data.Set as Set
106106import System.Directory
107107import Text.Pandoc.MIME (getMimeType)
@@ -766,21 +766,22 @@ readDataFileUTF8 userDir fname =
766766-- Returns raw content and maybe mime type.
767767fetchItem :: Maybe String -> String
768768 -> IO (Either E.SomeException (BS.ByteString, Maybe String))
769−fetchItem sourceURL s
770− | isURI s = openURL s
771− | otherwise =
772− case sourceURL >>= parseURIReference of
773− Just u -> case parseURIReference s of
774− Just s' -> openURL $ show $
775− s' `nonStrictRelativeTo` u
776− Nothing -> openURL $ show u ++ "/" ++ s
777− Nothing -> E.try readLocalFile
769+fetchItem sourceURL s =
770+ case (sourceURL >>= parseURIReference . ensureEscaped, ensureEscaped s) of
771+ (_, s') | isURI s' -> openURL s'
772+ (Just u, s') -> -- try fetching from relative path at source
773+ case parseURIReference s' of
774+ Just u' -> openURL $ show $ u' `nonStrictRelativeTo` u
775+ Nothing -> openURL s' -- will throw error
776+ (Nothing, _) -> E.try readLocalFile -- get from local file system
778777 where readLocalFile = do
779778 let mime = case takeExtension s of
780779 ".gz" -> getMimeType $ dropExtension s
781780 x -> getMimeType x
782− cont <- BS.readFile $ unEscapeString s
781+ cont <- BS.readFile $ unEscapeString $ dropFragmentAndQuery s
783782 return (cont, mime)
783+ dropFragmentAndQuery = takeWhile (\c -> c /= '?' && c /= '#')
784+ ensureEscaped = escapeURIString isAllowedInURI
784785
785786-- | Like 'fetchItem', but also looks for items in a 'MediaBag'.
786787fetchItem' :: MediaBag -> Maybe String -> String