Android-Password-Store/contrib/oisafe2pstore/oisafe2pstore.hs

86 lines
2.4 KiB
Haskell
Raw Normal View History

{-
oisafe2psore - Quick and dirty script to convert OI Safe export CSV
into the password-store tree format.
Copyright 2016 Eugene Crosser
License: BSD, Apache or GPLv3 - chose whatever suits you.
You will need to adjust paths to the GnuPG program and the CSV
file produced by OI Safe. Also fill in the PGP key I.D.
Description becomes the file name. '*' in the Description is
converted to '+', '/' - to '-'. If this is not sufficient,
adjust the function `sanitize`.
-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
--import Data.Text hiding (head, tail, reverse, length, map)
import Control.Monad
import Text.CSV
import System.Directory
import System.Process
import System.Exit
--gpg = "/usr/local/bin/gpg2"
gpg = "/usr/bin/gpg2"
keyid = "01234567" -- !!!Fill in the real I.D. here!!!
data Entry = Entry { fCategory :: String
, fDescription :: String
, fWebsite :: String
, fUsername :: String
, fPassword :: String
, fNotes :: String
};
instance Show Entry where
show e = fPassword e
++ nonempty "User" (fUsername e)
++ nonempty "Website" (fWebsite e)
++ nonempty "Notes" (fNotes e)
where
nonempty :: String -> String -> String
nonempty l v = if length v > 0 then "\n" ++ l ++ ": " ++ v else ""
pathOf e = (sanitize (fCategory e), sanitize (fDescription e))
sanitize = map substsafe
where
substsafe '/' = '-'
substsafe '*' = '+'
substsafe x = x
record2entry :: Record -> Maybe Entry
record2entry [fCat,fDesc,fWeb,fUser,fPass,fNote,_] =
Just (Entry { fCategory = fCat
, fDescription = fDesc
, fWebsite = fWeb
, fUsername = fUser
, fPassword = fPass
, fNotes = fNote
})
record2entry _ = Nothing
main = parseCSVFromFile "oisafe.csv"
>>= either (error . show) ((mapM_ makeEntry) . tail)
makeEntry :: Record -> IO ()
makeEntry = buildFile . record2entry
buildFile :: Maybe Entry -> IO ()
buildFile Nothing = return ()
buildFile (Just e) = do
let
(sub, file) = pathOf e
dir = "password-store/" ++ sub
path = dir ++ "/" ++ file ++ ".gpg"
cont = show e
(rc, stdout, stderr) <- readProcessWithExitCode gpg ["-ae", "-r", keyid] cont
when (rc /= ExitSuccess) $ error $ "gpg rc " ++ (show rc) ++ " message " ++ stderr
createDirectoryIfMissing True dir
writeFile path stdout