Update Rails, rails_xss and Bundler

Update Bundler to 1.0.15.
Update Rails to 2.3.12.
Update rails_xss plugin.

The latter two were the
source of a considerable
amount of grief, as rails_xss
is now MUCH stricter about what
string methods can be used.

Also made it possible to use
rake 0.9.x with Instiki. But
you probably REALLY want to use

 ruby bundle exec rake ...

instead of just saying

 rake ....
This commit is contained in:
Jacques Distler 2011-06-15 00:43:38 -05:00
parent ec443685a6
commit 9e909d5be3
1105 changed files with 14278 additions and 4667 deletions

View file

@ -1,5 +1,7 @@
unless $gems_rake_task
if !(Rails::VERSION::MAJOR.to_i >= 2 && Rails::VERSION::MINOR.to_i >=3 && Rails::VERSION::TINY.to_i >=8)
if Rails::VERSION::MAJOR >= 3
$stderr.puts "You don't need to install rails_xss as a plugin for Rails 3 and after."
elsif Rails::VERSION::MAJOR <= 2 && Rails::VERSION::MINOR <= 3 && Rails::VERSION::TINY <= 7
$stderr.puts "rails_xss requires Rails 2.3.8 or later. Please upgrade to enable automatic HTML safety."
else
require 'rails_xss'

View file

@ -15,6 +15,15 @@ module ActionView
end
module Helpers
module CaptureHelper
def content_for(name, content = nil, &block)
ivar = "@content_for_#{name}"
content = capture(&block) if block_given?
instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{ERB::Util.h(content)}".html_safe)
nil
end
end
module TextHelper
def concat(string, unused_binding = nil)
if unused_binding
@ -23,15 +32,53 @@ module ActionView
output_buffer.concat(string)
end
def simple_format(text, html_options={})
start_tag = tag('p', html_options, true)
text = ERB::Util.h(text).to_str.dup
text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n
text.gsub!(/\n\n+/, "</p>\n\n#{start_tag}") # 2+ newline -> paragraph
text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
text.insert 0, start_tag
text.html_safe.safe_concat("</p>")
end
end
module TagHelper
private
def content_tag_string_with_escaping(name, content, options, escape = true)
content_tag_string_without_escaping(name, ERB::Util.h(content), options, escape)
content_tag_string_without_escaping(name, escape ? ERB::Util.h(content) : content, options, escape)
end
alias_method_chain :content_tag_string, :escaping
end
module UrlHelper
def link_to(*args, &block)
if block_given?
options = args.first || {}
html_options = args.second
concat(link_to(capture(&block), options, html_options))
else
name = args.first
options = args.second || {}
html_options = args.third
url = url_for(options)
if html_options
html_options = html_options.stringify_keys
href = html_options['href']
convert_options_to_javascript!(html_options, url)
tag_options = tag_options(html_options)
else
tag_options = nil
end
href_attr = "href=\"#{url}\"" unless href
"<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe
end
end
end
end
end
@ -49,35 +96,6 @@ module RailsXss
end
end
end
module HelperOverrides
def link_to(*args, &block)
if block_given?
options = args.first || {}
html_options = args.second
concat(link_to(capture(&block), options, html_options))
else
name = args.first
options = args.second || {}
html_options = args.third
url = url_for(options)
if html_options
html_options = html_options.stringify_keys
href = html_options['href']
convert_options_to_javascript!(html_options, url)
tag_options = tag_options(html_options)
else
tag_options = nil
end
href_attr = "href=\"#{url}\"" unless href
"<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe
end
end
end
end
Module.class_eval { include RailsXss::SafeHelpers }
ActionController::Base.helper(RailsXss::HelperOverrides)

View file

@ -11,8 +11,10 @@ module RailsXss
src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
end
BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
def add_expr_literal(src, code)
if code =~ /\s*raw\s+(.*)/
if code =~ BLOCK_EXPR
src << "@output_buffer.safe_concat((" << $1 << ").to_s);"
else
src << '@output_buffer << ((' << code << ').to_s);'

View file

@ -9,6 +9,19 @@ ActiveSupport::SafeBuffer.class_eval do
end
end
alias << concat
UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase"].freeze
for unsafe_method in UNSAFE_STRING_METHODS
class_eval <<-EOT, __FILE__, __LINE__
def #{unsafe_method}(*args)
super.to_str
end
def #{unsafe_method}!(*args)
raise TypeError, "Cannot modify SafeBuffer in place"
end
EOT
end
end
class String

View file

@ -0,0 +1,74 @@
require 'test_helper'
class ActiveRecordHelperTest < ActionView::TestCase
silence_warnings do
Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on)
Post.class_eval do
alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast)
alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
end
end
def setup_post
@post = Post.new
def @post.errors
Class.new {
def on(field)
case field.to_s
when "author_name"
"can't be empty"
when "body"
true
else
false
end
end
def empty?() false end
def count() 1 end
def full_messages() [ "Author name can't be empty" ] end
}.new
end
def @post.new_record?() true end
def @post.to_param() nil end
def @post.column_for_attribute(attr_name)
Post.content_columns.select { |column| column.name == attr_name }.first
end
silence_warnings do
def Post.content_columns() [ Column.new(:string, "title", "Title"), Column.new(:text, "body", "Body") ] end
end
@post.title = "Hello World"
@post.author_name = ""
@post.body = "Back to the hill and over it again!"
@post.secret = 1
@post.written_on = Date.new(2004, 6, 15)
end
def setup
setup_post
@response = ActionController::TestResponse.new
@controller = Object.new
def @controller.url_for(options)
options = options.symbolize_keys
[options[:action], options[:id].to_param].compact.join('/')
end
end
def test_text_field_with_errors_is_safe
assert text_field("post", "author_name").html_safe?
end
def test_text_field_with_errors
assert_dom_equal(
%(<div class="fieldWithErrors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /></div>),
text_field("post", "author_name")
)
end
end

View file

@ -0,0 +1,49 @@
require 'test_helper'
class AssetTagHelperTest < ActionView::TestCase
def setup
@controller = Class.new do
attr_accessor :request
def url_for(*args) "http://www.example.com" end
end.new
end
def test_auto_discovery_link_tag
assert_dom_equal(%(<link href="http://www.example.com" rel="Not so alternate" title="ATOM" type="application/atom+xml" />),
auto_discovery_link_tag(:atom, {}, {:rel => "Not so alternate"}))
end
def test_javascript_include_tag_with_blank_asset_id
ENV["RAILS_ASSET_ID"] = ""
assert_dom_equal(%(<script src="/javascripts/test.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>),
javascript_include_tag("test", :defaults))
end
def test_javascript_include_tag_with_given_asset_id
ENV["RAILS_ASSET_ID"] = "1"
assert_dom_equal(%(<script src="/javascripts/prototype.js?1" type="text/javascript"></script>\n<script src="/javascripts/effects.js?1" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js?1" type="text/javascript"></script>\n<script src="/javascripts/controls.js?1" type="text/javascript"></script>\n<script src="/javascripts/application.js?1" type="text/javascript"></script>),
javascript_include_tag(:defaults))
ENV["RAILS_ASSET_ID"] = ""
end
def test_javascript_include_tag_is_html_safe
assert javascript_include_tag(:defaults).html_safe?
assert javascript_include_tag("prototype").html_safe?
end
def test_stylesheet_link_tag
assert_dom_equal(%(<link href="http://www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />),
stylesheet_link_tag("http://www.example.com/styles/style"))
end
def test_stylesheet_link_tag_is_html_safe
assert stylesheet_link_tag('dir/file').html_safe?
assert stylesheet_link_tag('dir/other/file', 'dir/file2').html_safe?
assert stylesheet_tag('dir/file', {}).html_safe?
end
def test_image_tag
assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='/images/mouse_over.png'" onmouseout="this.src='/images/mouse.png'" src="/images/mouse.png" />),
image_tag("mouse.png", :mouseover => image_path("mouse_over.png")))
end
end

View file

@ -0,0 +1,54 @@
require 'test_helper'
CACHE_DIR = 'test_cache'
# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed
FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR)
ActionController::Base.page_cache_directory = FILE_STORE_PATH
ActionController::Base.cache_store = :file_store, FILE_STORE_PATH
class FragmentCachingTestController < ActionController::Base
def some_action; end;
end
class FragmentCachingTest < ActionController::TestCase
def setup
ActionController::Base.perform_caching = true
@store = ActiveSupport::Cache::MemoryStore.new
ActionController::Base.cache_store = @store
@controller = FragmentCachingTestController.new
@params = {:controller => 'posts', :action => 'index'}
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@controller.params = @params
@controller.request = @request
@controller.response = @response
@controller.send(:initialize_current_url)
@controller.send(:initialize_template_class, @response)
@controller.send(:assign_shortcuts, @request, @response)
end
def test_fragment_for
@store.write('views/expensive', 'fragment content')
fragment_computed = false
buffer = 'generated till now -> '.html_safe
@controller.fragment_for(buffer, 'expensive') { fragment_computed = true }
assert !fragment_computed
assert_equal 'generated till now -> fragment content', buffer
end
def test_html_safety
assert_nil @store.read('views/name')
content = 'value'.html_safe
assert_equal content, @controller.write_fragment('name', content)
cached = @store.read('views/name')
assert_equal content, cached
assert_equal String, cached.class
html_safe = @controller.read_fragment('name')
assert_equal content, html_safe
assert html_safe.html_safe?
end
end

View file

@ -0,0 +1,39 @@
require 'test_helper'
class ContentForTest < ActionView::TestCase
def test_content_for_should_yield_html_safe_string
content_for(:testing, "Some <p>html</p>")
content = instance_variable_get(:"@content_for_testing")
assert content.html_safe?
end
def test_content_for_should_escape_content
content_for(:testing, "Some <p>html</p>")
content = instance_variable_get(:"@content_for_testing")
expected = %{Some &lt;p&gt;html&lt;/p&gt;}
assert_dom_equal expected, content
end
def test_content_for_should_not_escape_html_safe_content
content_for(:testing, "Some <p>html</p>".html_safe)
content = instance_variable_get(:"@content_for_testing")
expected = %{Some <p>html</p>}
assert_dom_equal expected, content
end
def test_content_for_should_escape_content_from_block
content_for(:testing){ "Some <p>html</p>" }
content = instance_variable_get(:"@content_for_testing")
expected = %{Some &lt;p&gt;html&lt;/p&gt;}
assert_dom_equal expected, content
end
def test_content_for_should_not_escape_html_safe_content_from_block
content_for(:testing){ "Some <p>html</p>".html_safe }
content = instance_variable_get(:"@content_for_testing")
expected = %{Some <p>html</p>}
assert_dom_equal expected, content
end
end

View file

@ -0,0 +1,29 @@
require 'test_helper'
class DateHelperTest < ActionView::TestCase
silence_warnings do
Post = Struct.new("Post", :id, :written_on, :updated_at)
end
def test_select_html_safety
assert select_day(16).html_safe?
assert select_month(8).html_safe?
assert select_year(Time.mktime(2003, 8, 16, 8, 4, 18)).html_safe?
assert select_minute(Time.mktime(2003, 8, 16, 8, 4, 18)).html_safe?
assert select_second(Time.mktime(2003, 8, 16, 8, 4, 18)).html_safe?
assert select_minute(8, :use_hidden => true).html_safe?
assert select_month(8, :prompt => 'Choose month').html_safe?
assert select_time(Time.mktime(2003, 8, 16, 8, 4, 18), {}, :class => 'selector').html_safe?
assert select_date(Time.mktime(2003, 8, 16), :date_separator => " / ", :start_year => 2003, :end_year => 2005, :prefix => "date[first]").html_safe?
end
def test_object_select_html_safety
@post = Post.new
@post.written_on = Date.new(2004, 6, 15)
assert date_select("post", "written_on", :default => Time.local(2006, 9, 19, 15, 16, 35), :include_blank => true).html_safe?
assert time_select("post", "written_on", :ignore_date => true).html_safe?
end
end

View file

@ -0,0 +1,112 @@
require 'test_helper'
class DeprecatedOutputSafetyTest < ActiveSupport::TestCase
def setup
@string = "hello"
end
test "A string can be marked safe using html_safe!" do
assert_deprecated do
@string.html_safe!
assert @string.html_safe?
end
end
test "Marking a string safe returns the string using html_safe!" do
assert_deprecated do
assert_equal @string, @string.html_safe!
end
end
test "Adding a safe string to another safe string returns a safe string using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
@string.html_safe!
@combination = @other_string + @string
assert_equal "otherhello", @combination
assert @combination.html_safe?
end
end
test "Adding an unsafe string to a safe string returns an unsafe string using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
@combination = @other_string + "<foo>"
@other_combination = @string + "<foo>"
assert_equal "other<foo>", @combination
assert_equal "hello<foo>", @other_combination
assert !@combination.html_safe?
assert !@other_combination.html_safe?
end
end
test "Concatting safe onto unsafe yields unsafe using html_safe!" do
assert_deprecated do
@other_string = "other"
@string.html_safe!
@other_string.concat(@string)
assert !@other_string.html_safe?
end
end
test "Concatting unsafe onto safe yields unsafe using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
string = @other_string.concat("<foo>")
assert_equal "other<foo>", string
assert !string.html_safe?
end
end
test "Concatting safe onto safe yields safe using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
@string.html_safe!
@other_string.concat(@string)
assert @other_string.html_safe?
end
end
test "Concatting safe onto unsafe with << yields unsafe using html_safe!" do
assert_deprecated do
@other_string = "other"
@string.html_safe!
@other_string << @string
assert !@other_string.html_safe?
end
end
test "Concatting unsafe onto safe with << yields unsafe using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
string = @other_string << "<foo>"
assert_equal "other<foo>", string
assert !string.html_safe?
end
end
test "Concatting safe onto safe with << yields safe using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
@string.html_safe!
@other_string << @string
assert @other_string.html_safe?
end
end
test "Concatting a fixnum to safe always yields safe using html_safe!" do
assert_deprecated do
@string.html_safe!
@string.concat(13)
assert_equal "hello".concat(13), @string
assert @string.html_safe?
end
end
end

View file

@ -0,0 +1,36 @@
require 'test_helper'
class ErbUtilTest < Test::Unit::TestCase
include ERB::Util
ERB::Util::HTML_ESCAPE.each do |given, expected|
define_method "test_html_escape_#{expected.gsub(/\W/, '')}" do
assert_equal expected, html_escape(given)
end
unless given == '"'
define_method "test_json_escape_#{expected.gsub(/\W/, '')}" do
assert_equal ERB::Util::JSON_ESCAPE[given], json_escape(given)
end
end
end
def test_html_escape_is_html_safe
escaped = h("<p>")
assert_equal "&lt;p&gt;", escaped
assert escaped.html_safe?
end
def test_html_escape_passes_html_escpe_unmodified
escaped = h("<p>".html_safe)
assert_equal "<p>", escaped
assert escaped.html_safe?
end
def test_rest_in_ascii
(0..127).to_a.map {|int| int.chr }.each do |chr|
next if %w(& " < >).include?(chr)
assert_equal chr, html_escape(chr)
end
end
end

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,354 @@
require 'test_helper'
class FormTagHelperTest < ActionView::TestCase
def setup
@controller = Class.new do
def url_for(options)
"http://www.example.com"
end
end
@controller = @controller.new
end
VALID_HTML_ID = /^[A-Za-z][-_:.A-Za-z0-9]*$/ # see http://www.w3.org/TR/html4/types.html#type-name
def test_check_box_tag
actual = check_box_tag "admin"
expected = %(<input id="admin" name="admin" type="checkbox" value="1" />)
assert_dom_equal expected, actual
end
def test_check_box_tag_id_sanitized
label_elem = root_elem(check_box_tag("project[2][admin]"))
assert_match VALID_HTML_ID, label_elem['id']
end
def test_form_tag
actual = form_tag
expected = %(<form action="http://www.example.com" method="post">)
assert_dom_equal expected, actual
end
def test_form_tag_multipart
actual = form_tag({}, { 'multipart' => true })
expected = %(<form action="http://www.example.com" enctype="multipart/form-data" method="post">)
assert_dom_equal expected, actual
end
def test_form_tag_with_method_put
actual = form_tag({}, { :method => :put })
expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="put" /></div>)
assert_dom_equal expected, actual
end
def test_form_tag_with_method_delete
actual = form_tag({}, { :method => :delete })
expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="delete" /></div>)
assert_dom_equal expected, actual
end
def test_form_tag_with_block_in_erb
__in_erb_template = ''
form_tag("http://example.com") { concat "Hello world!" }
expected = %(<form action="http://example.com" method="post">Hello world!</form>)
assert_dom_equal expected, output_buffer
end
def test_form_tag_with_block_and_method_in_erb
__in_erb_template = ''
form_tag("http://example.com", :method => :put) { concat "Hello world!" }
expected = %(<form action="http://example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="put" /></div>Hello world!</form>)
assert_dom_equal expected, output_buffer
end
def test_hidden_field_tag
actual = hidden_field_tag "id", 3
expected = %(<input id="id" name="id" type="hidden" value="3" />)
assert_dom_equal expected, actual
end
def test_hidden_field_tag_id_sanitized
input_elem = root_elem(hidden_field_tag("item[][title]"))
assert_match VALID_HTML_ID, input_elem['id']
end
def test_file_field_tag
assert_dom_equal "<input name=\"picsplz\" type=\"file\" id=\"picsplz\" />", file_field_tag("picsplz")
end
def test_file_field_tag_with_options
assert_dom_equal "<input name=\"picsplz\" type=\"file\" id=\"picsplz\" class=\"pix\"/>", file_field_tag("picsplz", :class => "pix")
end
def test_password_field_tag
actual = password_field_tag
expected = %(<input id="password" name="password" type="password" />)
assert_dom_equal expected, actual
end
def test_radio_button_tag
actual = radio_button_tag "people", "david"
expected = %(<input id="people_david" name="people" type="radio" value="david" />)
assert_dom_equal expected, actual
actual = radio_button_tag("num_people", 5)
expected = %(<input id="num_people_5" name="num_people" type="radio" value="5" />)
assert_dom_equal expected, actual
actual = radio_button_tag("gender", "m") + radio_button_tag("gender", "f")
expected = %(<input id="gender_m" name="gender" type="radio" value="m" /><input id="gender_f" name="gender" type="radio" value="f" />)
assert_dom_equal expected, actual
actual = radio_button_tag("opinion", "-1") + radio_button_tag("opinion", "1")
expected = %(<input id="opinion_-1" name="opinion" type="radio" value="-1" /><input id="opinion_1" name="opinion" type="radio" value="1" />)
assert_dom_equal expected, actual
actual = radio_button_tag("person[gender]", "m")
expected = %(<input id="person_gender_m" name="person[gender]" type="radio" value="m" />)
assert_dom_equal expected, actual
end
def test_select_tag
actual = select_tag "people", "<option>david</option>".html_safe
expected = %(<select id="people" name="people"><option>david</option></select>)
assert_dom_equal expected, actual
end
def test_select_tag_with_multiple
actual = select_tag "colors", "<option>Red</option><option>Blue</option><option>Green</option>".html_safe, :multiple => :true
expected = %(<select id="colors" multiple="multiple" name="colors"><option>Red</option><option>Blue</option><option>Green</option></select>)
assert_dom_equal expected, actual
end
def test_select_tag_disabled
actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>".html_safe, :disabled => :true
expected = %(<select id="places" disabled="disabled" name="places"><option>Home</option><option>Work</option><option>Pub</option></select>)
assert_dom_equal expected, actual
end
def test_select_tag_id_sanitized
input_elem = root_elem(select_tag("project[1]people", "<option>david</option>"))
assert_match VALID_HTML_ID, input_elem['id']
end
def test_select_tag_with_array_options
assert_deprecated /array/ do
select_tag "people", ["<option>david</option>"]
end
end
def test_text_area_tag_size_string
actual = text_area_tag "body", "hello world", "size" => "20x40"
expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>)
assert_dom_equal expected, actual
end
def test_text_area_tag_size_symbol
actual = text_area_tag "body", "hello world", :size => "20x40"
expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>)
assert_dom_equal expected, actual
end
def test_text_area_tag_should_disregard_size_if_its_given_as_an_integer
actual = text_area_tag "body", "hello world", :size => 20
expected = %(<textarea id="body" name="body">hello world</textarea>)
assert_dom_equal expected, actual
end
def test_text_area_tag_id_sanitized
input_elem = root_elem(text_area_tag("item[][description]"))
assert_match VALID_HTML_ID, input_elem['id']
end
def test_text_area_tag_escape_content
actual = text_area_tag "body", "<b>hello world</b>", :size => "20x40"
expected = %(<textarea cols="20" id="body" name="body" rows="40">&lt;b&gt;hello world&lt;/b&gt;</textarea>)
assert_dom_equal expected, actual
end
def test_text_area_tag_unescaped_content
actual = text_area_tag "body", "<b>hello world</b>", :size => "20x40", :escape => false
expected = %(<textarea cols="20" id="body" name="body" rows="40"><b>hello world</b></textarea>)
assert_dom_equal expected, actual
end
def test_text_area_tag_unescaped_nil_content
actual = text_area_tag "body", nil, :escape => false
expected = %(<textarea id="body" name="body"></textarea>)
assert_dom_equal expected, actual
end
def test_text_field_tag
actual = text_field_tag "title", "Hello!"
expected = %(<input id="title" name="title" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_text_field_tag_class_string
actual = text_field_tag "title", "Hello!", "class" => "admin"
expected = %(<input class="admin" id="title" name="title" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_text_field_tag_size_symbol
actual = text_field_tag "title", "Hello!", :size => 75
expected = %(<input id="title" name="title" size="75" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_text_field_tag_size_string
actual = text_field_tag "title", "Hello!", "size" => "75"
expected = %(<input id="title" name="title" size="75" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_text_field_tag_maxlength_symbol
actual = text_field_tag "title", "Hello!", :maxlength => 75
expected = %(<input id="title" name="title" maxlength="75" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_text_field_tag_maxlength_string
actual = text_field_tag "title", "Hello!", "maxlength" => "75"
expected = %(<input id="title" name="title" maxlength="75" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_text_field_disabled
actual = text_field_tag "title", "Hello!", :disabled => :true
expected = %(<input id="title" name="title" disabled="disabled" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_text_field_tag_with_multiple_options
actual = text_field_tag "title", "Hello!", :size => 70, :maxlength => 80
expected = %(<input id="title" name="title" size="70" maxlength="80" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_text_field_tag_id_sanitized
input_elem = root_elem(text_field_tag("item[][title]"))
assert_match VALID_HTML_ID, input_elem['id']
end
def test_label_tag_without_text
actual = label_tag "title"
expected = %(<label for="title">Title</label>)
assert_dom_equal expected, actual
end
def test_label_tag_with_symbol
actual = label_tag :title
expected = %(<label for="title">Title</label>)
assert_dom_equal expected, actual
end
def test_label_tag_with_text
actual = label_tag "title", "My Title"
expected = %(<label for="title">My Title</label>)
assert_dom_equal expected, actual
end
def test_label_tag_class_string
actual = label_tag "title", "My Title", "class" => "small_label"
expected = %(<label for="title" class="small_label">My Title</label>)
assert_dom_equal expected, actual
end
def test_label_tag_id_sanitized
label_elem = root_elem(label_tag("item[title]"))
assert_match VALID_HTML_ID, label_elem['for']
end
def test_boolean_options
assert_dom_equal %(<input checked="checked" disabled="disabled" id="admin" name="admin" readonly="readonly" type="checkbox" value="1" />), check_box_tag("admin", 1, true, 'disabled' => true, :readonly => "yes")
assert_dom_equal %(<input checked="checked" id="admin" name="admin" type="checkbox" value="1" />), check_box_tag("admin", 1, true, :disabled => false, :readonly => nil)
assert_dom_equal %(<input type="checkbox" />), tag(:input, :type => "checkbox", :checked => false)
assert_dom_equal %(<select id="people" multiple="multiple" name="people[]"><option>david</option></select>), select_tag("people", "<option>david</option>".html_safe, :multiple => true)
assert_dom_equal %(<select id="people_" multiple="multiple" name="people[]"><option>david</option></select>), select_tag("people[]", "<option>david</option>".html_safe, :multiple => true)
assert_dom_equal %(<select id="people" name="people"><option>david</option></select>), select_tag("people", "<option>david</option>".html_safe, :multiple => nil)
end
def test_stringify_symbol_keys
actual = text_field_tag "title", "Hello!", :id => "admin"
expected = %(<input id="admin" name="title" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
def test_submit_tag
assert_dom_equal(
%(<input name='commit' onclick="if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';alert('hello!');result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" type="submit" value="Save" />),
submit_tag("Save", :disable_with => "Saving...", :onclick => "alert('hello!')")
)
end
def test_submit_tag_with_no_onclick_options
assert_dom_equal(
%(<input name='commit' onclick="if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" type="submit" value="Save" />),
submit_tag("Save", :disable_with => "Saving...")
)
end
def test_submit_tag_with_confirmation
assert_dom_equal(
%(<input name='commit' type='submit' value='Save' onclick="if (!confirm('Are you sure?')) return false; return true;"/>),
submit_tag("Save", :confirm => "Are you sure?")
)
end
def test_submit_tag_with_confirmation_and_with_disable_with
assert_dom_equal(
%(<input name="commit" onclick="if (!confirm('Are you sure?')) return false; if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }else { hiddenCommit = document.createElement('input');hiddenCommit.type = 'hidden';hiddenCommit.value = this.value;hiddenCommit.name = this.name;this.form.appendChild(hiddenCommit); }this.setAttribute('originalValue', this.value);this.disabled = true;this.value='Saving...';result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;" type="submit" value="Save" />),
submit_tag("Save", :disable_with => "Saving...", :confirm => "Are you sure?")
)
end
def test_image_submit_tag_with_confirmation
assert_dom_equal(
%(<input type="image" src="/images/save.gif" onclick="return confirm('Are you sure?');"/>),
image_submit_tag("save.gif", :confirm => "Are you sure?")
)
end
def test_pass
assert_equal 1, 1
end
def test_field_set_tag_in_erb
__in_erb_template = ''
field_set_tag("Your details") { concat "Hello world!" }
expected = %(<fieldset><legend>Your details</legend>Hello world!</fieldset>)
assert_dom_equal expected, output_buffer
self.output_buffer = ''.html_safe
field_set_tag { concat "Hello world!" }
expected = %(<fieldset>Hello world!</fieldset>)
assert_dom_equal expected, output_buffer
self.output_buffer = ''.html_safe
field_set_tag('') { concat "Hello world!" }
expected = %(<fieldset>Hello world!</fieldset>)
assert_dom_equal expected, output_buffer
self.output_buffer = ''.html_safe
field_set_tag('', :class => 'format') { concat "Hello world!" }
expected = %(<fieldset class="format">Hello world!</fieldset>)
assert_dom_equal expected, output_buffer
end
def protect_against_forgery?
false
end
private
def root_elem(rendered_content)
HTML::Document.new(rendered_content).root.children[0]
end
end

View file

@ -0,0 +1,19 @@
require 'test_helper'
class OutputEscapingTest < ActiveSupport::TestCase
test "escape_html shouldn't die when passed nil" do
assert ERB::Util.h(nil).blank?
end
test "escapeHTML should escape strings" do
assert_equal "&lt;&gt;&quot;", ERB::Util.h("<>\"")
end
test "escapeHTML shouldn't touch explicitly safe strings" do
# TODO this seems easier to compose and reason about, but
# this should be verified
assert_equal "<", ERB::Util.h("<".html_safe)
end
end

View file

@ -0,0 +1,115 @@
require 'test_helper'
class OutputSafetyTest < ActiveSupport::TestCase
def setup
@string = "hello"
@object = Class.new(Object) do
def to_s
"other"
end
end.new
end
test "A string is unsafe by default" do
assert !@string.html_safe?
end
test "A string can be marked safe" do
string = @string.html_safe
assert string.html_safe?
end
test "Marking a string safe returns the string" do
assert_equal @string, @string.html_safe
end
test "A fixnum is safe by default" do
assert 5.html_safe?
end
test "An object is unsafe by default" do
assert !@object.html_safe?
end
test "Adding an object to a safe string returns a safe string" do
string = @string.html_safe
string << @object
assert_equal "helloother", string
assert string.html_safe?
end
test "Adding a safe string to another safe string returns a safe string" do
@other_string = "other".html_safe
string = @string.html_safe
@combination = @other_string + string
assert_equal "otherhello", @combination
assert @combination.html_safe?
end
test "Adding an unsafe string to a safe string escapes it and returns a safe string" do
@other_string = "other".html_safe
@combination = @other_string + "<foo>"
@other_combination = @string + "<foo>"
assert_equal "other&lt;foo&gt;", @combination
assert_equal "hello<foo>", @other_combination
assert @combination.html_safe?
assert !@other_combination.html_safe?
end
test "Concatting safe onto unsafe yields unsafe" do
@other_string = "other"
string = @string.html_safe
@other_string.concat(string)
assert !@other_string.html_safe?
end
test "Concatting unsafe onto safe yields escaped safe" do
@other_string = "other".html_safe
string = @other_string.concat("<foo>")
assert_equal "other&lt;foo&gt;", string
assert string.html_safe?
end
test "Concatting safe onto safe yields safe" do
@other_string = "other".html_safe
string = @string.html_safe
@other_string.concat(string)
assert @other_string.html_safe?
end
test "Concatting safe onto unsafe with << yields unsafe" do
@other_string = "other"
string = @string.html_safe
@other_string << string
assert !@other_string.html_safe?
end
test "Concatting unsafe onto safe with << yields escaped safe" do
@other_string = "other".html_safe
string = @other_string << "<foo>"
assert_equal "other&lt;foo&gt;", string
assert string.html_safe?
end
test "Concatting safe onto safe with << yields safe" do
@other_string = "other".html_safe
string = @string.html_safe
@other_string << string
assert @other_string.html_safe?
end
test "Concatting a fixnum to safe always yields safe" do
string = @string.html_safe
string = string.concat(13)
assert_equal "hello".concat(13), string
assert string.html_safe?
end
end

View file

@ -21,114 +21,3 @@ class RailsXssTest < ActiveSupport::TestCase
end
end
end
class DeprecatedOutputSafetyTest < ActiveSupport::TestCase
def setup
@string = "hello"
end
test "A string can be marked safe using html_safe!" do
assert_deprecated do
@string.html_safe!
assert @string.html_safe?
end
end
test "Marking a string safe returns the string using html_safe!" do
assert_deprecated do
assert_equal @string, @string.html_safe!
end
end
test "Adding a safe string to another safe string returns a safe string using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
@string.html_safe!
@combination = @other_string + @string
assert_equal "otherhello", @combination
assert @combination.html_safe?
end
end
test "Adding an unsafe string to a safe string returns an unsafe string using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
@combination = @other_string + "<foo>"
@other_combination = @string + "<foo>"
assert_equal "other<foo>", @combination
assert_equal "hello<foo>", @other_combination
assert !@combination.html_safe?
assert !@other_combination.html_safe?
end
end
test "Concatting safe onto unsafe yields unsafe using html_safe!" do
assert_deprecated do
@other_string = "other"
@string.html_safe!
@other_string.concat(@string)
assert !@other_string.html_safe?
end
end
test "Concatting unsafe onto safe yields unsafe using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
string = @other_string.concat("<foo>")
assert_equal "other<foo>", string
assert !string.html_safe?
end
end
test "Concatting safe onto safe yields safe using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
@string.html_safe!
@other_string.concat(@string)
assert @other_string.html_safe?
end
end
test "Concatting safe onto unsafe with << yields unsafe using html_safe!" do
assert_deprecated do
@other_string = "other"
@string.html_safe!
@other_string << @string
assert !@other_string.html_safe?
end
end
test "Concatting unsafe onto safe with << yields unsafe using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
string = @other_string << "<foo>"
assert_equal "other<foo>", string
assert !string.html_safe?
end
end
test "Concatting safe onto safe with << yields safe using html_safe!" do
assert_deprecated do
@other_string = "other".html_safe!
@string.html_safe!
@other_string << @string
assert @other_string.html_safe?
end
end
test "Concatting a fixnum to safe always yields safe using html_safe!" do
assert_deprecated do
@string.html_safe!
@string.concat(13)
assert_equal "hello".concat(13), @string
assert @string.html_safe?
end
end
end

View file

@ -0,0 +1,18 @@
require 'test_helper'
class RawOutputHelperTest < ActionView::TestCase
def setup
@string = "hello"
end
test "raw returns the safe string" do
result = raw(@string)
assert_equal @string, result
assert result.html_safe?
end
test "raw handles nil values correctly" do
assert_equal "", raw(nil)
end
end

View file

@ -0,0 +1,51 @@
require 'test_helper'
class SafeBufferTest < ActiveSupport::TestCase
def setup
@buffer = ActiveSupport::SafeBuffer.new
end
test "Should look like a string" do
assert @buffer.is_a?(String)
assert_equal "", @buffer
end
test "Should escape a raw string which is passed to them" do
@buffer << "<script>"
assert_equal "&lt;script&gt;", @buffer
end
test "Should NOT escape a safe value passed to it" do
@buffer << "<script>".html_safe
assert_equal "<script>", @buffer
end
test "Should not mess with an innocuous string" do
@buffer << "Hello"
assert_equal "Hello", @buffer
end
test "Should not mess with a previously escape test" do
@buffer << ERB::Util.html_escape("<script>")
assert_equal "&lt;script&gt;", @buffer
end
test "Should be considered safe" do
assert @buffer.html_safe?
end
test "Should return a safe buffer when calling to_s" do
new_buffer = @buffer.to_s
assert_equal ActiveSupport::SafeBuffer, new_buffer.class
end
test "Should not return a safe buffer when using sub" do
assert !@buffer.sub('', "asdf").html_safe?
end
test "Should raise argument error when using sub!" do
assert_raise TypeError do
@buffer.sub!('', "asdf")
end
end
end

View file

@ -0,0 +1,21 @@
require 'test_helper'
class TagHelperTest < ActionView::TestCase
def test_content_tag
assert_equal "<a href=\"create\">Create</a>", content_tag("a", "Create", "href" => "create")
assert content_tag("a", "Create", "href" => "create").html_safe?
assert_equal content_tag("a", "Create", "href" => "create"),
content_tag("a", "Create", :href => "create")
assert_equal "<p>&lt;script&gt;evil_js&lt;/script&gt;</p>",
content_tag(:p, '<script>evil_js</script>')
assert_equal "<p><script>evil_js</script></p>",
content_tag(:p, '<script>evil_js</script>', nil, false)
end
def test_tag_honors_html_safe_for_param_values
['1&amp;2', '1 &lt; 2', '&#8220;test&#8220;'].each do |escaped|
assert_equal %(<a href="#{escaped}" />), tag('a', :href => escaped.html_safe)
end
end
end

View file

@ -2,4 +2,5 @@ abort 'RAILS_ROOT=/path/to/rails/2.3/app rake test' unless ENV['RAILS_ROOT']
require File.expand_path('config/environment', ENV['RAILS_ROOT'])
require File.expand_path('../../init', __FILE__)
require 'active_support/test_case'
require 'action_view/test_case'
require 'test/unit'

View file

@ -0,0 +1,30 @@
require 'test_helper'
class TextHelperTest < ActionView::TestCase
def setup
@controller = Class.new do
attr_accessor :request
def url_for(*args) "http://www.example.com" end
end.new
end
def test_simple_format_with_escaping_html_options
assert_dom_equal(%(<p class="intro">It's nice to have options.</p>),
simple_format("It's nice to have options.", :class=>"intro"))
end
def test_simple_format_should_not_escape_safe_content
assert_dom_equal(%(<p>This is <script>safe_js</script>.</p>),
simple_format('This is <script>safe_js</script>.'.html_safe))
end
def test_simple_format_escapes_unsafe_content
assert_dom_equal(%(<p>This is &lt;script&gt;evil_js&lt;/script&gt;.</p>),
simple_format('This is <script>evil_js</script>.'))
end
def test_truncate_should_not_be_html_safe
assert !truncate("Hello World!", :length => 12).html_safe?
end
end

View file

@ -0,0 +1,39 @@
require 'test_helper'
class UrlHelperTest < ActionView::TestCase
def abcd(hash = {})
hash_for(:a => :b, :c => :d).merge(hash)
end
def hash_for(opts = {})
{:controller => "foo", :action => "bar"}.merge(opts)
end
def test_url_for_does_not_escape_urls_if_explicitly_stated
assert_equal "/foo/bar?a=b&c=d", url_for(abcd(:escape => false))
end
def test_link_tag_with_img
link = link_to("<img src='/favicon.jpg' />".html_safe, "/")
expected = %{<a href="/"><img src='/favicon.jpg' /></a>}
assert_dom_equal expected, link
end
def test_link_to_should_not_escape_content_for_html_safe
link = link_to("Some <p>html</p>".html_safe, "/")
expected = %{<a href="/">Some <p>html</p></a>}
assert_dom_equal link, expected
end
def test_link_to_escapes_content_for_non_safe
link = link_to("Some <p>html</p>", "/")
expected = %{<a href="/">Some &lt;p&gt;html&lt;/p&gt;</a>}
assert_dom_equal link, expected
end
def test_url_for_escaping_is_safety_aware
assert url_for(abcd(:escape => true)).html_safe?, "escaped urls should be html_safe?"
assert !url_for(abcd(:escape => false)).html_safe?, "non-escaped urls should not be html_safe?"
end
end