lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 249fa3098ef81e6a84cb0eae585413f1da5f069f
parent 33d71ec6edde049ed71c4d843477ad43fbd11706
Author: Sean Enck <sean@ttypty.com>
Date:   Fri, 23 Jul 2021 19:51:40 -0400

clipboard for totp should work

Diffstat:
Mcmd/bash/completions.bash | 23++++++++++++++++-------
Mcmd/lb/main.go | 36+++---------------------------------
Mcmd/totp/main.go | 28++++++++++++++++++++++------
Ainternal/clip.go | 44++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 85 insertions(+), 46 deletions(-)

diff --git a/cmd/bash/completions.bash b/cmd/bash/completions.bash @@ -13,7 +13,7 @@ _lb() { opts="-m $(lb ls)" ;; "totp") - opts=$(lb totp ls) + opts="-c clip $(lb totp ls)" ;; "pwgen") opts="-length -transform -special" @@ -23,12 +23,21 @@ _lb() { ;; esac fi - if [ $COMP_CWORD -eq 3 ] && [ "${COMP_WORDS[1]}" == "insert" ]; then - if [ "${COMP_WORDS[2]}" == "-m" ]; then - opts=$(lb ls) - else - opts="-m" - fi + if [ $COMP_CWORD -eq 3 ]; then + case "${COMP_WORDS[1]}" in + "insert") + if [ "${COMP_WORDS[2]}" == "-m" ]; then + opts=$(lb ls) + else + opts="-m" + fi + ;; + "totp") + if [ "${COMP_WORDS[2]}" == "-c" ] || [ "${COMP_CWORDS[2]}" == "clip" ]; then + opts=$(lb totp ls) + fi + ;; + esac fi if [ ! -z "$opts" ]; then COMPREPLY=( $(compgen -W "$opts" -- $cur) ) diff --git a/cmd/lb/main.go b/cmd/lb/main.go @@ -69,34 +69,6 @@ func readInput() (string, error) { return first, nil } -func pipeTo(command, value string, wait bool, args ...string) { - cmd := exec.Command(command, args...) - stdin, err := cmd.StdinPipe() - if err != nil { - internal.Die("unable to get stdin pipe", err) - } - - go func() { - defer stdin.Close() - if _, err := stdin.Write([]byte(value)); err != nil { - fmt.Printf("failed writing to stdin: %v\n", err) - } - }() - var ran error - if wait { - ran = cmd.Run() - } else { - ran = cmd.Start() - } - if ran != nil { - internal.Die("failed to run command", ran) - } -} - -func clipboard(value string) { - pipeTo("pbcopy", value, true) -} - func main() { args := os.Args if len(args) < 2 { @@ -198,9 +170,7 @@ func main() { fmt.Println(value) return } - clipboard(value) - fmt.Println("clipboard will clear in 45 seconds") - pipeTo("lb", value, false, "clear") + internal.CopyToClipboard(value) case "clear": idx := 0 val, err := stdin(false) @@ -208,7 +178,7 @@ func main() { internal.Die("unable to read value to clear", err) } val = strings.TrimSpace(val) - for idx < 45 { + for idx < internal.MaxClipTime { idx++ time.Sleep(1 * time.Second) out, err := exec.Command("pbpaste").Output() @@ -221,7 +191,7 @@ func main() { return } } - clipboard("") + internal.CopyToClipboard("") default: tryCommand := fmt.Sprintf("lb-%s", command) c := exec.Command(tryCommand, args[2:]...) diff --git a/cmd/totp/main.go b/cmd/totp/main.go @@ -44,7 +44,7 @@ func clear() { } } -func display(token string) error { +func display(token string, clip bool) error { tok := strings.TrimSpace(token) store := filepath.Join(getEnv(), tok+internal.Extension) if !internal.PathExists(store) { @@ -58,7 +58,9 @@ func display(token string) error { if err != nil { return err } - clear() + if !clip { + clear() + } totpToken := string(val) first := true running := 0 @@ -86,8 +88,14 @@ func display(token string) error { if err != nil { return err } - outputs = append(outputs, fmt.Sprintf("%s\n %s", tok, code)) - outputs = append(outputs, "-> CTRL+C to exit") + if !clip { + outputs = append(outputs, fmt.Sprintf("%s\n %s", tok, code)) + outputs = append(outputs, "-> CTRL+C to exit") + } else { + fmt.Printf("\n -> %s\n\n", expires) + internal.CopyToClipboard(code) + return nil + } startColor := "" endColor := "" if left < 10 { @@ -101,7 +109,7 @@ func display(token string) error { func main() { args := os.Args - if len(args) != 2 { + if len(args) > 3 { internal.Die("subkey required", internal.NewLockboxError("invalid arguments")) } cmd := args[1] @@ -116,7 +124,15 @@ func main() { } return } - if err := display(cmd); err != nil { + clip := false + if len(args) == 3 { + if cmd != "-c" && cmd != "clip" { + internal.Die("subcommand not supported", internal.NewLockboxError("invalid sub command")) + } + clip = true + cmd = args[2] + } + if err := display(cmd, clip); err != nil { internal.Die("failed to show totp token", err) } } diff --git a/internal/clip.go b/internal/clip.go @@ -0,0 +1,44 @@ +package internal + +import ( + "fmt" + "os/exec" +) + +const ( + // MaxClipTime is the max time to let something stay in the clipboard. + MaxClipTime = 45 +) + +// CopyToClipboard will copy to clipboard, if non-empty will clear later. +func CopyToClipboard(value string) { + pipeTo("pbcopy", value, true) + if value != "" { + fmt.Printf("clipboard will clear in %d seconds\n", MaxClipTime) + pipeTo("lb", value, false, "clear") + } +} + +func pipeTo(command, value string, wait bool, args ...string) { + cmd := exec.Command(command, args...) + stdin, err := cmd.StdinPipe() + if err != nil { + Die("unable to get stdin pipe", err) + } + + go func() { + defer stdin.Close() + if _, err := stdin.Write([]byte(value)); err != nil { + fmt.Printf("failed writing to stdin: %v\n", err) + } + }() + var ran error + if wait { + ran = cmd.Run() + } else { + ran = cmd.Start() + } + if ran != nil { + Die("failed to run command", ran) + } +}