Report panic details (stack trace w/args&stdin) to clients; drop synccycles.StringGen() (moved to go-boilerplate)

This commit is contained in:
2025-12-11 18:23:01 -05:00
parent 7e7fbd15b4
commit 4e6c18db8a
7 changed files with 20 additions and 76 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ go 1.25.5
require (
github.com/pkg/sftp v1.13.10
github.com/pquerna/otp v1.5.0
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251110055016-10ee4f91fcb6
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251211171453-df1fb21b2366
github.com/rwinkhart/rcw v0.2.3
golang.org/x/crypto v0.45.0
gopkg.in/ini.v1 v1.67.0
+2 -2
View File
@@ -12,8 +12,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251110055016-10ee4f91fcb6 h1:tGGtw5Wr4laDrU7Ooe95g4E+O6c+oY18atamcMPaMY8=
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251110055016-10ee4f91fcb6/go.mod h1:cnzIF45I0FCOvE4YIB+26pLCUx2kWyY2llKYZruNaRY=
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251211171453-df1fb21b2366 h1:aKB7jcFstg11bRqDnjNzQIGM4+VA4JlE1HDNaPRpm8g=
github.com/rwinkhart/go-boilerplate v0.1.1-0.20251211171453-df1fb21b2366/go.mod h1:cnzIF45I0FCOvE4YIB+26pLCUx2kWyY2llKYZruNaRY=
github.com/rwinkhart/go-winio v0.1.0 h1:b72agLW+dETGmhR3VbcbwnStfgKfc5AfgJOXBJDkaHg=
github.com/rwinkhart/go-winio v0.1.0/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0=
github.com/rwinkhart/peercred-mini v0.1.2 h1:4cGWDbv0whvLeVvbUdx84V/9p+2fS+DEXgrA1KxlRFo=
+9
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"os"
"runtime/debug"
"strings"
"github.com/rwinkhart/go-boilerplate/back"
@@ -33,6 +34,14 @@ func main() {
}
}
// allow reporting panic details to clients
defer func() {
if r := recover(); r != nil {
fmt.Printf("{\"errMsg\":\"SERVER-SIDE PANIC OCCURRED!%sARGS: (%v)%sSTDIN: (%v)%sSTACK TRACE: %s\"}", global.FSSpace, os.Args, global.FSSpace, stdin, global.FSSpace, strings.ReplaceAll(strings.ReplaceAll(string(debug.Stack()), "\n", global.FSSpace), "\t", ""))
return
}
}()
switch args[1] {
case "fetch":
// print all information needed for syncing to stdout for interpretation by the client
+1 -1
View File
@@ -155,7 +155,7 @@ func getRemoteDataFromClient(sshClient *ssh.Client) (map[string]int64, map[strin
return nil, nil, nil, nil, 0, 0, errors.New("unable to unmarshal server fetch response: " + err.Error())
}
if fetchResp.ErrMsg != nil {
return nil, nil, nil, nil, 0, 0, errors.New("unable to complete fetch; server-side error occurred: " + *fetchResp.ErrMsg)
return nil, nil, nil, nil, 0, 0, errors.New("unable to complete fetch; server-side error occurred: " + strings.ReplaceAll(*fetchResp.ErrMsg, global.FSSpace, "\n"))
}
entryModMap := make(map[string]int64)
+3 -3
View File
@@ -48,7 +48,7 @@ func ShearRemoteFromClient(vanityPath string, onlyShearAgeFile bool) error {
return errors.New("unable to shear target remotely: " + err.Error())
}
if len(output) > 11 {
return errors.New("unable to complete shear; server-side error occurred: " + string(output)[11:len(output)-2])
return errors.New("unable to complete shear; server-side error occurred: " + strings.ReplaceAll(string(output)[11:len(output)-2], global.FSSpace, "\n"))
}
// close the SSH client
@@ -100,7 +100,7 @@ func RenameRemoteFromClient(oldVanityPath, newVanityPath string) error {
return errors.New("unable to rename target remotely: " + err.Error())
}
if len(output) > 11 {
return errors.New("unable to complete rename; server-side error occurred: " + string(output)[11:len(output)-2])
return errors.New("unable to complete rename; server-side error occurred: " + strings.ReplaceAll(string(output)[11:len(output)-2], global.FSSpace, "\n"))
}
// close the SSH client
@@ -141,7 +141,7 @@ func AddFolderRemoteFromClient(vanityPath string) error {
return errors.New("unable to add folder remotely: " + err.Error())
}
if len(output) > 11 {
return errors.New("unable to complete addfolder; server-side error occurred: " + string(output)[11:len(output)-2])
return errors.New("unable to complete addfolder; server-side error occurred: " + strings.ReplaceAll(string(output)[11:len(output)-2], global.FSSpace, "\n"))
}
// close the SSH client
+4 -2
View File
@@ -6,9 +6,11 @@ import (
"math/rand"
"os"
"strconv"
"strings"
"time"
"github.com/rwinkhart/go-boilerplate/back"
"github.com/rwinkhart/go-boilerplate/stringy"
"github.com/rwinkhart/libmutton/global"
"github.com/rwinkhart/libmutton/syncclient"
"github.com/rwinkhart/libmutton/synccommon"
@@ -24,7 +26,7 @@ func DeviceIDGen(oldDeviceID, prefix string) (string, string, string, error) {
if prefix == "" {
prefix, _ = os.Hostname()
}
newDeviceID := prefix + "-" + StringGen(rand.Intn(32)+48, 0.2, 1) + "-" + strconv.FormatInt(time.Now().Unix(), 10)
newDeviceID := prefix + "-" + stringy.StringGen(rand.Intn(32)+48, 0.2, 1) + "-" + strconv.FormatInt(time.Now().Unix(), 10)
// create new device ID file (locally)
newDeviceIDPath := global.ConfigDir + global.PathSeparator + "devices" + global.PathSeparator + newDeviceID
@@ -68,7 +70,7 @@ func DeviceIDGen(oldDeviceID, prefix string) (string, string, string, error) {
}
if registerResp.ErrMsg != nil {
cleanupOnFail()
return "", "", "", errors.New("unable to complete register; server-side error occurred: " + *registerResp.ErrMsg)
return "", "", "", errors.New("unable to complete register; server-side error occurred: " + strings.ReplaceAll(*registerResp.ErrMsg, global.FSSpace, "\n"))
}
_ = sshClient.Close() // ignore error; non-critical/unlikely/not much could be done about it
-67
View File
@@ -1,67 +0,0 @@
package synccycles
import (
"crypto/rand"
"fmt"
"math"
"math/big"
"strings"
)
// StringGen generates a random string of a specified length and complexity.
// Requires: complexity (minimum percentage of special characters to be returned in the generated string; set to 0 to generate a simple string),
// complexCharsetLevel (1 = safe for filenames, 2 = safe for most password entries, 3 = safe only for well-made password entries)
func StringGen(length int, complexity float64, complexCharsetLevel uint8) string {
var actualSpecialChars int // track the number of special characters in the generated string
var minSpecialChars int // track the minimum number of special characters to accept
var extendedCharset string // additions to character set used for complex strings
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" // default character set used for all strings
const extendedCharsetFiles = "!#$%&+,-.;=@_~^()[]{}`'" // additional special characters for complex strings (safe in file names)
const extendedCharsetMostPassword = "*:><?|" // additional special characters for complex strings (NOT safe in file names)
const extendedCharsetSpecialPassword = "\"/\\" // additional special characters for complex strings (NOT safe in file names)
if complexity > 0 {
minSpecialChars = int(math.Round(float64(length) * complexity)) // determine minimum number of special characters to accept
switch complexCharsetLevel {
case 1:
extendedCharset = extendedCharsetFiles
case 2:
extendedCharset = extendedCharsetMostPassword + extendedCharsetFiles[:len(extendedCharsetFiles)-9]
case 3:
extendedCharset = extendedCharsetFiles + extendedCharsetMostPassword + extendedCharsetSpecialPassword
}
charset += extendedCharset
}
// loop until a string of the desired complexity is generated
for {
// generate a random string
result := make([]byte, length)
for i := range result {
val, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
result[i] = charset[val.Int64()]
}
// return early if the string is not complex
if complexity <= 0 {
return string(result)
}
// count the number of special characters in the generated string
for _, char := range string(result) {
if strings.ContainsRune(extendedCharset, char) {
actualSpecialChars++
}
}
// return the generated string if it contains enough special characters
if actualSpecialChars >= minSpecialChars {
return string(result)
}
// reset special character counter
fmt.Println("Regenerating string until desired complexity is achieved...")
actualSpecialChars = 0
}
}