Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Index update #22

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions assets/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ ApplicationWindow {

MouseArea {
id: mouseRegion
property variant clickPos: "1,1"
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0

property var clickPos: "1, 1"
anchors.fill: parent;

onPressed: {
Expand All @@ -44,10 +39,6 @@ ApplicationWindow {

color: "#333"
radius: 10
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0
anchors.fill: parent
border.width: 2
border.color: "#aaa"
Expand Down Expand Up @@ -335,7 +326,7 @@ ApplicationWindow {
property var view: ListView.view
property int itemIndex: index

text: passwords.get(index).name;
text: passwords.get(index);
font.pixelSize: 18
color: ListView.isCurrentItem? "#dd00bb":"gray"

Expand Down
9 changes: 2 additions & 7 deletions keyinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,6 @@ func parseKeyinfo(statusLine string) GPGAgentKeyInfo {
}
}

func (p *Password) isCached() bool {
ki := p.KeyInfo()
return ki.Cached
}

var algoNames map[packet.PublicKeyAlgorithm]string

func init() {
Expand All @@ -91,11 +86,11 @@ func algoString(a packet.PublicKeyAlgorithm) string {
}

// KeyInfo gets the KeyInfo for this password
func (p *Password) KeyInfo() KeyInfo {
func keyInfo(path string) KeyInfo {
gpgmeMutex.Lock()
defer gpgmeMutex.Unlock()
// Find the keyID for the encrypted data
encKeyID := findKey(p.Path)
encKeyID := findKey(path)

// Extract key from gpgme
c, _ := gpgme.New()
Expand Down
32 changes: 16 additions & 16 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type Passwords struct {
Selected int
Len int
store *PasswordStore
hits []Password
hits []string
}

// Quit the application
Expand All @@ -55,13 +55,13 @@ func (ui *UI) ToggleShowMetadata() {
}

// Get gets the password at a specific index
func (p *Passwords) Get(index int) Password {
func (p *Passwords) Get(index int) string {
if index > len(p.hits) {
fmt.Println("Bad password fetch", index, len(p.hits), p.Len)
return Password{}
return ""
}
pw := p.hits[index]
return pw
return p.store.passwords[pw]
}

// ClearClipboard clears the clipboard
Expand Down Expand Up @@ -101,8 +101,7 @@ func (p *Passwords) CopyToClipboard(selected int) {
ui.setStatus("No password selected")
return
}
pw := (p.hits)[selected]
pass := pw.Password()
pass := Password(p.hits[selected])
if err := clipboard.WriteAll(pass); err != nil {
panic(err)
}
Expand All @@ -121,7 +120,7 @@ func (p *Passwords) Select(selected int) {
// Query updates the hitlist with the given query
func (ui *UI) Query(q string) {
ui.query = q
passwords.Update("queried")
passwords.Update("Queried")
}

func (ui *UI) setStatus(s string) {
Expand All @@ -143,12 +142,12 @@ func (p *Passwords) Update(status string) {
p.hits = p.store.Query(ui.query)
p.Len = len(p.hits)

var pw Password
var pw string

ui.Password.Info = "Test"
if p.Selected < p.Len {
pw = (p.hits)[p.Selected]
ki := pw.KeyInfo()
ki := keyInfo(pw)
if ki.Algorithm != "" {
ui.Password.Info = fmt.Sprintf("Encrypted with %d bit %s key %s",
ki.BitLength, ki.Algorithm, ki.Fingerprint)
Expand All @@ -157,30 +156,31 @@ func (p *Passwords) Update(status string) {
ui.Password.Info = "Not encrypted"
ui.Password.Cached = false
}
ui.Password.Name = pw.Name
ui.Password.Name = p.store.passwords[pw]
}

if ui.ShowMetadata {
ui.Password.Metadata = pw.Metadata()
ui.Password.Metadata = Metadata(pw)
} else {
ui.Password.Metadata = "Press enter to decrypt"
ui.Password.Metadata = pw.Raw()
ui.Password.Metadata = Raw(pw)
}
qml.Changed(p, &p.Len)
qml.Changed(&ui, &ui.Password)
qml.Changed(&ui, &ui.Password.Metadata)
qml.Changed(&ui, &ui.Password.Name)
ui.setStatus(status)
if status != "" {
ui.setStatus(status)
}
}

var ui UI
var passwords Passwords
var ps *PasswordStore

func main() {
ps = NewPasswordStore()
passwords.store = ps
ps := NewPasswordStore()
ps.Subscribe(passwords.Update)
passwords.store = ps
passwords.Update("Started")
if err := qml.Run(run); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
Expand Down
96 changes: 60 additions & 36 deletions pass.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bufio"
"encoding/base64"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
Expand All @@ -14,53 +13,49 @@ import (
"path/filepath"
"strings"

"sort"

"github.com/proglottis/gpgme"
"github.com/rjeczalik/notify"
)

// PasswordStore keeps track of all the passwords
type PasswordStore struct {
passwords []Password
passwords map[string]string
Prefix string
subscribers []Subscriber
}

// Subscriber is a callback for changes in the PasswordStore
type Subscriber func(status string)

// A Password entry in Passwords
type Password struct {
Name string
Path string
}

func (p *Password) decrypt() (io.Reader, error) {
func decrypt(path string) (io.Reader, error) {
gpgmeMutex.Lock()
defer gpgmeMutex.Unlock()
file, _ := os.Open(p.Path)
file, _ := os.Open(path)
defer file.Close()
return gpgme.Decrypt(file)
}

// Raw returns the password in encrypted form
func (p *Password) Raw() string {
file, _ := os.Open(p.Path)
func Raw(path string) string {
file, _ := os.Open(path)
defer file.Close()
data, _ := ioutil.ReadAll(file)
return base64.StdEncoding.EncodeToString(data)
}

// Metadata of the password
func (p *Password) Metadata() string {
out, _ := p.decrypt()
func Metadata(path string) string {
out, _ := decrypt(path)
nr := bufio.NewReader(out)
nr.ReadString('\n')
metadata, _ := nr.ReadString('\003')
return metadata
}

func (p *Password) Password() string {
decrypted, _ := p.decrypt()
func Password(path string) string {
decrypted, _ := decrypt(path)
nr := bufio.NewReader(decrypted)
password, _ := nr.ReadString('\n')
return password
Expand All @@ -74,19 +69,22 @@ func NewPasswordStore() *PasswordStore {
log.Fatal(err)
}
ps.Prefix = path
ps.passwords = make(map[string]string)
ps.indexAll()
ps.watch()
return ps
}

// Query the PasswordStore
func (ps *PasswordStore) Query(q string) []Password {
var hits []Password
for _, p := range ps.passwords {
if match(q, p.Name) {
hits = append(hits, p)
func (ps *PasswordStore) Query(q string) []string {
var hits []string
for pwPath, pwName := range ps.passwords {
if match(q, pwName) {
hits = append(hits, pwPath)
}
}

sort.Strings(hits)
return hits
}

Expand Down Expand Up @@ -119,23 +117,30 @@ func match(query, candidate string) bool {

}

func generateName(path, prefix string) string {
name := strings.TrimPrefix(path, prefix)
name = strings.TrimSuffix(name, ".gpg")
name = strings.TrimPrefix(name, "/")
const MaxLen = 40
if len(name) > MaxLen {
name = "..." + name[len(name)-MaxLen:]
}
return name
}

func (ps *PasswordStore) indexFile(path string, info os.FileInfo, err error) error {
if strings.HasSuffix(path, ".gpg") {
name := strings.TrimPrefix(path, ps.Prefix)
name = strings.TrimSuffix(name, ".gpg")
name = strings.TrimPrefix(name, "/")
const MaxLen = 40
if len(name) > MaxLen {
name = "..." + name[len(name)-MaxLen:]
}

ps.add(Password{Name: name, Path: path})
ps.add(path)
}
return nil
}

func (ps *PasswordStore) index(path string) {
filepath.Walk(path, ps.indexFile)
}

func (ps *PasswordStore) indexAll() {
filepath.Walk(ps.Prefix, ps.indexFile)
ps.index(ps.Prefix)
}

func (ps *PasswordStore) watch() {
Expand All @@ -146,15 +151,34 @@ func (ps *PasswordStore) watch() {

go func() {
for {
<-c
ps.indexAll()
ps.updateIndex(<-c)
}
}()
}

func (ps *PasswordStore) add(p Password) {
ps.passwords = append(ps.passwords, p)
ps.publishUpdate(fmt.Sprintf("Indexed %d entries", len(ps.passwords)))
func (ps *PasswordStore) updateIndex(eventInfo notify.EventInfo) {
switch eventInfo.Event() {
case notify.Create:
ps.index(eventInfo.Path())
ps.publishUpdate("Entry added")
case notify.Remove:
ps.remove(eventInfo.Path())
ps.publishUpdate("Entry removed")
case notify.Rename:
ps.remove(eventInfo.Path())
ps.indexAll()
ps.publishUpdate("Index updated")
case notify.Write:
// Path and Name haven ot changed, ignore.
}
}

func (ps *PasswordStore) add(path string) {
ps.passwords[path] = generateName(path, ps.Prefix)
}

func (ps *PasswordStore) remove(path string) {
delete(ps.passwords, path)
}

func findPasswordStore() (string, error) {
Expand Down