Merge pull request #70 from hakanf/escape_chars

Allow search strings to escape special chars ' ', ':' and '-' using '\'
This commit is contained in:
David Dworken 2023-02-13 21:34:23 -08:00 committed by GitHub
commit f79ab37bcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1098,7 +1098,7 @@ func MakeWhereQueryFromSearch(ctx *context.Context, db *gorm.DB, query string) (
tx := db.Model(&data.HistoryEntry{}).Where("true")
for _, token := range tokens {
if strings.HasPrefix(token, "-") {
if strings.Contains(token, ":") {
if containsUnescaped(token, ":") {
query, v1, v2, err := parseAtomizedToken(ctx, token[1:])
if err != nil {
return nil, err
@ -1111,7 +1111,7 @@ func MakeWhereQueryFromSearch(ctx *context.Context, db *gorm.DB, query string) (
}
tx = tx.Where("NOT "+query, v1, v2, v3)
}
} else if strings.Contains(token, ":") {
} else if containsUnescaped(token, ":") {
query, v1, v2, err := parseAtomizedToken(ctx, token)
if err != nil {
return nil, err
@ -1150,14 +1150,14 @@ func Search(ctx *context.Context, db *gorm.DB, query string, limit int) ([]*data
}
func parseNonAtomizedToken(token string) (string, interface{}, interface{}, interface{}, error) {
wildcardedToken := "%" + token + "%"
wildcardedToken := "%" + deEscape(token) + "%"
return "(command LIKE ? OR hostname LIKE ? OR current_working_directory LIKE ?)", wildcardedToken, wildcardedToken, wildcardedToken, nil
}
func parseAtomizedToken(ctx *context.Context, token string) (string, interface{}, interface{}, error) {
splitToken := strings.SplitN(token, ":", 2)
field := splitToken[0]
val := splitToken[1]
splitToken := splitEscaped(token, ':', 2)
field := deEscape(splitToken[0])
val := deEscape(splitToken[1])
switch field {
case "user":
return "(local_username = ?)", val, nil, nil
@ -1237,7 +1237,52 @@ func tokenize(query string) ([]string, error) {
if query == "" {
return []string{}, nil
}
return strings.Split(query, " "), nil
return splitEscaped(query, ' ', -1), nil
}
func splitEscaped(query string, separator rune, maxSplit int) []string {
var token []rune
var tokens []string
splits := 1
runeQuery := []rune(query)
for i := 0; i < len(runeQuery); i++ {
if (maxSplit < 0 || splits < maxSplit) && runeQuery[i] == separator {
tokens = append(tokens, string(token))
token = token[:0]
splits++
} else if runeQuery[i] == '\\' && i+1 < len(runeQuery) {
token = append(token, runeQuery[i], runeQuery[i+1])
i++
} else {
token = append(token, runeQuery[i])
}
}
tokens = append(tokens, string(token))
return tokens
}
func containsUnescaped(query string, token string) bool {
runeQuery := []rune(query)
for i := 0; i < len(runeQuery); i++ {
if runeQuery[i] == '\\' && i+1 < len(runeQuery) {
i++
} else if string(runeQuery[i:i+len(token)]) == token {
return true
}
}
return false
}
func deEscape(query string) string {
runeQuery := []rune(query)
var newQuery []rune
for i := 0; i < len(runeQuery); i++ {
if runeQuery[i] == '\\' && i+1 < len(runeQuery) {
i++
}
newQuery = append(newQuery, runeQuery[i])
}
return string(newQuery)
}
func GetDumpRequests(config hctx.ClientConfig) ([]*shared.DumpRequest, error) {