@@ -110,8 +110,9 @@ import Data.Char ( toLower, isLower, isUpper, isAlpha,
110110import Data.List ( find, stripPrefix, intercalate )
111111import Data.Version ( showVersion )
112112import qualified Data.Map as M
113−import Network.URI ( escapeURIString, isURI, nonStrictRelativeTo,
114− unEscapeString, parseURIReference, isAllowedInURI )
113+import Network.URI ( escapeURIString, nonStrictRelativeTo,
114+ unEscapeString, parseURIReference, isAllowedInURI,
115+ parseURI, URI(..) )
115116import qualified Data.Set as Set
116117import System.Directory
117118import System.FilePath (splitDirectories, isPathSeparator)
@@ -879,18 +880,30 @@ readDataFileUTF8 :: Maybe FilePath -> FilePath -> IO String
879880readDataFileUTF8 userDir fname =
880881 UTF8.toString `fmap` readDataFile userDir fname
881882
883+-- | Specialized version of parseURIReference that disallows
884+-- single-letter schemes. Reason: these are usually windows absolute
885+-- paths.
886+parseURIReference' :: String -> Maybe URI
887+parseURIReference' s =
888+ case parseURIReference s of
889+ Just u | length (uriScheme u) > 2 -> Just u
890+ _ -> Nothing
891+
882892-- | Fetch an image or other item from the local filesystem or the net.
883893-- Returns raw content and maybe mime type.
884894fetchItem :: Maybe String -> String
885895 -> IO (Either E.SomeException (BS.ByteString, Maybe MimeType))
886896fetchItem sourceURL s =
887− case (sourceURL >>= parseURIReference . ensureEscaped, ensureEscaped s) of
888− (_, s') | isURI s' -> openURL s'
897+ case (sourceURL >>= parseURIReference' . ensureEscaped, ensureEscaped s) of
889898 (Just u, s') -> -- try fetching from relative path at source
890− case parseURIReference s' of
899+ case parseURIReference' s' of
891900 Just u' -> openURL $ show $ u' `nonStrictRelativeTo` u
892901 Nothing -> openURL s' -- will throw error
893− (Nothing, _) -> E.try readLocalFile -- get from local file system
902+ (Nothing, s') ->
903+ case parseURI s' of -- requires absolute URI
904+ -- We don't want to treat C:/ as a scheme:
905+ Just u' | length (uriScheme u') > 2 -> openURL (show u')
906+ _ -> E.try readLocalFile -- get from local file system
894907 where readLocalFile = do
895908 cont <- BS.readFile fp
896909 return (cont, mime)