haml-edge 2.3.51 → 2.3.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/EDGE_GEM_VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.51
1
+ 2.3.52
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.51
1
+ 2.3.52
data/lib/haml/buffer.rb CHANGED
@@ -130,6 +130,8 @@ module Haml
130
130
  Haml::Util.def_static_method(self, :format_script, [:result],
131
131
  :preserve_script, :in_tag, :preserve_tag, :escape_html,
132
132
  :nuke_inner_whitespace, :interpolated, :ugly, <<RUBY)
133
+ <% # Escape HTML here so that the safety of the string is preserved in Rails
134
+ result_name = escape_html ? "html_escape(result.to_s)" : "result.to_s" %>
133
135
  <% unless ugly %>
134
136
  # If we're interpolated,
135
137
  # then the custom tabulation is handled in #push_text.
@@ -140,13 +142,11 @@ module Haml
140
142
  <% end %>
141
143
 
142
144
  tabulation = @real_tabs
143
- result = result.to_s.<% if nuke_inner_whitespace %>strip<% else %>rstrip<% end %>
145
+ result = <%= result_name %>.<% if nuke_inner_whitespace %>strip<% else %>rstrip<% end %>
144
146
  <% else %>
145
- result = result.to_s<% if nuke_inner_whitespace %>.strip<% end %>
147
+ result = <%= result_name %><% if nuke_inner_whitespace %>.strip<% end %>
146
148
  <% end %>
147
149
 
148
- <% if escape_html %> result = html_escape(result) <% end %>
149
-
150
150
  <% if preserve_tag %>
151
151
  result = Haml::Helpers.preserve(result)
152
152
  <% elsif preserve_script %>
data/lib/haml/engine.rb CHANGED
@@ -288,6 +288,7 @@ module Haml
288
288
  :ugly => @options[:ugly],
289
289
  :format => @options[:format],
290
290
  :encoding => @options[:encoding],
291
+ :escape_html => @options[:escape_html],
291
292
  }
292
293
  end
293
294
 
@@ -35,6 +35,21 @@ module Haml
35
35
  controller.controller_name + " " + controller.action_name
36
36
  end
37
37
  alias_method :generate_content_class_names, :page_class
38
+
39
+ # Treats all input to \{Haml::Helpers#haml\_concat} within the block
40
+ # as being HTML safe for Rails' XSS protection.
41
+ # This is useful for wrapping blocks of code that concatenate HTML en masse.
42
+ #
43
+ # This has no effect if Rails' XSS protection isn't enabled.
44
+ #
45
+ # @yield A block in which all input to `#haml_concat` is treated as raw.
46
+ # @see Haml::Util#rails_xss_safe?
47
+ def with_raw_haml_concat
48
+ @_haml_concat_raw = true
49
+ yield
50
+ ensure
51
+ @_haml_concat_raw = false
52
+ end
38
53
  end
39
54
  end
40
55
  end
@@ -26,6 +26,7 @@ module ActionView
26
26
 
27
27
  def set_output_buffer_with_haml(new)
28
28
  if is_haml?
29
+ new = String.new(new) if Haml::Util.rails_xss_safe? && new.is_a?(ActionView::SafeBuffer)
29
30
  haml_buffer.buffer = new
30
31
  else
31
32
  set_output_buffer_without_haml new
@@ -0,0 +1,94 @@
1
+ module Haml
2
+ module Helpers
3
+ # This module overrides Haml helpers to work properly
4
+ # in the context of ActionView.
5
+ # Currently it's only used for modifying the helpers
6
+ # to work with Rails' XSS protection methods.
7
+ module XssMods
8
+ def self.included(base)
9
+ %w[html_escape find_and_preserve preserve list_of surround
10
+ precede succeed capture_haml haml_concat haml_indent
11
+ haml_tag escape_once].each do |name|
12
+ base.send(:alias_method, "#{name}_without_haml_xss", name)
13
+ base.send(:alias_method, name, "#{name}_with_haml_xss")
14
+ end
15
+ end
16
+
17
+ # Don't escape text that's already safe,
18
+ # output is always HTML safe
19
+ def html_escape_with_haml_xss(text)
20
+ return text if text.html_safe?
21
+ html_escape_without_haml_xss(text).html_safe!
22
+ end
23
+
24
+ # Output is always HTML safe
25
+ def find_and_preserve_with_haml_xss(*args, &block)
26
+ find_and_preserve_without_haml_xss(*args, &block).html_safe!
27
+ end
28
+
29
+ # Output is always HTML safe
30
+ def preserve_with_haml_xss(*args, &block)
31
+ preserve_without_haml_xss(*args, &block).html_safe!
32
+ end
33
+
34
+ # Output is always HTML safe
35
+ def list_of_with_haml_xss(*args, &block)
36
+ list_of_without_haml_xss(*args, &block).html_safe!
37
+ end
38
+
39
+ # Input is escaped, output is always HTML safe
40
+ def surround_with_haml_xss(front, back = front, &block)
41
+ surround_without_haml_xss(
42
+ haml_xss_html_escape(front),
43
+ haml_xss_html_escape(back),
44
+ &block).html_safe!
45
+ end
46
+
47
+ # Input is escaped, output is always HTML safe
48
+ def precede_with_haml_xss(str, &block)
49
+ precede_without_haml_xss(haml_xss_html_escape(str), &block).html_safe!
50
+ end
51
+
52
+ # Input is escaped, output is always HTML safe
53
+ def succeed_with_haml_xss(str, &block)
54
+ succeed_without_haml_xss(haml_xss_html_escape(str), &block).html_safe!
55
+ end
56
+
57
+ # Output is always HTML safe
58
+ def capture_haml_with_haml_xss(*args, &block)
59
+ capture_haml_without_haml_xss(*args, &block).html_safe!
60
+ end
61
+
62
+ # Input is escaped
63
+ def haml_concat_with_haml_xss(text = "")
64
+ haml_concat_without_haml_xss(@_haml_concat_raw ? text : haml_xss_html_escape(text))
65
+ end
66
+
67
+ # Output is always HTML safe
68
+ def haml_indent_with_haml_xss
69
+ haml_indent_without_haml_xss.html_safe!
70
+ end
71
+
72
+ # Input is escaped, haml_concat'ed output is always HTML safe
73
+ def haml_tag_with_haml_xss(name, *rest, &block)
74
+ name = haml_xss_html_escape(name.to_s)
75
+ rest.unshift(haml_xss_html_escape(rest.shift.to_s)) unless [Symbol, Hash, NilClass].any? {|t| rest.first.is_a? t}
76
+ with_raw_haml_concat {haml_tag_without_haml_xss(name, *rest, &block)}
77
+ end
78
+
79
+ # Output is always HTML safe
80
+ def escape_once_with_haml_xss(*args)
81
+ escape_once_without_haml_xss(*args).html_safe!
82
+ end
83
+
84
+ private
85
+
86
+ # Escapes the HTML in the text if and only if
87
+ # Rails XSS protection is enabled *and* the `:escape_html` option is set.
88
+ def haml_xss_html_escape(text)
89
+ return text unless Haml::Util.rails_xss_safe? && haml_buffer.options[:escape_html]
90
+ html_escape(text)
91
+ end
92
+ end
93
+ end
94
+ end
data/lib/haml/helpers.rb CHANGED
@@ -467,6 +467,10 @@ END
467
467
  # Returns a copy of `text` with ampersands, angle brackets and quotes
468
468
  # escaped into HTML entities.
469
469
  #
470
+ # Note that if ActionView is loaded and XSS protection is enabled
471
+ # (as is the default for Rails 3.0+, and optional for version 2.3.5+),
472
+ # this won't escape text declared as "safe".
473
+ #
470
474
  # @param text [String] The string to sanitize
471
475
  # @return [String] The sanitized string
472
476
  def html_escape(text)
data/lib/haml/template.rb CHANGED
@@ -27,6 +27,21 @@ else
27
27
  require 'haml/template/patch'
28
28
  end
29
29
 
30
+ if ActionView::Base.respond_to?(:xss_safe?) && ActionView::Base.xss_safe?
31
+ Haml::Template.options[:escape_html] = true
32
+
33
+ module Haml::Util
34
+ def rails_xss_safe?
35
+ true
36
+ end
37
+ end
38
+
39
+ require 'haml/helpers/xss_mods'
40
+ module Haml::Helpers
41
+ include XssMods
42
+ end
43
+ end
44
+
30
45
  if defined?(RAILS_ROOT)
31
46
  # Update init.rb to the current version
32
47
  # if it's out of date.
data/lib/haml/util.rb CHANGED
@@ -122,6 +122,26 @@ module Haml
122
122
  end
123
123
  end
124
124
 
125
+ ## Rails XSS Safety
126
+
127
+ # Whether or not ActionView's XSS protection is available and enabled,
128
+ # as is the default for Rails 3.0+, and optional for version 2.3.5+.
129
+ # Overridden in haml/template.rb if this is the case.
130
+ #
131
+ # @return [Boolean]
132
+ def rails_xss_safe?
133
+ false
134
+ end
135
+
136
+ # Assert that a given object (usually a String) is HTML safe
137
+ # according to Rails' XSS handling, if it's loaded.
138
+ #
139
+ # @param text [Object]
140
+ def assert_html_safe!(text)
141
+ return unless rails_xss_safe? && text && !text.to_s.html_safe?
142
+ raise Haml::Error.new("Expected #{text.inspect} to be HTML-safe.")
143
+ end
144
+
125
145
  ## Cross-Ruby-Version Compatibility
126
146
 
127
147
  # Whether or not this is running under Ruby 1.8 or lower.
@@ -85,6 +85,7 @@ class TemplateTest < Test::Unit::TestCase
85
85
  end
86
86
 
87
87
  def render(text, opts = {})
88
+ return @base.render(:inline => text, :type => :haml) if opts == :action_view
88
89
  Haml::Engine.new(text, opts).to_html(@base)
89
90
  end
90
91
 
@@ -95,6 +96,8 @@ class TemplateTest < Test::Unit::TestCase
95
96
  end
96
97
 
97
98
  def assert_renders_correctly(name, &render_method)
99
+ old_options = Haml::Template.options.dup
100
+ Haml::Template.options[:escape_html] = false
98
101
  if ActionPack::VERSION::MAJOR < 2 ||
99
102
  (ActionPack::VERSION::MAJOR == 2 && ActionPack::VERSION::MINOR < 2)
100
103
  render_method ||= proc { |name| @base.render(name) }
@@ -112,6 +115,8 @@ class TemplateTest < Test::Unit::TestCase
112
115
  else
113
116
  raise e
114
117
  end
118
+ ensure
119
+ Haml::Template.options = old_options
115
120
  end
116
121
 
117
122
  def test_empty_render_should_remain_empty
@@ -176,12 +181,13 @@ class TemplateTest < Test::Unit::TestCase
176
181
  end
177
182
 
178
183
  def test_haml_options
179
- Haml::Template.options = { :suppress_eval => true }
180
- assert_equal({ :suppress_eval => true }, Haml::Template.options)
184
+ old_options = Haml::Template.options.dup
185
+ Haml::Template.options[:suppress_eval] = true
181
186
  old_base, @base = @base, create_base
182
187
  assert_renders_correctly("eval_suppressed")
188
+ ensure
183
189
  @base = old_base
184
- Haml::Template.options = {}
190
+ Haml::Template.options = old_options
185
191
  end
186
192
 
187
193
  def test_with_output_buffer_with_ugly
@@ -231,5 +237,41 @@ END
231
237
  else
232
238
  assert false
233
239
  end
234
- end
240
+ end
241
+
242
+ ## XSS Protection Tests
243
+
244
+ if Haml::Util.rails_xss_safe?
245
+ def test_escape_html_option_set
246
+ assert Haml::Template.options[:escape_html]
247
+ end
248
+
249
+ def test_xss_protection
250
+ assert_equal("Foo &amp; Bar\n", render('= "Foo & Bar"', :action_view))
251
+ end
252
+
253
+ def test_xss_protection_with_safe_strings
254
+ assert_equal("Foo & Bar\n", render('= "Foo & Bar".html_safe!', :action_view))
255
+ end
256
+
257
+ def test_xss_protection_with_bang
258
+ assert_equal("Foo & Bar\n", render('!= "Foo & Bar"', :action_view))
259
+ end
260
+
261
+ def test_xss_protection_in_interpolation
262
+ assert_equal("Foo &amp; Bar\n", render('Foo #{"&"} Bar', :action_view))
263
+ end
264
+
265
+ def test_xss_protection_with_bang_in_interpolation
266
+ assert_equal("Foo & Bar\n", render('! Foo #{"&"} Bar', :action_view))
267
+ end
268
+
269
+ def test_xss_protection_with_safe_strings_in_interpolation
270
+ assert_equal("Foo & Bar\n", render('Foo #{"&".html_safe!} Bar', :action_view))
271
+ end
272
+
273
+ def test_xss_protection_with_mixed_strings_in_interpolation
274
+ assert_equal("Foo & Bar &amp; Baz\n", render('Foo #{"&".html_safe!} Bar #{"&"} Baz', :action_view))
275
+ end
276
+ end
235
277
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml-edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.51
4
+ version: 2.3.52
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Weizenbaum
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-10-16 00:00:00 -04:00
13
+ date: 2009-10-17 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -63,6 +63,7 @@ files:
63
63
  - lib/haml/helpers
64
64
  - lib/haml/helpers/action_view_extensions.rb
65
65
  - lib/haml/helpers/action_view_mods.rb
66
+ - lib/haml/helpers/xss_mods.rb
66
67
  - lib/haml/html.rb
67
68
  - lib/haml/precompiler.rb
68
69
  - lib/haml/shared.rb
@@ -152,8 +153,8 @@ files:
152
153
  - test/haml/rhtml/action_view.rhtml
153
154
  - test/haml/rhtml/standard.rhtml
154
155
  - test/haml/spec
155
- - test/haml/spec_test.rb
156
156
  - test/haml/template_test.rb
157
+ - test/haml/spec_test.rb
157
158
  - test/haml/templates
158
159
  - test/haml/templates/_av_partial_1.haml
159
160
  - test/haml/templates/_av_partial_1_ugly.haml
@@ -300,8 +301,8 @@ test_files:
300
301
  - test/haml/engine_test.rb
301
302
  - test/haml/helper_test.rb
302
303
  - test/haml/html2haml_test.rb
303
- - test/haml/spec_test.rb
304
304
  - test/haml/template_test.rb
305
+ - test/haml/spec_test.rb
305
306
  - test/haml/util_test.rb
306
307
  - test/sass/css2sass_test.rb
307
308
  - test/sass/engine_test.rb