Implement clipboard clearing functionality on Wayland

This commit is contained in:
2024-03-02 00:12:55 -05:00
parent 4bd44e7b44
commit 3d621f5e38
2 changed files with 68 additions and 23 deletions
+25 -16
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"bufio"
"github.com/rwinkhart/MUTN/src/cli" "github.com/rwinkhart/MUTN/src/cli"
"github.com/rwinkhart/MUTN/src/offline" "github.com/rwinkhart/MUTN/src/offline"
"os" "os"
@@ -9,28 +10,28 @@ import (
func main() { func main() {
args := os.Args[1:] args := os.Args
argsCount := len(args) argsCount := len(args)
// if no arguments are supplied... // if no arguments are supplied...
if argsCount == 0 { if argsCount == 1 {
// list all entries // list all entries
cli.EntryListGen() cli.EntryListGen()
} else { } else {
// if the first argument is an entry... // if the first argument is an entry...
if strings.HasPrefix(args[0], "/") { if strings.HasPrefix(args[1], "/") {
// store location of target entry // store location of target entry
targetLocation := offline.EntryRoot + offline.PathSeparator + args[0][1:] targetLocation := offline.EntryRoot + offline.PathSeparator + args[1][1:]
// entry reader shortcut (if no other arguments are supplied) // entry reader shortcut (if no other arguments are supplied)
if argsCount == 1 { if argsCount == 2 {
cli.EntryReaderShortcut(targetLocation, true) cli.EntryReaderShortcut(targetLocation, true)
// perform other operations on the entry (if other arguments are supplied) // perform other operations on the entry (if other arguments are supplied)
} else if argsCount == 2 { } else if argsCount == 3 {
switch args[1] { switch args[2] {
case "show", "-s": case "show", "-s":
cli.EntryReaderShortcut(targetLocation, false) cli.EntryReaderShortcut(targetLocation, false)
case "shear": // TODO offline.Shear(targetLocation), exit after run case "shear": // TODO offline.Shear(targetLocation), exit after run
@@ -45,14 +46,14 @@ func main() {
cli.HelpMain() cli.HelpMain()
} }
} else if argsCount == 3 { } else if argsCount == 4 {
// declare entry field to perform target operation on // declare entry field to perform target operation on
switch args[1] { switch args[2] {
case "copy": case "copy":
var field uint8 var field uint8
switch args[2] { switch args[3] {
case "password", "-p": case "password", "-p":
field = 0 field = 0
case "username", "-u": case "username", "-u":
@@ -64,11 +65,11 @@ func main() {
default: default:
cli.HelpCopy() cli.HelpCopy()
} }
offline.CopyField(targetLocation, field) offline.CopyField(targetLocation, field, args[0])
case "edit": case "edit":
var field rune var field rune
field = field // TODO temporary to avoid unused variable error field = field // TODO temporary to avoid unused variable error
switch args[2] { switch args[3] {
case "password", "-p": case "password", "-p":
field = 'p' field = 'p'
case "username", "-u": case "username", "-u":
@@ -85,7 +86,7 @@ func main() {
case "add": case "add":
var field rune var field rune
field = field // TODO temporary to avoid unused variable error field = field // TODO temporary to avoid unused variable error
switch args[2] { switch args[3] {
case "password", "-p": case "password", "-p":
field = 'p' field = 'p'
case "note", "-n": case "note", "-n":
@@ -98,7 +99,7 @@ func main() {
case "gen": case "gen":
var field rune var field rune
field = field // TODO temporary to avoid unused variable error field = field // TODO temporary to avoid unused variable error
switch args[2] { switch args[3] {
case "update", "-u": // TODO offline.GenUpdate(targetLocation), exit after run case "update", "-u": // TODO offline.GenUpdate(targetLocation), exit after run
default: default:
cli.HelpGen() cli.HelpGen()
@@ -110,11 +111,19 @@ func main() {
// if the first argument is not an entry... // if the first argument is not an entry...
} else { } else {
switch args[0] { switch args[1] {
case "clipclear":
// read previous clipboard contents from stdin
clipScanner := bufio.NewScanner(os.Stdin)
if clipScanner.Scan() {
oldContents := clipScanner.Text()
offline.ClipClear(oldContents)
} else {
os.Exit(0)
}
case "sync": // TODO online.Sync(), exit after run case "sync": // TODO online.Sync(), exit after run
case "init": // TODO offline.Init(), exit after run case "init": // TODO offline.Init(), exit after run
case "tweak": // TODO offline.Tweak(), exit after run case "tweak": // TODO offline.Tweak(), exit after run
case "add": case "add":
cli.HelpAdd() cli.HelpAdd()
case "edit": case "edit":
+43 -7
View File
@@ -5,24 +5,60 @@ import (
"io" "io"
"os" "os"
"os/exec" "os/exec"
"strings"
"time"
) )
func CopyField(targetLocation string, field uint8) { // TODO Handle cmd.Run errors, especially those due to missing clipboard utilities
// CopyField copies a field from an entry to the clipboard
// TODO Implement support for Windows via powershell, MacOS via pbcopy, Termux via termux-clipboard-set, X11 via xclip
// TODO Monitor Go support for Haiku, if possible implement support via clipboard command
func CopyField(targetLocation string, field uint8, executableName string) {
if isFile, _ := TargetIsFile(targetLocation, true); isFile { if isFile, _ := TargetIsFile(targetLocation, true); isFile {
copySubject := DecryptGPG(targetLocation)[field] copySubject := DecryptGPG(targetLocation)[field]
//hash := getSha512Sum(copySubject)
cmd := exec.Command("wl-copy") cmd := exec.Command("wl-copy")
stdin, _ := cmd.StdinPipe() writeToStdin(cmd, copySubject)
go func() {
defer stdin.Close()
io.WriteString(stdin, copySubject)
}()
cmd.Run() cmd.Run()
// TODO Unpair from mutn, as this breaks library functionality
// TODO Maybe use this method for mutn and strongly encourage other implementations to support a clipclear argument
// TODO If an implementation opts out of doing this, this may error out
//cmd = exec.Command(executableName, "clipclear", hash)
cmd = exec.Command(executableName, "clipclear")
writeToStdin(cmd, copySubject)
cmd.Start()
} else { } else {
fmt.Println(AnsiError + "Failed to read \"" + targetLocation + "\" - it is a directory" + AnsiReset) fmt.Println(AnsiError + "Failed to read \"" + targetLocation + "\" - it is a directory" + AnsiReset)
} }
os.Exit(0) os.Exit(0)
} }
func clipClear() { // ClipClear is called in a separate process to clear the clipboard after 30 seconds
// TODO Implement support for Windows via powershell, MacOS via pbcopy, Termux via termux-clipboard-set, X11 via xclip
// TODO Make clear time period configurable
func ClipClear(oldContents string) {
time.Sleep(30 * time.Second)
cmd := exec.Command("wl-paste")
newContents, _ := cmd.Output()
if oldContents == strings.TrimRight(string(newContents), "\n") {
cmd := exec.Command("wl-copy", "-c")
cmd.Run()
}
os.Exit(0)
}
// writeToStdin writes a string to a command's stdin
func writeToStdin(cmd *exec.Cmd, input string) {
stdin, _ := cmd.StdinPipe()
go func() {
defer stdin.Close()
io.WriteString(stdin, input)
}()
} }