diff options
author | Mohamed Zenadi <zeapo@users.noreply.github.com> | 2016-07-30 19:23:58 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-30 19:23:58 +0100 |
commit | 113725e3ab94fa72824b81595fb3a8d64a636e6e (patch) | |
tree | 2978b830c330773eac904f3dda8b68c17e9464ba | |
parent | 8be387c5a72dddd80d9ecfd93e41da0d8f22381f (diff) | |
parent | 99934d35b99fc2188c962a53cf7bc0f8b83fe58f (diff) |
Merge pull request #201 from crosser/oisafe2pstore
oisafe2pstore.hs: script to migrate from OI Safe
-rw-r--r-- | contrib/oisafe2pstore/oisafe2pstore.hs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/contrib/oisafe2pstore/oisafe2pstore.hs b/contrib/oisafe2pstore/oisafe2pstore.hs new file mode 100644 index 00000000..0417fc0a --- /dev/null +++ b/contrib/oisafe2pstore/oisafe2pstore.hs @@ -0,0 +1,85 @@ +{- + 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 |