From fb453d578f3bdea8590d2d12ebd9b36c0e4a483f Mon Sep 17 00:00:00 2001 From: Amarjeet Anand Date: Wed, 5 Aug 2020 17:13:31 +0530 Subject: [PATCH] [MM-24526] Filter * characters from the search terms in DB (#14884) --- store/searchtest/post_layer.go | 2 +- store/sqlstore/post_store.go | 8 +++----- store/sqlstore/utils.go | 36 ++++++++++++++++++++++++++++++++++ store/sqlstore/utils_test.go | 27 +++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/store/searchtest/post_layer.go b/store/searchtest/post_layer.go index 20de0a87c5..8f57573e8a 100644 --- a/store/searchtest/post_layer.go +++ b/store/searchtest/post_layer.go @@ -126,7 +126,7 @@ var searchPostStoreTests = []searchTest{ { Name: "Should discard a wildcard if it's not placed immediately by text", Fn: testSearchDiscardWildcardAlone, - Tags: []string{ENGINE_ELASTICSEARCH}, + Tags: []string{ENGINE_POSTGRES, ENGINE_MYSQL, ENGINE_ELASTICSEARCH}, }, { Name: "Should support terms with dash", diff --git a/store/sqlstore/post_store.go b/store/sqlstore/post_store.go index 51761c7222..a14b7d15e4 100644 --- a/store/sqlstore/post_store.go +++ b/store/sqlstore/post_store.go @@ -1750,11 +1750,9 @@ func (s *SqlPostStore) SearchPostsInTeamForUser(paramsList []*model.SearchParams pchan := make(chan store.StoreResult, len(paramsList)) for _, params := range paramsList { - // Don't allow users to search for everything. - if params.Terms == "*" { - continue - } - + // remove any unquoted term that contains only non-alphanumeric chars + // ex: abcd "**" && abc >> abcd "**" abc + params.Terms = removeNonAlphaNumericUnquotedTerms(params.Terms, " ") params.IncludeDeletedChannels = includeDeletedChannels params.OrTerms = isOrSearch diff --git a/store/sqlstore/utils.go b/store/sqlstore/utils.go index 1ca8f1fe70..c4e3cd80fa 100644 --- a/store/sqlstore/utils.go +++ b/store/sqlstore/utils.go @@ -7,6 +7,7 @@ import ( "database/sql" "strconv" "strings" + "unicode" "github.com/mattermost/gorp" "github.com/mattermost/mattermost-server/v5/mlog" @@ -52,3 +53,38 @@ func finalizeTransaction(transaction *gorp.Transaction) { mlog.Error("Failed to rollback transaction", mlog.Err(err)) } } + +// removeNonAlphaNumericUnquotedTerms removes all unquoted words that only contain +// non-alphanumeric chars from given line +func removeNonAlphaNumericUnquotedTerms(line, separator string) string { + words := strings.Split(line, separator) + filteredResult := make([]string, 0, len(words)) + + for _, w := range words { + if isQuotedWord(w) || containsAlphaNumericChar(w) { + filteredResult = append(filteredResult, strings.TrimSpace(w)) + } + } + return strings.Join(filteredResult, separator) +} + +// containsAlphaNumericChar returns true in case any letter or digit is present, false otherwise +func containsAlphaNumericChar(s string) bool { + for _, r := range s { + if unicode.IsLetter(r) || unicode.IsDigit(r) { + return true + } + } + return false +} + +// isQuotedWord return true if the input string is quoted, false otherwise. Ex :- +// "quoted string" - will return true +// unquoted string - will return false +func isQuotedWord(s string) bool { + if len(s) < 2 { + return false + } + + return s[0] == '"' && s[len(s)-1] == '"' +} diff --git a/store/sqlstore/utils_test.go b/store/sqlstore/utils_test.go index 7db47c61ac..3c2ab99261 100644 --- a/store/sqlstore/utils_test.go +++ b/store/sqlstore/utils_test.go @@ -76,3 +76,30 @@ func TestSanitizeSearchTerm(t *testing.T) { result = sanitizeSearchTerm(term, "*") require.Equal(t, result, expected) } + +func TestRemoveNonAlphaNumericUnquotedTerms(t *testing.T) { + const ( + sep = " " + chineseHello = "你好" + japaneseHello = "こんにちは" + ) + tests := []struct { + term string + want string + name string + }{ + {term: "", want: "", name: "empty"}, + {term: "h", want: "h", name: "singleChar"}, + {term: "hello", want: "hello", name: "multiChar"}, + {term: `hel*lo "**" **& hello`, want: `hel*lo "**" hello`, name: "quoted_unquoted_english"}, + {term: japaneseHello + chineseHello, want: japaneseHello + chineseHello, name: "japanese_chinese"}, + {term: japaneseHello + ` "*" ` + chineseHello, want: japaneseHello + ` "*" ` + chineseHello, name: `quoted_japanese_and_chinese`}, + {term: japaneseHello + ` "*" &&* ` + chineseHello, want: japaneseHello + ` "*" ` + chineseHello, name: "quoted_unquoted_japanese_and_chinese"}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := removeNonAlphaNumericUnquotedTerms(test.term, sep) + require.Equal(t, test.want, got) + }) + } +}