From 25516874b59e5a605425371684ab5ee72d9547c4 Mon Sep 17 00:00:00 2001 From: Rimian Perkins Date: Mon, 16 Jan 2017 16:24:47 +1100 Subject: [PATCH] FIX: Escape regexp chars in `SiteSetting.censored_words`. --- lib/validators/censored_words_validator.rb | 11 ++++- spec/models/post_spec.rb | 2 +- spec/models/topic_spec.rb | 47 +++++++++++++++------- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/lib/validators/censored_words_validator.rb b/lib/validators/censored_words_validator.rb index 58abb9a6cd6..ed97a13d2af 100644 --- a/lib/validators/censored_words_validator.rb +++ b/lib/validators/censored_words_validator.rb @@ -1,7 +1,7 @@ class CensoredWordsValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) if !SiteSetting.censored_words.blank? && - !(censored_words = value.scan(/#{SiteSetting.censored_words}/i)).empty? + !(censored_words = value.scan(censored_words_regexp)).empty? record.errors.add( attribute, :contains_censored_words, @@ -22,6 +22,13 @@ class CensoredWordsValidator < ActiveModel::EachValidator def join_censored_words(censored_words) censored_words.map!(&:downcase) censored_words.uniq! - censored_words.join(", ") + censored_words.join(", ".freeze) + end + + def censored_words_regexp + Regexp.new( + SiteSetting.censored_words.split('|'.freeze).map! { |w| Regexp.escape(w) }.join('|'.freeze), + true + ) end end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 1e827c0e6d4..73c18249eba 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -493,7 +493,7 @@ describe Post do expect(Fabricate.build(:post, post_args)).to be_valid end - it 'treate blank posts as invalid' do + it 'create blank posts as invalid' do expect(Fabricate.build(:post, raw: "")).not_to be_valid end end diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index 46b0126e0db..4ae69364d25 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -13,6 +13,22 @@ describe Topic do context "#title" do it { is_expected.to validate_presence_of :title } + describe 'censored pattern' do + describe 'when title matches censored pattern' do + it 'should not be valid' do + SiteSetting.censored_pattern = 'orange.*' + + topic.title = 'I have orangEjuice orange monkey orange stuff' + + expect(topic).to_not be_valid + + expect(topic.errors.full_messages.first).to include(I18n.t( + 'errors.messages.matches_censored_pattern', censored_words: 'orangejuice orange monkey orange stuff' + )) + end + end + end + describe 'censored words' do describe 'when title contains censored words' do it 'should not be valid' do @@ -28,20 +44,6 @@ describe Topic do end end - describe 'when title matches censored pattern' do - it 'should not be valid' do - SiteSetting.censored_pattern = 'orange.*' - - topic.title = 'I have orangEjuice orange monkey orange stuff' - - expect(topic).to_not be_valid - - expect(topic.errors.full_messages.first).to include(I18n.t( - 'errors.messages.matches_censored_pattern', censored_words: 'orangejuice orange monkey orange stuff' - )) - end - end - describe 'when title does not contain censored words' do it 'should be valid' do topic.title = 'The cake is a lie' @@ -49,6 +51,23 @@ describe Topic do expect(topic).to be_valid end end + + describe 'escape special characters in censored words' do + before do + SiteSetting.censored_words = 'co(onut|coconut|a**le' + end + + it 'should not valid' do + topic.title = "I have a co(onut a**le" + + expect(topic.valid?).to eq(false) + + expect(topic.errors.full_messages.first).to include(I18n.t( + 'errors.messages.contains_censored_words', + censored_words: 'co(onut, a**le' + )) + end + end end end end