diff --git a/app/models/topic.rb b/app/models/topic.rb index 92951e1e543..8aa2c1e5bf9 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -65,6 +65,9 @@ class Topic < ActiveRecord::Base before_validation do + if SiteSetting.title_sanitize + self.title = sanitize(title.to_s, tags: [], attributes: []).strip.presence + end self.title = TextCleaner.clean_title(TextSentinel.title_sentinel(title).text) if errors[:title].empty? end @@ -241,14 +244,19 @@ class Topic < ActiveRecord::Base end def fancy_title - sanitized_title = title.gsub(/['&\"<>]/, { - "'" => ''', - '&' => '&', - '"' => '"', - '<' => '<', - '>' => '>', - }) + sanitized_title = if SiteSetting.title_sanitize + sanitize(title.to_s, tags: [], attributes: []).strip.presence + else + title.gsub(/['&\"<>]/, { + "'" => ''', + '&' => '&', + '"' => '"', + '<' => '<', + '>' => '>', + }) + end + return unless sanitized_title return sanitized_title unless SiteSetting.title_fancy_entities? # We don't always have to require this, if fancy is disabled diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index dd624decff2..75038c5ce15 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -799,6 +799,7 @@ en: max_similar_results: "How many similar topics to show a user while they are composing a new topic" title_prettify: "Prevent common title typos and errors, including all caps, lowercase first character, multiple ! and ?, extra . at end, etc." + title_sanitize: "Remove html tags from the title" topic_views_heat_low: "The number of views after which a topic's heat level is low." topic_views_heat_medium: "The number of views after which a topic's heat level is medium." diff --git a/config/site_settings.yml b/config/site_settings.yml index e64c397a6a9..f32b740ecf1 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -185,6 +185,7 @@ posting: default: 255 title_min_entropy: 10 title_prettify: true + title_sanitize: false title_fancy_entities: true min_private_message_title_length: client: true diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index fd332debcdf..56eca86cde7 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -120,16 +120,40 @@ describe Topic do let(:topic_image) { build_topic_with_title("Topic with image in its title" ) } let(:topic_script) { build_topic_with_title("Topic with script in its title" ) } - it "escapes script contents" do - topic_script.fancy_title.should == "Topic with <script>alert(‘title’)</script> script in its title" + context "title_sanitize disabled" do + + before { SiteSetting.stubs(:title_sanitize).returns(false) } + + it "escapes script contents" do + topic_script.fancy_title.should == "Topic with <script>alert(‘title’)</script> script in its title" + end + + it "escapes bold contents" do + topic_bold.fancy_title.should == "Topic with <b>bold</b> text in its title" + end + + it "escapes image contents" do + topic_image.fancy_title.should == "Topic with <img src=‘something’> image in its title" + end + end - it "escapes bold contents" do - topic_bold.fancy_title.should == "Topic with <b>bold</b> text in its title" - end + context "title_sanitize enabled" do + + before { SiteSetting.stubs(:title_sanitize).returns(true) } + + it "removes script contents" do + topic_script.fancy_title.should == "Topic with script in its title" + end + + it "removes bold contents" do + topic_bold.fancy_title.should == "Topic with bold text in its title" + end + + it "removes image contents" do + topic_image.fancy_title.should == "Topic with image in its title" + end - it "escapes image contents" do - topic_image.fancy_title.should == "Topic with <img src=‘something’> image in its title" end end @@ -1330,7 +1354,7 @@ describe Topic do end describe "expandable_first_post?" do - let(:topic) { Fabricate.build(:topic) } + let(:topic) { Fabricate.build(:topic) } before do SiteSetting.stubs(:embeddable_host).returns("http://eviltrout.com")