From 4ec0543362e58cd950d0cf23dc09fad526206ce1 Mon Sep 17 00:00:00 2001
From: Neil Lalonde <neillalonde@gmail.com>
Date: Thu, 28 Nov 2013 15:57:21 -0500
Subject: [PATCH] FIX: emails with embedded posts should always use absolute
 URLs

---
 app/views/email/_post.html.erb      |  2 +-
 lib/pretty_text.rb                  | 16 ++++++++++++++++
 spec/components/pretty_text_spec.rb | 29 +++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/app/views/email/_post.html.erb b/app/views/email/_post.html.erb
index 7293eb1e341..dfa2939897f 100644
--- a/app/views/email/_post.html.erb
+++ b/app/views/email/_post.html.erb
@@ -10,7 +10,7 @@
       </td>
     </tr>
     <tr>
-      <td class='body'><%= post.cooked.html_safe %></td>
+      <td class='body'><%= PrettyText.make_all_links_absolute(post.cooked).html_safe %></td>
     </tr>
   </tbody>
 </table>
diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb
index d0c87a2fe43..84503d6c62e 100644
--- a/lib/pretty_text.rb
+++ b/lib/pretty_text.rb
@@ -234,6 +234,22 @@ module PrettyText
     fragment.to_html
   end
 
+  def self.make_all_links_absolute(html)
+    site_uri = nil
+    doc = Nokogiri::HTML.fragment(html)
+    doc.css("a").each do |l|
+      href = l["href"].to_s
+      begin
+        uri = URI(href)
+        site_uri ||= URI(Discourse.base_url)
+        l["href"] = "#{site_uri}#{l['href']}" unless uri.host.present?
+      rescue URI::InvalidURIError
+        # leave it
+      end
+    end
+    doc.to_html
+  end
+
   protected
 
   def self.ctx_load(ctx, *files)
diff --git a/spec/components/pretty_text_spec.rb b/spec/components/pretty_text_spec.rb
index be9e55c1914..1398937d0db 100644
--- a/spec/components/pretty_text_spec.rb
+++ b/spec/components/pretty_text_spec.rb
@@ -177,4 +177,33 @@ describe PrettyText do
     end
   end
 
+  describe "make_all_links_absolute" do
+    let(:base_url) { "http://baseurl.net" }
+
+    before do
+      Discourse.stubs(:base_url).returns(base_url)
+    end
+
+    it "adds base url to relative links" do
+      html = "<p><a class=\"mention\" href=\"/users/wiseguy\">@wiseguy</a>, <a class=\"mention\" href=\"/users/trollol\">@trollol</a> what do you guys think? </p>"
+      output = described_class.make_all_links_absolute(html)
+      output.should == "<p><a class=\"mention\" href=\"#{base_url}/users/wiseguy\">@wiseguy</a>, <a class=\"mention\" href=\"#{base_url}/users/trollol\">@trollol</a> what do you guys think? </p>"
+    end
+
+    it "doesn't change external absolute links" do
+      html = "<p>Check out <a href=\"http://mywebsite.com/users/boss\">this guy</a>.</p>"
+      described_class.make_all_links_absolute(html).should == html
+    end
+
+    it "doesn't change internal absolute links" do
+      html = "<p>Check out <a href=\"#{base_url}/users/boss\">this guy</a>.</p>"
+      described_class.make_all_links_absolute(html).should == html
+    end
+
+    it "can tolerate invalid URLs" do
+      html = "<p>Check out <a href=\"not a real url\">this guy</a>.</p>"
+      expect { described_class.make_all_links_absolute(html) }.to_not raise_error
+    end
+  end
+
 end