From 454f11e59781342066406aac5373f6cce4170709 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9gis=20Hanol?= <regis@hanol.fr>
Date: Fri, 18 Apr 2014 21:01:21 +0200
Subject: [PATCH] FEATURE: new title_sanitize site setting

---
 app/models/topic.rb          | 22 +++++++++++++-------
 config/locales/server.en.yml |  1 +
 config/site_settings.yml     |  1 +
 spec/models/topic_spec.rb    | 40 ++++++++++++++++++++++++++++--------
 4 files changed, 49 insertions(+), 15 deletions(-)

diff --git a/app/models/topic.rb b/app/models/topic.rb
index 92951e1e5..8aa2c1e5b 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(/['&\"<>]/, {
-      "'" => '&#39;',
-      '&' => '&amp;',
-      '"' => '&quot;',
-      '<' => '&lt;',
-      '>' => '&gt;',
-    })
+    sanitized_title = if SiteSetting.title_sanitize
+      sanitize(title.to_s, tags: [], attributes: []).strip.presence
+    else
+      title.gsub(/['&\"<>]/, {
+        "'" => '&#39;',
+        '&' => '&amp;',
+        '"' => '&quot;',
+        '<' => '&lt;',
+        '>' => '&gt;',
+      })
+    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 dd624decf..75038c5ce 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 e64c397a6..f32b740ec 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 fd332debc..56eca86cd 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 <img src='something'> image in its title" ) }
     let(:topic_script) { build_topic_with_title("Topic with <script>alert('title')</script> script in its title" ) }
 
-    it "escapes script contents" do
-      topic_script.fancy_title.should == "Topic with &lt;script&gt;alert(&lsquo;title&rsquo;)&lt;/script&gt; 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 &lt;script&gt;alert(&lsquo;title&rsquo;)&lt;/script&gt; script in its title"
+      end
+
+      it "escapes bold contents" do
+        topic_bold.fancy_title.should == "Topic with &lt;b&gt;bold&lt;/b&gt; text in its title"
+      end
+
+      it "escapes image contents" do
+        topic_image.fancy_title.should == "Topic with &lt;img src=&lsquo;something&rsquo;&gt; image in its title"
+      end
+
     end
 
-    it "escapes bold contents" do
-      topic_bold.fancy_title.should == "Topic with &lt;b&gt;bold&lt;/b&gt; 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 &lt;img src=&lsquo;something&rsquo;&gt; 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")