FIX: Properly handle quotes and backslash in `Search.set_tsquery_weight_filter`
This commit is contained in:
parent
500d22bf32
commit
68fc2a18b1
|
@ -188,7 +188,7 @@ class Search
|
|||
|
||||
if term.present?
|
||||
@term = Search.prepare_data(term, Topic === @search_context ? :topic : nil)
|
||||
@original_term = PG::Connection.escape_string(@term)
|
||||
@original_term = Search.escape_string(@term)
|
||||
end
|
||||
|
||||
if @search_pms || @opts[:type_filter] == 'private_messages'
|
||||
|
@ -1100,14 +1100,17 @@ class Search
|
|||
|
||||
def self.to_tsquery(ts_config: nil, term:, joiner: nil)
|
||||
ts_config = ActiveRecord::Base.connection.quote(ts_config) if ts_config
|
||||
tsquery = "TO_TSQUERY(#{ts_config || default_ts_config}, '#{term}')"
|
||||
tsquery = "REPLACE(#{tsquery}::text, '&', '#{PG::Connection.escape_string(joiner)}')::tsquery" if joiner
|
||||
tsquery = "TO_TSQUERY(#{ts_config || default_ts_config}, '#{self.escape_string(term)}')"
|
||||
tsquery = "REPLACE(#{tsquery}::text, '&', '#{self.escape_string(joiner)}')::tsquery" if joiner
|
||||
tsquery
|
||||
end
|
||||
|
||||
def self.set_tsquery_weight_filter(term, weight_filter)
|
||||
term = term.gsub("'", "''")
|
||||
"''#{PG::Connection.escape_string(term)}'':*#{weight_filter}"
|
||||
"'#{self.escape_string(term)}':*#{weight_filter}"
|
||||
end
|
||||
|
||||
def self.escape_string(term)
|
||||
PG::Connection.escape_string(term).gsub('\\', '\\\\\\')
|
||||
end
|
||||
|
||||
def ts_query(ts_config = nil, weight_filter: nil)
|
||||
|
@ -1237,7 +1240,7 @@ class Search
|
|||
|
||||
def posts_scope(default_scope = Post.all)
|
||||
if SiteSetting.use_pg_headlines_for_excerpt
|
||||
search_term = @term.present? ? PG::Connection.escape_string(@term) : nil
|
||||
search_term = @term.present? ? Search.escape_string(@term) : nil
|
||||
ts_config = default_ts_config
|
||||
|
||||
default_scope
|
||||
|
|
|
@ -134,12 +134,20 @@ describe Search do
|
|||
expect(search.term).to eq('a b c okaylength')
|
||||
end
|
||||
|
||||
it 'escapes non alphanumeric characters' do
|
||||
expect(Search.execute('foo :!$);}]>@\#\"\'').posts.length).to eq(0) # There are at least three levels of sanitation for Search.query!
|
||||
end
|
||||
context 'query sanitizaton' do
|
||||
let!(:post) { Fabricate(:post, raw: 'hello world') }
|
||||
|
||||
it "doesn't raise an error when single quotes are present" do
|
||||
expect(Search.execute("'hello' world").posts.length).to eq(0) # There are at least three levels of sanitation for Search.query!
|
||||
it 'escapes backslash' do
|
||||
expect(Search.execute('hello\\').posts).to contain_exactly(post)
|
||||
end
|
||||
|
||||
it 'escapes single quote' do
|
||||
expect(Search.execute("hello'").posts).to contain_exactly(post)
|
||||
end
|
||||
|
||||
it 'escapes non-alphanumeric characters' do
|
||||
expect(Search.execute('hello :!$);}]>@\#\"\'').posts).to contain_exactly(post)
|
||||
end
|
||||
end
|
||||
|
||||
it 'works when given two terms with spaces' do
|
||||
|
@ -755,7 +763,7 @@ describe Search do
|
|||
let(:result) { Search.execute('запись') }
|
||||
|
||||
it 'finds something when given cyrillic query' do
|
||||
expect(result.posts).to be_present
|
||||
expect(result.posts).to contain_exactly(post)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1622,6 +1630,14 @@ describe Search do
|
|||
expect { DB.exec(+"SELECT to_tsvector('bbb') @@ " << ts_query) }.to_not raise_error
|
||||
expect(ts_query).to include("baz")
|
||||
end
|
||||
|
||||
it 'esacpes the term correctly' do
|
||||
expect(Search.ts_query(term: 'Title with trailing backslash\\'))
|
||||
.to eq("TO_TSQUERY('english', '''Title with trailing backslash\\\\\\\\'':*')")
|
||||
|
||||
expect(Search.ts_query(term: "Title with trailing quote'"))
|
||||
.to eq("TO_TSQUERY('english', '''Title with trailing quote'''''':*')")
|
||||
end
|
||||
end
|
||||
|
||||
context '#word_to_date' do
|
||||
|
|
Loading…
Reference in New Issue