Commit 3fe538f12e2bbe1eb4e77dc91abd93bfc9963da5

Authored by Daniela Feitosa
Committed by Antonio Terceiro
1 parent 347fbb41

Allowed environment to set trusted sites on iframes

Added setting trusted_sites_for_iframes to environment
WhiteListFilter lib to filter iframes from fields
Removed "on hand" iframe filter from plugins

(ActionItem1631)
app/models/environment.rb
@@ -219,6 +219,8 @@ class Environment < ActiveRecord::Base @@ -219,6 +219,8 @@ class Environment < ActiveRecord::Base
219 settings_items :currency_separator, :type => String, :default => '.' 219 settings_items :currency_separator, :type => String, :default => '.'
220 settings_items :currency_delimiter, :type => String, :default => ',' 220 settings_items :currency_delimiter, :type => String, :default => ','
221 221
  222 + settings_items :trusted_sites_for_iframe, :type => Array, :default => ['itheora.org', 'tv.softwarelivre.org', 'stream.softwarelivre.org']
  223 +
222 def news_amount_by_folder=(amount) 224 def news_amount_by_folder=(amount)
223 settings[:news_amount_by_folder] = amount.to_i 225 settings[:news_amount_by_folder] = amount.to_i
224 end 226 end
@@ -468,6 +470,9 @@ class Environment < ActiveRecord::Base @@ -468,6 +470,9 @@ class Environment < ActiveRecord::Base
468 470
469 xss_terminate :only => [ :message_for_disabled_enterprise ], :with => 'white_list', :on => 'validation' 471 xss_terminate :only => [ :message_for_disabled_enterprise ], :with => 'white_list', :on => 'validation'
470 472
  473 + include WhiteListFilter
  474 + filter_iframes :message_for_disabled_enterprise, :whitelist => lambda { trusted_sites_for_iframe }
  475 +
471 476
472 # ################################################# 477 # #################################################
473 # Business logic in general 478 # Business logic in general
app/models/event.rb
@@ -26,6 +26,9 @@ class Event < Article @@ -26,6 +26,9 @@ class Event < Article
26 {:conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}]} 26 {:conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}]}
27 } 27 }
28 28
  29 + include WhiteListFilter
  30 + filter_iframes :description, :link, :address, :whitelist => lambda { profile && profile.environment && profile.environment.trusted_sites_for_iframe }
  31 +
29 def self.description 32 def self.description
30 _('A calendar event') 33 _('A calendar event')
31 end 34 end
app/models/folder.rb
@@ -6,6 +6,9 @@ class Folder &lt; Article @@ -6,6 +6,9 @@ class Folder &lt; Article
6 6
7 xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation' 7 xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation'
8 8
  9 + include WhiteListFilter
  10 + filter_iframes :body, :whitelist => lambda { profile && profile.environment && profile.environment.trusted_sites_for_iframe }
  11 +
9 def self.select_views 12 def self.select_views
10 [[_('Folder'), 'folder'], [_('Image gallery'), 'image_gallery']] 13 [[_('Folder'), 'folder'], [_('Image gallery'), 'image_gallery']]
11 end 14 end
app/models/product.rb
@@ -42,6 +42,9 @@ class Product &lt; ActiveRecord::Base @@ -42,6 +42,9 @@ class Product &lt; ActiveRecord::Base
42 42
43 acts_as_mappable 43 acts_as_mappable
44 44
  45 + include WhiteListFilter
  46 + filter_iframes :description, :whitelist => lambda { enterprise && enterprise.environment && enterprise.environment.trusted_sites_for_iframe }
  47 +
45 def self.units 48 def self.units
46 { 49 {
47 _('Litre') => 'litre', 50 _('Litre') => 'litre',
app/models/profile.rb
@@ -314,6 +314,10 @@ class Profile &lt; ActiveRecord::Base @@ -314,6 +314,10 @@ class Profile &lt; ActiveRecord::Base
314 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation' 314 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation'
315 xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list', :on => 'validation' 315 xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list', :on => 'validation'
316 316
  317 + include WhiteListFilter
  318 + filter_iframes :custom_header, :custom_footer, :whitelist => lambda { environment && environment.trusted_sites_for_iframe }
  319 +
  320 +
317 # returns the contact email for this profile. 321 # returns the contact email for this profile.
318 # 322 #
319 # Subclasses may -- and should -- override this method. 323 # Subclasses may -- and should -- override this method.
app/models/tiny_mce_article.rb
@@ -9,6 +9,10 @@ class TinyMceArticle &lt; TextArticle @@ -9,6 +9,10 @@ class TinyMceArticle &lt; TextArticle
9 end 9 end
10 10
11 xss_terminate :except => [ :abstract, :body ] 11 xss_terminate :except => [ :abstract, :body ]
  12 +
12 xss_terminate :only => [ :abstract, :body ], :with => 'white_list', :on => 'validation' 13 xss_terminate :only => [ :abstract, :body ], :with => 'white_list', :on => 'validation'
13 14
  15 + include WhiteListFilter
  16 + filter_iframes :abstract, :body, :whitelist => lambda { profile && profile.environment && profile.environment.trusted_sites_for_iframe }
  17 +
14 end 18 end
lib/white_list_filter.rb 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +module WhiteListFilter
  2 +
  3 + def check_iframe_on_content(content, trusted_sites)
  4 + if content.blank? || !content.include?('iframe')
  5 + return content
  6 + end
  7 + content.gsub!(/<iframe[^>]*>\s*<\/iframe>/i) do |iframe|
  8 + result = ''
  9 + unless iframe =~ /src=['"].*src=['"]/
  10 + trusted_sites.each do |trusted_site|
  11 + re_dom = trusted_site.gsub('.', '\.')
  12 + if iframe =~ /src=["']https?:\/\/(www\.)?#{re_dom}\//
  13 + result = iframe
  14 + end
  15 + end
  16 + end
  17 + result
  18 + end
  19 + content
  20 + end
  21 +
  22 + module ClassMethods
  23 + def filter_iframes(*opts)
  24 + options = opts.pop
  25 + white_list_method = options[:whitelist]
  26 + opts.each do |field|
  27 + before_validation do |obj|
  28 + obj.check_iframe_on_content(obj.send(field), obj.instance_eval(&white_list_method))
  29 + end
  30 + end
  31 + end
  32 + end
  33 +
  34 + def self.included(c)
  35 + c.send(:extend, WhiteListFilter::ClassMethods)
  36 + end
  37 +end
public/stylesheets/application.css
@@ -1444,7 +1444,6 @@ input.disabled { @@ -1444,7 +1444,6 @@ input.disabled {
1444 ***********************************************************/ 1444 ***********************************************************/
1445 1445
1446 .block iframe { 1446 .block iframe {
1447 - width: 100%;  
1448 border: none; 1447 border: none;
1449 } 1448 }
1450 1449
test/unit/environment_test.rb
@@ -1074,4 +1074,15 @@ class EnvironmentTest &lt; Test::Unit::TestCase @@ -1074,4 +1074,15 @@ class EnvironmentTest &lt; Test::Unit::TestCase
1074 assert_equal 15, env.profile_cache_in_minutes 1074 assert_equal 15, env.profile_cache_in_minutes
1075 end 1075 end
1076 1076
  1077 + should 'have a list of trusted sites by default' do
  1078 + assert_equal ['itheora.org', 'tv.softwarelivre.org', 'stream.softwarelivre.org'], Environment.new.trusted_sites_for_iframe
  1079 + end
  1080 +
  1081 + should 'have a list of trusted sites' do
  1082 + e = Environment.default
  1083 + e.trusted_sites_for_iframe = ['trusted.site.org']
  1084 + e.save!
  1085 +
  1086 + assert_equal ['trusted.site.org'], Environment.default.trusted_sites_for_iframe
  1087 + end
1077 end 1088 end
test/unit/event_test.rb
@@ -265,5 +265,4 @@ class EventTest &lt; ActiveSupport::TestCase @@ -265,5 +265,4 @@ class EventTest &lt; ActiveSupport::TestCase
265 assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, event.description 265 assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, event.description
266 assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, event.address 266 assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, event.address
267 end 267 end
268 -  
269 end 268 end
test/unit/tiny_mce_article_test.rb
@@ -54,19 +54,49 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase @@ -54,19 +54,49 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase
54 assert_equal "the <!–-[if IE]> just for ie... <![endif]-–>", article.body 54 assert_equal "the <!–-[if IE]> just for ie... <![endif]-–>", article.body
55 end 55 end
56 56
57 - should 'not mess with <iframe and </iframe if it is from itheora' do  
58 - article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://itheora.org'></iframe>")  
59 - assert_equal "<iframe src=\"http://itheora.org\"></iframe>", article.body 57 + should 'remove iframe if it is not from a trusted site' do
  58 + article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://anything/videos.ogg'></iframe>")
  59 + assert_equal "", article.body
60 end 60 end
61 61
62 - should 'remove iframe if it is not from itheora or softwarelivre' do  
63 - article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='anything'></iframe>")  
64 - assert_equal "", article.body 62 + should 'not mess with <iframe and </iframe if it is from itheora by default' do
  63 + assert_includes Environment.default.trusted_sites_for_iframe, 'itheora.org'
  64 + article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://itheora.org/demo/index.php?v=example.ogv'></iframe>")
  65 + assert_tag_in_string article.body, :tag => 'iframe', :attributes => { :src => "http://itheora.org/demo/index.php?v=example.ogv"}
65 end 66 end
66 67
67 - should 'allow iframe if it is from stream.softwarelivre.org' do  
68 - article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://stream.softwarelivre.org'></iframe>")  
69 - assert_equal "<iframe src=\"http://stream.softwarelivre.org\"></iframe>", article.body 68 + should 'allow iframe if it is from stream.softwarelivre.org by default' do
  69 + assert_includes Environment.default.trusted_sites_for_iframe, 'stream.softwarelivre.org'
  70 + article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://stream.softwarelivre.org/fisl10/sites/default/files/videos.ogg'></iframe>")
  71 + assert_tag_in_string article.body, :tag => 'iframe', :attributes => { :src => "http://stream.softwarelivre.org/fisl10/sites/default/files/videos.ogg"}
  72 + end
  73 +
  74 + should 'allow iframe if it is from tv.softwarelivre.org by default' do
  75 + assert_includes Environment.default.trusted_sites_for_iframe, 'tv.softwarelivre.org'
  76 + article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe id='player-base' src='http://tv.softwarelivre.org/embed/1170' width='482' height='406' align='right' frameborder='0' scrolling='no'></iframe>")
  77 + assert_tag_in_string article.body, :tag => 'iframe', :attributes => { :src => "http://tv.softwarelivre.org/embed/1170", :width => "482", :height => "406", :align => "right", :frameborder => "0", :scrolling => "no"}
  78 + end
  79 +
  80 + should 'allow iframe if it is from a trusted site' do
  81 + env = Environment.default
  82 + env.trusted_sites_for_iframe = ['avideosite.com']
  83 + env.save
  84 + assert_includes Environment.default.trusted_sites_for_iframe, 'avideosite.com'
  85 + article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://avideosite.com/videos.ogg'></iframe>")
  86 + assert_tag_in_string article.body, :tag => 'iframe', :attributes => { :src => "http://avideosite.com/videos.ogg"}
  87 + end
  88 +
  89 + should 'remove only the iframe from untrusted site' do
  90 + article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://stream.softwarelivre.org/videos.ogg'></iframe><iframe src='http://untrusted_site.com/videos.ogg'></iframe>")
  91 + assert_tag_in_string article.body, :tag => 'iframe', :attributes => { :src => "http://stream.softwarelivre.org/videos.ogg"}
  92 + assert_no_tag_in_string article.body, :tag => 'iframe', :attributes => { :src => "http://untrusted_site.com/videos.ogg"}
  93 + end
  94 +
  95 + should 'remove iframe if it has 2 or more src' do
  96 + assert_includes Environment.default.trusted_sites_for_iframe, 'itheora.org'
  97 +
  98 + article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://itheora.org/videos.ogg' src='http://untrusted_site.com/videos.ogg'></iframe>")
  99 + assert_equal '', article.body
70 end 100 end
71 101
72 #TinymMCE convert config={"key":(.*)} in config={&quotkey&quot:(.*)} 102 #TinymMCE convert config={"key":(.*)} in config={&quotkey&quot:(.*)}
@@ -83,9 +113,4 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase @@ -83,9 +113,4 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase
83 assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, article.body 113 assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, article.body
84 end 114 end
85 115
86 - should 'allow iframe if it is from tv.softwarelivre.org' do  
87 - article = TinyMceArticle.create!(:profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe id='player-base' src='http://tv.softwarelivre.org/embed/1170' width='482' height='406' align='right' frameborder='0' scrolling='no'></iframe>")  
88 - assert_tag_in_string article.body, :tag => 'iframe', :attributes => { :src => "http://tv.softwarelivre.org/embed/1170", :width => "482", :height => "406", :align => "right", :frameborder => "0", :scrolling => "no"}  
89 - end  
90 -  
91 end 116 end
test/unit/white_list_filter_test.rb 0 → 100644
@@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class WhiteListFilterTest < Test::Unit::TestCase
  4 +
  5 + include WhiteListFilter
  6 +
  7 + def environment
  8 + @environment ||= Environment.default
  9 + end
  10 +
  11 + should 'remove iframe if it is not from a trusted site' do
  12 + content = "<iframe src='http://anything/videos.ogg'></iframe>"
  13 + assert_equal "", check_iframe_on_content(content, environment.trusted_sites_for_iframe)
  14 + end
  15 +
  16 + should 'not mess with <iframe and </iframe if it is from itheora by default' do
  17 + assert_includes Environment.default.trusted_sites_for_iframe, 'itheora.org'
  18 + content = "<iframe src='http://itheora.org/demo/index.php?v=example.ogv'></iframe>"
  19 + assert_equal "<iframe src='http://itheora.org/demo/index.php?v=example.ogv'></iframe>", check_iframe_on_content(content, environment.trusted_sites_for_iframe)
  20 + end
  21 +
  22 + should 'allow iframe if it is from stream.softwarelivre.org by default' do
  23 + assert_includes Environment.default.trusted_sites_for_iframe, 'stream.softwarelivre.org'
  24 + content = "<iframe src='http://stream.softwarelivre.org/fisl10/sites/default/files/videos.ogg'></iframe>"
  25 + assert_equal "<iframe src='http://stream.softwarelivre.org/fisl10/sites/default/files/videos.ogg'></iframe>", check_iframe_on_content(content, environment.trusted_sites_for_iframe)
  26 + end
  27 +
  28 + should 'allow iframe if it is from tv.softwarelivre.org by default' do
  29 + assert_includes Environment.default.trusted_sites_for_iframe, 'tv.softwarelivre.org'
  30 + content = "<iframe id='player-base' src='http://tv.softwarelivre.org/embed/1170' width='482' height='406' align='right' frameborder='0' scrolling='no'></iframe>"
  31 + assert_equal "<iframe id='player-base' src='http://tv.softwarelivre.org/embed/1170' width='482' height='406' align='right' frameborder='0' scrolling='no'></iframe>", check_iframe_on_content(content, environment.trusted_sites_for_iframe)
  32 + end
  33 +
  34 + should 'allow iframe if it is from a trusted site' do
  35 + env = Environment.default
  36 + env.trusted_sites_for_iframe = ['avideosite.com']
  37 + env.save
  38 + assert_includes Environment.default.trusted_sites_for_iframe, 'avideosite.com'
  39 + content = "<iframe src='http://avideosite.com/videos.ogg'></iframe>"
  40 + assert_equal "<iframe src='http://avideosite.com/videos.ogg'></iframe>", check_iframe_on_content(content, environment.trusted_sites_for_iframe)
  41 + end
  42 +
  43 + should 'remove only the iframe from untrusted site' do
  44 + content = "<iframe src='http://stream.softwarelivre.org/videos.ogg'></iframe><iframe src='http://untrusted_site.com/videos.ogg'></iframe>"
  45 + assert_equal "<iframe src='http://stream.softwarelivre.org/videos.ogg'></iframe>", check_iframe_on_content(content, environment.trusted_sites_for_iframe)
  46 + end
  47 +
  48 + should 'remove iframe if it has 2 or more src' do
  49 + assert_includes Environment.default.trusted_sites_for_iframe, 'itheora.org'
  50 +
  51 + content = "<iframe src='http://itheora.org/videos.ogg' src='http://untrusted_site.com/videos.ogg'></iframe>"
  52 + assert_equal '', check_iframe_on_content(content, environment.trusted_sites_for_iframe)
  53 + end
  54 +end
vendor/plugins/white_list_sanitizer_unescape_before_reescape/init.rb
@@ -11,13 +11,6 @@ HTML::WhiteListSanitizer.module_eval do @@ -11,13 +11,6 @@ HTML::WhiteListSanitizer.module_eval do
11 final_text = text.gsub(/&lt;!/, '<!') 11 final_text = text.gsub(/&lt;!/, '<!')
12 final_text = final_text.gsub(/<!--.*\[if IE\]-->(.*)<!--\[endif\]-->/, '<!–-[if IE]>\1<![endif]-–>') #FIX for itheora comments 12 final_text = final_text.gsub(/<!--.*\[if IE\]-->(.*)<!--\[endif\]-->/, '<!–-[if IE]>\1<![endif]-–>') #FIX for itheora comments
13 13
14 - if final_text =~ /iframe/  
15 - itheora_video = /<iframe(.*)src=(.*)itheora.org(.*)<\/iframe>/  
16 - sl_video = /<iframe(.*)src=\"http:\/\/(stream|tv).softwarelivre.org(.*)<\/iframe>/  
17 - unless (final_text =~ itheora_video || final_text =~ sl_video)  
18 - final_text = final_text.gsub(/<iframe(.*)<\/iframe>/, '')  
19 - end  
20 - end  
21 final_text = final_text.gsub(/&amp;quot;/, '&quot;') #FIX problems with archive.org 14 final_text = final_text.gsub(/&amp;quot;/, '&quot;') #FIX problems with archive.org
22 final_text 15 final_text
23 end 16 end