packages feed

skeleton (empty) → 0.1.0.0

raw patch · 5 files changed

+154/−0 lines, 5 filesdep +argparserdep +attoparsecdep +basesetup-changed

Dependencies added: argparser, attoparsec, base, bytestring, filepath, hex, posix-escape, process, time

Files

+ LICENSE view
@@ -0,0 +1,3 @@+Dual licensed under the MIT and GPL licenses:+http://www.opensource.org/licenses/mit-license.php+http://www.gnu.org/licenses/gpl.html
+ README.md view
@@ -0,0 +1,15 @@+# Skeleton+## Quickly access the OSX keychain++skeleton is a command line tool used to quickly access passwords+stored in the OSX keychain. You can search by account, server+name or any other available attribute and get a list of fuzzy+matched result. The first match is be copied to the clipbdoard.++### Usage+Run skeleton -h for help++### License+Dual licensed under the MIT and GPL licenses:  +http://www.opensource.org/licenses/mit-license.php  +http://www.gnu.org/licenses/gpl.html
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ skeleton.cabal view
@@ -0,0 +1,35 @@+name:                skeleton+version:             0.1.0.0+synopsis:            a tool to access the OSX keychain+description:+  +  skeleton is a command line tool used to quickly access passwords+  stored in the OSX keychain. You can search by account, server+  name or any other available attribute and get a list of fuzzy+  matched result. The first match is be copied to the clipbdoard.++license:             MIT+license-file:        LICENSE+author:              rnhmjoj+maintainer:          micheleguerinirocco@me.com+copyright:           (C) Michele Guerini Rocco+category:            Utility+build-type:          Simple+extra-source-files:  README.md, LICENSE+cabal-version:       >=1.10++source-repository head+  type: git+  location: https://github.com/rnhmjoj/skeleton++executable skeleton+  main-is:             Main.hs+  hs-source-dirs:      src+  default-language:    Haskell2010+  other-extensions:    OverloadedStrings, RecordWildCards,+                       ViewPatterns, FlexibleInstances,+                       TypeSynonymInstances+  build-depends:       base >=4.8 && <= 5.0, filepath, process,+                       attoparsec, bytestring, hex, time,+                       argparser, posix-escape+  ghc-options:         -O2
+ src/Main.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE RecordWildCards #-}++import Skeleton.Types+import Skeleton.Pretty+import Skeleton.Parser++import Control.Monad       (when)+import Data.List           (isInfixOf)+import System.FilePath     (takeBaseName)+import System.Process      (readProcess, callCommand)+import System.Posix.Escape (escape)+import System.Console.ArgParser+++-- Search functions --++byAttrib :: Attrib -> Keychain -> [Item]+byAttrib a = filter (elem 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 = do+  raw <- readProcess "security" ["list-keychains"] ""+  case runParser parseKeychainList raw of+    Just list -> return $ filter ((/="System") . takeBaseName) list+    Nothing   -> error "failed to parse active keychains list"++getKeychain :: [FilePath] -> IO Keychain+getKeychain paths = do+  raw <- readProcess "security" ("dump-keychain" : "-d" : paths) ""+  case runParser parseKeychain raw of+    Just items -> return items+    Nothing    -> error "failed to parse keychain"++sendClipboard :: String -> IO ()+sendClipboard text =+  callCommand $ "echo " ++ (escape text) ++ " | pbcopy"+++-- CLI arguments --++data ProgArgs = ProgArgs+  { searchTerm   :: String+  , keychain     :: FilePath+  , exactMatches :: String+  , resultsLimit :: Int+  , contentOnly  :: Bool+  , noClipboard  :: Bool+  } deriving (Show)++parser :: ParserSpec ProgArgs+parser = ProgArgs+  `parsedBy` reqPos      "term"        `Descr` "Keychain search term"+  `andBy`    optFlag  "" "keychain"    `Descr` "Use a specific keychain (default: all except System)"+  `andBy`    optFlag  "" "exact"       `Descr` "Return exact matches with the given class"+  `andBy`    optFlag  10 "limit"       `Descr` "Set upper results limit (default: 10, 0: unlimited)"+  `andBy`    boolFlag    "content"     `Descr` "Print only the items content"+  `andBy`    boolFlag    "noclipboard" `Descr` "Disable paste to clipboard"++interface :: IO (CmdLnInterface ProgArgs)+interface =+  (`setAppDescr` "Quickly access the OSX keychain") <$>+  (`setAppEpilog` "The skeleton key") <$>+  mkApp parser++main :: IO ()+main = interface >>= (`runApp` search)+++-- Program --++search :: ProgArgs -> IO ()+search ProgArgs {..} = do+  paths <- if null keychain +             then keychainList+             else return [keychain]+  items <- getKeychain paths+  let select = if resultsLimit == 0+                 then id+                 else take resultsLimit+  let res = if null exactMatches+              then select (fuzzy searchTerm items)+              else select (byAttrib (Left exactMatches, Str searchTerm) items)+  if null res+    then putStrLn "No results found"+    else do+      if contentOnly+        then mapM_ putStrLn (map content res)+      else pprint res+      when (not noClipboard) (sendClipboard (content $ head res))