mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-28 12:56:31 -04:00
126 lines
3.6 KiB
Go
126 lines
3.6 KiB
Go
package core
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
steamtotp "github.com/fortis/go-steam-totp"
|
|
"github.com/pquerna/otp/totp"
|
|
)
|
|
|
|
// CopyArgument copies a field from an entry to the clipboard.
|
|
func CopyArgument(targetLocation string, field int) {
|
|
if isFile, _ := TargetIsFile(targetLocation, true, 2); isFile {
|
|
|
|
decryptedEntry := DecryptGPG(targetLocation)
|
|
var copySubject string // will store data to be copied
|
|
|
|
// ensure field exists in entry
|
|
if len(decryptedEntry) > field {
|
|
|
|
// ensure field is not empty
|
|
if decryptedEntry[field] == "" {
|
|
fmt.Println(AnsiError + "Field is empty" + AnsiReset)
|
|
os.Exit(ErrorTargetNotFound)
|
|
}
|
|
|
|
if field != 2 {
|
|
copySubject = decryptedEntry[field]
|
|
} else { // TOTP mode
|
|
var secret string // stores secret for TOTP generation
|
|
var forSteam bool // indicates whether to generate TOTP in Steam format
|
|
|
|
if strings.HasPrefix(decryptedEntry[2], "steam@") {
|
|
secret = decryptedEntry[2][6:]
|
|
forSteam = true
|
|
} else {
|
|
secret = decryptedEntry[2]
|
|
}
|
|
|
|
fmt.Println("Clipboard will be kept up to date with the current TOTP code until this process is closed")
|
|
|
|
for { // keep token copied to clipboard, refresh on 30-second intervals
|
|
currentTime := time.Now()
|
|
copyString(true, GenTOTP(secret, currentTime, forSteam))
|
|
// sleep until next 30-second interval
|
|
time.Sleep(time.Duration(30-(currentTime.Second()%30)) * time.Second)
|
|
}
|
|
}
|
|
} else {
|
|
fmt.Println(AnsiError + "Field does not exist in entry" + AnsiReset)
|
|
os.Exit(ErrorTargetNotFound)
|
|
}
|
|
|
|
// copy field to clipboard, launch clipboard clearing process
|
|
copyString(false, copySubject)
|
|
}
|
|
}
|
|
|
|
// ClipClearArgument reads the assigned clipboard contents from stdin and passes them to clipClearProcess.
|
|
func ClipClearArgument() {
|
|
// read previous clipboard contents from stdin
|
|
clipScanner := bufio.NewScanner(os.Stdin)
|
|
if clipScanner.Scan() {
|
|
assignedContents := clipScanner.Text()
|
|
clipClearProcess(assignedContents)
|
|
} else {
|
|
os.Exit(0) // use os.Exit instead of core.Exit, as this function runs out of a background subprocess that is invisible to the user (will never appear in GUI/TUI environment)
|
|
}
|
|
}
|
|
|
|
// clipClearProcess clears the clipboard after 30 seconds if the clipboard contents have not changed.
|
|
// assignedContents can be omitted to clear the clipboard immediately and unconditionally.
|
|
func clipClearProcess(assignedContents string) {
|
|
cmdPaste, cmdClear := getClipCommands()
|
|
|
|
clearClipboard := func() {
|
|
err := cmdClear.Run()
|
|
if err != nil {
|
|
fmt.Println(AnsiError+"Failed to clear clipboard:", err.Error()+AnsiReset)
|
|
os.Exit(ErrorClipboard)
|
|
}
|
|
Exit(0)
|
|
}
|
|
|
|
// if assignedContents is empty, clear the clipboard immediately and unconditionally
|
|
if assignedContents == "" {
|
|
clearClipboard()
|
|
return
|
|
}
|
|
|
|
// wait 30 seconds before checking clipboard contents
|
|
time.Sleep(30 * time.Second)
|
|
|
|
newContents, err := cmdPaste.Output()
|
|
if err != nil {
|
|
fmt.Println(AnsiError+"Failed to read clipboard contents:", err.Error()+AnsiReset)
|
|
os.Exit(ErrorClipboard)
|
|
}
|
|
|
|
if assignedContents == strings.TrimRight(string(newContents), "\r\n") {
|
|
clearClipboard()
|
|
}
|
|
}
|
|
|
|
// GenTOTP generates a TOTP token from a secret (supports standard and Steam TOTP).
|
|
func GenTOTP(secret string, time time.Time, forSteam bool) string {
|
|
var totpToken string
|
|
var err error
|
|
|
|
if forSteam {
|
|
totpToken, err = steamtotp.GenerateAuthCode(secret, time)
|
|
} else {
|
|
totpToken, err = totp.GenerateCode(secret, time)
|
|
}
|
|
|
|
if err != nil {
|
|
fmt.Println(AnsiError + "Error generating TOTP code" + AnsiReset)
|
|
os.Exit(ErrorOther)
|
|
}
|
|
|
|
return totpToken
|
|
}
|