2019-02-09 06:54:22 +09:00
|
|
|
{- This file is part of Vervis.
|
|
|
|
-
|
|
|
|
- Written in 2019 by fr33domlover <fr33domlover@riseup.net>.
|
|
|
|
-
|
|
|
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
|
|
|
-
|
|
|
|
- The author(s) have dedicated all copyright and related and neighboring
|
|
|
|
- rights to this software to the public domain worldwide. This software is
|
|
|
|
- distributed without any warranty.
|
|
|
|
-
|
|
|
|
- You should have received a copy of the CC0 Public Domain Dedication along
|
|
|
|
- with this software. If not, see
|
|
|
|
- <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Data.KeyFile
|
|
|
|
( KeyFile (..)
|
2019-03-11 11:01:41 +09:00
|
|
|
, KeyFileLoadMode ()
|
|
|
|
, determineKeyFileLoadMode
|
2019-02-09 06:54:22 +09:00
|
|
|
, loadKeyFile
|
|
|
|
)
|
|
|
|
where
|
|
|
|
|
2019-03-11 11:01:41 +09:00
|
|
|
import Control.Monad
|
2019-02-09 06:54:22 +09:00
|
|
|
import Data.ByteString (ByteString)
|
2019-03-11 11:01:41 +09:00
|
|
|
import System.Directory
|
2019-02-09 06:54:22 +09:00
|
|
|
|
|
|
|
import qualified Data.ByteString as B (readFile, writeFile)
|
|
|
|
|
|
|
|
class KeyFile a where
|
|
|
|
generateKey :: IO a
|
|
|
|
parseKey :: ByteString -> IO a
|
|
|
|
renderKey :: a -> ByteString
|
|
|
|
|
2019-03-11 11:01:41 +09:00
|
|
|
data KeyFileLoadMode
|
|
|
|
= WriteAll
|
|
|
|
| ImportExisting
|
|
|
|
| LoadAll
|
|
|
|
| WriteMissing
|
|
|
|
|
|
|
|
determineKeyFileLoadMode :: Bool -> IO KeyFileLoadMode
|
|
|
|
determineKeyFileLoadMode setup = do
|
|
|
|
laxSetup <- checkSwitch "_keyfile_import_existing"
|
|
|
|
laxLater <- checkSwitch "_keyfile_write_missing"
|
|
|
|
if setup
|
|
|
|
then do
|
|
|
|
when laxLater $ fail "Non-setup switch present during setup"
|
|
|
|
return $ if laxSetup then ImportExisting else WriteAll
|
|
|
|
else do
|
|
|
|
when laxSetup $ fail "Setup switch present after initial setup"
|
|
|
|
return $ if laxLater then WriteMissing else LoadAll
|
|
|
|
where
|
|
|
|
checkSwitch file = do
|
|
|
|
exists <- doesFileExist file
|
|
|
|
if exists
|
|
|
|
then do
|
|
|
|
blank <- (== 0) <$> getFileSize file
|
|
|
|
if blank
|
|
|
|
then do
|
|
|
|
removeFile file
|
|
|
|
return True
|
|
|
|
else fail $ "Switch file " ++ file ++ "isn't empty!"
|
|
|
|
else return False
|
|
|
|
|
|
|
|
loadKeyFile :: KeyFile a => KeyFileLoadMode -> FilePath -> IO a
|
|
|
|
loadKeyFile mode path = do
|
2019-02-09 06:54:22 +09:00
|
|
|
e <- doesFileExist path
|
|
|
|
if e
|
2019-03-11 11:01:41 +09:00
|
|
|
then case mode of
|
|
|
|
WriteAll -> fail $ "loadKeyFile: Initial setup but file already exists: " ++ path
|
|
|
|
_ -> parseKey =<< B.readFile path
|
|
|
|
else case mode of
|
|
|
|
LoadAll -> fail $ "loadKeyFile: File not found: " ++ path
|
|
|
|
_ -> do
|
2019-02-09 06:54:22 +09:00
|
|
|
k <- generateKey
|
|
|
|
B.writeFile path $ renderKey k
|
|
|
|
return k
|