Rename to passgo and run go fmt.

This commit is contained in:
Greg 2019-09-05 06:41:39 -04:00
parent fc7a4c272e
commit 28ccd6d107
8 changed files with 135 additions and 138 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
cmd/gpass/gpass
cmd/gpass-gui/gpass-gui
cmd/gpass/passgo
cmd/gpass-gui/passgo-gui

View File

@ -1,4 +1,4 @@
# gpass
# passgo
This repository includes Go code to interact with pass, the Unix password
manager. Library code is provided to open a password store, list
@ -7,7 +7,7 @@ a simple passphrase input function, or, if gpg-agent is running (on MacOS),
it will connect automatically to request your GPG passphrase.
```go
store, err := gpass.GetStore()
store, err := passgo.GetStore()
if err != nil { ... }
passlist := store.List()
//storeDir := store.Dir
@ -15,7 +15,7 @@ for _,x := range passlist {
if x.Pathname = "myPass" {
p, err := store.Decrypt(x.Pathname)
if err == nil {
gpass.Clip(p) // put on the clipboard
passgo.Clip(p) // put on the clipboard
} else {
log.Fatal("Cannot decrypt ", x.Pathname)
}

View File

@ -1,28 +0,0 @@
package main
import (
golog "log"
"os"
)
type logLevelT int
const (
Fatal logLevelT = 1 << iota
Error
Warn
Info
Debug
DebugGfx
)
var loglevel = Fatal | Error | Warn | Info
func log(level logLevelT, msg ...interface{}) {
if level & loglevel != 0 {
golog.Print(msg...)
}
if level & Fatal != 0 {
os.Exit(-1)
}
}

28
cmd/passgo-gui/log.go Normal file
View File

@ -0,0 +1,28 @@
package main
import (
golog "log"
"os"
)
type logLevelT int
const (
Fatal logLevelT = 1 << iota
Error
Warn
Info
Debug
DebugGfx
)
var loglevel = Fatal | Error | Warn | Info
func log(level logLevelT, msg ...interface{}) {
if level&loglevel != 0 {
golog.Print(msg...)
}
if level&Fatal != 0 {
os.Exit(-1)
}
}

View File

@ -4,56 +4,55 @@ package main
import (
//"fmt"
"path"
"strings"
"image"
"image/color"
"path"
"strings"
"sync"
"gioui.org/ui"
"gioui.org/ui/app"
"gioui.org/ui/f32"
"gioui.org/ui/gesture"
"gioui.org/ui/input"
"gioui.org/ui/key"
"gioui.org/ui/layout"
"gioui.org/ui/text"
"gioui.org/ui/measure"
"gioui.org/ui/f32"
"gioui.org/ui/paint"
"gioui.org/ui/gesture"
"gioui.org/ui/pointer"
"gioui.org/ui/text"
"github.com/fsnotify/fsnotify"
"golang.org/x/image/font/gofont/goregular"
"golang.org/x/image/font/sfnt"
"git.wow.st/gmp/gpass"
"git.wow.st/gmp/passgo"
)
func main() {
var err error
store,err = gpass.GetStore()
store, err = passgo.GetStore()
if err != nil {
log(Fatal, err)
}
updated = make(chan struct{})
go Updater()
log(Info,"Staring event loop")
log(Info, "Staring event loop")
go eventLoop()
app.Main()
log(Info,"Event loop returned")
log(Info, "Event loop returned")
}
var (
l []gpass.Pass
mux sync.Mutex
store *gpass.Store
l []passgo.Pass
mux sync.Mutex
store *passgo.Store
updated chan struct{}
)
func Updater() {
update := func() {
ltmp,err := store.List()
ltmp, err := store.List()
if err != nil {
log(Fatal, err)
}
@ -74,16 +73,16 @@ func Updater() {
case <-watcher.Events:
update()
case e := <-watcher.Errors:
log(Info, "Watcher error: ",e)
log(Info, "Watcher error: ", e)
}
}
}
type Button struct {
Face text.Face
Label string
Click gesture.Click
Color color.RGBA
Face text.Face
Label string
Click gesture.Click
Color color.RGBA
clicked bool
}
@ -114,7 +113,6 @@ func rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) {
b.End()
}
func (b *Button) Layout(c ui.Config, ops *ui.Ops, q input.Queue, cs layout.Constraints) layout.Dimensions {
b.clicked = false
for ev, ok := b.Click.Next(q); ok; ev, ok = b.Click.Next(q) {
@ -142,7 +140,7 @@ func (b *Button) Layout(c ui.Config, ops *ui.Ops, q input.Queue, cs layout.Const
c1 := st.End(layoutRRect(b.Color, c, ops, st.Expand()))
dims = st.Layout(c1, c2)
return ins.End(dims)
}
}
func (b *Button) Clicked() bool {
return b.clicked
@ -165,23 +163,25 @@ func eventLoop() {
passInput.SetText("passphrase")
passSubmit := &Button{Face: face, Label: "submit"}
lst := &layout.List{Axis: layout.Vertical}
passBtns := make([]*Button,0)
passBtns := make([]*Button, 0)
_ = passInput
_ = passSubmit
pathnames := make([]string,0)
pathnames := make([]string, 0)
updateBtns := func() {
passBtns = passBtns[:0]
pathnames = pathnames[:0]
mux.Lock()
for _,x := range l {
for _, x := range l {
_, n := path.Split(x.Pathname)
s := strings.Repeat(" /",x.Level)
s := strings.Repeat(" /", x.Level)
z := ""
if x.Dir { z = "/" }
passBtns = append(passBtns,&Button{
Face:face,
Label:strings.Join([]string{s,n,z},""),
if x.Dir {
z = "/"
}
passBtns = append(passBtns, &Button{
Face: face,
Label: strings.Join([]string{s, n, z}, ""),
Color: color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xf0},
})
pathnames = append(pathnames, x.Pathname)
@ -190,21 +190,20 @@ func eventLoop() {
}
updateBtns()
for {
select {
case <-updated:
log(Info,"UPDATE")
for {
select {
case <-updated:
log(Info, "UPDATE")
updateBtns()
w.Invalidate()
case e := <-w.Events():
w.Invalidate()
case e := <-w.Events():
switch e := e.(type) {
case app.DestroyEvent:
return
case app.UpdateEvent:
c := &e.Config
ops.Reset()
faces.Reset(c)
faces.Reset(c)
var dims layout.Dimensions
cs := layout.RigidConstraints(e.Size)
cs = margin.Begin(c, ops, cs)
@ -219,15 +218,15 @@ func eventLoop() {
lst.End(dims)
if btn.Clicked() {
// don't block UI thread on decryption attempt
log(Info,"Clicked ", btn.Label)
log(Info, "Clicked ", btn.Label)
go func(name string) {
//p,err := store.Decrypt(name, prompt)
p,err := store.Decrypt(name)
p, err := store.Decrypt(name)
if err == nil {
gpass.Clip(p)
passgo.Clip(p)
} else {
log(Info,"Can't decrypt ", name)
log(Info,err)
log(Info, "Can't decrypt ", name)
log(Info, err)
}
}(pathnames[lst.Index()])
}
@ -235,9 +234,8 @@ func eventLoop() {
mux.Unlock()
dims = lst.Layout()
dims = margin.End(dims)
w.Update(ops)
w.Update(ops)
}
}
}
}
}
}

View File

@ -6,11 +6,11 @@ import (
"path"
"strings"
"git.wow.st/gmp/gpass"
"git.wow.st/gmp/passgo"
)
func usage() {
fmt.Println("gpass [-c|--clip] [name]")
fmt.Println("passgo [-c|--clip] [name]")
os.Exit(-1)
}
@ -18,53 +18,55 @@ type options struct {
clip bool
}
func parse(args []string) ([]string,options) {
ret := make([]string,0)
func parse(args []string) ([]string, options) {
ret := make([]string, 0)
opts := options{}
for _,a := range args {
for _, a := range args {
switch {
case a == "-c",a == "--clip":
case a == "-c", a == "--clip":
opts.clip = true
case a[0] == '-':
usage()
default:
ret = append(ret,a)
ret = append(ret, a)
}
}
return ret,opts
return ret, opts
}
func main() {
store,err := gpass.GetStore()
store, err := passgo.GetStore()
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
args := os.Args[1:]
args,opts := parse(args)
args, opts := parse(args)
switch len(args) {
case 0:
l,err := store.List()
l, err := store.List()
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
for _, x := range l {
_, n := path.Split(x.Pathname)
s := strings.Repeat(" /",x.Level)
s := strings.Repeat(" /", x.Level)
z := ""
if x.Dir { z = "/" }
fmt.Println(strings.Join([]string{s,n,z},""))
if x.Dir {
z = "/"
}
fmt.Println(strings.Join([]string{s, n, z}, ""))
}
case 1:
p,err := store.Decrypt(args[0])
p, err := store.Decrypt(args[0])
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
if opts.clip {
gpass.Clip(p)
passgo.Clip(p)
} else {
fmt.Print(p)
}
@ -72,4 +74,3 @@ func main() {
usage()
}
}

View File

@ -1,11 +1,11 @@
//+build !android !linux
package gpass
package passgo
import (
"fmt"
"bufio"
"bytes"
"fmt"
"os"
"os/exec"
"os/user"
@ -73,7 +73,7 @@ func setAgentInfo() {
}
s := fmt.Sprintf("%s:%d:1", filename, pid)
fmt.Printf("GPG_AGENT_INFO = %s\n", s)
os.Setenv("GPG_AGENT_INFO",s)
os.Setenv("GPG_AGENT_INFO", s)
// gpg-agent is running, so use GPGPrompt as password prompt
ask = GPGPrompt
@ -90,4 +90,3 @@ func Clip(x string) {
cmd.Stdin = b
cmd.Run()
}

75
main.go
View File

@ -1,4 +1,4 @@
package gpass
package passgo
import (
"bufio"
@ -22,7 +22,7 @@ import (
var (
basename *regexp.Regexp
ask openpgp.PromptFunction
ask openpgp.PromptFunction
)
func init() {
@ -30,19 +30,19 @@ func init() {
}
type Store struct {
Dir string
Dir string
keyring openpgp.KeyRing
}
func GetStore() (*Store, error) {
ret := &Store{}
u, err := user.Current()
if err != nil {
return ret, fmt.Errorf("Can't get current user.")
}
ret.Dir = path.Join(u.HomeDir,".password-store")
u, err := user.Current()
if err != nil {
return ret, fmt.Errorf("Can't get current user.")
}
ret.Dir = path.Join(u.HomeDir, ".password-store")
fd, err := os.Open(path.Join(u.HomeDir,".gnupg/secring.gpg"))
fd, err := os.Open(path.Join(u.HomeDir, ".gnupg/secring.gpg"))
defer fd.Close()
if err != nil {
return ret, fmt.Errorf("Can't open keyring file")
@ -52,30 +52,30 @@ func GetStore() (*Store, error) {
return ret, fmt.Errorf("Can't open gnupg keyring.")
}
ret.keyring = kr
return ret, nil
return ret, nil
}
type caseInsensitive []os.FileInfo
func (fs caseInsensitive) Len() int { return len(fs) }
func (fs caseInsensitive) Len() int { return len(fs) }
func (fs caseInsensitive) Swap(i, j int) { fs[i], fs[j] = fs[j], fs[i] }
func (fs caseInsensitive) Less(i, j int) bool {
return strings.ToLower(fs[i].Name()) < strings.ToLower(fs[j].Name())
return strings.ToLower(fs[i].Name()) < strings.ToLower(fs[j].Name())
}
type Pass struct {
Pathname string
Level int
Dir bool
Level int
Dir bool
}
func (s *Store) List() ([]Pass,error) {
return s.list(0,"")
func (s *Store) List() ([]Pass, error) {
return s.list(0, "")
}
func (s *Store) list(level int, p string) ([]Pass,error) {
ret := make([]Pass,0)
dir := path.Join(s.Dir,p)
func (s *Store) list(level int, p string) ([]Pass, error) {
ret := make([]Pass, 0)
dir := path.Join(s.Dir, p)
fd, err := os.Open(dir)
defer fd.Close()
if err != nil {
@ -87,25 +87,25 @@ func (s *Store) list(level int, p string) ([]Pass,error) {
}
sort.Sort(caseInsensitive(files))
for _, x := range files {
n := basename.ReplaceAllLiteralString(x.Name(),"")
entry := Pass{Pathname: path.Join(p,n),Level: level}
n := basename.ReplaceAllLiteralString(x.Name(), "")
entry := Pass{Pathname: path.Join(p, n), Level: level}
if n[0] == '.' {
continue
}
if x.IsDir() {
entry.Dir = true
ret = append(ret,entry)
l,err := s.list(level+1,path.Join(p,x.Name()))
ret = append(ret, entry)
l, err := s.list(level+1, path.Join(p, x.Name()))
if err != nil {
return nil,err
return nil, err
}
ret = append(ret,l...)
ret = append(ret, l...)
} else {
ret = append(ret,entry)
ret = append(ret, entry)
}
}
return ret,nil
return ret, nil
}
func AskPass(prompts ...func() []byte) openpgp.PromptFunction {
@ -124,7 +124,7 @@ func AskPass(prompts ...func() []byte) openpgp.PromptFunction {
var err error
var passphrase []byte
dec := func(p *packet.PrivateKey) {
for i := 0; i<3; i++ {
for i := 0; i < 3; i++ {
if err = p.Decrypt(passphrase); err == nil {
break
}
@ -135,7 +135,7 @@ func AskPass(prompts ...func() []byte) openpgp.PromptFunction {
var ret openpgp.PromptFunction
ret = func(keys []openpgp.Key, symmetric bool) ([]byte, error) {
if !symmetric {
for _,k := range keys {
for _, k := range keys {
if p := k.PrivateKey; p != nil && p.Encrypted {
dec(p)
}
@ -175,18 +175,18 @@ func GPGPrompt(keys []openpgp.Key, symmetric bool) ([]byte, error) {
return nil, fmt.Errorf("Unable to find key")
}
func (s *Store) Decrypt(name string, prompts ...func() []byte) (string,error) {
func (s *Store) Decrypt(name string, prompts ...func() []byte) (string, error) {
if ask == nil {
ask = AskPass(prompts...)
}
file := path.Join(s.Dir, strings.Join([]string{name,".gpg"},""))
file := path.Join(s.Dir, strings.Join([]string{name, ".gpg"}, ""))
if _, err := os.Stat(file); os.IsNotExist(err) {
return "",fmt.Errorf("Not in password store.")
return "", fmt.Errorf("Not in password store.")
}
fd, err := os.Open(file)
defer fd.Close()
if err != nil {
return "",err
return "", err
}
var reader io.Reader
unarmor, err := armor.Decode(fd)
@ -197,19 +197,18 @@ func (s *Store) Decrypt(name string, prompts ...func() []byte) (string,error) {
fd, err = os.Open(file)
defer fd.Close()
if err != nil {
return "",err
return "", err
}
reader = fd
}
md, err := openpgp.ReadMessage(reader,s.keyring,ask,nil)
md, err := openpgp.ReadMessage(reader, s.keyring, ask, nil)
if err != nil {
fmt.Println("Error reading message")
return "",err
return "", err
}
ra, err := ioutil.ReadAll(md.UnverifiedBody)
if err != nil {
return "",err
return "", err
}
return string(ra), nil
}