Description
Describe the bug
The file+noindex
scheme is underspecified for Windows paths. It seems to follow the file
scheme (RFC 8089), but Windows paths are not properly parsed by network-uri
. A path like file:///C:/some/path
should produce the path C:/some/path
, however it produces
/C:/some/path
.
$ cabal repl network-uri
...
ghci> import Network.URI
ghci> uri = fromJust $ parseURI "file+noindex:///C:/some/path"
ghci> putStr $ unlines ["Scheme: " <> uriScheme uri, "Auth: " <> show (uriAuthority uri), "Path: " <> uriPath uri, "Frag: " <> uriFragment uri]
Scheme: local+noindex:
Auth: Just (URIAuth {uriUserInfo = "", uriRegName = "", uriPort = ""})
Path: /C:/some/path
Frag:
ghci> readFile $ uriPath uri
*** Exception: /C:/some/path: openFile: invalid argument (Invalid argument)
And if the last slash is removed, then the C:
part is parsed as part of the auth:
$ cabal repl -b network-uri
...
ghci> import Network.URI
ghci> uri = fromJust $ parseURI "file+noindex://C:/some/path"
ghci> putStr $ unlines ["Scheme: " <> uriScheme uri, "Auth: " <> show (uriAuthority uri), "Path: " <> uriPath uri, "Frag: " <> uriFragment uri]
Scheme: local+noindex:
Auth: Just (URIAuth {uriUserInfo = "", uriRegName = "C", uriPort = ":"})
Path: /some/path
Frag:
ghci> readFile $ uriPath uri
"The contents of the file in C:/some/path\n"
ghci>
$ cd D:/
$ cabal repl -b network-uri
...
ghci> readFile "/some/path"
*** Exception: /some/path: openFile: does not exist (No such file or directory)
Just by luck, paths starting with /
are interpreted as paths in the current drive so if we just happen to want that it might work.
If no volume or drive letter is specified and the directory name begins with the directory separator character, the path is relative from the root of the current drive.
The right parsing would be what file-uri
does:
ghci> import System.URI.File
ghci> uri = fromRight undefined $ parseFileURI ExtendedWindows "file:///C:/some/path"
ghci> uri
FileURI {fileAuth = Nothing, filePath = "C:/some/path"}
ghci> readFile $ Data.ByteString.Char8.unpack $ filePath uri
"The contents of the file in C:/some/path\n"
Which results in a path accessible from everywhere in the system. However this is not the end of the story because:
file-uri
only allowsfile:
schemes, it will not allowfile+noindex:
uris.- The file uri RFC does not mention fragments, so
file-uri
does not parse those.
We can either define a parser for file+noindex
from scratch, or do some tricks to parse the uri as a network-uri
uri, then fabricate an intermediate uri with the file:
scheme and use file-uri
or something else. I just didn't want this finding to go missing again.
Activity