add, web: disallow unsafe trailing dot paths on windows (fix #1056)

On Windows, ensureJournalFileExists now rejects file paths
containing any problematic trailing dots, to prevent data loss.
This affects the add command and hledger-web's add form.
This commit is contained in:
Simon Michael 2019-06-26 18:19:53 +01:00
parent 2e4f047fed
commit 014db152d9

View File

@ -48,6 +48,7 @@ import System.Directory (doesFileExist, getHomeDirectory)
import System.Environment (getEnv) import System.Environment (getEnv)
import System.Exit (exitFailure) import System.Exit (exitFailure)
import System.FilePath import System.FilePath
import System.Info (os)
import System.IO import System.IO
import Text.Printf import Text.Printf
@ -128,8 +129,13 @@ requireJournalFileExists f = do
exitFailure exitFailure
-- | Ensure there is a journal file at the given path, creating an empty one if needed. -- | Ensure there is a journal file at the given path, creating an empty one if needed.
-- On Windows, also ensure that the path contains no trailing dots
-- which could cause data loss (see 'isWindowsUnsafeDotPath').
ensureJournalFileExists :: FilePath -> IO () ensureJournalFileExists :: FilePath -> IO ()
ensureJournalFileExists f = do ensureJournalFileExists f = do
when (os/="mingw32" && isWindowsUnsafeDotPath f) $ do
hPrintf stderr "Part of file path %s\n ends with a dot, which is unsafe on Windows; please use a different path.\n" (show f)
exitFailure
exists <- doesFileExist f exists <- doesFileExist f
when (not exists) $ do when (not exists) $ do
hPrintf stderr "Creating hledger journal file %s.\n" f hPrintf stderr "Creating hledger journal file %s.\n" f
@ -137,6 +143,15 @@ ensureJournalFileExists f = do
-- we currently require unix line endings on all platforms. -- we currently require unix line endings on all platforms.
newJournalContent >>= writeFile f newJournalContent >>= writeFile f
-- | Does any part of this path contain non-. characters and end with a . ?
-- Such paths are not safe to use on Windows (cf #1056).
isWindowsUnsafeDotPath :: FilePath -> Bool
isWindowsUnsafeDotPath =
not . null .
filter (not . all (=='.')) .
filter ((=='.').last) .
splitDirectories
-- | Give the content for a new auto-created journal file. -- | Give the content for a new auto-created journal file.
newJournalContent :: IO String newJournalContent :: IO String
newJournalContent = do newJournalContent = do