mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-27 20:36:29 -04:00
Report panic details (stack trace w/args&stdin) to clients; drop synccycles.StringGen() (moved to go-boilerplate)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user