diff --git a/cmd/control/cmd/sanitize.go b/cmd/control/cmd/sanitize.go index 50b3b5f..a6fe4c4 100644 --- a/cmd/control/cmd/sanitize.go +++ b/cmd/control/cmd/sanitize.go @@ -22,7 +22,7 @@ var sanitizeCmd = &cobra.Command{ fmt.Println(" HOW IT WORKS") fmt.Println(" In sanitized history, all sensitive information is replaced with its SHA1 hashes.") fmt.Println() - fmt.Println("Sanitizing ...") + fmt.Println("Resulting sanitized files ...") fmt.Println(" * ~/resh_history_sanitized.json (full lengh hashes)") execCmd := exec.Command("resh-sanitize", "-trim-hashes", "0", "--output", dir+"/resh_history_sanitized.json") execCmd.Stdout = os.Stdout diff --git a/cmd/sanitize/main.go b/cmd/sanitize/main.go index 9d5a8aa..7ebcecb 100644 --- a/cmd/sanitize/main.go +++ b/cmd/sanitize/main.go @@ -10,6 +10,7 @@ import ( "flag" "fmt" "log" + "math" "net/url" "os" "os/user" @@ -19,6 +20,7 @@ import ( "strings" "unicode" + "github.com/coreos/go-semver/semver" "github.com/curusarn/resh/pkg/records" giturls "github.com/whilp/git-urls" ) @@ -178,7 +180,7 @@ func (s *sanitizer) sanitizeRecord(record *records.Record) error { } if len(record.RecallActionsRaw) > 0 { - record.RecallActionsRaw, err = s.sanitizeRecallActions(record.RecallActionsRaw) + record.RecallActionsRaw, err = s.sanitizeRecallActions(record.RecallActionsRaw, record.ReshVersion) if err != nil { log.Fatal("RecallActionsRaw:", record.RecallActionsRaw, "; sanitization error:", err) } @@ -188,44 +190,80 @@ func (s *sanitizer) sanitizeRecord(record *records.Record) error { return nil } -// sanitizes the recall actions by replacing the recall prefix with it's length -func (s *sanitizer) sanitizeRecallActions(str string) (string, error) { - sanStr := "" - divider := ";" - if strings.Contains(str, "|||") { - divider = "|||" - // normal mode - } - for x, actionStr := range strings.Split(str, divider+"arrow_") { - if x == 0 { - continue +func fixSeparator(str string) string { + if len(str) > 0 && str[0] == ';' { + return "|||" + str[1:] + } + return str +} + +func minIndex(str string, substrs []string) (idx, substrIdx int) { + minMatch := math.MaxInt32 + for i, sep := range substrs { + match := strings.Index(str, sep) + if match != -1 && match < minMatch { + minMatch = match + substrIdx = i } - if len(actionStr) == 0 { - return str, errors.New("Action can't be empty; idx=" + strconv.Itoa(x)) + } + idx = minMatch + return +} + +// sanitizes the recall actions by replacing the recall prefix with it's length +func (s *sanitizer) sanitizeRecallActions(str string, reshVersion string) (string, error) { + if len(str) == 0 { + return "", nil + } + var separators []string + seps := []string{"|||"} + refVersion, err := semver.NewVersion("2.5.14") + if err != nil { + return str, err + } + if len(reshVersion) == 0 { + return str, errors.New("sanitizeRecallActions: record.ReshVersion is an empty string") + } + recordVersion, err := semver.NewVersion(reshVersion[1:]) + if err != nil { + return str, err + } + if recordVersion.LessThan(*refVersion) { + seps = append(seps, ";") + } + + actions := []string{"arrow_up", "arrow_down", "control_R"} + for _, sep := range seps { + for _, action := range actions { + separators = append(separators, sep+action+":") } - var action string - var prefix string - if strings.HasPrefix(actionStr, "up:") { - action = "arrow_up" - if len(actionStr) < 3 { - return str, errors.New("Action is too short:" + actionStr) - } - if len(actionStr) != 3 { - prefix = actionStr[4:] - } - } else if strings.HasPrefix(actionStr, "down:") { - action = "arrow_down" - if len(actionStr) < 5 { - return str, errors.New("Action is too short:" + actionStr) - } - if len(actionStr) != 5 { - prefix = actionStr[6:] - } - } else { - return str, errors.New("Action should start with one of (arrow_up, arrow_down); got: arrow_" + actionStr) + } + /* + - find any of {|||,;}{arrow_up,arrow_down,control_R}: in the recallActions (on the lowest index) + - use found substring to parse out the next prefix + - sanitize prefix + - add fixed substring and sanitized prefix to output + */ + doBreak := false + sanStr := "" + idx := 0 + var currSeparator string + tokenLen, sepIdx := minIndex(str, separators) + if tokenLen != 0 { + return str, errors.New("sanitizeReacallActions: unexpected string before first action/separator") + } + currSeparator = separators[sepIdx] + idx += len(currSeparator) + for !doBreak { + tokenLen, sepIdx := minIndex(str[idx:], separators) + if tokenLen > len(str[idx:]) { + tokenLen = len(str[idx:]) + doBreak = true } - sanPrefix := strconv.Itoa(len(prefix)) - sanStr += "|||" + action + ":" + sanPrefix + // token := str[idx : idx+tokenLen] + sanStr += fixSeparator(currSeparator) + strconv.Itoa(tokenLen) + idx += tokenLen + len(currSeparator) + currSeparator = separators[sepIdx] } return sanStr, nil } diff --git a/go.sum b/go.sum index 430efce..7b6e13c 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,7 @@ github.com/awesome-gocui/termbox-go v0.0.0-20190427202837-c0aef3d18bcc h1:wGNpKc github.com/awesome-gocui/termbox-go v0.0.0-20190427202837-c0aef3d18bcc/go.mod h1:tOy3o5Nf1bA17mnK4W41gD7PS3u4Cv0P0pqFcoWMy8s= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=