Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing HTML Escaping in Rails 3

I'm running into an issue with the rails auto-escaping. It currently thinks a string is html_safe (which it is), but for display purposes I need it to still escape the html. Here's the steps the string is taking.

my_string = render(:partial => "set_string", :locals => {:item => @item})
<%= my_string %>

and the partial is basically

<h2>Page Header</h2>
<strong><%= item.name %></strong>
<%= item.body %>
etc

My understanding is that because I'm displaying text in a view directly (the h2, etc) it assumes it is safe, and it also properly escapes the item outputs, which makes the whole my_string safe. So, when I try to display it with the

<%= my_string %>

It doesn't escape the remaining html. I tried adding h to force the escaping but that didn't work.

So my question is, is there anyway to force html escaping of a safe string other than calling something on the string that will make it unsafe?

Thanks a lot for your help.

like image 272
Jason Logsdon Avatar asked Jun 05 '12 17:06

Jason Logsdon


2 Answers

Escape from ActiveSupport::SafeBuffer in Rails 3+

In this instance <%= my_string.to_str %> will double-escape as required.

SafeBuffer workings

When a string is escaped by Rails you get an ActiveSupport::SafeBuffer. From that point, extra escaping is skipped because the SafeBuffer is html_safe?. It's a clever solution! There are times though, that we wish to escape such cleverness.

Why double-escape?

I needed to re-escape content generated by tag helpers to pass generated markup to data- attributes. This has also come in handy for displaying template-generated code.

Force-escape for a String that's html_safe?

Call to_str on the SafeBuffer, which returns a String.

# Example html safe content
content = content_tag :code, 'codez<>'
content.html_safe? # true

# call .to_str
escaped = content.to_str
escaped.html_safe? # false

# The escaped String will now be re-escaped when used in a template

The to_s gotcha

The to_s method looks very much like the to_str method. Don't use to_s here, ActionView::SafeBuffer#to_s just returns self, where to_str is called above the SafeBuffer context, returning a naturally unsafe String.

like image 57
captainpete Avatar answered Oct 28 '22 17:10

captainpete


Thanks to Sebastien for the suggestion, I wanted to get the real answer here and not buried in the comments:

I looks like this works:

<%= raw CGI::escapeHTML(my_string) %>

You need the "raw" call otherwise the escapeHTML makes the string unsafe in addition to escaping it so the auto escape double escapes it.

like image 26
Jason Logsdon Avatar answered Oct 28 '22 18:10

Jason Logsdon