mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-27 20:36:29 -04:00
Address JetBrains warnings
This commit is contained in:
@@ -26,7 +26,10 @@ func clipClearProcess(assignedContents string) error {
|
||||
|
||||
// if assignedContents is empty, clear the clipboard immediately and unconditionally
|
||||
if assignedContents == "" {
|
||||
clearClipboard()
|
||||
err := clearClipboard()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+11
-4
@@ -52,7 +52,10 @@ func CopyArgument(targetLocation string, field int) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copyString(true, token)
|
||||
err = copyString(true, token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// sleep until next 30-second interval
|
||||
time.Sleep(time.Duration(30-(currentTime.Second()%30)) * time.Second)
|
||||
}
|
||||
@@ -62,18 +65,22 @@ func CopyArgument(targetLocation string, field int) error {
|
||||
}
|
||||
|
||||
// copy field to clipboard, launch clipboard clearing process
|
||||
copyString(false, copySubject)
|
||||
err = copyString(false, copySubject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClipClearArgument reads the assigned clipboard contents from stdin and passes them to clipClearProcess.
|
||||
func ClipClearArgument() {
|
||||
func ClipClearArgument() error {
|
||||
assignedContents := back.ReadFromStdin()
|
||||
if assignedContents == "" {
|
||||
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(assignedContents)
|
||||
err := clipClearProcess(assignedContents)
|
||||
return err
|
||||
}
|
||||
|
||||
// GenTOTP generates a TOTP token from a secret (supports standard and Steam TOTP).
|
||||
|
||||
+17
-5
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// LibmuttonInit creates the libmutton config structure based on user input.
|
||||
// rcwPassphrase and clientSpecificIniData are cab be left blank if not needed.
|
||||
// rcwPassphrase and clientSpecificIniData can be left blank if not needed.
|
||||
func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData [][3]string, rcwPassphrase []byte, preserveOldConfigDir bool) error {
|
||||
r := strings.ToLower(inputCB("Configure SSH settings (for synchronization)? (y/N)"))
|
||||
if len(r) > 0 && r[0] == 'y' {
|
||||
@@ -44,7 +44,7 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData [][
|
||||
}
|
||||
//// write config file
|
||||
//// temporarily assign sshEntryRoot and sshIsWindows to null to pass initial device ID registration
|
||||
cfg.WriteConfig(append(
|
||||
err = cfg.WriteConfig(append(
|
||||
clientSpecificIniData,
|
||||
[][3]string{
|
||||
{"LIBMUTTON", "sshUser", sshUser},
|
||||
@@ -54,18 +54,30 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData [][
|
||||
{"LIBMUTTON", "sshKeyProtected", strconv.FormatBool(sshKeyProtected)},
|
||||
{"LIBMUTTON", "sshEntryRoot", "null"},
|
||||
{"LIBMUTTON", "sshIsWindows", "false"}}...), nil, false)
|
||||
if err != nil {
|
||||
return errors.New("unable to write config file: " + err.Error())
|
||||
}
|
||||
// generate and register device ID
|
||||
sshEntryRoot, sshIsWindows, err := synccycles.DeviceIDGen(oldDeviceID)
|
||||
if err != nil {
|
||||
return errors.New("unable to generate device ID: " + err.Error())
|
||||
}
|
||||
cfg.WriteConfig([][3]string{{"LIBMUTTON", "sshEntryRoot", sshEntryRoot}, {"LIBMUTTON", "sshIsWindows", sshIsWindows}}, nil, true)
|
||||
err = cfg.WriteConfig([][3]string{{"LIBMUTTON", "sshEntryRoot", sshEntryRoot}, {"LIBMUTTON", "sshIsWindows", sshIsWindows}}, nil, true)
|
||||
if err != nil {
|
||||
return errors.New("unable to write config file: " + err.Error())
|
||||
}
|
||||
} else {
|
||||
// initialize libmutton directories
|
||||
global.DirInit(preserveOldConfigDir)
|
||||
_, err := global.DirInit(preserveOldConfigDir)
|
||||
if err != nil {
|
||||
return errors.New("unable to initialize libmutton directories: " + err.Error())
|
||||
}
|
||||
// write config file
|
||||
if len(clientSpecificIniData) > 0 { // TODO test passing empty clientSpecificIniData
|
||||
cfg.WriteConfig(clientSpecificIniData, nil, false)
|
||||
err = cfg.WriteConfig(clientSpecificIniData, nil, false)
|
||||
if err != nil {
|
||||
return errors.New("unable to write config file: " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
// generate rcw sanity check file (if requested)
|
||||
|
||||
@@ -15,6 +15,6 @@ import (
|
||||
func LaunchClipClearProcess(copySubject string, isWayland bool) {
|
||||
cmd := exec.Command(os.Args[0], "clipclear", strconv.FormatBool(isWayland))
|
||||
back.WriteToStdin(cmd, copySubject)
|
||||
cmd.Start()
|
||||
_ = cmd.Start()
|
||||
os.Exit(0) // use os.Exit directly since this version of this function is only meant for non-interactive CLI implementations
|
||||
}
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ func launchRCWDProcess() []byte {
|
||||
if Daemonize {
|
||||
cmd := exec.Command(os.Args[0], "startrcwd")
|
||||
back.WriteToStdin(cmd, string(passphrase))
|
||||
cmd.Start()
|
||||
_ = cmd.Start()
|
||||
}
|
||||
|
||||
return passphrase
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// GetOldDeviceID returns the current device ID or
|
||||
// GetCurrentDeviceID returns the current device ID or
|
||||
// FSMisc if there is no device ID (e.g. first run).
|
||||
func GetCurrentDeviceID() (string, error) {
|
||||
deviceIDList, err := GenDeviceIDList()
|
||||
|
||||
+8
-5
@@ -38,23 +38,23 @@ func main() {
|
||||
case "fetch":
|
||||
// print all information needed for syncing to stdout for interpretation by the client
|
||||
// stdin[0] is expected to be the device ID
|
||||
syncserver.GetRemoteDataFromServer(stdin[0])
|
||||
_ = syncserver.GetRemoteDataFromServer(stdin[0])
|
||||
case "rename":
|
||||
// move an entry to a new location before using fallthrough to add its previous iteration to the deletions directory
|
||||
// stdin[0] is evaluated after fallthrough
|
||||
// stdin[1] is expected to be the OLD incomplete target location with FSPath representing path separators - Always pass in UNIX format
|
||||
// stdin[2] is expected to be the NEW incomplete target location with FSPath representing path separators - Always pass in UNIX format
|
||||
synccommon.RenameLocal(strings.ReplaceAll(stdin[1], global.FSPath, "/"), strings.ReplaceAll(stdin[2], global.FSPath, "/"), true)
|
||||
_ = synccommon.RenameLocal(strings.ReplaceAll(stdin[1], global.FSPath, "/"), strings.ReplaceAll(stdin[2], global.FSPath, "/"), true)
|
||||
fallthrough // fallthrough to add the old entry to the deletions directory
|
||||
case "shear":
|
||||
// shear an entry from the server and add it to the deletions directory
|
||||
// stdin[0] is expected to be the device ID
|
||||
// stdin[1] is expected to be the incomplete target location with FSPath representing path separators - Always pass in UNIX format
|
||||
synccommon.ShearLocal(strings.ReplaceAll(stdin[1], global.FSPath, "/"), stdin[0])
|
||||
_, _, _ = synccommon.ShearLocal(strings.ReplaceAll(stdin[1], global.FSPath, "/"), stdin[0])
|
||||
case "addfolder":
|
||||
// add a new folder to the server
|
||||
// stdin[0] is expected to be the incomplete target location with FSPath representing path separators - Always pass in UNIX format
|
||||
synccommon.AddFolderLocal(strings.ReplaceAll(stdin[0], global.FSPath, "/"))
|
||||
_ = synccommon.AddFolderLocal(strings.ReplaceAll(stdin[0], global.FSPath, "/"))
|
||||
case "register":
|
||||
// register a new device ID
|
||||
// stdin[0] is expected to be the device ID
|
||||
@@ -68,7 +68,10 @@ func main() {
|
||||
fmt.Print(global.EntryRoot + global.FSSpace + strconv.FormatBool(global.IsWindows))
|
||||
case "init":
|
||||
// create the necessary directories for libmuttonserver to function
|
||||
global.DirInit(false)
|
||||
_, err := global.DirInit(false)
|
||||
if err != nil {
|
||||
back.PrintError("Failed to initialize libmuttonserver directories: "+err.Error(), back.ErrorWrite, true)
|
||||
}
|
||||
_ = os.MkdirAll(global.ConfigDir+global.PathSeparator+"deletions", 0700) // error ignored; failure would have occurred by this point in core.DirInit
|
||||
fmt.Println("libmuttonserver directories initialized")
|
||||
case "version":
|
||||
|
||||
+24
-9
@@ -343,7 +343,7 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow
|
||||
|
||||
// syncLists determines which entries need to be downloaded and uploaded for synchronizations and calls sftpSync with this information.
|
||||
// Using maps means that syncing will be done in an arbitrary order, but it is a worthy tradeoff for speed and simplicity.
|
||||
func syncLists(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows, timeSynced, returnLists bool, localEntryModMap, remoteEntryModMap map[string]int64) [3][]string {
|
||||
func syncLists(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows, timeSynced, returnLists bool, localEntryModMap, remoteEntryModMap map[string]int64) ([3][]string, error) {
|
||||
// initialize slices to store entries that need to be downloaded or uploaded
|
||||
var downloadList, uploadList []string
|
||||
|
||||
@@ -376,7 +376,10 @@ func syncLists(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows, timeSyn
|
||||
// call sftpSync with the download and upload lists
|
||||
if timeSynced && (max(len(downloadList), len(uploadList)) > 0) { // only call sftpSync if there are entries to download or upload
|
||||
fmt.Println() // add a gap between list-add messages and the actual sync messages from sftpSync
|
||||
sftpSync(sshClient, sshEntryRoot, sshIsWindows, downloadList, uploadList)
|
||||
err := sftpSync(sshClient, sshEntryRoot, sshIsWindows, downloadList, uploadList)
|
||||
if err != nil {
|
||||
return [3][]string{nil, nil, nil}, errors.New("unable to sync entries: " + err.Error())
|
||||
}
|
||||
} else if !timeSynced {
|
||||
// do not call sftpSync if the client and server times are out of sync
|
||||
back.Exit(1)
|
||||
@@ -385,9 +388,9 @@ func syncLists(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows, timeSyn
|
||||
fmt.Println("Client is synchronized with server")
|
||||
|
||||
if returnLists {
|
||||
return [3][]string{nil, downloadList, uploadList}
|
||||
return [3][]string{nil, downloadList, uploadList}, nil
|
||||
}
|
||||
return [3][]string{nil, nil, nil}
|
||||
return [3][]string{nil, nil, nil}, nil
|
||||
}
|
||||
|
||||
// deletionSync removes entries from the client that have been deleted on the server (multi-client deletion).
|
||||
@@ -448,10 +451,16 @@ func RunJob(manualSync, returnLists bool) ([3][]string, error) {
|
||||
}
|
||||
|
||||
// sync deletions
|
||||
deletionSync(deletions)
|
||||
err = deletionSync(deletions)
|
||||
if err != nil {
|
||||
return [3][]string{nil, nil, nil}, errors.New("unable to sync deletions: " + err.Error())
|
||||
}
|
||||
|
||||
// sync folders
|
||||
folderSync(remoteFolders)
|
||||
err = folderSync(remoteFolders)
|
||||
if err != nil {
|
||||
return [3][]string{nil, nil, nil}, errors.New("unable to sync folders: " + err.Error())
|
||||
}
|
||||
|
||||
// fetch local lists
|
||||
localEntryModMap, err := getLocalData()
|
||||
@@ -459,7 +468,7 @@ func RunJob(manualSync, returnLists bool) ([3][]string, error) {
|
||||
return [3][]string{nil, nil, nil}, errors.New("unable to fetch local entry data: " + err.Error())
|
||||
}
|
||||
|
||||
// prior to syncing lists, ensure the client and server clocks are synced within 45 seconds
|
||||
// before syncing lists, ensure the client and server clocks are synced within 45 seconds
|
||||
var timeSynced = true
|
||||
timeDiff := serverTime - clientTime
|
||||
if timeDiff < -45 || timeDiff > 45 {
|
||||
@@ -470,11 +479,17 @@ func RunJob(manualSync, returnLists bool) ([3][]string, error) {
|
||||
// sync new and updated entries
|
||||
var lists [3][]string
|
||||
if returnLists {
|
||||
lists = syncLists(sshClient, sshEntryRoot, sshIsWindows, timeSynced, true, localEntryModMap, remoteEntryModMap)
|
||||
lists, err = syncLists(sshClient, sshEntryRoot, sshIsWindows, timeSynced, true, localEntryModMap, remoteEntryModMap)
|
||||
if err != nil {
|
||||
return [3][]string{nil, nil, nil}, errors.New("unable to sync entries: " + err.Error())
|
||||
}
|
||||
lists[0] = deletions
|
||||
return lists, nil
|
||||
}
|
||||
syncLists(sshClient, sshEntryRoot, sshIsWindows, timeSynced, false, localEntryModMap, remoteEntryModMap)
|
||||
_, err = syncLists(sshClient, sshEntryRoot, sshIsWindows, timeSynced, false, localEntryModMap, remoteEntryModMap)
|
||||
if err != nil {
|
||||
return [3][]string{nil, nil, nil}, errors.New("unable to sync entries: " + err.Error())
|
||||
}
|
||||
back.Exit(0) // exit program if running non-interactively
|
||||
return lists, nil // dummy return for when not returning lists
|
||||
}
|
||||
|
||||
+20
-5
@@ -30,7 +30,10 @@ func ShearRemoteFromClient(targetLocationIncomplete string, forceOffline bool) e
|
||||
}
|
||||
|
||||
// call the server to remotely shear the target and add it to the deletions list
|
||||
GetSSHOutput(sshClient, "libmuttonserver shear", deviceID+"\n"+strings.ReplaceAll(targetLocationIncomplete, global.PathSeparator, global.FSPath))
|
||||
_, err = GetSSHOutput(sshClient, "libmuttonserver shear", deviceID+"\n"+strings.ReplaceAll(targetLocationIncomplete, global.PathSeparator, global.FSPath))
|
||||
if err != nil {
|
||||
return errors.New("unable to shear target remotely: " + err.Error())
|
||||
}
|
||||
|
||||
// close the SSH client
|
||||
err = sshClient.Close()
|
||||
@@ -46,7 +49,10 @@ func ShearRemoteFromClient(targetLocationIncomplete string, forceOffline bool) e
|
||||
// RenameRemoteFromClient renames oldLocationIncomplete to newLocationIncomplete on the local system and calls the server to perform the rename remotely and add the old target to the deletions list.
|
||||
// It can safely be called in offline mode, as well, so this is the intended interface for renaming (RenameLocal should only be used directly by the server binary).
|
||||
func RenameRemoteFromClient(oldLocationIncomplete, newLocationIncomplete string, forceOffline bool) error {
|
||||
synccommon.RenameLocal(oldLocationIncomplete, newLocationIncomplete, false) // move the target on the local system
|
||||
err := synccommon.RenameLocal(oldLocationIncomplete, newLocationIncomplete, false) // move the target on the local system
|
||||
if err != nil {
|
||||
return errors.New("unable to rename target locally: " + err.Error())
|
||||
}
|
||||
|
||||
deviceIDList, err := global.GenDeviceIDList()
|
||||
if err != nil {
|
||||
@@ -60,10 +66,13 @@ func RenameRemoteFromClient(oldLocationIncomplete, newLocationIncomplete string,
|
||||
}
|
||||
|
||||
// call the server to move the target on the remote system and add the old target to the deletions list
|
||||
GetSSHOutput(sshClient, "libmuttonserver rename",
|
||||
_, err = GetSSHOutput(sshClient, "libmuttonserver rename",
|
||||
(deviceIDList)[0].Name()+"\n"+
|
||||
strings.ReplaceAll(oldLocationIncomplete, global.PathSeparator, global.FSPath)+"\n"+
|
||||
strings.ReplaceAll(newLocationIncomplete, global.PathSeparator, global.FSPath))
|
||||
if err != nil {
|
||||
return errors.New("unable to rename target remotely: " + err.Error())
|
||||
}
|
||||
|
||||
// close the SSH client
|
||||
err = sshClient.Close()
|
||||
@@ -79,7 +88,10 @@ func RenameRemoteFromClient(oldLocationIncomplete, newLocationIncomplete string,
|
||||
// AddFolderRemoteFromClient creates a new entry-containing directory on the local system and calls the server to create the folder remotely.
|
||||
// It can safely be called in offline mode, as well, so this is the intended interface for adding folders (AddFolderLocal should only be used directly by the server binary).
|
||||
func AddFolderRemoteFromClient(targetLocationIncomplete string, forceOffline bool) error {
|
||||
synccommon.AddFolderLocal(targetLocationIncomplete) // add the folder on the local system
|
||||
err := synccommon.AddFolderLocal(targetLocationIncomplete) // add the folder on the local system
|
||||
if err != nil {
|
||||
return errors.New("unable to add folder locally: " + err.Error())
|
||||
}
|
||||
|
||||
deviceIDList, err := global.GenDeviceIDList()
|
||||
if err != nil {
|
||||
@@ -93,7 +105,10 @@ func AddFolderRemoteFromClient(targetLocationIncomplete string, forceOffline boo
|
||||
}
|
||||
|
||||
// call the server to create the folder remotely
|
||||
GetSSHOutput(sshClient, "libmuttonserver addfolder", strings.ReplaceAll(targetLocationIncomplete, global.PathSeparator, global.FSPath)) // call the server to create the folder remotely
|
||||
_, err = GetSSHOutput(sshClient, "libmuttonserver addfolder", strings.ReplaceAll(targetLocationIncomplete, global.PathSeparator, global.FSPath)) // call the server to create the folder remotely
|
||||
if err != nil {
|
||||
return errors.New("unable to add folder remotely: " + err.Error())
|
||||
}
|
||||
|
||||
// close the SSH client
|
||||
err = sshClient.Close()
|
||||
|
||||
+1
-1
@@ -8,4 +8,4 @@ Clipboard managers save a history of what has been copied to the clipboard, whic
|
||||
It is likely other popular clipboard managers exhibit this behavior. I noticed it with KDE Klipper, which is what prompted me to create this wiki page. **Clipboard managers should not be enabled by default in any environment** or distribution due to their **potential security implications**.
|
||||
### Termux cannot clear the clipboard from the background
|
||||
***
|
||||
If using libmutton on Termux (Android), the clipboard may not successfully be cleared after the 30 second timeout period if Termux is not actively in the foreground when the sleep timer expires. This is an unfortunate side-effect of running on Android and cannot be easily fixed. Due to Termux being at the bottom of the platform support priority list, I will not be investing time into working around this.
|
||||
If using libmutton on Termux (Android), the clipboard may not successfully be cleared after the 30-second timeout period if Termux is not actively in the foreground when the sleep timer expires. This is an unfortunate side effect of running on Android and cannot be easily fixed. Due to Termux being at the bottom of the platform support priority list, I will not be investing time in working around this.
|
||||
Reference in New Issue
Block a user