import Types import Pretty import Parser import Data.List (isInfixOf) import System.FilePath (takeBaseName) import System.Process (readProcess, callCommand) -- Search functions -- byServer :: String -> Keychain -> [Item] byServer s = byAttrib (Left "srv", Str s) byAccount :: String -> Keychain -> [Item] byAccount a = byAttrib (Left "acct", Str a) byAttrib :: Attrib -> Keychain -> [Item] byAttrib a = filter (elem a . attrs) attrib :: Name -> Item -> Maybe Value attrib a = lookup a . attrs fuzzy :: String -> Keychain -> [Item] fuzzy x = filter (any (isInfixOf x) . strings) where strings = map unvalue . attrs unvalue (_, Str s) = s unvalue _ = "" -- Keychain access -- keychainList :: IO [FilePath] keychainList = runParser parseKeychainList <$> readProcess "security" ["list-keychains"] "" getKeychain :: IO Keychain getKeychain = do paths <- filter ((/="System") . takeBaseName) <$> keychainList dump <- readProcess "security" ("dump-keychain" : "-d" : paths) "" return (runParser parseKeychain dump) sendClipboard :: String -> IO () sendClipboard text = callCommand $ "echo " ++ (show text) ++ " | pbcopy" main :: IO () main = do res <- fuzzy "gog.com" <$> getKeychain sendClipboard (content (head res)) pprint res