Address JetBrains warnings

This commit is contained in:
2025-05-29 22:05:57 -04:00
parent 16aaa4f330
commit a1c47b06a1
10 changed files with 88 additions and 33 deletions
+4 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.