pmichna
pmichna

Reputation: 4888

Displaying user input html with newlines

I have comments section in my application where users enter input in a text area. I want to prevent the line breaks they enter but also display html as a string. For example, if comment.body is

Hello, this is the code: <a href='foo'>foo</a>

Bye

I want it to be displayed just as above. The same with anything else, including iframe tags.

The closest I got is:

= simple_format(comment.body)

but it sanitizes html code and it's not displayed. Example: foo <iframe>biz</iframe> bar is displayed as:

foo biz bar

What should I do to achieve what I want?

Upvotes: 0

Views: 159

Answers (3)

Michael Gorman
Michael Gorman

Reputation: 1077

HTML safe allows the html in the comment to be used as html, but would skip the newlines, so doing a quick replace of \n with <br /> would cover the new lines

comment.body.gsub("\n", "<br />").html_safe

If you want the html to be displayed instead of rendered then checkout CGI::escapeHTML(), then do the gsub so that the <br /> does not get escaped.

CGI::escapeHTML(comment.body).gsub("\n", "<br />")

Upvotes: 2

Gerry
Gerry

Reputation: 10497

Just use it without any method, it will be rendered as plain text:

= comment.body

Using your second example, the output will be:

foo <iframe>biz</iframe> bar

To make \n behave as <br>, you can use CSS:

.add-line {
  white-space: pre-wrap;
}

And use it in your view:

.add-line = comment.body

Using your first example:

comment.body = "Hello, this is the code: <a href='foo'>foo</a>\n\nBye"

The output will be:

Hello, this is the code: <a href='foo'>foo</a>

Bye

Upvotes: 2

fbelanger
fbelanger

Reputation: 3568

Having done something similar in the past, I think you must first understand why HTML is sanitized from user input.

Imagine I wrote the following into a field that accepted HTML and displays this to the front page.

<script>alert('Hello')</script>

The code would execute for anyone visiting the front-page and annoyingly trigger a JS alert for every visitor.

Maybe not much of an issue yet, but imagine I wrote some AJAX request that sent user session IDs to my own server. Now this is an issue... because people's sessions are being hijacked.

Furthermore, there is a full JavaScript based exploitation framework called BeEF that relies on this type of website exploit called Cross-site Scripting (XSS).

BeEF does extremely scary stuff and is worth taking a look at when considering user generated HTML.

http://guides.rubyonrails.org/security.html#cross-site-scripting-xss

So what to do? Well if you checked in your DB you'd see that the tags are actually being stored, but like you pointed out aren't displayed.

You could .html_safe the content, but again I strongly advise against this.

Maybe instead you should write an alternative .html_safe method yourself, something like html_safe_whitelisted_tags.

As for removing newlines, you say you want to display as is. So replacing /n with <br>, as pointed out by Michael, would be the solution for you.

comment.body.gsub('\n', '<br />').html_safe_whitelisted_tags

Upvotes: 2

Related Questions