Commit 8235fc9d9cb92ae0d98145ed4f5e79dedcd6c929

Authored by Braulio Bhavamitra
1 parent fb028d5a

metadata: marks urls as html safe

app/models/article.rb
@@ -742,9 +742,10 @@ class Article < ActiveRecord::Base @@ -742,9 +742,10 @@ class Article < ActiveRecord::Base
742 end 742 end
743 743
744 def body_images_paths 744 def body_images_paths
745 - require 'uri'  
746 Nokogiri::HTML.fragment(self.body.to_s).css('img[src]').collect do |i| 745 Nokogiri::HTML.fragment(self.body.to_s).css('img[src]').collect do |i|
747 - (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i['src'])).to_s : i['src'] 746 + src = i['src']
  747 + src = URI.escape src if self.new_record? # xss_terminate runs on save
  748 + (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, src).to_s : src
748 end 749 end
749 end 750 end
750 751
plugins/metadata/lib/ext/article.rb
@@ -12,9 +12,9 @@ class Article @@ -12,9 +12,9 @@ class Article
12 end, 12 end,
13 title: proc{ |a, plugin| "#{a.title} - #{a.profile.name}" }, 13 title: proc{ |a, plugin| "#{a.title} - #{a.profile.name}" },
14 image: proc do |a, plugin| 14 image: proc do |a, plugin|
15 - img = a.body_images_paths  
16 - img = "#{a.profile.environment.top_url}#{a.profile.image.public_filename}" if a.profile.image if img.blank?  
17 - img ||= MetadataPlugin.config[:open_graph][:environment_logo] rescue nil if img.blank? 15 + img = a.body_images_paths.map! &:html_safe
  16 + img = "#{a.profile.environment.top_url}#{a.profile.image.public_filename}".html_safe if a.profile.image if img.blank?
  17 + img ||= MetadataPlugin.config[:open_graph][:environment_logo].html_safe rescue nil if img.blank?
18 img 18 img
19 end, 19 end,
20 see_also: [], 20 see_also: [],
@@ -31,10 +31,10 @@ class Article @@ -31,10 +31,10 @@ class Article
31 card: 'summary', 31 card: 'summary',
32 description: proc do |a, plugin| 32 description: proc do |a, plugin|
33 description = a.body.to_s || a.environment.name 33 description = a.body.to_s || a.environment.name
34 - CGI.escapeHTML(plugin.helpers.truncate(plugin.helpers.strip_tags(description), length: 200)) 34 + plugin.helpers.truncate plugin.helpers.strip_tags(description), length: 200
35 end, 35 end,
36 title: proc{ |a, plugin| "#{a.title} - #{a.profile.name}" }, 36 title: proc{ |a, plugin| "#{a.title} - #{a.profile.name}" },
37 - image: proc{ |a, plugin| a.body_images_paths }, 37 + image: proc{ |a, plugin| a.body_images_paths.map! &:html_safe },
38 } 38 }
39 39
40 metadata_spec namespace: :article, key_attr: :property, tags: { 40 metadata_spec namespace: :article, key_attr: :property, tags: {
plugins/metadata/lib/ext/product.rb
@@ -14,8 +14,8 @@ class Product @@ -14,8 +14,8 @@ class Product
14 description: proc{ |p, plugin| ActionView::Base.full_sanitizer.sanitize p.description }, 14 description: proc{ |p, plugin| ActionView::Base.full_sanitizer.sanitize p.description },
15 15
16 image: proc do |p, plugin| 16 image: proc do |p, plugin|
17 - img = "#{p.environment.top_url}#{p.image.public_filename}" if p.image  
18 - img = "#{p.environment.top_url}#{p.profile.image.public_filename}" if img.blank? and p.profile.image 17 + img = "#{p.environment.top_url}#{p.image.public_filename}".html_safe if p.image
  18 + img = "#{p.environment.top_url}#{p.profile.image.public_filename}".html_safe if img.blank? and p.profile.image
19 img ||= MetadataPlugin.config[:open_graph][:environment_logo] rescue nil if img.blank? 19 img ||= MetadataPlugin.config[:open_graph][:environment_logo] rescue nil if img.blank?
20 img 20 img
21 end, 21 end,
plugins/metadata/lib/ext/profile.rb
@@ -5,8 +5,8 @@ class Profile @@ -5,8 +5,8 @@ class Profile
5 metadata_spec namespace: :og, tags: { 5 metadata_spec namespace: :og, tags: {
6 type: proc{ |p, plugin| plugin.context.params[:og_type] || MetadataPlugin.og_types[:profile] || :profile }, 6 type: proc{ |p, plugin| plugin.context.params[:og_type] || MetadataPlugin.og_types[:profile] || :profile },
7 image: proc do |p, plugin| 7 image: proc do |p, plugin|
8 - img = "#{p.environment.top_url}#{p.image.public_filename}" if p.image  
9 - img ||= MetadataPlugin.config[:open_graph][:environment_logo] rescue nil if img.blank? 8 + img = "#{p.environment.top_url}#{p.image.public_filename}".html_safe if p.image
  9 + img ||= MetadataPlugin.config[:open_graph][:environment_logo].html_safe rescue nil if img.blank?
10 img 10 img
11 end, 11 end,
12 title: proc{ |p, plugin| if p.nickname.present? then p.nickname else p.name end }, 12 title: proc{ |p, plugin| if p.nickname.present? then p.nickname else p.name end },
plugins/metadata/lib/ext/uploaded_file.rb
@@ -13,7 +13,7 @@ class UploadedFile @@ -13,7 +13,7 @@ class UploadedFile
13 plugin.og_url_for url 13 plugin.og_url_for url
14 end, 14 end,
15 title: proc{ |u, plugin| u.title }, 15 title: proc{ |u, plugin| u.title },
16 - image: proc{ |u, plugin| "#{u.environment.top_url}#{u.public_filename}" if u.image? }, 16 + image: proc{ |u, plugin| "#{u.environment.top_url}#{u.public_filename}".html_safe if u.image? },
17 description: proc{ |u, plugin| u.abstract || u.title }, 17 description: proc{ |u, plugin| u.abstract || u.title },
18 } 18 }
19 19
plugins/metadata/lib/metadata_plugin/base.rb
@@ -50,7 +50,8 @@ class MetadataPlugin::Base < Noosfero::Plugin @@ -50,7 +50,8 @@ class MetadataPlugin::Base < Noosfero::Plugin
50 Array(values).each do |value| 50 Array(values).each do |value|
51 value = value.call(object, plugin) if value.is_a? Proc rescue nil 51 value = value.call(object, plugin) if value.is_a? Proc rescue nil
52 next if value.blank? 52 next if value.blank?
53 - r << tag(:meta, key_attr => key, value_attr => CGI.escape_html(value.to_s)) 53 + value = h value unless value.html_safe?
  54 + r << tag(:meta, {key_attr => key, value_attr => value.to_s}, false, false)
54 end 55 end
55 end 56 end
56 end 57 end
plugins/metadata/lib/metadata_plugin/url_helper.rb
@@ -7,7 +7,8 @@ module MetadataPlugin::UrlHelper @@ -7,7 +7,8 @@ module MetadataPlugin::UrlHelper
7 def og_url_for options 7 def og_url_for options
8 options.delete :port 8 options.delete :port
9 options[:host] = self.og_domain 9 options[:host] = self.og_domain
10 - Noosfero::Application.routes.url_helpers.url_for options 10 + url = Noosfero::Application.routes.url_helpers.url_for options
  11 + url.html_safe
11 end 12 end
12 13
13 def og_profile_url profile 14 def og_profile_url profile
plugins/metadata/test/functional/content_viewer_controller_test.rb
@@ -48,6 +48,14 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -48,6 +48,14 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
48 assert_tag tag: 'meta', attributes: { property: 'og:image', content: /\/images\/x.png/ } 48 assert_tag tag: 'meta', attributes: { property: 'og:image', content: /\/images\/x.png/ }
49 end 49 end
50 50
  51 + should 'escape utf8 characters correctly' do
  52 + a = TinyMceArticle.create(name: 'Article to be shared with images', body: 'This article should be shared with all social networks <img src="/images/ç.png" />', profile: profile)
  53 +
  54 + get :view_page, profile: profile.identifier, page: [ a.name.to_slug ]
  55 + assert_tag tag: 'meta', attributes: { property: 'og:image', content: /\/images\/%C3%A7.png/ }
  56 + end
  57 +
  58 +
51 should 'render not_found page properly' do 59 should 'render not_found page properly' do
52 assert_equal false, Article.exists?(:slug => 'non-existing-page') 60 assert_equal false, Article.exists?(:slug => 'non-existing-page')
53 assert_nothing_raised do 61 assert_nothing_raised do
test/unit/article_test.rb
@@ -1497,6 +1497,17 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1497,6 +1497,17 @@ class ArticleTest &lt; ActiveSupport::TestCase
1497 assert_includes a.body_images_paths, 'http://test.com/noosfero.png' 1497 assert_includes a.body_images_paths, 'http://test.com/noosfero.png'
1498 end 1498 end
1499 1499
  1500 + should 'escape utf8 characters correctly' do
  1501 + Environment.any_instance.stubs(:default_hostname).returns('noosfero.org')
  1502 + a = build TinyMceArticle, profile: @profile
  1503 + a.body = 'Noosfero <img src="http://noosfero.com/cabeça.png" /> '
  1504 + assert_includes a.body_images_paths, 'http://noosfero.com/cabe%C3%A7a.png'
  1505 +
  1506 + # check if after save (that is, after xss_terminate run)
  1507 + a.save!
  1508 + assert_includes a.body_images_paths, 'http://noosfero.com/cabe%C3%A7a.png'
  1509 + end
  1510 +
1500 should 'get absolute images paths in article body' do 1511 should 'get absolute images paths in article body' do
1501 Environment.any_instance.stubs(:default_hostname).returns('noosfero.org') 1512 Environment.any_instance.stubs(:default_hostname).returns('noosfero.org')
1502 a = build TinyMceArticle, :profile => @profile 1513 a = build TinyMceArticle, :profile => @profile